封装一个使用subprocess的Popen执行SHELL命令的函数, 支持超时判断,支持读取stdout和stderr
# !/usr/bin/python
# -*- coding: UTF-8 -*-
# @author:zz
import shlex
import datetime
import subprocess
import time
import os
code_dct = {
0: '执行成功',
7: '找不到表',
41: '查询字段不存在',
64: '表示缺失关键字',
127: '语句为空串'
}
def return_code_mean(code):
if code in code_dct.keys():
return code_dct[code]
else:
return "查询不到该返回状态值"
def execute_command(cmdstring, cwd=None, timeout=1200, shell=True):
"""执行一个SHELL命令
封装了subprocess的Popen方法, 支持超时判断,支持读取stdout和stderr
参数:
cwd: 运行命令时更改路径,如果被设定,子进程会直接先更改当前路径到cwd
timeout: 超时时间,秒,支持小数,精度0.1秒
shell: 是否通过shell运行
Returns: return_code
Raises: Exception: 执行超时
"""
if shell:
cmdstring_list = cmdstring
else:
cmdstring_list = shlex.split(cmdstring)
if timeout:
end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
print("> > > > > > > In execute_command() ... ")
print("comand: " + cmdstring)
# 没有指定标准输出和错误输出的管道,因此会打印到屏幕上;
sub = subprocess.Popen(cmdstring_list, cwd=cwd, stdin=subprocess.PIPE, shell=shell,stdout=subprocess.PIPE,stderr=subprocess.PIPE, bufsize=4096)
# subprocess.poll()方法:检查子进程是否结束了,如果结束了,设定并返回码,放在subprocess.returncode变量中
err_info = ""
err_info_tmp = ""
while sub.poll() is None:
time.sleep(0.001)
err_info_line = sub.stderr.readline().decode()
if err_info_line:
err_info += err_info_line
print(err_info_line)
if timeout:
if end_time <= datetime.datetime.now():
if err_info_tmp == err_info:
print('Errror shell 执行超时')
break
else:
err_info_tmp = err_info
end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout)
if sub.returncode != 0:
print("error")
return sub.stdout.read().decode(), sub.returncode, err_info
if __name__ == '__main__':
print(execute_command('ls -l'))