[英]Difference between calling a bash script from the commandline and executing it via python
我目前正在通过 Django 自动化一些流程。 为此,我有一个 shell 脚本,它为我执行某些任务。 我的网络界面有一个“开始进程”按钮和一个“停止进程”按钮。
我想出了使用 shell 脚本的进程 ID 来终止进程的想法,当我想中止它时。 我的start.sh
看起来像这样:
pid=$$;
source ./stop.sh || true
echo $pid > "./processid.txt";
#do the actual stuff
我的stop.sh
看起来像这样:
pid=$(head -n 1 ./processid.txt)
kill $pid
它的作用是获取进程 ID 并将其临时存储在变量中,然后停止脚本(如果在脚本运行之前),然后将进程 ID 保存到processid.txt
文件中。 我的 stop.sh 只是将此 id 从文件中取出并终止该进程。
这确实可以从命令行工作......但是当我从我的 python 代码执行它时它不会。 我这样称呼它:
def start_bot():
popencommand = "sh -c \"cd ~/thetargetfolder && ./start.sh\""
Popen(popencommand, shell=True)
def stop_bot():
popencommand = "sh -c \"cd ~/thetargetfolder && ./stop.sh\""
Popen(popencommand, shell=True)
出于某种原因,这似乎不起作用。 我怀疑这与调用 python 脚本时我在start.sh
中获得的进程 ID 不是正确的有关...
当您使用subprocess.Popen("sh -c 'cd /somewhere &&./whatever'", shell=True)
时,您是在告诉 Python 启动运行三个进程的一系列事件:
shell=True
使 Python 运行sh -c '...yourcode...'
,它启动了shell=True
请求的第一个sh
副本sh
的第一个副本运行代码sh -c 'cd /somewhere &&./whatever'
,因为这是您给 Python 的字符串,因此它会启动sh
的第二个副本。sh
的第二个副本运行cd /somewhere &&./whatever
。 如果./whatever
是 shell 脚本,则意味着它启动了第三个shell。 这是很多不必要的复杂性! 没有理由拥有多个shell - 运行./whatever
的那个,由操作系统根据其 shebang( #!/bin/sh
或#!/usr/bin/env bash
等调用)。
您可以通过下降到只有一个shell(运行您的脚本的运行)来消除其中的一些问题。 确保脚本具有有效的 shebang( #!/usr/bin/env bash
或类似的)并且是可执行的( chmod +x start stop
)。
def start_bot():
subprocess.call(
[os.path.join(os.path.expanduser('~/thetargetfolder'), './start')],
cwd=os.path.expanduser('~/thetargetfolder')
)
def stop_bot():
subprocess.call(
[os.path.join(os.path.expanduser('~/thetargetfolder'), './stop')],
cwd=os.path.expanduser('~/thetargetfolder')
)
Finally, you can do even better by not using a shell for this at all, but just writing your logic directly in Python, or (even better than that;) relying on your operating system's process supervisor (most modern Linux distros ship systemd for the目的。而 MacOS 附带 launchd)。 如果您定义yourprogram.service
,则systemctl start yourprogram
启动脚本运行,而systemctl stop yourprogram
将其杀死——您可以将其配置为在启动时自动启动,或在计时器上,或在任何程序连接到预先打开的套接字时自动启动,或者你喜欢的其他方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.