[英]Popen fails to start a process when I call it from a python script that runs as a Linux service
I have a script which on certain conditions calls Popen to create new process. 我有一个脚本,在某些情况下会调用Popen来创建新进程。 If I run this script from the command line, then Popen creates a process.
如果我从命令行运行此脚本,则Popen将创建一个进程。 But if I run the same script as a linux systemd service, then script executes normally except Popen part which fails to start a process.
但是,如果我运行与linux systemd服务相同的脚本,则该脚本将正常执行,但Popen部分无法启动进程。 Same Popen failure thing happens if I start this script from within Java application deployed and running in Tomcat
如果我从在Tomcat中部署和运行的Java应用程序中启动此脚本,也会发生相同的Popen失败事件
I've tried to mix arguments in Popen construct, but I feel that I am missing something about the whole idea behind linux processes relationships Here is the code which executes perfectly if started from cmd terminal like this: "python3 myscript.py" and fails if run as systemd service( systemctl start myscript.service - config file ofcourse exists) Fails Popen part 我尝试在Popen构造中混合参数,但是我觉得我在linux进程关系背后的整个想法上缺少一些东西。如果从这样的cmd终端启动,则代码可以完美执行:“ python3 myscript.py”并失败如果作为systemd服务运行(systemctl启动myscript.service-课程的配置文件存在)Popen部分失败
Service config file: 服务配置文件:
[Unit]
Description=Some Service
After=multi-user.target
Conflicts=getty@tty1.service
[Service]
Type=simple
ExecStart=/usr/bin/python3 /usr/bin/my_service.py
StandardInput=tty-force
[Install]
WantedBy=multi-user.target
Python script my_service.py itself: Python脚本my_service.py本身:
import socket, os, signal, psutil
from subprocess import Popen, PIPE, DEVNULL
def find_free_port():
s = socket.socket()
# Bind to a free port provided by the host.
s.bind(('', 0))
return s.getsockname()[1]
HOST = '91.230.195.104'
PORT = 65440
lastProcess = None
currentPID = os.getpid()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
while True:
try:
print('Waiting for new Connection..')
conn, addr = s.accept()
if lastProcess != None:
current_process = psutil.Process(lastProcess.pid)
children = current_process.children(recursive=True)
for child in children:
if child.pid != currentPID:
os.kill(child.pid, signal.SIGKILL)
print('\nConnected to: '+str(addr))
port_sender = find_free_port()
port_videolink = None
while True:
port_videolink = find_free_port()
if port_sender != port_videolink:
break
with conn:
data = conn.recv(1024)
print('DRONE ID: '+str(data.decode()))
if data:
conn.sendall(bytes(str(port_sender)+':'+str(port_videolink), 'utf-8'))
lastProcess = Popen("python3 video_receiver.py --port_videolink="+str(port_videolink)+
" --port_sender="+str(port_sender), shell=True, preexec_fn=os.setpgrp, stdout=PIPE, stderr=PIPE)
print("Videofeed port: "+str(port_videolink)+"\n")
except Exception as e:
print(str(e))
there are no error or warning, just video_receiver.py process never starts :-\\ 没有错误或警告,只是video_receiver.py进程永远不会启动:-\\
The issue is that the CWD for the process is different. 问题在于该过程的CWD不同。 To debug this have your program log the result of
os.getcwd()
. 要调试它,请让您的程序记录
os.getcwd()
的结果。 Another common issue although not the one occurring here is that PATH is different. 尽管不是此处出现的另一个常见问题是PATH是不同的。
lastProcess = Popen("python3 video_receiver.py")
fails because os.path.isfile(os.path.join(os.getcwd(), "video_receiver.py")) == False
失败,因为
os.path.isfile(os.path.join(os.getcwd(), "video_receiver.py")) == False
One solution is to provide the full paths to python and your script in the Popen call. 一种解决方案是在Popen调用中提供python和脚本的完整路径。 The path to Python is only needed if you have Python installed in a virtual environment.
仅当您在虚拟环境中安装了Python时,才需要使用Python路径。
Another is to use os.chdir()
or set the working directory in the service configuration. 另一种方法是使用
os.chdir()
或在服务配置中设置工作目录。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.