【问题标题】:How to access subprocess Popen pass_fds argument from subprocess?如何从子进程访问子进程 Popen pass_fds 参数?
【发布时间】:2018-06-12 12:12:12
【问题描述】:

所以标题有点长,但这是我在网上唯一找不到的东西,有点搜索。如何从子进程访问 pass_fds 参数?

# parent.py
import subprocess

subprocess.Popen(['run', 'some', 'program'], pass_fds=(afd, bfd))

# child.py
import subprocess

# need to access pass_fds argument? but how?

【问题讨论】:

  • 所以我想唯一的方法是在不使用其他一些 ipc 技术的情况下将文件描述符发送到子进程的标准输入。然后孩子会从标准输入读取并根据收到的 fd 采取行动
  • ...您可以使用任何特定于操作系统的接口(即 procfs)来反省子级可用的开放 FD,并尝试从元数据中推断出有趣的(即,如果您希望有两个 TCP 套接字,则扫描它们),但这似乎很容易出错,而不是具有显式接口。
  • @charles 当然我通常会使用共享内存之类的东西,但这似乎不是 python-ish 并且认为我可能错过了一些信息。但是在深入研究subprocess.Popen 的 cpython 源代码后,我注意到它们试图尽可能通用,因此它们没有包含机制,如果所述命令仍在调用 python 并做一些(魔术)技巧来处理和存储到预定义变量等
  • subprocess 旨在用于调用非 Python 代码。如果您创建子进程是为了明确地在其中运行 Python 代码,那么您应该使用multiprocessing

标签: python python-3.x subprocess popen file-descriptor


【解决方案1】:

您需要以某种方式明确告知子代传递的 fds。最常见/最简单的机制是:

  1. 通过为孩子设置的环境变量
  2. 通过传递给孩子的参数
  3. (不太常见,但可能)写给孩子的stdin

所有这些当然都需要孩子的配合;它需要定义一个接口来通知它传递的fds。

openssl 的命令行工具支持所有这些机制以实现类似目的(将密码短语传达给孩子而不将其放在命令行上)。您传递-pass 和第二个参数,该参数定义在哪里查找密码。如果第二个参数是stdin,它从stdin 读取,如果它是-pass fd:#(其中# 是fd 编号)它从提供的任意文件描述符-pass env:var(其中var 是环境变量的名称)从环境中读取,等等。

【讨论】:

  • 我猜是最简单的方法,也可能是最安全的方法,通过参数传递它。因为无论如何我已经对参数进行了一些预处理。感谢您的帮助
【解决方案2】:

好吧,也许这不是最好的技术答案,但我想深入了解文件描述符。根据您的问题,我制作了这两个脚本。 os 创建管道,父级通过 pass_fds 元组向子级发送描述符。更多信息在python docsos.read() 描述中。之后,父母的 fdw 作为字节推送到子 proc,然后用于发送回一些答案。

希望对你有帮助。

编辑: 在 Google 论坛中找到 this post

##### child.py
import subprocess, os

fdr_data = os.read(3,20) # 3 is inherited by pass_fds    
fdw = int(fdr_data)      # 4

print("CHILD fdw = ", fdw , "\n")

os.write(fdw, bytes("some answer".encode())) 
exit()


##### parent.py
import subprocess, os, time

fdr, fdw = os.pipe() # new file descriptor read , fd write
print("PARENT", "fdr = ", fdr , " fdw = " , fdw)

subprocess.Popen(['python3','child.py'], pass_fds=(fdr, fdw))    
os.write(fdw, bytes("{}".format(fdw).encode())) # pipe file descriptor write (out 4)

time.sleep(1)   # so subproc can execute

read_pipe = os.read(fdr, 20) # pipe file descriptor read (in 3)    
print("PARENT" , read_pipe.decode())

【讨论】:

  • 孩子怎么知道必须从3开始读?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
  • 2014-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多