好吧,在运行我可以在google上找到的每个样本后,我正式完成了想法,直到第19页。我有一个“提供者”脚本。这个python脚本的目标是启动其他服务,即使在此“提供程序”停止运行后也无限期运行。基本上,启动过程然后忘记它,但继续脚本而不是停止它...
我的问题:python-daemon ...我有动作(从启动的服务启动/停止/获取状态的Web服务调用)。我会动态创建启动命令,并根据需要对配置文件执行变量替换。
让我们从这一点开始:我有一个运行命令(一个执行java进程的bash脚本 - 一个将在稍后停止的长时间运行的服务)。
def start(command, working_directory):
pidfile = os.path.join(working_directory, 'application.pid')
# I expect the pid of the started application to be here. The file is not created. Nothing is there.
context = daemon.DaemonContext(working_directory=working_directory,
pidfile=daemon.pidfile.PIDLockFile(pidfile))
with context:
psutil.Popen(command)
# This part never runs. Even if I put a simple print statement at this point, that never appears. Debugging in pycharms shows that my script returns with 0 on with context
with open(pidfile, 'r') as pf:
pid = pf.read()
return pid
从我的调用者到这个方法,我准备一个json对象返回到客户端,它基本上包含一个instance_id(不介意)和一个pid(它将用于在另一个请求中停止这个进程)
会发生什么?在使用上下文后,我的应用程序以状态0退出,没有返回任何内容,也没有创建json响应,只有执行的psutil.Popen命令运行才会创建pidfile。我怎样才能达到我的需要?我需要一个独立运行的进程,需要知道它的PID,以便以后停止它。即使当前python脚本由于某种原因停止,执行的进程也必须运行。我无法绕过shell脚本,因为该应用程序不是我的,我必须使用我拥有的。
感谢任何提示!
@Edit: 我尝试使用psutil / subprocess中的Popen,结果更有希望。
def start(self, command):
import psutil/subprocess
proc = psutil.Popen(command)
return str(proc.pid)
现在如果我调试应用程序并在return语句上等待一些未定义的时间,一切都很好!该服务正在运行pid,我可以稍后停止。然后我只是运行提供程序而不进行调试。它返回pid,但进程未运行。似乎Popen没有时间启动服务,因为整个提供商停止更快。
@Update: 使用os.fork:
@staticmethod
def __start_process(command, working_directory):
pid = os.fork()
if pid == 0:
os.chdir(working_directory)
proc = psutil.Popen(command)
with open('application.pid', 'w') as pf:
pf.write(proc.pid)
def start(self):
...
__start_process(command, working_directory)
with open(os.path.join(working_directory, 'application.pid'), 'r') as pf:
pid = int(pf.read())
proc = psutil.Process(pid)
print("RUNNING" if proc.status() == psutil.STATUS_RUNNING else "...")
运行上面的示例后,RUNNING将写入控制台。主脚本退出后,因为我不够快:
ps auxf | grep的 没有实例正在运行......
检查pid文件;确定它在那里创建了
cat /application.pid EMPTY 0bytes
答案 0 :(得分:1)
您是否尝试过os.fork()
?
简而言之,os.fork()
会生成一个新进程并返回该新进程的PID。
你可以这样做:
#!/usr/bin/env python
import os
import subprocess
import sys
import time
command = 'ls' # YOUR COMMAND
working_directory = '/etc' # YOUR WORKING DIRECTORY
def child(command, directory):
print "I'm the child process, will execute '%s' in '%s'" % (command, directory)
# Change working directory
os.chdir(directory)
# Execute command
cmd = subprocess.Popen(command
, shell=True
, stdout=subprocess.PIPE
, stderr=subprocess.PIPE
, stdin=subprocess.PIPE
)
# Retrieve output and error(s), if any
output = cmd.stdout.read() + cmd.stderr.read()
print output
# Exiting
print 'Child process ending now'
sys.exit(0)
def main():
print "I'm the main process"
pid = os.fork()
if pid == 0:
child(command, working_directory)
else:
print 'A subprocess was created with PID: %s' % pid
# Do stuff here ...
time.sleep(5)
print 'Main process ending now.'
sys.exit(0)
if __name__ == '__main__':
main()
更多信息:
答案 1 :(得分:1)
从我得到的多个部分提示,终于设法让它工作......
def start(command, working_directory):
pid = os.fork()
if pid == 0:
os.setsid()
os.umask(0) # I'm not sure about this, not on my notebook at the moment
os.execv(command[0], command) # This was strange as i needed to use the name of the shell script twice: command argv[0] [args]. Upon using ksh as command i got a nice error...
else:
with open(os.path.join(working_directory, 'application.pid'), 'w') as pf:
pf.write(str(pid))
return pid
这一起解决了这个问题。启动的进程不是正在运行的python脚本的子进程,并且在脚本终止时不会停止。