[英]How can I start a process and put it to background in python?
我目前正在編寫我的第一個python程序(在Python 2.6.6中)。 該程序有助於啟動和停止在服務器上運行的不同應用程序,這些應用程序提供用戶公共命令(例如在Linux服務器上啟動和停止系統服務)。
我正在啟動應用程序的啟動腳本
p = subprocess.Popen(startCommand, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate()
print(output)
問題是,一個應用程序的啟動腳本保持在前台,因此p.communicate()會永遠等待。 我已經嘗試在startCommand前使用“nohup startCommand&”,但是沒有按預期工作。
作為一種解決方法,我現在使用以下bash腳本來調用應用程序的啟動腳本:
#!/bin/bash
LOGFILE="/opt/scripts/bin/logs/SomeServerApplicationStart.log"
nohup /opt/someDir/startSomeServerApplication.sh >${LOGFILE} 2>&1 &
STARTUPOK=$(tail -1 ${LOGFILE} | grep "Server started in RUNNING mode" | wc -l)
COUNTER=0
while [ $STARTUPOK -ne 1 ] && [ $COUNTER -lt 100 ]; do
STARTUPOK=$(tail -1 logs/SomeServerApplicationStart.log | grep "Server started in RUNNING mode" | wc -l)
if (( STARTUPOK )); then
echo "STARTUP OK"
exit 0
fi
sleep 1
COUNTER=$(( $COUNTER + 1 ))
done
echo "STARTUP FAILED"
從我的python代碼調用bash腳本。 這種解決方法很完美但我寧願在python中做所有...
是subprocess.Popen錯誤的方式? 我怎么能只用Python來完成我的任務?
首先,通過不調用通信很容易不阻止Python腳本的通信! 只需從命令的輸出或錯誤輸出中讀取,直到找到正確的消息並忘記命令。
# to avoid waiting for an EOF on a pipe ...
def getlines(fd):
line = bytearray()
c = None
while True:
c = fd.read(1)
if c is None:
return
line += c
if c == '\n':
yield str(line)
del line[:]
p = subprocess.Popen(startCommand, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT) # send stderr to stdout, same as 2>&1 for bash
for line in getlines(p.stdout):
if "Server started in RUNNING mode" in line:
print("STARTUP OK")
break
else: # end of input without getting startup message
print("STARTUP FAILED")
p.poll() # get status from child to avoid a zombie
# other error processing
上面的問題是,服務器仍然是Python進程的子進程,可能會收到不需要的信號,如SIGHUP。 如果要使其成為守護程序,則必須首先啟動下一個啟動服務器的子進程。 這樣,當第一個子節點結束時,它可以被調用者等待,服務器將獲得PPID為1(由init進程采用)。 您可以使用多處理模塊來簡化該部分
代碼可以是:
import multiprocessing
import subprocess
# to avoid waiting for an EOF on a pipe ...
def getlines(fd):
line = bytearray()
c = None
while True:
c = fd.read(1)
if c is None:
return
line += c
if c == '\n':
yield str(line)
del line[:]
def start_child(cmd):
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
shell=True)
for line in getlines(p.stdout):
print line
if "Server started in RUNNING mode" in line:
print "STARTUP OK"
break
else:
print "STARTUP FAILED"
def main():
# other stuff in program
p = multiprocessing.Process(target = start_child, args = (server_program,))
p.start()
p.join()
print "DONE"
# other stuff in program
# protect program startup for multiprocessing module
if __name__ == '__main__':
main()
當文件對象本身是一次返回一行的迭代器時,人們可能想知道對getlines
生成器的需求是什么。 問題是,當文件未連接到終端時,它內部調用read
直到EOF的讀取。 因為它現在連接到PIPE,所以在服務器結束之前你不會得到任何東西......這不是預期的
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.