如何在Python中运行需动态输入的Unix命令并实现无人干预
问题与解决方案
背景信息
需要执行的Unix命令:
/opt/oracle/admin/bin/dboc configure dbfs --home /oracle/client/18.3.0/
手动执行时需依次输入以下内容:
- Validating DBFS Client 输入值:
asdjascads- Enter Connectstring for dbaas 输入值:
akxhsakc- Enter password 输入值:
xbvcascha
用户编写的Python脚本无法等待输入,仅显示提示后直接退出,原代码如下:
#!/usr/bin/env python3 import subprocess def run_dboc_command(args): command = ['/opt/oracle/admin/bin/dboc'] + args result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) return result.stdout.decode(), result.stderr.decode() args=['configure', 'dbfs', '--home', ' /oracle/client/18.3.0/'] stdout,stderr = run_dboc_command(args) print ("Output:") print (stdout) print ("Error:") print (stderr)
问题1:解决脚本无法等待输入的问题
原代码的核心问题:
subprocess.run仅捕获了stdout和stderr,但未将子进程的stdin与终端关联,导致命令需要输入时无法获取输入流,直接退出。args中的路径参数多了一个前置空格,可能导致命令解析错误。
修改后的代码(支持手动交互输入):
#!/usr/bin/env python3 import subprocess def run_dboc_command(args): command = ['/opt/oracle/admin/bin/dboc'] + args # 让子进程继承父进程的标准输入、输出、错误流,实现终端交互 result = subprocess.run(command, stdin=None, stdout=None, stderr=None) return result.returncode # 修正路径参数的前置空格 args=['configure', 'dbfs', '--home', '/oracle/client/18.3.0/'] return_code = run_dboc_command(args) print(f"命令执行返回码: {return_code}")
问题2:是否可以自动传入所有输入,无需手动干预?
可以。通过subprocess.run的communicate方法,将所有输入按顺序拼接成带换行的字符串,一次性传入子进程的stdin即可。
自动执行的代码示例:
#!/usr/bin/env python3 import subprocess def run_dboc_command(args, auto_inputs): command = ['/opt/oracle/admin/bin/dboc'] + args # 拼接输入内容,每个输入后加换行符匹配命令的输入要求 input_content = '\n'.join(auto_inputs) + '\n' result = subprocess.run( command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True # 使用文本模式,避免字节流编码处理 ) stdout, stderr = result.communicate(input=input_content) return stdout, stderr, result.returncode # 修正后的命令参数 args=['configure', 'dbfs', '--home', '/oracle/client/18.3.0/'] # 按顺序传入三个输入值 auto_inputs = ['asdjascads', 'akxhsakc', 'xbvcascha'] stdout, stderr, return_code = run_dboc_command(args, auto_inputs) print("输出内容:") print(stdout) print("\n错误信息:") print(stderr) print(f"\n返回码: {return_code}")
注意事项
- 如果命令使用了终端交互库(如
getpass)读取密码,上述方法可能失效,此时需使用pexpect库模拟终端交互。 - 密码硬编码在脚本中存在安全风险,建议通过环境变量、加密配置文件或密钥管理工具读取。
内容的提问来源于stack exchange,提问作者LearningCpp
相关产品推荐
相关产品推荐

