gpt4 book ai didi

python - 如何从 Python 脚本在后台执行 shell 脚本

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:55:29 25 4
gpt4 key购买 nike

我正致力于从 Python 执行 shell 脚本,到目前为止它运行良好。但我坚持一件事。

在我的 Unix 机器上,我在后台使用 & 执行一个命令,就像这样。此命令将启动我的应用服务器 -

david@machineA:/opt/kml$ /opt/kml/bin/kml_http --config=/opt/kml/config/httpd.conf.dev &

现在我需要从我的 Python 脚本中执行同样的事情,但是一旦它执行我的命令,它就永远不会转到 else block 并且永远不会打印出 execute_steps::Successful,它就卡在那里。

proc = subprocess.Popen("/opt/kml/bin/kml_http --config=/opt/kml/config/httpd.conf.dev &", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/bash')
if proc.returncode != 0:
logger.error("execute_steps::Errors while executing the shell script: %s" % stderr)
sleep(0.05) # delay for 50 ms
else:
logger.info("execute_steps::Successful: %s" % stdout)

我在这里做错了什么?我想在后台执行shell脚本后打印出execute_steps::Successful

所有其他命令都可以正常工作,但只有我尝试在后台运行的命令无法正常工作。

最佳答案

这里发生了几件事。

首先,您在后台启动一个 shell,然后告诉该 shell 在后台运行该程序。我不知道为什么你认为你需要两者,但让我们暂时忽略它。事实上,通过在 shell=True 之上添加 executable='/bin/bash',您实际上是在尝试运行一个 shell运行 shell 以在后台运行程序,尽管这实际上并不完全有效。*

其次,您正在使用 PIPE 处理过程的输出和错误,但没有读取它们。这可能会导致 child 死锁。如果您不想要输出,请使用 DEVNULL,而不是 PIPE。如果您希望自己处理输出,请使用 proc.communicate().**,或使用更高级的函数,如 check_output。如果您只是想让它与您自己的输出混合,请不要使用这些参数。

* 如果您使用 shell 因为 kml_http 是一个不可执行的脚本,必须由 /bin/bash 运行,那么不要不要为此使用 shell=Trueexecutable,只需将 make /bin/bash 作为命令行中的第一个参数,然后 /opt/kml/bin/kml_http 第二个。但这似乎不太可能;为什么要将不可执行的东西安装到 bin 目录中?

** 或者您可以从 proc.stdoutproc.stderr 中显式读取它,但这会变得更加复杂。


无论如何,在后台执行某事的全部意义在于它一直在后台运行,而您的脚本一直在前台运行。因此,您要在它完成之前检查它的 returncode,然后继续执行代码中的下一步,再也不会回来了。


看来你想等它完成。在这种情况下,不要在后台运行它——使用 proc.wait,或者只使用 subprocess.call() 而不是创建 Popen对象。当然,也不要使用 & 。当我们这样做时,也不要使用 shell:

retcode = subprocess.call(["/opt/kml/bin/kml_http",
"--config=/opt/kml/config/httpd.conf.dev"],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if retcode != 0:
# etc.

现在,在 kml_http 完成运行之前,您不会到达 if 语句。


如果你想等待它完成,但同时继续做其他事情,那么你试图在你的程序中同时做两件事,这意味着你需要一个线程来完成等待:

def run_kml_http():
retcode = subprocess.call(["/opt/kml/bin/kml_http",
"--config=/opt/kml/config/httpd.conf.dev"],
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
if retcode != 0:
# etc.

t = threading.Thread(target=run_kml_http)
t.start()
# Now you can do other stuff in the main thread, and the background thread will
# wait around until kml_http is finished and execute the `if` statement whenever
# that happens

关于python - 如何从 Python 脚本在后台执行 shell 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26519602/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com