假设我打开一个带有主进程的父进程,该主进程将标准输出分配给一个文件以进行日志记录。
然后假设我使用父进程通过 execvp (或任何其他 exec 系列函数)打开子进程。
根据文件,子进程将保留父进程的进程ID。
主要问题:这是否意味着子进程将继承父进程的管道(特别是 stdout 和 stderr)?
答案1
答案2
是的,使用 exec 并继承与父进程相同的 pid 意味着子进程默认保持管道连接,只要文件描述符没有标记为 close-on-exec (这可以通过福康特尔,参见马克·普洛特尼克的回答)。
当我写下我的问题时,我正处于用经验数据进行自我回答的边缘,然后我进行了自我回答,所以我是这样做的:
在文件中master.py
:
import subprocess
import logging
def main():
proc = ['python', 'parent.py']
logpath = 'parent.log'
with open(logpath, 'ab') as f:
p = subprocess.Popen(proc, stdout=f, stderr=subprocess.STDOUT)
logging.warn('task started, waiting to finish')
res = p.wait()
logging.warn(res)
if __name__ == '__main__':
main()
在parent.py
:
import os
import logging
def main():
proc = ['python', 'child.py']
logging.warn('parent is logging, pid: {0}'.format(os.getpid()))
os.execvp(proc[0], proc)
if __name__ == '__main__':
main()
并在child.py
:
import os
import logging
import time
def main():
for i in range(2):
logging.warn('child is logging, pid: {0}'.format(os.getpid()))
time.sleep(15)
if __name__ == '__main__':
main()
当我python master.py
在命令行上运行时,命令行输出:
WARNING:root:task started, waiting to finish
大约 15 秒后:
WARNING:root:0
并且parent.log 文件包含以下内容:
WARNING:root:parent is logging, pid 8515
WARNING:root:child is logging, pid 8515
WARNING:root:child is logging, pid 8515
这根据经验证明,当使用 exec 系列函数时,子进程会从父进程继承管道和 pid。很难找到这方面的支持文档,但有一个例子在这里给出(大约材料的一半。)