![*모든* 표준 입력이 있는 경우 프로그램이 실패하는 문제를 어떻게 해결합니까?](https://linux55.com/image/49094/*%EB%AA%A8%EB%93%A0*%20%ED%91%9C%EC%A4%80%20%EC%9E%85%EB%A0%A5%EC%9D%B4%20%EC%9E%88%EB%8A%94%20%EA%B2%BD%EC%9A%B0%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%9D%B4%20%EC%8B%A4%ED%8C%A8%ED%95%98%EB%8A%94%20%EB%AC%B8%EC%A0%9C%EB%A5%BC%20%EC%96%B4%EB%96%BB%EA%B2%8C%20%ED%95%B4%EA%B2%B0%ED%95%A9%EB%8B%88%EA%B9%8C%3F.png)
예를 들어 다음은 정상적으로 작동합니다.
/usr/bin/program
일부 출력을 생성하고 결과를 얻습니다.
하지만 내가 이렇게 부르면:
echo -n | /usr/bin/program
아니면 이거
echo -n | bash -c "/usr/bin/program"
아니면 이것도:
echo -n | bash -c "wc -c; /usr/bin/program"
일부 출력 라인을 생성한 다음 실패합니다. 프로그램의 소스 코드에 접근할 수 없기 때문에 이러한 동작을 일으키는 원인이 무엇인지조차 알 수 없습니다.
Python 스크립트에서 호출하려고 하면 동일한 결과가 나타납니다.
echo | python -c 'from subprocess import call; call("/usr/bin/program", shell=True)'
("echo" 접두사가 없는 버전은 잘 작동합니다)
왜 이런 일이 일어나는지조차 모르겠습니다. 프로그램이 어디에서 읽어야 하는지 명시적으로 지정하지 않더라도 표준 입력이 열려 있으므로 이것이 원인이 되어서는 안 됩니다.
이 문제를 해결할 방법이 있나요?
편집하다:
출력의 마지막 네 줄 strace
- 유일한 다른 줄은 다음과 같습니다.
# without echo
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
select(1, [0], NULL, NULL, {0, 0}) = 0 (Timeout)
...
# with echo
select(1, [0], NULL, NULL, {0, 0}) = 1 (in [0], left {0, 0})
write(4, "\0\0\0j\0\0\0\3\0\0\0\4\0\0\0\0\377\377\377\377", 20) = 20
write(3, "\0\0\0j\0\0\0\3\0\0\0\4\0\0\0\0\377\377\377\377", 20) = 20
exit_group(1) = ?
부분적인 해결책:
sleep 20 | /usr/bin/program
program
stdin에서 어떤 일이 일어날 때까지 기다리고 개행이나 EOF가 발생하면 종료하는 것 같습니다 ( select
strace 출력의 호출에서 볼 수 있습니다. 입력이 "실제" 사용자로부터 오는 경우 시간 초과됩니다). 따라서 우리는 표준 입력을 열어두면서 표준 입력에 아무것도 쓰지 않고 sleep
작업을 수행하는 프로그램이 필요합니다.
답변1
당신이 요구하는 것을 수행하는 Perl 한 줄짜리 코드는 다음과 같습니다:
perl -e '$SIG{CHLD} = sub{exit 0}; open $fh, "|-", @ARGV or die; sleep 20 while 1;' /usr/bin/program
sleep forever | /usr/bin/program
이는 프로그램 완료를 모니터링하고 완료되자마자 종료된다는 점을 제외하면 본질적으로 Myth* 와 동일합니다 . /usr/bin/program에 매개변수가 필요한 경우 해당 매개변수를 행 끝에 추가할 수 있습니다.
*는 sleep forever
작동하지 않지만, GNU sleep은 영원히 잠들 것입니다 sleep inf
!