Python 正在运行返回管道输入的命令

Python 正在运行返回管道输入的命令,python,bash,python-3.x,Python,Bash,Python 3.x,我将此Python 3代码存储在pipe.py中,它接受一些管道输入并逐行打印: import sys for i, line in enumerate(sys.stdin): print("{}: {}".format(i, line)) 然后,我可以在Bash中运行此命令: $ echo "Test" | python pipe.py 0: Test 这是按预期工作的,但我感兴趣的是,是否有一种方法可以实际运行命令,从而产生管道输入。因此,在我上面的示例中,值Test通过管道传

我将此Python 3代码存储在
pipe.py
中,它接受一些管道输入并逐行打印:

import sys

for i, line in enumerate(sys.stdin):
    print("{}: {}".format(i, line))
然后,我可以在Bash中运行此命令:

$ echo "Test" | python pipe.py
0: Test
这是按预期工作的,但我感兴趣的是,是否有一种方法可以实际运行命令,从而产生管道输入。因此,在我上面的示例中,值
Test
通过管道传输到程序中,但执行
echo“Test”
以获得该值

有没有办法在我的Python程序中将
echo“Test”
命令作为字符串获取?

这是可能的——至少在Linux上,当您有
/proc
文件系统时,如果a)您的stdin是一个管道,b)管道发送器还没有消失

想法是检查
/proc
文件系统中相应的管道条目:

  • Python脚本将管道连接到stdin(文件描述符0)
  • 管道的另一端连接到发送进程的标准输出文件描述符(1)
例如,假设您的Python脚本具有进程id 1001,而发送方具有pid 1000,您将看到:

$ ls -l /proc/1001/fd/0
lr-x------ 1 user users 64 Sep 22 14:41 /proc/1001/fd/0 -> 'pipe:[507536]'

$ ls -l /proc/1000/fd/1
l-wx------ 1 user users 64 Sep 22 14:41 /proc/1000/fd/1 -> 'pipe:[507536]'
因此,只需在
/proc
中进行少量搜索,您就可以得到您想要的下面是
bash
中的一个示例,它实现了您想要的功能
——输出是

$ yes 1 2  | ./find-piper.sh 
sender pid is 21380, command is "yes 1 2 "
find piper.sh
脚本如下所示:

#!/bin/bash

myPid=$$

# determine pipe connected to stdin:
myPipeNumber=$( readlink /proc/$myPid/fd/0 | sed -n 's,^pipe:\[\([0-9]\+\)\]$,\1,;T;p' )
if [[ -z $myPipeNumber ]] ; then
  echo "input is not a pipe"
else
  # find process with stdout connected to our pipe
  senderPipe=$( find /proc -mindepth 3 -maxdepth 3 -path "*/fd/1" -lname "pipe:\[$myPipeNumber\]" 2>/dev/null )
  senderPid=$( sed -n 's,/proc/\([0-9]\+\)/.*,\1,;T;p' <<< "$senderPipe" )

  # report pid and command line of sender
  if [[ -z $senderPid ]] ; then
    echo "could not find sender pid"
  else
    echo "sender pid is $senderPid, command is \"$( tr '\000' ' ' </proc/$senderPid/cmdline )\""
  fi
fi

# eat input
cat > /dev/null
#/bin/bash
粘虫=$$
#确定连接至标准DIN的管道:
myPipeNumber=$(readlink/proc/$myPid/fd/0 | sed-n's,^pipe:\[\([0-9]\+\)\]$,\1,;T;p')
如果[-z$myPipeNumber]];然后
echo“输入不是管道”
其他的
#查找将标准输出连接到管道的流程
senderPipe=$(find/proc-mindepth 3-maxdepth 3-path“*/fd/1”-lname”管道:\[$myPipeNumber\]”2>/dev/null)

senderPid=$(sed-n's,/proc/\([0-9]\+\)/.*,\1,;T;p'Std-in可以是一个文件或整个命令管道,也可以只是一个终端,因此通常没有“命令”这样的东西您可能会得到。确定
sys.stdin
是否连接到磁盘文件或管道很有用,但可能不太需要知道管道另一端的实际命令。@chepner有没有办法找出
sys.stdin
的来源?@OrangeFlash81您可以通过查看
sys.stdin.isa来判断它来自管道tty()
当它是管道时,它将是
False
,但我不知道如何找到另一端的内容,甚至不知道antlersoft提到的另一端有多少内容。如果脚本之前有一个由5个命令组成的字符串,你会想要什么?顺便提一下,为什么要重新实现
nl
(或者,
cat-n
)?看起来很有趣!我稍后会仔细看看。