Python 编程过程中经常会用到系统命令,本文记录实现方法。
os.system
os.system()
是C语言 system()
函数的封装,返回命令的退出状态码,命令执行结果输出到标准输出(stdout/窗口)。
os.system("command")
import os
command = "ifconfig"
exit_code = os.system(command)
# 执行 sh 脚本
os.system('sh /root/script/test,sh')
import os
a=os.system("ping 192.168.1.101") #使用a接收返回值
print(a)
# 理论上command是一个字符串,但实际看command还是得变为字节数组
# 当命令中存在中文时可能会报编码错误,此时可以自己给命令编一下码
# exit_code = os.system(command.encode("gbk"))
read()
或 readlines()
方法可以读取输出内容。
os.popen(command[, mode[, bufsize]])
os.system(cmd)
或 os.popen(cmd)
,前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容。import os
command = "ifconfig"
command_output = os.popen(command).readlines()
print(command_output)
a=os.popen("ipconfig")
print(a.read())
>>>
以太网适配器 以太网:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe81::b0ed:2b1b:7385:97d1%8
IPv4 地址 . . . . . . . . . . . . : 192.168.1.100
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.1.1
使用Popen可以创建进程,并与进程进行复杂的交互。
child = subprocess.Popen(["cmd","arg1"...])
参数 | 作用 |
---|---|
args | 一般是一个字符串,是要执行的shell命令内容 |
bufsize | 设置缓冲,负数表示系统默认缓冲,0表示无缓冲,正数表示自定义缓冲行数 |
stdin | 程序的标准输入句柄,NONE表示不进行重定向,继承父进程,PIPE表示创建管道 |
stdout | 程序的标准输出句柄,参数意义同上 |
stderr | 程序的标准错误句柄,参数意义同上,特殊,可以设置成STDOUT,表示与标准输出一致 |
shell | 为True时,表示将通过shell来执行 |
cwd | 用来设置当前子进程的目录 |
env | 用于指定子进程的环境变量。如果env=None,则默认从父进程继承环境变量 |
universal_newlines | 不同系统的的换行符不同,当该参数设定为true时,则表示使用\n作为换行符。 |
from subprocess import PIPE, Popen
# 返回的是 Popen 实例对象
proc = Popen(
'ipconfig', # cmd特定的查询空间的命令
stdin=None, # 标准输入 键盘
stdout=PIPE, # -1 标准输出(演示器、终端) 保存到管道中以便进行操作
stderr=PIPE, # 标准错误,保存到管道
shell=True)
# print(proc.communicate()) # 标准输出的字符串+标准错误的字符串
outinfo, errinfo = proc.communicate()
print(outinfo.decode('gbk')) # 外部程序(windows系统)决定编码格式
print(errinfo.decode('gbk'))
>>>
以太网适配器 以太网:
连接特定的 DNS 后缀 . . . . . . . :
本地链接 IPv6 地址. . . . . . . . : fe81::b0ed:2b1b:7385:97d1%8
IPv4 地址 . . . . . . . . . . . . : 192.168.1.100
子网掩码 . . . . . . . . . . . . : 255.255.255.0
默认网关. . . . . . . . . . . . . : 192.168.1.1
Process finished with exit code 0
>>> a = subprocess.Popen(['tail','-f', '/apps/apache-tomcat-8.5.29/logs/catalina.out'])
>>> a = subprocess.Popen('tail -f /apps/apache-tomcat-8.5.29/logs/catalina.out',shell=True)
subprocess.call("command")
# linux获取磁盘空间
import subprocess
subprocess.call(['df', '-h']) # 数组作为参数运行命令
输出:
Filesystem Size Used Avail Use% Mounted on
devtmpfs 909M 0 909M 0% /dev
tmpfs 920M 32K 920M 1% /dev/shm
tmpfs 920M 472K 919M 1% /run
tmpfs 920M 0 920M 0% /sys/fs/cgroup
/dev/vda1 50G 6.2G 41G 14% /
tmpfs 184M 0 184M 0% /run/user/0
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)
import subprocess
completed = subprocess.run(['ls', '-1'])
print('returncode:', completed.returncode)
import subprocess
ret, val = subprocess.getstatusoutput("ping www.baidu.com")
print(ret)
print(val)
0
正在 Ping www.a.shifen.com [14.215.177.39] 具有 32 字节的数据:
来自 14.215.177.39 的回复: 字节=32 时间=29ms TTL=53
来自 14.215.177.39 的回复: 字节=32 时间=29ms TTL=53
来自 14.215.177.39 的回复: 字节=32 时间=29ms TTL=53
来自 14.215.177.39 的回复: 字节=32 时间=30ms TTL=53
14.215.177.39 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 29ms,最长 = 30ms,平均 = 29ms
import subprocess
command = "ifconfig"
# 命令如果带参数则不能直接使用字符串的形式,不然后报FileNotFoundError: [Errno 2] No such file or directory: 'ifconfig -a'等错误
# 此时有两种处理办法,一种是写成以空格为分割的列表形式。可借助shlex.split(command_line)实现自动分割
# command = ["ifconfig", "-a"]
# 别一种是将shell参数置为True
# completed_process_obj = subprocess.run(command, shell=True)
# 当配置了stdout参数,completed_process_obj的stdout属性就会保存命令的输出
completed_process_obj = subprocess.run(command, stdout=subprocess.PIPE)
print(completed_process_obj.stdout.decode())
# subprocess.Popen()基础参数和run()差不多,比run()对命令进程有更强的控制能力。其也能用来获取命令输出
# popen_obj = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
# print(popen_obj.stdout.readlines())
# 其他如subprocess.call()、subprocess.check_call()、subprocess.check_output()都是旧方法了,Python3.5+都建议用run()
subprocess.check_call(args, *, stdin = None, stdout = None, stderr = None, shell = False)
a = subprocess.check_call('df -h',shell=True)
>>>
文件系统 容量 已用 可用 已用% 挂载点
/dev/vda3 80G 3.6G 77G 5% /
devtmpfs 7.8G 0 7.8G 0% /dev
tmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs 7.8G 8.6M 7.8G 1% /run
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
/dev/vda6 404G 2.2G 402G 1% /data1
/dev/vda2 497M 128M 370M 26% /boot
tmpfs 1.2G 0 1.2G 0% /run/user/0
print(a)
>>>
0