subprocess.Popen().communicate()无法向stdin发送数据问题求助
问题
运行以下代码时,Easyrsa脚本未接收脚本传入的数据,反而弹出自身的输入对话框,请问哪里操作出错了?
def create_serverkey(password, ca_password, server_filename='vpn_server'): cmd = [f'{EASYRSA}/./easyrsa', 'build-server-full', server_filename] input_msg = f'{password}\n{password}\n{ca_password}\n' with subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf8', text=True) as proc_serverkey: stdout, stderr = proc_serverkey.communicate(input=input_msg) proc_serverkey.wait()

解决方法
EasyRSA会检测标准输入是否为终端(TTY),如果是则弹出交互式对话框,反之才会读取标准输入内容。你的代码未生效,主要是两个原因,对应解决方式如下:
直接通过参数指定密码,禁用交互模式
EasyRSA支持通过--passout和--passin参数直接传递密码,不需要依赖标准输入,彻底避免触发交互式弹窗:def create_serverkey(password, ca_password, server_filename='vpn_server'): cmd = [ f'{EASYRSA}/./easyrsa', '--passout', f'pass:{password}', # 指定服务器密钥的密码 '--passin', f'pass:{ca_password}', # 指定CA密钥的密码 'build-server-full', server_filename ] with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf8', text=True) as proc_serverkey: stdout, stderr = proc_serverkey.communicate()这种方式比传递
stdin更可靠,因为不需要严格匹配输入提示的顺序。开启批量模式,强制禁用交互
如果必须通过标准输入传递密码,需要设置环境变量EASYRSA_BATCH=1,让EasyRSA进入批量模式,跳过交互式检测:import os def create_serverkey(password, ca_password, server_filename='vpn_server'): cmd = [f'{EASYRSA}/./easyrsa', 'build-server-full', server_filename] input_msg = f'{password}\n{password}\n{ca_password}\n' # 注入批量模式环境变量 env = os.environ.copy() env['EASYRSA_BATCH'] = '1' with subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf8', text=True, env=env) as proc_serverkey: stdout, stderr = proc_serverkey.communicate(input=input_msg)注意:这种方式需要严格匹配EasyRSA的输入提示顺序,否则会出现密码验证失败的问题。
内容的提问来源于stack exchange,提问作者Арман Айрапетов
相关产品推荐
相关产品推荐

