python控制linux命令反馈
windows下访问python控制linux命令反馈
- **1. `subprocess.call()`**
- **2. `subprocess.check_call()`**
- **3. `subprocess.check_output()`**
- **4. `subprocess.Popen`**
- **方法对比表**
- **进阶用法:实时读取输出**
- **安全建议**
- **选择指南**
from flask import Flask,request
import subprocessapp = Flask(__name__)@app.route('/')
def hello_world():return 'Hello, World!'@app.route('/run', methods=['POST'])
def run_command():data = request.get_json()command = data.get('command', '')process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)output, error = process.communicate()return output.decode('utf-8')if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)
subprocess
模块是 Python 中用于创建和管理子进程的标准库,提供了多种执行外部命令的方法。以下是这些方法的详细对比和使用场景:
1. subprocess.call()
- 功能:执行命令并等待其完成,返回命令的退出状态码(整数)。
- 参数:与
check_call()
基本相同。 - 返回值:命令的退出状态码(0 表示成功,非零表示失败)。
- 异常:不抛出异常,无论命令是否执行成功。
示例:
returncode = subprocess.call(["ls", "-l"])
print(f"命令返回码: {returncode}")
2. subprocess.check_call()
- 功能:执行命令并等待其完成,若命令返回非零状态码,则抛出异常。
- 参数:与
call()
相同。 - 返回值:成功时返回 0。
- 异常:命令执行失败时抛出
subprocess.CalledProcessError
。
示例:
try:subprocess.check_call(["ls", "nonexistent_file"])
except subprocess.CalledProcessError as e:print(f"命令失败,返回码: {e.returncode}")
3. subprocess.check_output()
- 功能:执行命令并捕获其标准输出,若命令失败则抛出异常。
- 参数:支持
stdin
、stderr
、shell
等参数(见上一条回答)。 - 返回值:命令的标准输出(字节或字符串,取决于
encoding
参数)。 - 异常:失败时抛出
subprocess.CalledProcessError
,包含returncode
和output
。
示例:
try:output = subprocess.check_output(["ls", "-l"], encoding="utf-8")print(output)
except subprocess.CalledProcessError as e:print(f"错误: {e.output}")
4. subprocess.Popen
- 功能:创建一个新的子进程,提供更底层的进程控制(非阻塞执行)。
- 参数:与其他方法类似,但更灵活,支持更多选项(如
bufsize
、env
)。 - 返回值:
Popen
对象,用于与子进程交互。 - 特点:
- 非阻塞:调用后立即返回,不会等待命令执行完成。
- 可控制输入/输出流,支持异步通信。
示例:
# 执行命令并获取标准输出流
process = subprocess.Popen(["ls", "-l"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)# 异步读取输出
stdout, stderr = process.communicate() # 等待命令完成并获取输出print(f"标准输出:\n{stdout.decode('utf-8')}")
print(f"错误输出:\n{stderr.decode('utf-8')}")
print(f"返回码: {process.returncode}")
方法对比表
方法 | 是否阻塞 | 异常处理 | 返回值 | 适用场景 |
---|---|---|---|---|
call() | 是 | 不抛出异常 | 退出状态码 | 简单执行命令,不关心输出 |
check_call() | 是 | 失败时抛出异常 | 0(成功) | 需确保命令成功执行 |
check_output() | 是 | 失败时抛出异常 | 标准输出内容 | 获取命令输出并验证执行结果 |
Popen | 否 | 需手动处理 | Popen 对象 | 复杂场景(如异步执行、实时交互) |
进阶用法:实时读取输出
Popen
可用于实时读取命令输出,适合长时间运行的进程:
process = subprocess.Popen(["ping", "google.com"], stdout=subprocess.PIPE, text=True)for line in iter(process.stdout.readline, ''):print(f"实时输出: {line.strip()}")process.wait() # 等待进程结束
安全建议
- 避免
shell=True
:尤其是处理用户输入时,防止命令注入攻击。 - 优先使用列表参数:
["ls", "-l"]
比"ls -l"
更安全。 - 设置超时:对可能长时间运行的命令使用
timeout
参数。
选择指南
- 简单执行:用
call()
或check_call()
。 - 获取输出:用
check_output()
。 - 复杂控制(异步、实时交互):用
Popen
。
在 Python 3.5+ 中,subprocess.run()
可替代大部分场景,它是一个更通用的接口,返回 CompletedProcess
对象,包含所有执行结果信息。
是的,在 Python 3.5 之前,subprocess.run()
方法尚未引入,而是使用 subprocess.call()
、subprocess.check_call()
、subprocess.check_output()
等方法。下面我将提供一个兼容老版本 Python 的实现:
在linux中会出现cd没命了不适用的情况
因为subprocess.Popen是用子程序调用的情况来改变的
当执行完退出子程序时会改变更改之前的目录
所以没有用而且会报错
可以用os.chdir改变工作目录 亲测可以用
import subprocess
process = subprocess.Popen(['ls'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = process.communicate()
print(output.decode('utf-8'))new_dir = "/opt"
os.chdir(new_dir)