如何使用paramiko启动后台任务?

8 投票
3 回答
6765 浏览
提问于 2025-04-15 18:54

这是我的情况:我想用Paramiko来自动化一些任务。这些任务需要按照特定的顺序启动(用(主机,任务)表示):(A,1),(B,2),(C,2),(A,3),(B,3)——基本上是为了测试而按正确的顺序启动服务器和客户端。此外,由于在测试中网络可能会出现问题,而且我需要一些测试的输出,所以我想把输出直接重定向到一个文件里。

在类似的情况下,常见的解决办法是使用'screen -m -d'或者'nohup'。但是使用Paramiko的exec_cmd时,nohup并不能真正退出。使用:

bash -c -l nohup test_cmd & 

也不行,exec_cmd仍然会阻塞,直到进程结束。

在使用screen的情况下,输出重定向效果也不好(实际上,按照我所能理解的,根本就不行)。

所以,经过这些解释,我的问题是:有没有简单优雅的方法来分离进程并捕获输出,以便结束Paramiko的exec_cmd阻塞?

更新

dtach命令对此非常有效!

3 个回答

0

为此,我写了一个小的shell脚本,在远程机器上执行:

#!/bin/bash

# check for command line arguments
if [ $# -lt 2 ]; then
        echo "usage: runcommand.sh EXECUTIONSTRING TASKNAME"
        exit -1
fi

taskname=$2
execstr=$1
logfile=$taskname.log

echo START $taskname > $logfile
echo OWNPID $BASHPID >> $logfile
stime=`date -u +"%Y-%m-%d_%H-%M-%S"`
stimes=`date -u +"%s"`
echo STARTTIME $stime >> $logfile
echo STARTTIMES $stimes >> $logfile
# execute program
$execstr 1>$taskname.stdout 2>$taskname.stderr 
echo RETVAL $? >> $logfile

stime=`date -u +"%Y-%m-%d_%H-%m-%S"`
stimes=`date -u +"%s"`
echo STOPTIME $stime >> $logfile
echo STOPTIMES $stimes >> $logfile
echo STOP $taskname >> $logfile

这个脚本的作用是:执行一个指定的任务,把标准输出和错误输出分别保存到两个不同的文件中,并创建一个日志文件,记录任务开始的时间、结束的时间和任务的返回值。

接着,我先把这个脚本复制到远程主机上,然后用exec_command在那边执行它:

command = './runcommand.sh "{execpath}" "{taskname}" > /dev/null 2>&1 &'
ssh.exec_command(command.format(execpath=anexecpath, taskname=ataskname)
0

我对paramiko和它的exec_cmd一点都不了解,不过也许可以试试bash里的disown命令。

#!/bin/bash -l
test_cmd &
disown test_cmd
4

不使用nohup或screen。

def command(channel, cmd):
    channel.exec_command(cmd + ' > /dev/null 2>&1 &')

这段话的意思是:“把命令的正常输出(STDOUT)发送到一个叫做dev/null的地方,然后把错误输出(STDERR)重新发送到正常输出,这样它们也就去了/dev/null。最后,把这个过程放到后台运行。”

这样做的话,exec_command就不会因为没有输出而卡住,所以它会正常返回。

撰写回答