簡體   English   中英

python 子進程 - 分離進程

[英]python subprocess - detach a process

我有一個 python 腳本af_audit_run.py ,它通過subprocess調用另一個 python 腳本request_audit.py

第二個腳本request_audit.py在后台調用另一個子進程並返回一個請求 ID。

問題是第一個腳本af_audit_run.py應該在第二個腳本返回請求 ID 后立即退出,正在等待整個后台進程完成。 有什么方法可以在返回請求 ID 后強制第一個腳本退出?

af_audit_run.py -- 使用communicate方法等待結果:

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 
stderr=subprocess.PIPE)
result, error = p.communicate()
print(result.decode('utf-8'))
print(error.decode('utf-8'))

request_audit.py -- 不等待,只是分離一個子進程(第 3 個 python 腳本)並返回請求 ID:

subprocess.Popen(cmd, shell=True, stdout=None, stderr=None, close_fds=True)
print(request_id)

環境:Linux

您需要確保標准 output 和第三個進程的標准錯誤被定向到 pipe 以外的其他地方, af_audit_run.py正在從中讀取 Z78E6221F6393D1356DZZCE.CE.

現有代碼的問題在於,通過使用stdout=None, stderr=None ,您正在請求默認操作(就好像您根本沒有使用這些關鍵字一樣)。 這是寫入與父進程相同的 output 流,在本例中為request_audit.py ,使用子進程分叉時繼承的文件描述符。 這意味着頂級af_audit_run.py將等待 output 因為它沒有看到 output ZF7B44CFAFD5C52223D5498196C8A2E7B 上的文件結尾,直到第三個過程完成。

這可以在lsof的output中看到——在下面的例子中,第三個進程是命令/bin/sleep 600 (見最后的測試代碼)。

這是第三個進程的lsof output 的一部分:

sleep   3057  myuser    0u   CHR 136,20      0t0      23 /dev/pts/20
sleep   3057  myuser    1w  FIFO   0,13      0t0 9441062 pipe
sleep   3057  myuser    2w  FIFO   0,13      0t0 9441063 pipe

這是頂級af_audit_run.pylsof output 的一部分:

python3 3053  myuser    0u   CHR 136,20      0t0      23 /dev/pts/20
python3 3053  myuser    1u   CHR 136,20      0t0      23 /dev/pts/20
python3 3053  myuser    2u   CHR 136,20      0t0      23 /dev/pts/20
python3 3053  myuser    3r  FIFO   0,13      0t0 9441062 pipe
python3 3053  myuser    5r  FIFO   0,13      0t0 9441063 pipe

如您所見,此示例中的sleep進程 (pid 3057) 將其 stdout (fd 1) 和 stderr (fd 2) 流連接到頂級進程 (pid 3053) 正在讀取的管道的寫入端 - - 注意倒數第二列中的 pipe 數字——即使它不是該進程的直接父進程。

您正在指定close_fds=True ,但這記錄如下:

“如果close_fds為真,除了0、1、2之外的所有文件描述符都會在子進程執行前關閉。” (強調我的)

所以它對標准輸入、標准輸出或標准錯誤流沒有任何影響,盡管任何其他打開的文件描述符都會在子進程中關閉。

如果您使用 stdout stdout=None, stderr=None而不是 stdout=subprocess.DEVNULL stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL subprocess.DEVNULL ,那么這會將這些流顯式定向到 null 設備(Linux 上的/dev/null ),然后是af_audit_run.py不必等待。

在這種情況下,來自lsof的一些 output :

sleep   3318  myuser    0u   CHR 136,20      0t0      23 /dev/pts/20
sleep   3318  myuser    1u   CHR    1,3      0t0       6 /dev/null
sleep   3318  myuser    2u   CHR    1,3      0t0       6 /dev/null

也可以使用stdin=subprocess.DEVNULL ,這樣如果進程嘗試讀取,那么它將看到文件結尾。 在這個例子中我沒有這樣做,它的輸入仍然連接到終端設備,雖然這並不影響af_audit_run.py是否等待它。


測試代碼

af_audit_run.py

import subprocess

cmd = "python3 request_audit.py"

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, 
                     stderr=subprocess.PIPE)
result, error = p.communicate()
print(result.decode('utf-8'))
print(error.decode('utf-8'))

request_audit.py

import subprocess

cmd = "/bin/sleep 600"

subprocess.Popen(cmd, shell=True,
                 stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

print(5)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM