常见问题/解答(FAQ)¶
这些是我们从用户那里收到的最常见的问题或常见问题。它们不能代替阅读文档的其余部分,因此如果您的问题没有在这里得到回答,请确保您已经检查过了。
备注
大多数API示例和链接都是针对版本2和更高版本的;针对版本1的常见问题通常会标记为类似的。
警告
回答了许多关于Shell命令执行和任务行为的问题 Invoke's FAQ page -请在那里也检查一下!
远程端未正确设置显式设置的环境变量!¶
如果您尝试为以下内容设置环境变量 Connection.run
appear to silently fail, you're almost certainly talking to an SSH server which is setting a highly restrictive AcceptEnv 。
要进行修复,您可以修改服务器的配置以允许您正在设置的环境变量,或者使用 inline_ssh_env
Connection
参数(或 global config option 同名),强制Fabric发送前缀在命令字符串之前的环境变量。
远程Shell环境与交互式Shell不匹配!¶
您可能会发现环境变量(或它们触发的行为)与通过Fabric编写脚本的环境变量不同。例如,您的计算机上的某个程序 $PATH
当您手动 ssh
在使用时可能看不到 Connection.run
;或者特殊的每个程序的环境变量,如那些用于Python、pip、Java等的环境变量没有生效;等等。
其根本原因通常是因为SSH服务器通过非常有限的Shell调用运行非交互命令: /path/to/shell -c "command"
(例如, OpenSSH )。当以这种方式运行时,大多数Shell都不会被认为是 interactive 或 login 这会影响加载哪些启动文件。
用户通常只修改与交互操作相关的Shell文件(例如 ~/.bash_profile
或 /etc/zshrc
);当SSH服务器运行一次性命令时,此类更改不会生效。
要解决此问题,请参考您的Shell文档,查看它是否提供了任何非登录、非交互的配置文件;例如, zsh
允许您配置 /etc/zshrc
或 ~/.zshenv
为了这个目的。
备注
bash
似乎不提供标准的非登录/非交互启动文件,即使在版本4中也是如此。但是,它可能会尝试确定它是否正在由远程执行守护程序运行,并显然会 ~/.bashrc
如果是,请检查您的目标系统上是否存在这种情况。
备注
另一种解决方法是 bash
用户将在其上回复 $BASH_ENV
功能,该功能将文件路径命名为要加载的启动文件:
将SSH服务器配置为
AcceptEnv BASH_ENV
,这样您实际上可以在顶层设置远程会话的env var(大多数SSH服务器默认不允许使用这种方法)。决定这应该是哪个文件,但是如果您已经在修改文件,比如
~/.bash_profile
或~/.bashrc
,您可能只想指向那条确切的路径。设置结构配置值
run.env
要瞄准上述道路,例如{"BASH_ENV": "~/.bash_profile"}
。
我的 (cd
/`` workon`/`` export``/etc)调用似乎不起作用!¶
虽然fabric可以用于许多类似shell脚本的任务,但有一个稍微不明确的捕获:每个 run
或 sudo
呼叫(或) run
/sudo
v1)中的函数有自己独特的shell会话。为了让fabric在命令运行后可靠地确定其标准out/error和返回代码是什么,这是必需的。
不幸的是,这意味着像下面这样的代码并不像您想象的那样工作:
@task
def deploy(c):
c.run("cd /path/to/application")
c.run("./update.sh")
如果那是一个shell脚本,那么第二个 run
调用的当前工作目录为 /path/to/application/
--但是,由于这两个命令都在各自的不同会话中通过ssh运行,因此它实际上尝试执行 $HOME/update.sh
相反(因为远程主目录是默认的工作目录)。
一个简单的解决方法是使用shell逻辑操作,例如 &&
,将多个表达式链接在一起(如果左侧执行时没有错误),如下所示:
def deploy(c):
c.run("cd /path/to/application && ./update.sh")
备注
您也可以使用绝对路径,跳过目录更改:
def deploy(c):
c.run("/path/to/application/update.sh")
但是,这要求所讨论的命令对当前工作目录不做任何假设!
为什么我有时会看到 err: stdin: is not a tty
是吗?¶
见 Invoke's FAQ 为此,即使对于不基于invoke的结构v1,答案也是一样的。
为什么我不能在后台运行程序 &
?它使 Fabric 挂起。¶
因为每次调用 run
或 sudo
(see also )时,后台进程可能会阻止调用shell退出,直到进程停止运行,这反过来又会阻止结构继续执行自己的执行。
修复此问题的关键是确保进程的标准管道都与调用shell断开,调用shell可以通过多种方式完成(按稳健性顺序列出):
如果手头的程序存在守护程序,请使用预先存在的守护程序技术——例如,调用init脚本而不是直接调用服务器二进制文件。
或利用流程管理器,如
supervisord
,upstart
或systemd
-这些工具允许您定义“运行”某个后台进程的含义,然后发出诸如start/stop/restart/status命令之类的init脚本。与经典的init脚本相比,它们也提供了许多优势。
使用
tmux
,screen
或dtach
为了使进程与正在运行的shell完全分离,这些工具的好处是允许您在以后需要时重新附加到进程(尽管它们比supervisord
像工具一样。在下运行程序
nohup
或者类似的“在shell中”工具——请注意,对于大多数用户来说,这种方法的成功率是有限的。
有时我被错误地要求输入 passphrase 而不是 password 。¶
由于在我们的ssh层中有一个类似的错误,目前Fabric不可能总是准确地检测所需的身份验证类型。我们必须尝试猜测我们是被要求使用私钥密码还是远程服务器密码,在某些情况下,我们的猜测是错误的。
最常见的这种情况是,本地用户您似乎有一个ssh keychain代理正在运行,但是远程服务器无法使用您的ssh密钥,例如,您还没有将公钥传输过来,或者使用的用户名不正确。在这种情况下,fabric会提示您“请输入私钥的密码短语”,但您输入的文本实际上正被发送到远程端的密码验证。
我们希望在将来的版本中通过对前面提到的ssh库的贡献来解决这个问题。