今日目标:Shell 虽然方便,但逻辑一复杂就成了”遗屎山”。今天学习 Python 的
subprocess 模块,学会如何在 Python 代码中优雅地执行系统命令,把 Shell 脚本重构为 Python 脚本。今天不只是写代码,而是要彻底理解 “为什么 subprocess 比 os.system 更安全”、“如何正确捕获命令输出” 以及 “如何避免 Shell 注入攻击”。学习内容 (30 mins)
在开始写代码前,先搞懂这些核心概念,否则后面的代码你会看得云里雾里。为什么放弃 os.system? (10 mins)
为什么放弃 os.system? (10 mins)
什么是 os.system?
os.system() 是 Python 早期用于执行系统命令的方法,它会直接调用 Shell 执行命令。为什么不再推荐使用?- 无法获取输出:
os.system()只能返回状态码(0 表示成功,非 0 表示失败)- 无法获取命令的标准输出(stdout)和错误输出(stderr)
- 输出直接打印到终端,无法在代码中处理
- 安全隐患:
- 如果命令包含用户输入,容易被 Shell 注入攻击
- 示例:
os.system(f"rm {user_input}")如果user_input是"file; rm -rf /"就会执行危险操作
- 跨平台问题:
- 不同操作系统的命令可能不同
- Windows 和 Linux 的命令格式差异很大
subprocess 模块,更安全、更灵活。subprocess 模块 (20 mins)
subprocess 模块 (20 mins)
什么是 subprocess?
subprocess 是 Python 标准库中用于创建子进程、执行系统命令的模块,是执行外部命令的官方推荐方式。为什么 subprocess 更好?- 可以捕获输出:可以获取命令的标准输出和错误输出
- 更安全:使用列表传参,避免 Shell 注入
- 更灵活:可以控制输入、输出、错误处理
- 跨平台:在不同操作系统上行为一致
subprocess.run()(推荐):- 执行命令并等待完成
capture_output=True:捕获 stdout 和 stderrtext=True:自动将字节流解码为字符串check=True:命令失败时自动抛出异常timeout=秒数:设置超时时间
subprocess.Popen()(高级):- 用于需要实时处理输出的场景
- 可以逐行读取输出,不等待命令完成
- 适合长时间运行的命令
- ✅ 推荐:使用列表传参
subprocess.run(["ls", "-l"]) - ❌ 禁止:使用字符串传参
subprocess.run("ls -l", shell=True)(除非必要) - 原因:列表形式避免了 Shell 解析,防止注入攻击
代码任务 (90 mins)
任务 A:基础命令执行
编写 代码解释:验证步骤:
11_run_cmd.py,演示 subprocess 的基本用法。- 列表传参:
["ls", "-l"]比"ls -l"更安全 capture_output=True:捕获输出,可以在代码中处理text=True:自动解码字节流为字符串check=True:失败时自动抛出异常timeout:防止命令无限执行
- 脚本能正常运行,无语法错误
- 观察命令输出是否正确
- 测试错误处理(如访问不存在的目录)
拓展任务 (30 mins)
挑战 1:实时输出处理
任务:使用
subprocess.Popen 实现实时打印 ping 命令的输出。提示:挑战 2:命令管道
任务:在 Python 中实现 Shell 管道功能,如
ps aux | grep python。提示:使用两个 Popen 对象,将第一个的输出连接到第二个的输入。今日产出物
11_run_cmd.py- subprocess 基础示例11_disk_monitor.py- 磁盘监控脚本(Python 版本)
参考代码
查看参考代码
在 GitHub 查看完整的示例代码
在线运行
使用在线编辑器测试代码
实际应用场景
subprocess 在运维中的应用
- 系统监控:执行系统命令获取资源使用情况(CPU、内存、磁盘)
- 服务管理:启动、停止、重启服务
- 文件操作:批量处理文件、备份数据
- 日志收集:执行命令收集日志信息
- 自动化部署:执行部署脚本、运行测试
最佳实践
- 使用列表传参:避免 Shell 注入攻击
- 设置超时:防止命令无限执行
- 捕获异常:优雅处理命令失败
- 解析输出:使用正则表达式或字符串处理解析命令输出
- 函数封装:将命令执行封装成函数,便于复用和测试
上一天: 文件处理
Day 10 | 文件处理与正则实战
下一天: 数据库操作
Day 12 | Python 操作 MySQL