python模块之 – subprocess执行unix/linux命令详解编程语言

subprocess模块提供了一种一致的方法来创建和处理附加进程,与标准库中的其它模块相比,提供了一个更高级的接口,subprocess模块用来生成子进程,并可以通过管道连接它们的
输入/输出/错误,以及获得它们的返回值.它用来代替多个旧模块和函数:
os.system
os.spawn*
os.popen*
popen2.*
commands.*

1.subprocess.call( commands ) 方法 :

subprocess的call方法可以用于执行一个外部命令,但该方法不能返回执行的结果,只能返回执行的状态码:成功(0)或错误(非0)
call()方法中的commands可以是一个列表,也可以是一个字符串,作为字符串时需要用原生的shell=True来执行:

示例:

>>> import subprocess 
>>> subprocess.call(["ls","-lh"]) 
total 8.0K 
-rw-r--r--. 1 root root 941 Oct 22  2013 socket_2.py 
-rw-r--r--. 1 root root 401 Oct 22  2013 socket_client.py 
0 
>>> subprocess.call("ls -lh",shell=True) 
total 8.0K 
-rw-r--r--. 1 root root 941 Oct 22  2013 socket_2.py 
-rw-r--r--. 1 root root 401 Oct 22  2013 socket_client.py 
0 
>>>  
如上实例所示,虽然我们能看到执行的结果和返回的一个状态码0,但保存为变量后实际获取的值只是状态码 
 
>>> cmd_result = subprocess.call("ls -lh",shell=True) 
total 8.0K 
-rw-r--r--. 1 root root 941 Oct 22  2013 socket_2.py 
-rw-r--r--. 1 root root 401 Oct 22  2013 socket_client.py 
>>> print(cmd_result) 
0 
>>>  

2.subprocess.check_call() 方法:

我们说过call执行返回一个状态码,我们可以通过check_call()函数来检测命令的执行结果,如果不成功将返回 subprocess.CalledProcessError 异常
#如果命令执行正确则返回结果,和subprocess.call效果一样.

示例:

>>> try: 
...   subprocess.check_call("ls -lh",shell=True) 
... except subprocess.CalledProcessError as err: 
...   print("Commands error") 
...  
total 8.0K 
-rw-r--r--. 1 root root 941 Oct 22  2013 socket_2.py 
-rw-r--r--. 1 root root 401 Oct 22  2013 socket_client.py 
0 
>>>  
#如果命令执行错误,则抛出异常. 
>>> try: 
...   subprocess.check_call("ls -jj",shell=True) 
... except subprocess.CalledProcessError as err: 
...   print("Commands error") 
...  
ls: invalid option -- 'j' 
Try `ls --help' for more information. 
Commands error 
>>>  

subprocess.call 和subprocess.check_call的区别:

subprocess.call:执行命令,返回结果
check_all :执行命令,如果执行状态码是0,则返回0,否则抛出异常.

subprocess.call如果命令执行错误不会抛出异常(经测试在linux系统上执行错误命令也会有异常错误,在pycharm上面则不抛出异常),而subprocess.check_call如果命令执行错误则抛出异常,如果命令执行正确则两者效果一样.

3.subprocess.Popen()方法: 

函数call(), check_call() 和 check_output() 都是Popen类的包装器。直接使用Popen会对如何运行命令以及如何处理其输入输出有更多控制。如通过为stdin, stdout和stderr传递不同的参数。

1.与进程的单向通信

通过Popen()方法调用命令后执行的结果,可以设置stdout值为PIPE,再调用communicate()获取结果 返回结果为tuple. 在python3中结果为byte类型,要得到str类型需要decode转换一下输出结果(读)

# 直接执行命令输出到屏幕 
 
>>> subprocess.Popen("ls -lh",shell=True) 
<subprocess.Popen object at 0x7f8ad576c450> 
>>> total 8.0K 
-rw-r--r--. 1 root root 941 Oct 22  2013 socket_2.py 
-rw-r--r--. 1 root root 401 Oct 22  2013 socket_client.py 
 
>>>  
 
# 不输出到屏幕,输出到变量 
#读取字符串 
>>> cmd_result=subprocess.Popen(["echo","welcome to china"],stdout=subprocess.PIPE) 
>>> print(cmd_result) 
<subprocess.Popen object at 0x7f8ad576c9d0> 
>>> stdout_var=cmd_result.communicate() 
>>> stdout_var 
('welcome to china/n', None) 
>>> print((stdout_var[0]).decode('utf-8')) 
welcome to china 
 
>>>  
 
#读取命令输出结果 
>>> cmd_result=subprocess.Popen(["ls","-lh"],stdout=subprocess.PIPE) 
>>> print(cmd_result) 
<subprocess.Popen object at 0x7f8ad576c990> 
>>> stdout_var=cmd_result.communicate() 
>>> print((stdout_var[0]).decode("utf-8")) 
total 8.0K 
-rw-r--r--. 1 root root 941 Oct 22  2013 socket_2.py 
-rw-r--r--. 1 root root 401 Oct 22  2013 socket_client.py 
 
>>>  
 
#将结果输出到文件 
 
>>> file_handle = open("/tmp/t.logs","w+") 
>>> subprocess.Popen("ls -lh",shell=True,stdout=file_handle) 
<subprocess.Popen object at 0x7f8ad576c990> 
>>>  
 
#在指定路径创建目录 
 
>>> import subprocess 
>>> obj = subprocess.Popen("mkdir t3",shell=True,cwd="/tmp",) 
>>> obj = subprocess.Popen("mkdir t4",shell=True,cwd="/tmp") 
>>>  

2 与进程的双向通信:  

>>> cmd_result=subprocess.Popen("cat",shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE) 
>>> msg="Hello World".encode("utf-8") 
# 写入到输入管道 
>>> cmd_result.stdin.write(msg) 
>>> stdout_var=cmd_result.communicate() 
>>> stdout_var 
('Hello World', None) 
>>> (stdout_var[0]).decode("utf-8") 
u'Hello World' 
>>> (stdout_var[0]).decode() 
u'Hello World' 
>>>  
>>> stdout_var[0] 
'Hello World' 
>>>  
 
#打开一个python终端,执行python print命令. 
>>> cmd_result=subprocess.Popen(["python"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE) 
>>> cmd_result.stdin.write('print("Good luck!")'.encode("utf-8")) 
>>> stdin_var,err_var=cmd_result.communicate() 
>>> print(err_var) 
 
>>> print(stdin_var) 
Good luck! 
>>> stdin_var 
'Good luck!/n' 
>>>  

Popen其它方法:

poll()                                                                                检查是否结束,设置返回值
wait() 等待结束,设置返回值
communicate() 参数是标准输入,返回标准输出和标准出错
send_signal() 发送信号 (主要在unix下有用)
terminate() 终止进程,unix对应的SIGTERM信号,windows下调用api函数TerminateProcess()
kill() 杀死进程(unix对应SIGKILL信号),windows下同上
stdin
stdout
stderr
参数中指定PIPE时,有用
pid 进程id
returncode 进程返回值

 

 脚本实例:

python模块之 - subprocess执行unix/linux命令详解编程语言

#!/usr/bin/env python 
#coding:utf-8 
import os 
import sys 
import subprocess 
import time 
import signal 
TOMCAT_HOME="/usr/local/tomcat-fraud/" 
TOMCAT_PORT=8083 
remote_ip="123.56.219.121" 
remote_port="'-e ssh -p 6168'" 
try: 
backup_dir='/data/backup/' + sys.argv[1] + os.sep + time.strftime('%Y%m%d') 
except IndexError: 
print("example : python fraud-dev.sh < projectname >") 
if len(sys.argv) < 2: 
print("you must use like this : python fraud-dev.sh <projectname>") 
sys.exit() 
if not os.path.isdir(backup_dir): 
os.makedirs(backup_dir) 
print("Sucessfully created directory",backup_dir) 
else: 
print("directory alreaty exist") 
#备份的模块(将项目的war包从jenkins目录取下来放到本地目录.) 
def backup(): 
print("download fraud.war...") 
#Jenkins服务器存放war包的目录 
packge_dir="/root/.jenkins/workspace/fraud-dev/fraud-web/target/" 
remote_ssh = remote_ip + ":" + packge_dir + sys.argv[1] + ".war" 
print(remote_ssh) 
#remote_ssh = remote_ip + ":" + packge_dir 
rsyn="/usr/bin/sudo rsync -avH --progress %s %s %s" %(remote_port,remote_ssh,backup_dir) 
if subprocess.call(rsyn,shell=True) == 0: 
print("download fraud.war sucess...") 
else: 
print("同步代码失败,check...") 
#代码更新函数: 
def rsync_java(): 
target_dir=TOMCAT_HOME + "webapps/" 
#os.chdir(target_dir) 
subprocess.Popen("rm -rf *", shell=True, cwd=target_dir) 
time.sleep(3) 
print("开始更新代码中...") 
rsync_ssh="/usr/bin/sudo rsync -avH --progress %s %s" %(backup_dir,target_dir) 
if subprocess.call(rsync_ssh,shell=True) == 0: 
print("代码更新完成...") 
else: 
print("代码更新失败...") 
#启停Java服务. 
def kill_pid(pid): 
try: 
a = os.kill(pid, signal.SIGKILL) 
print("已杀死pid为%s的进程,返回值是:%s" % (pid, a)) 
except OSError: 
print("没有这个进程号") 
def start_java(): 
java_service= TOMCAT_HOME + "bin/startup.sh" 
os.system(java_service) 
time.sleep(5) 
print("tomcat 启动完成...") 
if __name__ == "__main__": 
backup() 
li = [] 
#cmd="/usr/sbin/lsof -i:80 |egrep -v PID | awk {'print $2'} |sort -nr|uniq" 
cmd="/usr/sbin/lsof -i:%s | grep java |awk {'print $2'}" %(TOMCAT_PORT) 
pid = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
# print(pid.stdout.readlines()) 
for m in pid.stdout.readlines(): 
li.append(int(m)) 
for i in li: 
kill_pid(i) 
time.sleep(3) 
print("开始上传代码中...") 
rsync_java() 
start_java()

java备份和上传代码

python模块之 - subprocess执行unix/linux命令详解编程语言

#!/usr/bin/env python 
#coding:utf-8 
import os 
import time 
import subprocess 
packge_dir = "/root/.jenkins/workspace/shop-H5/" 
remote_ip = "59.110.164.99" 
remote_port = "'-e ssh -p 6168'" 
backup_dir = '/data/backup/' + time.strftime('%Y%m%d') 
source_dir = "shop-H5" 
def backup_php(): 
tgz = backup_dir + os.sep + "shop-H5_" + time.strftime('%Y%m%d%H') + '.tgz' 
backup_tgz = "tar -zcvf %s %s" % (tgz,source_dir) 
#print(time.strftime('%Y-%m-%d-%H:%M')) 
#print(backup_dir) 
if not os.path.exists(backup_dir): 
os.mkdir(backup_dir) 
print("Sucessfully created directory",backup_dir) 
print("开始备份代码中...") 
os.chdir('/opt') 
if subprocess.call(backup_tgz,shell=True) == 0: 
print("Successful backup to ", tgz) 
else: 
print("Backup FAILED!!") 
time.sleep(3) 
def rsync_php(): 
print("开始代码同步中...") 
remote_ssh = remote_ip + ":" + packge_dir 
rsyn = "/usr/bin/sudo rsync -avH --progress %s %s %s" %(remote_port,remote_ssh,source_dir) 
if subprocess.call(rsyn,shell=True) == 0: 
print("同步代码成功...") 
else: 
print("同步代码失败,check...") 
#递归改变目录的权限 
#os.chown(source_dir,509,509) 
mattr="chown -R phpci:phpci %s" %(source_dir) 
#subprocess.call(mattr,shell=True) 
subprocess.call(mattr,shell=True) 
if __name__ == "__main__": 
backup_php() 
rsync_php() 
PHP代码备份及上传

PHP代码备份及上传

python模块之 - subprocess执行unix/linux命令详解编程语言

#!/usr/bin/env python 
#coding:utf-8 
import os 
import time 
import subprocess 
packge_dir = "/root/.jenkins/workspace/pre-php-p/" 
remote_ip = "59.110.164.99" 
remote_port = "'-e ssh -p 6168'" 
backup_dir= '/data/backup/' + time.strftime('%Y%m%d') 
source_dir="shop-H5" 
source_URL="/data/web/xd" 
def backup_php(): 
tagz = backup_dir + os.sep + source_dir + "_" + time.strftime('%Y%m%d%H') + '.tgz' 
print "tagz=",tagz 
backup_tgz = "tar -zcvf %s %s" %(tagz,source_dir) 
if not os.path.exists(backup_dir): 
os.mkdir(backup_dir) 
print("Sucessfully created directory",backup_dir) 
print("开始备份代码中...") 
os.chdir(source_URL) 
#os.system(backup_tgz) 
#subprocess.call(backup_tgz,shell=True) 
if subprocess.call(backup_tgz,shell=True) == 0: 
print  "Successful backup to ", tagz 
else: 
print "Backup FAILED!!" 
time.sleep(3) 
def rsync_php(): 
print("开始代码同步中...") 
remote_ssh = remote_ip + ":" + packge_dir 
time.sleep(3) 
rsyn="/usr/bin/sudo rsync -avH --progress --exclude=.git %s %s %s" %(remote_port,remote_ssh,source_dir) 
#print rsyn 
if subprocess.call(rsyn,shell=True) == 0: 
print("同步代码成功...") 
else: 
print("同步代码失败,check...") 
#os.chown(source_dir,504,504) 
mattr="chown -R phpci:phpci %s" %(source_dir) 
subprocess.call(mattr,shell=True) 
if __name__ == "__main__": 
backup_php() 
rsync_php()

PHP代码备份及目录过滤

 

  

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/11657.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论