Python中判断subprocess调起的shell命令是否结束

前言

最近在使用subprocess遇到个问题,折腾了好半天才找到简单的解决办法,在这里记录下。

环境

Python:2.7.10

库:subprocess, logging

问题

使用subprocess的Popen类来执行shell命令,要怎么样才能知道命令执行结束了,以此来执行回调方法。

解决办法

使用subprocess.Popen.poll方法来获取命令的执行情况。

poll方法的返回值有两种情况   

1. 当命令未运行结束的时候,返回None   

2. 当命令结束时,返回命令的返回值

演示

这里使用logging模块来辅助显示命令执行时间

分别使用两种调用shell命令的方式来测试

shell=True

shell=False

完整演示

补充:system函数返回(如何判断调用的shell命令是否执行成功)

例:

status = system("./test.sh");

1、先统一两个说法:

(1)system返回值:指调用system函数后的返回值,比如上例中status为system返回值

(2)shell返回值:指system所调用的shell命令的返回值,比如上例中,test.sh中返回的值为shell返回值。

2、如何正确判断test.sh是否正确执行?

仅判断status是否==0?或者仅判断status是否!=-1?

都错!

3、man中对于system的说明

RETURN VALUE

The value returned is -1 on error (e.g. fork() failed), and the return

status of the command otherwise. This latter return status is in the

format specified in wait(2). Thus, the exit code of the command will

be WEXITSTATUS(status). In case /bin/sh could not be executed, the

exit status will be that of a command that does exit(127).

看得很晕吧?

system函数对返回值的处理,涉及3个阶段:

阶段1:创建子进程等准备工作。如果失败,返回-1。

阶段2:调用/bin/sh拉起shell脚本,如果拉起失败或者shell未正常执行结束(参见备注1),原因值被写入到status的低8~15比特位中。system的man中只说明了会写了127这个值,但实测发现还会写126等值。

阶段3:如果shell脚本正常执行结束,将shell返回值填到status的低8~15比特位中。

备注1:

只要能够调用到/bin/sh,并且执行shell过程中没有被其他信号异常中断,都算正常结束。

比如:不管shell脚本中返回什么原因值,是0还是非0,都算正常执行结束。即使shell脚本不存在或没有执行权限,也都算正常执行结束。

如果shell脚本执行过程中被强制kill掉等情况则算异常结束。

如何判断阶段2中,shell脚本是否正常执行结束呢?系统提供了宏:WIFEXITED(status)。如果WIFEXITED(status)为真,则说明正常结束。

如何取得阶段3中的shell返回值?你可以直接通过右移8bit来实现,但安全的做法是使用系统提供的宏:WEXITSTATUS(status)。

由于我们一般在shell脚本中会通过返回值判断本脚本是否正常执行,如果成功返回0,失败返回正数。

所以综上,判断一个system函数调用shell脚本是否正常结束的方法应该是如下3个条件同时成立:

(1)-1 != status

(2)WIFEXITED(status)为真

(3)0 == WEXITSTATUS(status)

注意:

根据以上分析,当shell脚本不存在、没有执行权限等场景下时,以上前2个条件仍会成立,此时WEXITSTATUS(status)为127,126等数值。

所以,我们在shell脚本中不能将127,126等数值定义为返回值,否则无法区分中是shell的返回值,还是调用shell脚本异常的原因值。shell脚本中的返回值最好多1开始递增。

判断shell脚本正常执行结束的健全代码如下:

#include  <stdio.h>
#include  <stdlib.h>
int main()
{
    pid_t status;
    status = system("./test.sh");
    if(status == -1)
    {
 printf("system error... \n");
     }
 else
 {
            if(WIFEXITED(status))
     {
                if(0 == WEXITSTATUS(status))
         {
                    printf("run  successfully... \n");
                }
  else
  {
                    printf("run failed %d \n",WEXITSTATUS(status));
                 }
             }
      else
     {
                printf("exit code %d \n",WEXITSTATUS(status));
            }
 }
    return 0;
 } 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • python中的subprocess.Popen()使用详解

    从python2.4版本开始,可以用subprocess这个模块来产生子进程,并连接到子进程的标准输入/输出/错误中去,还可以得到子进程的返回值. subprocess意在替代其他几个老的模块或者函数,比如:os.system os.spawn* os.popen* popen2.* commands.* 一.subprocess.Popen subprocess模块定义了一个类: Popen class subprocess.Popen( args, bufsize=0, executable

  • python subprocess pipe 实时输出日志的操作

    * test11.py import time print "1" time.sleep(2) print "1" time.sleep(2) print "1" time.sleep(2) print "1" * test.py import subprocess p = subprocess.Popen("python test11.py", shell=True, stdout=subprocess.

  • 详谈python中subprocess shell=False与shell=True的区别

    shell=True参数会让subprocess.call接受字符串类型的变量作为命令,并调用shell去执行这个字符串,当shell=False是,subprocess.call只接受数组变量作为命令,并将数组的第一个元素作为命令,剩下的全部作为该命令的参数. 举个例子来说明 from subprocess import call import shlex cmd = "cat test.txt; rm test.txt" call(cmd, shell=True) 上述脚本中,sh

  • 使用python执行shell脚本 并动态传参 及subprocess的使用详解

    最近工作需求中 有遇到这个情况 在web端获取配置文件内容 及 往shell 脚本中动态传入参数 执行shell脚本这个有多种方法 最后还是选择了subprocess这个python标准库 subprocess这个模块可以非常方便的启动一个子进程,并且控制其输入和输出 Class Popen(args,bufsize = 0,executable=None, stdin =None,stdout =None,stderr =None, preexec_fn = None,close_fds =

  • 解决python subprocess参数shell=True踩到的坑

    0x01 问题现象 写的程序使用subprocess创建子进程运行其他程序,判断其他程序运行完后进行处理. 在subprocess使用了shell=True,判断用户程序退出的代码如下 while self.proc.poll() is None: do_something 判断子进程是否运行结束,程序在子进程运行结束后,代码未向下继续运行,而是卡在了这个循环中. 0x02 原因分析 百度后对shell参数的解释如下: shell=True参数会让subprocess.Popen接受字符串类型的

  • 通过实例解析python subprocess模块原理及用法

    一.subprocess以及常用的封装函数 运行python的时候,我们都是在创建并运行一个进程.像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序.在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序. subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用.另外subprocess还提供了一些管理标准流(standard stream)

  • python3通过subprocess模块调用脚本并和脚本交互的操作

    因工作需要,需实现如题所示功能.查阅网上博客,资料,大多都是针对python2的,而且很多地方不明所以,所以自己整理了一下查阅的结果,重新写一篇博客. 预备知识 1.python3的默认字符串类型 Python 2.x 同时支持ASCII和 Unicode字符串,默认情况下是ASCII编码.而 Python 3中这种支持刚好调换:Unicode现在变成了默认类型,而 ASCII 字符串现在称为 bytes. bytes 数据结构包含字节值,并且它 不应该再被视为一个字符串,因为它是一个包含数据的

  • Python中判断subprocess调起的shell命令是否结束

    前言 最近在使用subprocess遇到个问题,折腾了好半天才找到简单的解决办法,在这里记录下. 环境 Python:2.7.10 库:subprocess, logging 问题 使用subprocess的Popen类来执行shell命令,要怎么样才能知道命令执行结束了,以此来执行回调方法. 解决办法 使用subprocess.Popen.poll方法来获取命令的执行情况. poll方法的返回值有两种情况    1. 当命令未运行结束的时候,返回None    2. 当命令结束时,返回命令的返

  • Python中使用subprocess库创建附加进程

    前言 subprocess库提供了一个API创建子进程并与之通信.这对于运行生产或消费文本的程序尤其有好处,因为这个API支持通过新进行的标准输入和输出通道来回传数据. 本篇,将详细介绍Python创建附加进行的库:subprocess. run(运行外部命令) subprocess库本身可以替换os.system(),os.spawnv()等函数.现在我们来通过subprocess库运行一个外部命令,但不采用os.system().示例如下: import subprocess complet

  • python中判断文件编码的chardet(实例讲解)

    1.实测,这个版本在32位window7和python3.2环境下正常使用. 2.使用方法:把解压后所得的chardet和docs两个文件夹拷贝到python3.2目录下的Lib\site-packages目录下就可以正常使用了. 3.判断文件编码的参考代码如下: file = open(fileName, "rb")#要有"rb",如果没有这个的话,默认使用gbk读文件. buf = file.read() result = chardet.detect(buf)

  • Python 中判断列表是否为空的方法

    在判断列表是否为空时,你更喜欢哪种方式?决定因素是什么? 在 Python 中有很多检查列表是否是空的方式,在讨论解决方案前,先说一下不同方法涉及到的不同因素. 我们可以把判断表达式可以分为两个阵营: 对空列表的显式比较 对空列表的隐式求值 这意味着什么? 显式比较 我们从显式比较开始说起,无论我们使用列表符号 [] 还是声明空列表的函数 list() ,遵循的策略是查看待检查列表是否与空列表完全相等. # 都是用来创建空列表 a = [] b = list() print(a == b) #

  • 如何在python中判断变量的类型

    python的数据类型有:数字(int).浮点(float).字符串(str),列表(list).元组(tuple).字典(dict).集合(set) 一般通过以下方法进行判断: 1.isinstance(参数1,参数2) 描述:该函数用来判断一个变量(参数1)是否是已知的变量类型(参数2) 类似于type() 参数1:变量 参数2:可以是直接或间接类名.基本类型或者由它们组成的元组. 返回值: 如果对象的类型与参数二的类型(classinfo)相同则返回 True,否则返回 False 例子:

  • python中判断文件结束符的具体方法

    python中判断文件结束符的方法:可以使用try except语句块来进行判断. 具体使用方法:[try:while True:s = input() except EOFError: pass]. Python 中,用try except语句块捕获并处理异常,其基本语法结构如下所示: try:     可能产生异常的代码块 except [ (Error1, Error2, ... ) [as e] ]:     处理异常的代码块1 except [ (Error3, Error4, ...

  • python中判断集合范围的方法小结

    我们在比较数值大小的时候,会使用一些比较符号来进行判断.在python集合中也有这样的比较,但有一点要注意的是,我们比较的是集合之间的包容性,而不是简单数值之间的大小比较,这点在文章的开头就进行明确,也是对于我们python初学者的提醒. 集合可以使用大于(>).小于(<).大于等于(>=).小于等于(<=).等于(==).不等于(!=)来判断某个集合是否完全包含于另一个集合,也可以使用子父集判断函数. 定义三个集合s1,s2,s3: >>> s1=set([1,

  • python中判断数字是否为质数的实例讲解

    在计算机程序中,算法是灵魂,是程序的精髓所在.程序执行效率的高低直接取决于算法的优劣,所以计算机算法是计算机课程必修课.算法可以快速计算出我们所需要的结果,例如判断质数,这是很基础的内容,具体如何操作呢?下面小编向大家演示在python如何判断数字是否为质数. 质数:一个大于1的自然数,除了1和它本身外,不能被其他自然数(质数)整除(2, 3, 5, 7等),换句话说就是该数除了1和它本身以外不再有其他的因数. 判断代码: def isprime(a): if isinstance(a,int)

  • Python使用paramiko连接远程服务器执行Shell命令的实现

    需求 在自动化测试场景里, 有时需要在代码里获取远程服务器的某些数据, 或执行一些查询命令,如获取Linux系统版本号 \ 获取CPU及内存的占用等, 本章记录一下使用paramiko模块SSH连接服务器的方法 1. 先安装paramiko库 pip3 install paramiko 2. 代码 #!/usr/bin/env python # coding=utf-8 """ # :author: Terry Li # :url: https://blog.csdn.net

随机推荐