我正在尝试运行一个简单的命令,该命令在执行我的自动化测试之前启动一个端口转发,但它每次都挂起。
最终目标是在会话结束时设置端口转发,获取PID并终止端口转发。
我在macOS上使用Python 3.9.7,并试图在PyCharm IDE中执行此操作。
以下是代码片段:
def setup_port_forward():
# command
command = 'kubectl port-forward api_service 8080:80 -n service_name'
# shell
shell_script = subprocess.Popen(command,
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
start_new_session=True)
# extract
try:
stdout, stderr = shell_script.communicate(timeout=15)
pid = int(stdout.decode().strip().split(' ')[-1])
except subprocess.TimeoutExpired:
shell_script.kill()
yield
# kill session
os.kill(pid, signal.SIGTERM)我不想假装知道它是做什么的,也不知道它是如何工作的,因为我还在学习python。
下面是我看过的一些帖子:
Python Script execute commands in Terminal
python subprocess.Popen hanging
Python Script execute commands in Terminal
Python hangs when executing a shell script that runs a process as a daemon
https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
许多线程都说在shell脚本中使用subprocess.PIPE可能会导致问题,但是在另一个线程上,关于如何获取PID,这就是所使用的方法。
我试过使用不同的方法,就像在不同的帖子中建议的那样:
command = 'kubectl port-forward api_service 8080:80 -n service_name'
# 1
os.system(command)
# 2
subprocess.Popen(command).communicate
# 3
subprocess.run(command)
# 4
subprocess.call(command)
# 5
commands.getstatusoutput(command)和他们所有的人一起,他们被吊死了。运行这是终端,它工作得很好。
发布于 2021-11-16 14:51:33
这里的主要问题是communicate。您只需要Popen进程,然后让它运行,直到您kill它。
如果可以的话,您肯定希望避免使用shell=True;另请参阅Actual meaning of
我也不认为stdout和stderr重定向有用。如果你只是想安静地运行它,可能只需要重定向到subprocess.DEVNULL或从它重定向。
在这里创建一个单独的会话似乎是有问题的;我可能也会放弃这一点。
对于在什么情况下首选哪种subprocess方法,Running Bash commands in Python有一些指导。当您想要等待进程完成时,TLDR是subprocess.run;当您不想等待进程完成时,则是subprocess.Popen (但是要了解您在管理对象方面的职责)。
def setup_port_forward():
proc = subprocess.Popen(
['kubectl', 'port-forward', 'api_service', '8080:80', '-n', 'service_name'],
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True)
yield
# When done
proc.kill()将此函数用作生成器的设计也有点奇怪;我可能建议您将其转换为context manager。
https://stackoverflow.com/questions/69991074
复制相似问题