stdin을 함수에 파이프하면 분할 오류 출력이 억제됩니다. 왜?

stdin을 함수에 파이프하면 분할 오류 출력이 억제됩니다. 왜?

바이너리를 실행하는 함수를 정의해 보겠습니다.

function execute() { ./binary; }

그런 다음 텍스트 파일을 첫 번째 함수로 파이프하는 두 번째 함수를 정의합니다.

function test() { cat in.txt | execute; }

binarysegfault와 충돌하는 경우 testCLI에서 호출하면 반환 코드가 발생 139하지만 "segfault" 오류는 터미널에 인쇄되지 않습니다.

직접 호출을 정의하면 test"세그먼트 오류"가 인쇄됩니다.binary

function test() { cat in.txt | ./binary; }

stdin을 입력하지 않고 호출을 정의하면 execute다음과 같이 인쇄됩니다.

function test() { execute; }

in.txt마지막으로 파이프를 통하지 않고 직접 리디렉션하는 경우 execute에도 인쇄됩니다.

function test() { execute <in.txt; }

이것은 Bash 4.4에서 테스트되었습니다. 왜 그런 겁니까?

답변1

이 진단 메시지는 대화형 셸에서 생성됩니다.직업 통제시스템은 사용자의 이익을 위해 기본 프로그램이 충돌하여 발생하지 않습니다. 쉘 함수를 파이프할 때서브쉘함수를 실행하기 위해 생성되며 하위 쉘은 사용자 측으로 간주되지 않습니다. 함수가 정상적으로 호출되면 원래 셸에서 실행되고 메시지가 인쇄됩니다.

현재 셸에서 작업 제어를 비활성화하여 이를 테스트할 수 있습니다.

set +m

그런 다음 ./binary다시 실행하세요. 이제 아무 것도 인쇄되지 않습니다. 작업 제어 다시 활성화 를 사용하십시오 set -m.

단순한 서브쉘이라도 동일한 효과를 갖습니다.

( : ; ./binary )

진단 정보는 인쇄되지 않습니다(하위 쉘 제거 최적화를 방지하려면 두 개의 명령이 필요함). 관로나가이 함수도 같은 일을 합니다.

작업 제어는 하위 셸에서 비활성화되며 수동으로 활성화하더라도 침묵됩니다. 이는 시스템의 불행한 결함입니다. 비대화형 쉘에서는 메시지가 대화형 쉘의 다른 모든 곳에 있기 때문에 항상 다른 메커니즘을 통해 보고됩니다.


진단 내용을 인쇄하는 것이 중요한 경우 함수 대신 스크립트를 작성하면 해당 내용이 항상 포함되도록 할 수 있습니다. 파이프라인에서 함수를 사용하고 있기 때문에 어쨌든 함수가 필요한 작업을 수행할 수 없으므로 이를 수행하는 데 상당한 비용이 들지 않습니다.


나는 이것이 실수라고 말하고 싶지 않습니다. 이런 식으로 행동하는 한 가지 가능한 이유는 다음과 같습니다.명령 대체$(...)서브셸도 실행하는 는 적절하게 작동합니다.

foo=$(echo|test)

foo파이프라인 오류로 인해 null 확장이 발생하도록 진단 메시지가 저장되어서는 안 됩니다 . 또 다른 접근 방식은 의도적으로 진단 메시지를 일시적으로 표시하지 않는 것입니다.

관련 정보