python subprocess 在 nohup 下的输出
我正在尝试用一个Python脚本来监控远程机器的可用硬盘空间,这个脚本通过执行命令df -h .
来实现,使用的是subprocess.popen这个功能。
import subprocess
import time
command = 'ssh remoteserver "df -h ."'
while True:
proc = subprocess.Popen(command,shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output,err=proc.communicate()
print output
print err
time.sleep(60)
当我在命令行中运行这个脚本时,它运行得很好,并且会把输出结果打印到终端上。
$> python2.7 script.py
Filesystem Size Used Avail Use% Mounted on
remoteserver:/home/user
555G 447G 109G 81% /home
但是,当我用nohup命令启动这个脚本时,它就没有任何输出,或者看起来像是被阻塞了。
$> nohup python2.7 script.py &
我希望这个脚本在使用nohup
启动时能够正常工作,并获取远程机器的硬盘空间信息。
2 个回答
你可以试着在调用子进程命令时,给它加上stdin=subprocess.PIPE,然后在下一行调用proc.stdin.close(),再调用communicate()。或者你可以把命令改成'ssh remoteserver "df -h ." </dev/null'。还有人提到可以用FNULL = open(os.devnull, 'r'),然后把FNULL传给stdin=这个参数,但我不太确定你是否需要在之后调用FNULL.close()。
SSH在通过nohup运行时,很可能因为某种原因在等待输入。也许它在nohup环境中无法进行身份验证,所以在请求输入密码?
为了确保SSH不在等待输入,可以试着在ssh命令中加上-o "BatchMode yes",看看在子进程的communicate调用中输出/错误信息里有没有一些线索。
我不太确定这里的具体问题是什么,但当你在命令行中使用NOHUP时,它会把一些输入输出(STDIN/STDOUT)和终端进程断开连接。我觉得这可能是导致你看到的一些交互问题。
因为你是在远程机器上操作,我建议你可以考虑使用像Fabric这样的库来完成你想做的事情。这个库使用起来很简单,而且能很好地处理终端会话,完成后也能帮你优雅地关闭。
可以参考这样的代码:
from fabric import api
from fabric.api import env
import fabric
env.host_string = '%s@%s' % (username, remote_host)
env.disable_known_hosts = True
env.password = password
fabric.state.output['stdout'] = False
fabric.state.output['stderr'] = False
results = api.run('df -h')