使用Fabric进入一个目录的sudo cd命令

3

我是Fabric的新手,试图进入一个没有权限的目录,所以我使用了sudo。(该目录的权限为drwx------,即700)

我正在使用Fabric 0.9.7。

我尝试了这个方法:

from fabric.api import run, env
from fabric.context_managers import cd

env.hosts = [ '1.2.3.4' ]
env.user = 'username'

def test():
       run('sudo cd /my/dir')
              run('ls')

但是这会给我带来“对不起,您必须拥有tty才能运行sudo”的提示,这是可以理解的。我还尝试了以下方法:

省略:

def test():
        with cd('/my/dir'):
                run('ls')

但是这会返回"permission denied",这是可以理解的。

简单来说,我要如何在Fabric中执行"sudo cd"?

3个回答

4

正如其他人已经解释过的那样,cd是Linux中的一个shell内建命令,但是sudo只能与可执行文件一起使用,因此sudo cd无法工作。

因此,即使是使用最新版本的Fabric与c.cd()sudo()也无法完成这个任务:

@task
def pwd(c):
    with c.cd('/tmp'):
        c.sudo('pwd')

导致以下错误的结果:

sudo: cd: command not found

这种可谓不太优雅的解决方法是,使用sudo()启动一个新的 shell 来运行命令,并手动在命令前加上cd

@task
def pwd(c):
    c.sudo('sh -c "cd /tmp && pwd"')

请查看此Invoke问题


3

你为什么不直接使用sudo()?它可能可以解决你遇到的问题。

如果你使用的是1.0版本之前的Fabric,你需要明确告诉它创建一个TTY

sudo("ls", pty=True)

否则,您可能需要编辑您的sudoers文件并删除或注释掉这一行:
Defaults    requiretty 

应该是:
#Defaults    requiretty

此外,虽然可能更加烦人,但如果with cd(...)引起问题,您始终可以将路径作为参数传递给ls
sudo("ls /my/dir")

当我使用def test(): sudo("ls", pty=True)时,我会看到一个“NameError: global name 'sudo' is not defined”的错误提示 - 可能是语法有误。 - ibash
@user1283693 你需要像导入 run 一样导入它:from fabric.api import run, env, sudo - Brendan Long
如果“语法”有误,Python 将会返回一个 SyntaxError :) - Iguananaut
是的,可以!pty=True和import sudo解决了我的问题。谢谢。 - ibash
@ibash 当有人解决了你的问题时,你可以点击其旁边的勾选标记将其答案标记为已接受。你也可以通过点击箭头来投票支持任意数量的答案(对于任何问题)。这两件事都是对帮助你的人的奖励。我在你的问题评论中链接了一个关于此的常见问题解答。 - Brendan Long

1
这是因为 cd 是一个 shell 内置命令,而不是可以使用 sudo 运行的实际程序。你之前尝试使用 with cd(...): 是正确的,可以尝试如下代码:
with cd('/my/dir'):
    sudo('ls')

我认为这将起作用,尽管我自己还没有尝试过。这是因为cd上下文管理器的工作方式是在使用run()sudo()运行任何命令时,在其前面加上cd <dirname> &&


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接