【Python】执行系统命令

引言

Python 编程中可能会需要调用系统命令。本文以一段测试网络连通性的代码来演示如何执行系统命令,并获取输出结果。

教程

os.system😐

import os


def ping(ip):
    os.system(f'ping {ip}')


if __name__=='__main__':
    ping(input('please enter the ip to ping: '))

执行上述代码,输入 baidu.com 并回车,控制台就会打印 ping 结果。

在这里插入图片描述


os.system 调用标准 C 函数来实现命令在子进程中执行。它会将命令执行的任何输出重定向到解释器(我们这里是 Python 解释器)的标准输出流。其返回值是进程的退出码,反映进程的退出状态,在 Windows 和 Unix 系统上会有所不同。实测是 Windows 系统上的退出码是 0,表示命令成功执行并关闭进程。

>>> import os
>>> os.system('pwd') 
/c/Users/87897/Desktop
0

os.popen😊

os.system 函数返回值是进程退出码,无法获取命令执行输出结果。而 os.popen 通过管道的方式连接到执行进程,可灵活地获得命令执行的输出。其返回值是一个连接到管道的打开文件对象,可以根据模式是 r (默认值) 还是 w 来读取或写入。


根据 os.popen 的特性,我们可以将上述代码简单变动一下:不在控制台打印 ping 结果,而是将其保存在一个名为 ping.log 的日志文件中,方便后续的 debug 或审查。

import os


def ping(ip):
    with open('ping.log', 'a', encoding='utf-8') as fw:
        with os.popen(f'ping {ip}', mode='r') as fr:
            fw.write(fr.read())


if __name__ == '__main__':
    ping(input('please enter the ip to ping: '))

subprocess😁

import subprocess


def ping(ip):
    p = subprocess.run(
        f'ping {ip}',
        capture_output=True,
        text=True
    )
    return p.stdout


if __name__ == '__main__':
    print(ping(input('please enter the ip to ping: ')))

官方开发 subprocess 模块就是为了替换 os.systemos.popen,因此更推荐使用 subprocess。通过 subprocess.run 函数开一个子进程来执行系统命令。如果指定 capture_output=True,将返回一个 CompletedProcess 的类实例,该类的 stdout 属性可查看命令的输出结果。

提示

如果想让一行执行多条关联命令,比如:先 cd 到一个目录,然后在该目录下新建文件夹,可以用 & 符号将多条命令连接起来,实例代码如下。

import os


def func():
    os.system('cd test & mkdir main')


if __name__=='__main__':
    func()

如果多条命令没有依赖关系的话,直接多调用几次函数,然后从上到下顺序执行。


如果执行的命令的时候需要进行人机交互(例如 SSH 远程连接服务器时需要输入密码),可以考虑使用 pexpect 库,这是一个 Python 第三方库,用来启动一个子进程,并对其进行自动化控制。其常规用法如下:

  1. 使用 spawn 方法来执行程序
  2. 使用 expect方法等待程序打印输入提示关键字
  3. 使用 send/sendline 方法发送字符串到程序

但该库目前仅支持 Unix 系统,对 Windows 系统的支持非常有限,请根据需求选择。

注意

上述所有执行系统命令的方式都有被注入恶意脚本的风险。因此,在实际应用场景下,要设置过滤策略,进行代码漏洞排查。


例如,下方的代码就在 ping 的同时添加了一条删除整个 test 文件夹的命令:

import os


def ping(ip):
    os.system(f'ping {ip} & rm -rf test/')


if __name__ == '__main__':
    ping(input('please enter the ip to ping: '))

如果把 rm -rf test/ 改为 rm -rf /,那就是删除整个系统文件了,所以一定要慎用!

参考

os.system 官方文档
os.popen 官方文档
subprocess 官方文档
Python学习之OS库的system函数
Python模块Pexpect详解
python pexpect模块的使用

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Xavier Jiezou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值