我正在运行etcd
进程,该进程一直处于活动状态,直到您将其终止为止。 (它没有提供守护进程模式选项。)我想分离它,这样我就可以继续运行更多的python。
我会在shell中做什么;
etcd & next_cmd
我在整个互联网的热情推荐下使用python的sh
库。我宁愿不涉及subprocess
或Popen
,但我也找不到使用这些解决方案。
我想要的东西;
sh.etcd(detach=True)
sh.next_cmd()
或
sh.etcd("&")
sh.next_cmd()
不幸的是,detach
不是kwarg而sh
将"&"
视为etcd
的标志。
我在这里遗漏了什么?这样做的好方法是什么?
答案 0 :(得分:6)
要实施sh
的{{1}},请避免货物编程并直接使用&
模块:
subprocess
这忽略了异常处理和你关于“守护进程模式”的讨论(如果你想在Python中实现一个守护进程;使用python-daemon。要将进程作为系统服务运行,请使用你提供的操作系统或主管程序如supervisord
)。
答案 1 :(得分:4)
sh的作者。我相信您想使用_bg
特殊关键字参数http://amoffat.github.io/sh/#background-processes
这将分叉您的命令并立即返回。即使您的脚本退出,该过程仍将继续运行。
答案 2 :(得分:1)
请注意以下两个示例中有一个调用
time.sleep(...)
我需要etcd
时间完成启动
发送请求。一个真正的解决方案可能涉及探测
API端点以查看它是否可用,如果没有则循环。
multiprocessing
模块):import sh
import requests
import time
from multiprocessing import Process
etcd = Process(target=sh.etcd)
try:
# start etcd
etcd.start()
time.sleep(3)
# do other stuff
r = requests.get('http://localhost:4001/v2/keys/')
print r.text
finally:
etcd.terminate()
这使用multiprocessing
模块来处理机制
产生后台任务。使用这个模型,你不会看到
来自etcd
的输出。
import os
import signal
import time
import requests
pid = os.fork()
if pid == 0:
# start etcd
os.execvp('etcd', ['etcd'])
try:
# do other stuff
time.sleep(3)
r = requests.get('http://localhost:4001/v2/keys/')
print r.text
finally:
os.kill(pid, signal.SIGTERM)
这使用传统的fork
和exec
模型,它的工作方式与此类似
很好地在Python中,就像在C中一样。在这个模型中,etcd
的输出
将显示在您的控制台上,这可能是您想要的,也可能不是。您可以通过在子流程中重定向stdout
和stderr
来控制此操作。
答案 3 :(得分:0)
子进程也很容易做到这一点:
这种方法有效(python3)。关键是使用“start_new_session=True”
更新:尽管 Popen 文档说这有效,但它没有。我发现通过 fork 孩子然后做 os.setsid() 它可以正常工作
client.py:
#!/usr/bin/env python3
import time
import subprocess
subprocess.Popen("python3 child.py", shell=True, start_new_session=True)
i = 0
while True:
i += 1
print("demon: %d" % i)
time.sleep(1)
child.py:
#!/usr/bin/env python3
import time
import subprocess
import os
pid = os.fork()
if (pid == 0):
os.setsid()
i = 0
while True:
i += 1
print("child: %d" % i)
time.sleep(1)
if i == 10:
print("child exiting")
break
输出:
./client.py
demon: 1
child: 1
demon: 2
child: 2
^CTraceback (most recent call last):
File "./client.py", line 9, in <module>
time.sleep(1)
KeyboardInterrupt
$ child: 3
child: 4
child: 5
child: 6
child: 7
child: 8
child: 9
child: 10
child exiting
答案 4 :(得分:-1)
如果除了我下次搜索相同问题时没有其他原因而发布此信息:
if os.fork() == 0:
os.close(0)
os.close(1)
os.close(2)
subprocess.Popen(('etcd'),close_fds=True)
sys.exit(0)
Popen close_fds关闭0,1,2以外的文件描述符,因此代码显式关闭它们。