【问题标题】:Popen Subprocess PythonPopen 子进程 Python
【发布时间】:2018-12-05 21:05:54
【问题描述】:

我正在使用 Popen 远程调用脚本

s = Popen(['ssh' , ssh_argument0 , ssh_argument1 , '/tmp/remote/dude_rc_admsvr.sh %s %s' %(DomainHome , ACTIVITY)]) 

stdout = s.communicate()

打印标准输出

脚本没有以shell脚本中提到的状态退出,而是只打印成功或失败状态..

我想按照 shell 脚本退出状态码。 这是shell脚本

tail -Fn0 ${ADM_DOMAIN_LOG} | \
while read LOG_LINE;
do
 echo ${LOG_LINE} | grep -q "${PASS_MSG}"
 if [ $? = 0 ]
 then
   echo "${STATUS_SUCCESS}"
   exit 0
 elif echo ${LOG_LINE} | grep -q "${FAIL_MSG}"
 then
   echo "${STATUS_FAILURE}"
   exit 1
 elif echo  ${LOG_LINE} | grep -q "${FAIL_MSG2}"
 then
    echo "${STATUS_FAILURE}"
    exit 1
 fi
done
exit 

如何获取返回的状态码?

【问题讨论】:

  • 但是我的shell脚本以状态码退出,为什么在Popen中使用时它不起作用
  • 脚本甚至没有退出,至少应该退出
  • 在这种情况下,我会说将状态写入文件,然后从那里读取,我知道这不是最好的方法,但它可以工作
  • 但是脚本甚至没有退出 Popen 命令...

标签: python shell subprocess popen


【解决方案1】:

来自subprocess.check_call's documentation

如果返回码为零则返回,否则为raise CalledProcessErrorCalledProcessError 对象将返回 returncode 属性中的代码。

因此,要获取状态码,需要捕获异常并检索returncode属性。

try:
    check_call(['ssh' , ssh_argument0 , ssh_argument1 , '/tmp/remote/dude_rc_admsvr.sh %s %s' %(DomainHome , ACTIVITY)]) 
except subprocess.CalledProcessError as e:
    print('status code = %s' % e.returncode)

【讨论】:

  • 但是为什么它不从shell脚本中获取退出代码,我已经添加了exit 0,exit 1到shell代码
  • 是的,同样的问题它没有退出 + echo '' '' '' ' ' '' + grep -q '服务器状态更改为 RUNNING' + [ 0 = 0 ] + echo P + exit 0
  • @user2900860 在您刚刚发布的内容中,脚本似乎以 0 退出,表示成功,因此check_call 自然而然地返回而不会引发异常,因此不会进入 except 块进行打印状态码。您是否尝试过脚本返回 1 的场景?
  • 它甚至没有退出 exit 1 grep -q 'Server state changed to RUNNING' + [ 0 = 0 ] + echo P + exit 1
  • “它甚至没有退出”是什么意思?剧本还没写完?您是否确保脚本首先在命令行中使用给定的参数运行?您是否尝试过先使用 ssh 在命令行中运行脚本?
【解决方案2】:

添加一个新答案,因为您将有问题的代码从使用 check_call 更改为使用 Popencommunicate

来自subprocess.communicate's documentation

注意,如果你想发送数据到进程的stdin,你需要 使用stdin=PIPE 创建Popen 对象。同样,得到任何东西 除了结果元组中的None,你需要给stdout=PIPE 和/或stderr=PIPE

换句话说,您需要在对Popen 的构造函数的调用中添加stdout=PIPE 才能使用communicate

s = Popen(['ssh' , ssh_argument0 , ssh_argument1 , '/tmp/remote/dude_rc_admsvr.sh %s %s' %(DomainHome , ACTIVITY)], stdout=PIPE)
stdout = s.communicate()
returncode = s.returncode

【讨论】:

  • shell脚本没有从popen ssh代码退出,我不关心返回码我只想从控制台/函数退出
  • @user2900860 尝试将input=PIPE 也添加到参数中。顺便说一句,您确实强调要在问题中获取状态代码(您说“如何返回状态代码?”)。说你现在不在乎它只是自相矛盾。
  • 脚本没有以shell脚本下提到的状态退出,而是“只打印成功或失败状态”。这就是我上面提到的我需要 shell 脚本退出状态而不是 popen ..
  • @user2900860 添加input=PIPE 有帮助吗?
  • 已解决 tail 正在持有 ssh 会话,该会话已通过添加 kill -9 |ps -eaf |grep tail.. 解决
【解决方案3】:

发现问题:

shell 脚本中的 tail 语句持有 SSH 会话,这就是为什么 Popen 无法退出子 shell 的原因,添加 kill -9 ps -eaf |grep tail 解决了这个问题。

【讨论】:

    猜你喜欢
    • 2014-09-15
    • 1970-01-01
    • 2012-03-03
    • 2011-08-05
    • 2017-02-03
    • 2017-08-22
    • 1970-01-01
    • 1970-01-01
    • 2012-07-04
    相关资源
    最近更新 更多