2016-04-01 6 views
4

У меня есть этот 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".

Есть ли способ, которым я могу получить команду echo "Test" как строку в моей программе Python?

+2

Std in может быть файлом или целым конвейером команд или просто терминалом, так что вообще нет такой вещи, как «команда», которую вы могли бы получить. – antlersoft

+0

Полезно определить, прикреплен ли файл 'sys.stdin' к файлу на диске или к каналу, но, вероятно, менее необходимо знать фактическую команду на другом конце канала. – chepner

+0

@chepner Есть ли способ узнать, откуда появился 'sys.stdin'? –

ответ

1

Это возможно - по крайней мере, на Linux, когда у вас есть /proc файловой системы, и если) ваш STDIN представляет собой труба, на всех, и б) отправитель трубы еще не ушел.

Идея заключается в том, чтобы чеке /proc файловой системы для соответствующих записей труб:

  • Ваш скрипт Python имеет трубу, соединенную с стандартного ввода (дескриптор файла 0).
  • Другой конец трубы подключен к дескриптору (1) файла stdout процесса отправки.

В качестве примера, при условии, что ваш сценарий Python имеет идентификатор процесса 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 

Переход на Python остается в качестве упражнения:)

Предоставления:

  • Второе предварительное условие («отправитель труб еще не ушел»), однако, не будет предоставлен в вашем случае, так как echo "Test" завершится очень быстро.
  • Если ваша труба отправителя состоит из нескольких команд (например, (echo "Test"; sleep 2) | python pipe.py), вы найдете несколько записей отправителя.
+0

Выглядит интересно! Позаботимся позже. –

Смежные вопросы