1

语境

我正在向现有的工作系统添加一些内容。有一台控制机器(一台本地 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 脚本执行一些工作,包括调用外部命令(使用systemand 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 远程调用此脚本时,必须显式使用nohupdtachscreen在后台运行作业。我得到了它的工作:

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 的后台作业的有趣信息,但我的问题似乎只特定于某些类型的后台作业。我试过了:

看来我的想法已经不多了。

对于我们正在做的事情,Fabric 似乎有些矫枉过正。我们甚至不使用“fabfile”方法,因为它集成在一个nose框架中,我运行它们调用nosetests. 也许我应该放弃 Fabric 以支持手动 SSH 命令,尽管我不喜欢更改工作系统的想法,因为它不支持我的新模块之一。

4

1 回答 1

0

在我的环境中,看起来它正在工作

from fabric.api import sudo

def atop():
    sudo('nohup atop -Pcpu 1 </dev/null '
        '| grep cpu > /tmp/log --line-buffered 2>&1 &',
        pty=False)

结果:

fabric:~$ fab atop -H web01
>>>[web01] Executing task 'atop'
>>>[web01] sudo: nohup atop -Pcpu 1 </dev/null | grep cpu > /tmp/log --line-buffered 2>&1 &
>>>
>>>Done.

web01:~$ cat /tmp/log 
>>>cpu web01 1374246222 2013/07/20 00:03:42 361905 100 0 5486 6968 0 9344927 3146 0 302 555 0 2494 100
>>>cpu web01 1374246223 2013/07/20 00:03:43 1 100 0 1 0 0 99 0 0 0 0 0 2494 100
>>>cpu web01 1374246224 2013/07/20 00:03:44 1 100 0 1 0 0 99 0 0 0 0 0 2494 100
...

atop 命令可能需要超级用户。这不起作用

from fabric.api import run

def atop():
    run('nohup atop -Pcpu 1 </dev/null '
        '| grep cpu > /tmp/log --line-buffered 2>&1 &',
        pty=False)

另一方面这项工作。

from fabric.api import run

def atop():
    run('sudo nohup atop -Pcpu 1 </dev/null '
        '| grep cpu > /tmp/log --line-buffered 2>&1 &',
        pty=False)
于 2013-07-19T15:26:55.223 回答