명명된 파이프에서 stdin 가져오기

명명된 파이프에서 stdin 가져오기

내가 하려는 것은 터미널 창에서 Python을 실행하고 명명된 파이프에서 stdin을 리디렉션하는 것입니다. 그런 다음 다른 터미널의 명명된 파이프에 쓰고 해당 명령이 Python에서 실행되도록 합니다.

터미널 1:

mkfifo p1
python < p1

터미널 2:

echo -n "print \"Hello World\"" > p1

무슨 일이 일어나는가 - 파이썬이 인쇄 Hello World하고 종료됩니다. 내가하고 싶은 것은 Python을 계속 실행하여 다음 명령을 수행하는 것입니다. 쉘에서 이 작업을 어떻게 수행합니까?

답변1

당신은

  • stdin이 터미널이 아니더라도 Python을 대화형으로 실행하십시오.python -i
  • 파이프의 쓰기 끝을 열어 두십시오. 그렇지 않으면 Python이 EOF를 감지하고 종료합니다.

그래서:

python -i < p1

그리고 다른 곳에서는:

# open p1 on fd 3 of the shell process¹ for instance so stdout is
# left untouched in case you still want to write messages there.
exec 3> p1

# write something on fd 3. For instance with ksh/zsh's print
# builtin:
print -u3 '1j*1j'

# or for commands such as echo that can only print things
# on stdout (fd 1), duplicate that fd 3 to their fd 1:
echo '1j*1j' >&3 # short for 1>&3

# after echo (a builtin² in virtually all shells) returns, fd 1
# is restored to what it was before, but fd 3 remains open on
# the writing end of the pipe, so python still doesn't see EOF
# there.

echo normal message on stdout
echo 1+1 >&3 # more instructions for python
...
# and when done, close that file descriptor so python sees the EOF
# (assuming that fd 3 was the only file descriptor left open on
# the writing end of that pipe):
exec 3>&-

특히 스크립트에서는 3를 사용하여 fd를 수동으로 열고 닫는 대신 전체 명령 그룹을 리디렉션할 수 있습니다 exec.

{
  echo ... >&3
  ...
  ...
} 3> p1

¹ fd 3은 하위 프로세스에 의해 상속되며 (실행 시 닫기 플래그를 설정하는 ksh93 제외) 해당 프로세스에서 실행되는 다른 명령에 의해 상속됩니다.

² 물론 내장되지 않은 명령에도 작동합니다. 내장되지 않은 경우 리디렉션은 명령을 실행하기 위해 분기된 하위 프로세스에서만 수행되므로 쉘은 fd 1을 저장하고 복원할 필요가 없습니다. 외부 명령의 경우 자동으로 수행하는 ksh93을 제외하고 실제로 해당 fd 3을 닫아 누출되지 않도록 하고 백그라운드 프로세스가 결국 생성될 수 있습니다( cmd >&3 3>&-).

3 이 경우 ksh93은 해당 fd 3에 close-on-exec 플래그를 설정하지 않습니다.

답변2

FIFO 에 쓴 tail -f후에 FIFO를 열어두는 데 사용할 수 있습니다 .echo

tail -n1 -f p1 | python

이것이 작동하는 이유

python님이 에서 읽고 있습니다 p1. 파일 끝에 도달하면 읽기를 중지합니다. 이는 파일이 명명된 파이프인 경우에도 파일 읽기에 대한 일반적인 동작입니다. (follow) 플래그를 tail사용하면 -f파일 끝에 도달한 후에도 파일을 계속 읽습니다.

답변3

전체 프로그램을 한 번에 보내야 합니다.

run을 호출하면 python < p1쉘은 Python을 호출하기 전에 입력을 기다리고 있습니다. 즉, Python은 실행을 시작하지도 않습니다.조금도전체 데이터 스트림이 셸에서 읽혀진 다음 전체가 python.

대신 실행하더라도 python -u p1(즉, 버퍼링되지 않고 file 에서 읽기 p1) python실행하기 전에 전체 파일을 읽으려고 시도합니다.

이 실험을 시도해 보세요.

터미널 1:

mkfifo p1
python < p1

터미널 2:

cat > p1
print "Hello World"
print "Hello World"

여러 줄을 보낼 수 있지만 1학기의 Python은 아무 작업도 수행하지 않는다는 것을 알 수 있습니다. 이제 ctrl+를 누르세요 D. 전체 프로그램이 한 번에 실행됩니다.

요약하자면, Python이 파이프에서 읽도록 하려면 전체 프로그램을 보내야 합니다. 이런 식으로 Python을 대화식으로 사용할 수 없습니다.

답변4

또 다른 해결책이 있습니다. 터미널 1:

alec@MacBook-Air ~/hello $ rm -f my.fifo; mkfifo my.fifo 
alec@MacBook-Air ~/hello $ cat my.fifo 
command1
command2
...
alec@MacBook-Air ~/hello $ 

터미널 2:

alec@MacBook-Air ~/hello $ cat > my.fifo 
command1
command2
...
alec@MacBook-Air ~/hello $ 

터미널 2에 명령을 입력하고 터미널 1에 나타나는 것을 지켜보세요. 터미널 1 출력을 다른 프로세스(예: )로 파이프할 수 있습니다 cat my.fifo | node .... 완료되면 stdinCtrl-D를 사용하여 터미널 2를 닫습니다. 그러면 닫히고 터미널 1의 my.fifo명령 cat이 종료됩니다.

관련 정보