当前位置:首页 > 问答 > 正文

自动化运维|脚本集成 python执行shell命令,python执行shell命令行的方法与实例解析

Python执行Shell命令:自动化运维的脚本利器

场景引入
凌晨3点,服务器突然报警——磁盘空间不足,运维小哥强撑睡意,手忙脚乱登录服务器查日志、删缓存… 如果这时候有个脚本能自动清理日志、发送报警邮件,该多好?没错,这就是Python+Shell的黄金组合能轻松搞定的场景!

今天我们就来聊聊,如何用Python优雅地执行Shell命令,让你的运维效率直接起飞。


为什么用Python执行Shell命令?

在自动化运维中,Shell脚本擅长处理系统级操作(如文件管理、进程监控),而Python更擅长逻辑控制和数据处理,二者结合能发挥最大威力:

  • 无缝衔接现有脚本:复用遗留的Shell脚本资产
  • 超强扩展性:用Python的异常处理、多线程等特性增强Shell
  • 跨平台更友好:相比纯Shell脚本,Python在Windows/Linux下表现更一致

5种Python执行Shell命令的方法

方法1:os.system() - 最简单粗暴

import os  
# 执行后返回退出状态码(0表示成功)
result = os.system("ls -l /tmp")  
print("返回值:", result)  # 输出:0(成功)或非零(失败)

特点

  • 直接打印命令输出到控制台
  • 适合简单命令,但无法捕获输出内容

方法2:os.popen() - 获取命令输出

import os  
# 读取命令输出
output = os.popen("df -h").read()  
print("磁盘空间:\n", output)

适用场景
需要获取命令执行结果时(比如解析磁盘使用率)

自动化运维|脚本集成 python执行shell命令,python执行shell命令行的方法与实例解析

方法3:subprocess.run() - 官方推荐(Python 3.5+)

import subprocess  
# 基本用法
result = subprocess.run(["ls", "-l"], capture_output=True, text=True)  
print("标准输出:\n", result.stdout)  
# 带超时控制(单位:秒)
try:
    subprocess.run(["ping", "example.com"], timeout=5)
except subprocess.TimeoutExpired:
    print("命令执行超时!")

优势

  • 可捕获标准输出/错误流
  • 支持超时控制
  • 参数传递更安全(自动处理空格等特殊字符)

方法4:subprocess.Popen() - 高级控制

from subprocess import Popen, PIPE  
# 实时获取输出(适合长时间任务)
process = Popen(["tail", "-f", "/var/log/syslog"], stdout=PIPE)  
while True:
    line = process.stdout.readline()  
    if not line: break
    print("实时日志:", line.decode().strip())

典型应用

  • 实时日志监控
  • 进程交互(通过stdin发送输入)

方法5:shlex分割复杂命令

当命令包含管道、重定向等复杂符号时:

import subprocess  
import shlex  
cmd = "grep 'ERROR' /var/log/app.log | head -n 5"  
args = shlex.split(cmd)  # 自动拆分成列表  
# 使用shell=True执行复杂命令
result = subprocess.run(cmd, shell=True, check=True)

注意
shell=True可能带来安全风险(如命令注入),慎用不可信输入

自动化运维|脚本集成 python执行shell命令,python执行shell命令行的方法与实例解析


实战案例:自动化日志清理

import subprocess  
from datetime import datetime  
def clean_logs(log_path, days=7):  
    # 构建find命令  
    cmd = f"find {log_path} -name '*.log' -mtime +{days} -delete"  
    try:  
        print(f"[{datetime.now()}] 开始清理{log_path}...")  
        subprocess.run(cmd, shell=True, check=True)  
        # 发送通知(假设有个send_mail.py)  
        subprocess.run(["python", "send_mail.py", "日志清理完成"])  
    except subprocess.CalledProcessError as e:  
        print(f"清理失败!错误码: {e.returncode}")  
clean_logs("/var/log/nginx")  

避坑指南

  1. 路径问题

    # 错误示范(~无法自动扩展)
    subprocess.run(["ls", "~/Downloads"])  
    # 正确做法  
    import os.path  
    downloads = os.path.expanduser("~/Downloads")  
    subprocess.run(["ls", downloads])
  2. 命令注入防护

    user_input = "malicious; rm -rf /"  # 恶意输入  
    # 危险!直接拼接字符串  
    subprocess.run(f"echo {user_input}", shell=True)  
    # 安全做法(使用参数列表)  
    subprocess.run(["echo", user_input])  
  3. 编码处理

    # 处理非UTF-8输出(如中文Windows)
    result = subprocess.run(["dir"], capture_output=True)  
    print(result.stdout.decode("gbk"))  # Windows中文默认编码为GBK

性能优化技巧

  • 批量执行:用subprocess.Popen()并行启动多个命令
  • 减少Shell启动:避免频繁使用shell=True
  • 复用进程:对需要交互的命令(如数据库备份),保持Popen对象长期存在


从简单的os.system()到强大的subprocess模块,Python为Shell命令执行提供了不同层次的解决方案,下次再遇到繁琐的运维操作时,不妨试试用Python写个自动化脚本——毕竟,优秀的工程师从不该被重复操作束缚双手。

自动化运维|脚本集成 python执行shell命令,python执行shell命令行的方法与实例解析

(本文方法验证环境:Python 3.8+/Linux,最后更新:2025年8月)

发表评论