다음 명령의 기능을 수행하는 쉬운 방법이 있습니까?
watch foo 2>/dev/null | tr ' ' '-'
strace foo 2>/dev/null | tr ' ' '-'
something_else foo 2>/dev/null | tr ' ' '-'
사물이 어떻게 행동해야 하는지에 대한 공유된 기대가 있습니까 something_else
? 이러한 명령(예: 어떤 프로그램의 출력이 리디렉션되는지 등)을 명확하게 할 수 있는 쉘 구조가 있습니까?
답변1
명령 자체는 리디렉션을 처리하지 않습니다. 쉘이 명령을 실행할 새 프로세스를 생성할 때 쉘은 지시에 따라 IO를 설정합니다. 명령 자체는 실행되므로 신경 쓸 필요가 없습니다.
귀하의 something_else
명령은 평소대로 출력을 stdout 및 stderr로 보냅니다.
답변2
간단히 말해서:
some_else가 어떻게 작동해야 하는지에 대한 공통된 기대가 있습니까?
예, 상설 명령입니다. 쉘은 두 개의 명령을 이해하지 못합니다. 이는 명령과 인수입니다( command1 command2
예를 들어 유효한 바이너리의 이름일 수도 있음). /bin
이는 command1
나중에 쉘이 아닌 시스템 호출을 command2
통해 실행됩니다.exec()
이러한 명령(예: 어떤 프로그램의 출력이 리디렉션되는지 등)을 명확하게 할 수 있는 쉘 구조가 있습니까?
아니요, someting_else
특별한 대우를 받지 않습니다. 위에서 언급했듯이 명령과 인수 이외의 구조는 없습니다. 이 문제에 대한 혼란은 다음과 같은 데 있는 것 같습니다.둘 다 strace
쉘에 의해 실행되는 것으로 가정 하지만 foo
실제로는 상위-하위 프로세스 체인입니다.
쉘이 명령과 리디렉션을 처리하는 방법
Bourne(예: bash
, dash
, ksh
)과 같은 쉘은 모두 명령 해석 방법에 대해 POSIX 규칙을 따릅니다.POSIX 지정: ""간단한 명령"은 임의의 순서로 선택적 변수 할당 및 리디렉션의 시퀀스이며 선택적으로 단어 및 리디렉션이 뒤따르고 제어 연산자에 의해 종료됩니다. 이는 테이블로 작성할 수 있습니다.
[VAR=foo BAR=baz] command1 [arg1, arg2...] [ n>m ]
일반적인 규칙은 대부분의 비할당 단어를 보존하는 명령에 리디렉션이 적용된다는 것입니다. 귀하의 예에서 strace
는 명령이고 foo
는 인수입니다 strace
. 리디렉션은 인수가 아닌 명령에 대해서만 작동합니다. 즉, 쉘에 의해 실행 strace
되지 않고 이 경우 하위 프로세스에 의해 실행됩니다 . 이번에도 매개변수가 있는 명령 으로 처리됩니다 .foo
strace
foo
strace
somethingelse
foo
파일 설명자
내장되지 않은 명령에 관한 한 해당 명령은 셸의 하위 프로세스이고 하위 프로세스는 셸의 파일 설명자를 상속하므로 일반적으로 리디렉션을 관리하지 않습니다. "미리 패키지된" 대상을 수신하므로 strace
현재로서는 2>/dev/null
그럴 수 있습니다 . 파일 설명자 2가 실제로 무엇인지는 신경 쓰지 않습니다(소스 코드 수준을 적극적으로 확인하지 않는 한). strace
출력은 여전히 파일 설명자 2에 기록되지만 쉘은 해당 파일 설명자를 /dev/null
.
strace stat noexist 2>stracelog.txt
파일 설명자는 상속되므로 두 오류 스트림에서 이와 같은 작업을 수행 strace
하고 stat
동일한 파일로 이동하는 이유도 설명됩니다. 이와 대조적으로 일부 명령에서는 대상을 옵션 중 하나로 명시적으로 지정할 수 있습니다. 따라서 파일에 출력만 있습니다 strace -o tracelog.txt stat noexist 2>stracelog.txt
. 파일 설명자가 상속되더라도 이제 플래그는 의 속성이고, 파일 설명자가 상속되더라도 출력은 명령으로 관리됩니다.stat
stracelog.txt
-o
strace
이는 또한 약간의 힌트를 제공합니다. 이론적으로 명령은 "리디렉션"될 수 있습니다. 즉, 파일 설명자는 시스템 호출을 통해 기존 파일 설명자로 복사됩니다 dup2()
. 이는 쉘에서 사용하는 메커니즘과 정확히 동일하지만 리디렉션 기호 의 >
용어 유형에 관한 한 이는 여전히 쉘 제어 하에 있으므로 상위 쉘에 의해서만 해석될 수 있습니다.
왜 2>/dev/null인가요?
일반적으로 진단 출력이 로 전송되는 것으로 알려져 있습니다 stderr
. 실제로 해당 주제에 대한 두 가지 훌륭한 기사가 이미 있습니다.
watch
귀하의 예 에서 규칙을 따르십시오 strace
. 그게 전부입니다. 2>/dev/null
그러한 명령의 출력을 숨기도록 지정하는 요구 사항 자체는 없습니다 .
예를 들어 인수로 전달된 명령에 대한 리디렉션을 실제로 지정하려면 strace
해당 명령 주위에 셸이 있어야 합니다. 예를 들어,
strace -f bash -c 'stat /etc/passwd nonexisting 2>/dev/null'
플래그 사용 시 주의하세요 -f
. 명령에 적용된 시스템 호출을 추적하는 데 초점을 맞추는 경우 stat
플래그 없이는 해당 호출을 볼 수 없기 때문입니다 -f
.