Python中利用subprocess远程登陆执行命令

本文介绍了一种使用Python的subprocess模块结合sshpass程序实现SSH远程连接的方法,并演示了如何通过脚本自动输入密码进行认证的过程。
AI助手已提取文章相关产品:
import subprocess

import os



(rfd, wfd) = os.pipe()

arg = "-d%d" % rfd

try:

    p = subprocess.Popen(["sshpass",arg,"ssh","-l","haohzhang","phxaishdc9dn1447.stratus.phx.ebay.com","ls","/tmp/"], stdin=subprocess.PIPE,stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    os.close(rfd)

    os.write(wfd,"PASSWORD\n")

    os.close(wfd)

    stdout, stderr = p.communicate()

    print stdout, stderr

except OSError:

    print("to use the 'ssh' connection type with passwords, you must install the sshpass program")

 

您可能感兴趣的与本文相关内容

<think>我们正在讨论Python 3中使用subprocess.Popen执行命令的方法和示例。根据引用[1]和引用[2]的信息,我们可以知道subprocess.Popen用于执行外部命令,并且可以与其交互。同时,引用[2]提供了一个示例,展示了如何执行命令并读取输出(包括处理编码问题)。 引用[3]则提到了subprocess.run()和subprocess.Popen()的区别,但用户的问题集中在Popen的使用上,因此我们将重点放在Popen。 下面我将分步骤说明如何使用subprocess.Popen执行命令: 1. 导入subprocess模块 2. 使用Popen构造函数创建子进程,传入参数包括命令(字符串或列表)、shell参数、标准输出和标准错误的重定向设置等。 3. 与子进程交互,例如读取输出、发送输入、等待完成等。 注意:在Python 3中,输出通常为字节串(bytes),因此需要解码(decode)为字符串。同时,为了避免乱码,需要确保使用正确的编码(如'utf-8')。 示例1:执行一个简单的命令(例如,执行一个Python脚本)并捕获其输出。 ```python import subprocess # 使用Popen执行命令,将stdout重定向到管道,以便我们可以读取 # 注意:这里使用列表形式传递命令,以避免shell注入攻击,同时设置stdout和stderr # 如果命令简单且安全,也可以使用字符串形式并设置shell=True,但要注意安全性 process = subprocess.Popen( ['python', 'test.py'], # 命令和参数列表 stdout=subprocess.PIPE, # 将标准输出重定向到管道 stderr=subprocess.PIPE # 将标准错误重定向到管道 ) # 等待进程完成并获取输出 stdout, stderr = process.communicate() # 将字节输出解码为字符串(假设输出是utf-8编码) if stdout: print("标准输出:", stdout.decode('utf-8')) if stderr: print("标准错误:", stderr.decode('utf-8')) ``` 示例2:实时读取输出(逐行读取),如引用[2]所示: ```python import subprocess # 构造Popen对象,注意这里使用字符串命令并设置shell=True,也可以使用列表而不需要shell=True # 但注意,使用shell=True可能有安全风险,如果命令字符串来自用户输入,则要谨慎 p = subprocess.Popen( 'python test2.py', # 命令字符串,因为设置了shell=True shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) # 逐行读取输出(标准输出) # 注意:iter(p.stdout.readline, b'') 会一直读取直到遇到空字节串 for line in iter(p.stdout.readline, b''): # 解码并输出,去掉行尾的换行符(print本身会换行,所以可以用end='') print(line.decode('utf-8'), end='') # 关闭管道 p.stdout.close() # 等待进程结束 p.wait() # 如果有错误,也可以类似地读取标准错误(但上面的循环只读取了标准输出,标准错误可以单独处理) # 注意:同时读取stdout和stderr可能会导致死锁,如果错误流很大,最好使用上面的communicate()或者分别读取 ``` 重要提示: - 使用`communicate()`可以一次性获取所有输出,适用于输出量不大的情况。对于大量输出,建议使用逐行读取。 - 设置`shell=True`可以让命令通过系统的shell执行(如/bin/sh或cmd.exe),这样可以使用shell的特性(如通配符、管道等),但要注意安全风险(如果命令字符串来自不可信的输入,可能导致命令注入)。 - 推荐使用列表形式传递命令,这样不需要shell=True,并且可以避免shell注入攻击。 另外,关于编码问题:如果遇到乱码,可能是因为命令输出的编码与Python解码使用的编码不一致。在Windows上,命令输出通常是GBK编码,而Linux/macOS通常是UTF-8。因此,可能需要根据系统调整解码方式,例如: ```python # 在Windows上可能需要使用'gbk' print(line.decode('gbk'), end='') ``` 或者使用当前系统的默认编码: ```python import sys encoding = sys.stdout.encoding # 获取当前控制台的编码,但注意这不一定和命令输出的编码一致 ``` 所以,最可靠的方法是知道被调用程序的输出编码。 相关问题: 1. 如何避免使用subprocess.Popen时出现死锁? 2. subprocess.Popensubprocess.run有什么区别? 3. 在Windows和Linux下使用subprocess.Popen处理编码问题有什么不同? 4. 如何通过subprocess.Popen向子进程输入数据? </think>### Python 3中`subprocess.Popen`使用指南 `subprocess.Popen`是Python执行外部命令的核心工具,允许细粒度控制子进程。以下是关键使用方法和示例: #### 一、基础用法 ```python import subprocess # 执行简单命令 process = subprocess.Popen( ['ls', '-l'], # 命令参数列表 stdout=subprocess.PIPE, # 捕获标准输出 stderr=subprocess.PIPE, text=True # Python 3.7+ 自动解码为字符串 ) stdout, stderr = process.communicate() # 等待进程结束 print(stdout) ``` #### 二、实时输出处理 ```python process = subprocess.Popen( ['ping', 'google.com'], stdout=subprocess.PIPE, bufsize=1, # 行缓冲 universal_newlines=True # 文本模式 ) # 逐行读取输出 while True: line = process.stdout.readline() if not line: break print(line.strip()) process.wait() # 等待进程退出 ``` #### 三、解决乱码问题 ```python # 显式指定编码(Windows通常为'gbk',Linux为'utf-8') process = subprocess.Popen( 'dir', # Windows命令 shell=True, stdout=subprocess.PIPE, encoding='gbk' # 关键解决中文乱码 ) output = process.communicate()[0] print(output) ``` #### 四、输入交互示例 ```python process = subprocess.Popen( ['python'], # 启动Python交互环境 stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True ) # 发送命令并获取输出 commands = "print('Hello!')\nexit()\n" stdout, _ = process.communicate(commands) print(stdout) # 输出: Hello! ``` #### 五、高级控制 ```python # 超时控制 try: process = subprocess.Popen(['sleep', '10']) process.wait(timeout=5) # 5秒后超时 except subprocess.TimeoutExpired: process.terminate() # 环境变量设置 env = {'PATH': '/usr/local/bin'} subprocess.Popen(['echo', '$PATH'], env=env, shell=True) ``` #### 六、安全注意事项 1. **避免`shell=True`**:除非需要shell特性(如管道`|`),否则应使用列表传参防止注入攻击 ```python # 不安全 subprocess.Popen(f"rm {user_input}", shell=True) # 安全替代 subprocess.Popen(['rm', user_input]) ``` 2. **资源清理**:始终使用`with`块或显式调用`wait()/terminate()` --- ### 关键区别(与`subprocess.run`对比) | 特性 | `Popen` | `run()` | |---------------------|------------------------------------|-----------------------------| | 实时交互 | ✅ 支持 | ❌ 一次性返回所有输出 | | 超时控制 | 需手动实现 | ✅ 内置`timeout`参数 | | 后台执行 | ✅ `process.detach()` | ❌ 总是阻塞 | | 输入/输出流控制 | ✅ 精细控制 | ️ 有限控制 | | 错误处理 | 需手动检查返回码 | ✅ 自动抛出`CalledProcessError` | > 推荐:简单任务用`run()`,复杂交互用`Popen`[^3] ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值