【发布时间】:2021-04-20 21:42:39
【问题描述】:
我有一个 python 脚本,它调用一个 bash 脚本来连接一个 vpn 帐户。如果我从控制台运行 python 脚本,我可以执行 2FA 并无缝连接到我的 VPN 帐户。但是,如果我将此 python 脚本作为后台进程运行(使用nohup 等),那么每当我尝试连接 VPN 并且 python 程序没有响应时,python 进程就会暂停(+ suspended (tty output))(看起来它被卡住了)处于需要输入的状态)。
vpn_manager.py:
connection_command = 'sh {}'.format(os.path.join(base_path, 'scripts', 'vpn.sh'))
response = subprocess.run(connection_command, shell=True, stdout=subprocess.PIPE)
stdout = response.stdout.decode('utf-8')
if 'state: Connected' in stdout:
update_icon(environment)
Shell 脚本vpn.sh:
printf "1\nUSERNAME\nPASSWORD\n2\n" | /opt/cisco/anyconnect/bin/vpn -s connect VPN_HOST
通常,此 VPN 命令要求输入用户名和密码,然后等待我通过手机上的 2FA 应用程序进行验证。
我怎样才能让这个 python 代码作为后台进程运行,并且不会被 VPN 提示打断?
【问题讨论】:
-
请注意,这段代码不应该使用
shell=True;您不需要外壳来运行可执行脚本。 (如果您确实需要一个shell,这意味着vpn.sh不可执行或没有有效的shebang;这些都是错误,应该在此修复)。 -
即使您不修复这些问题,
subprocess.Popen(['sh', os.path.join(base_path, 'scripts', 'vpn.sh')]也可以工作(但您确实应该:修复问题将使脚本选择自己的解释器,因此您可以将其重写为 bash 脚本而不是 sh 脚本、ksh 脚本或其他 Python 脚本等;并且调用代码不需要知道或关心更改)。 -
...理想的方法是
subprocess.Popen([os.path.join(base_path, 'scripts', 'vpn.sh')])-- 没有sh,没有shell=True,所以你让vpn.sh告诉操作系统它希望如何通过其调用#!/bin/sh行(或该行包含的任何其他内容)。 -
请注意,如果您不希望您的子进程与 TTY 交互,您可能应该设置
stdin=PIPE或stdin=DEVNULL除了任何重定向 stdout (@ 987654337@,如果你想从 Python 读取标准输出)。 -
@CharlesDuffy 使用
pexpect而不是popen解决了我所有的问题。对于这种类型的要求,pexpect是一种更好的方法。谢谢。
标签: python bash subprocess background-process tty