语境
我正在向现有的工作系统添加一些内容。有一台控制机器(一台本地 Linux PC)运行一些测试脚本,这些脚本涉及通过 SSH 远程向几台不同的机器发送大量命令。测试框架是用Python编写的,并使用Fabric来访问不同的机器。
所有命令都使用通用调用函数处理,简化如下:
def cmd(host, cmd, args):
...
with fabric.api.settings(host_string=..., user='root', use_ssh_config=True, disable_known_hosts=True):
return fabric.api.run('%s %s' % (cmd, args))
发送到每台机器的实际命令通常涉及在远程端运行现有的 python 脚本。这些 python 脚本执行一些工作,包括调用外部命令(使用system
and subprocess
)。远程 python 脚本完成后,测试 PC 上调用的run()
命令将返回。
有一次,我需要其中一个远程 python 脚本来启动后台任务:使用openvpn --config /path/to/config.openvpn
. 在一个普通的 python 脚本中,我会使用&
:
system('openvpn --config /path/to/config.openvpn > /var/log/openvpn.log 2>&1 &')
当通过 Fabric 远程调用此脚本时,必须显式使用nohup
、dtach
等screen
在后台运行作业。我得到了它的工作:
system("nohup openvpn --config /path/to/config.openvpn > /var/log/openvpn.log 2>&1 < /dev/null &"
Fabric 常见问题解答对此进行了一些详细说明。它适用于某些后台命令。
问题:不适用于所有类型的后台命令
这种技术不适用于我需要的所有命令。在某些脚本中,我需要启动一个后台atop
命令(它是top
类固醇)并将其标准输出重定向到一个文件。
我的代码(注意:atop -P
用于可解析输出):
system('nohup atop -P%s 1 < /dev/null | grep %s > %s 2>&1 &' % (dataset, grep_options, filename))
当通过 Fabric 远程调用包含该命令的脚本时,会立即终止 atop 进程。输出文件已生成,但为空。通过 SSH 登录远程计算机时调用相同的脚本可以正常工作,该atop
命令会定期将数据转储到我的输出文件中。
一些谷歌搜索和挖掘给我带来了有关使用 Fabric 的后台作业的有趣信息,但我的问题似乎只特定于某些类型的后台作业。我试过了:
- 附加睡眠
- 使用 pty=False 运行
- 替换
nohup
为dtach -n
:相同的症状 - 我读到了诸如 top 在 Fabric 中失败之类的命令,其中 stdin 重定向到 /dev/null,不太确定该怎么做。我玩弄了不同的组合或(非)STDIN、STDOUT 和 STDERR 重定向
看来我的想法已经不多了。
对于我们正在做的事情,Fabric 似乎有些矫枉过正。我们甚至不使用“fabfile”方法,因为它集成在一个nose
框架中,我运行它们调用nosetests
. 也许我应该放弃 Fabric 以支持手动 SSH 命令,尽管我不喜欢更改工作系统的想法,因为它不支持我的新模块之一。