[bash] stdout이 아닌 stderr를 파이프하는 방법은 무엇입니까?

나는에 정보를 기록하는 프로그램이 stdout과를 stderr, 그리고에 내가 필요로 grep무엇에오고 통해 표준 에러 무시하면서, 표준 출력을 .

물론 2 단계로 수행 할 수 있습니다.

command > /dev/null 2> temp.file
grep 'something' temp.file

하지만 임시 파일 없이이 작업을 수행하는 것을 선호합니다. 똑똑한 파이핑 트릭이 있습니까?



답변

먼저 stderr을 stdout (파이프)으로 리디렉션합니다. 그런 다음 stdout을 /dev/null(stderr의 위치를 ​​변경하지 않고) 리디렉션하십시오 .

command 2>&1 >/dev/null | grep 'something'

모든 종류의 I / O 리디렉션에 대한 자세한 내용은 Bash 참조 매뉴얼의 리디렉션 에 대한 장을 참조하십시오 .

I / O 리디렉션 시퀀스는 왼쪽에서 오른쪽으로 해석되지만 파이프는 I / O 리디렉션이 해석되기 전에 설정됩니다. 1 및 2와 같은 파일 디스크립터는 열린 파일 설명을 참조합니다. 이 조작 2>&1은 파일 디스크립터 2 (일명 stderr)가 파일 디스크립터 1 (일명 stdout이 현재 참조 dup2()하고 있음 open()) 과 동일한 열린 파일 설명을 참조하게합니다 . 동작은 >/dev/null다음을위한 오픈 파일 설명을 참조하도록 파일 기술자 1을 변경 /dev/null,하지만 파일 기술자 (2)는 파일 기술자 1 원래 가리키는 된 열린 파일 설명을 참조한다는 사실은 변경되지 않습니다 – 즉, 파이프.


답변

또는 표준 오류의 출력과 표준 출력을 바꾸려면 다음을 사용하십시오.

command 3>&1 1>&2 2>&3

새 파일 디스크립터 (3)를 작성하여 1 (표준 출력)과 동일한 위치에 지정한 다음 fd 1 (표준 출력)을 fd 2 (표준 오류)와 동일한 위치에 지정하고 마지막으로 fd 2 (표준 오류)를 지정합니다 fd 3 (표준 출력)과 같은 곳에

표준 오류는 이제 표준 출력으로 제공되며 이전 표준 출력은 표준 오류로 유지됩니다. 이것은 과잉 일 수 있지만 Bash 파일 설명자에 대한 자세한 내용을 제공하기를 바랍니다 (각 프로세스마다 9 가지 사용 가능).


답변

Bash에서는 프로세스 대체를 사용하여 서브 쉘로 리디렉션 할 수도 있습니다 .

command > >(stdlog pipe)  2> >(stderr pipe)

당면한 경우 :

command 2> >(grep 'something') >/dev/null


답변

다음과 같은 경우 최선의 답변을 결합하십시오.

command 2> >(grep -v something 1>&2)

… 그런 다음 모든 stdout은 stdout으로 유지 되고 모든 stderr은 stderr로 유지되지만 stderr에는 “something”이라는 문자열이 포함 된 줄이 표시되지 않습니다.

이것은 stdout과 stderr를 되돌 리거나 버리지 않고 함께 밀거나 임시 파일을 사용하지 않는 독특한 이점이 있습니다.


답변

“리디렉션”및 “파이프”로 실제로 진행되는 작업에 대해 생각하면 사물을 시각화하는 것이 훨씬 쉽습니다. bash의 경로 재 지정 및 파이프는 한 가지 작업을 수행합니다. 프로세스 파일 디스크립터 0, 1 및 2가 가리키는 위치를 수정하십시오 (/ proc / [pid] / fd / * 참조).

파이프 또는 “|” bash는 fifo를 생성하고 왼쪽 명령의 FD 1을이 fifo로 가리키고 오른쪽 명령의 FD 0을 동일한 fifo로 가리 킵니다.

다음으로 각 측면의 리디렉션 연산자 가 왼쪽에서 오른쪽으로 평가 되고 설명자 복제가 발생할 때마다 현재 설정이 사용됩니다. 파이프가 먼저 설정 되었기 때문에 FD1 (왼쪽)과 FD0 (오른쪽)이 이미 원래 있던 것에서 이미 변경되었으므로 이러한 중복이 해당 사실을 반영하기 때문에 중요합니다.

따라서 다음과 같은 내용을 입력하면

command 2>&1 >/dev/null | grep 'something'

다음은 순서대로 수행됩니다.

  1. 파이프 (fifo)가 생성됩니다. “명령 FD1″이이 파이프를 가리 킵니다. “grep FD0″도이 파이프를 가리 킵니다
  2. “명령 FD2″는 “명령 FD1″이 현재 가리키는 곳 (파이프)을 가리 킵니다.
  3. “명령 FD1″은 / dev / null을 가리 킵니다.

따라서 “command”가 FD 2 (stderr)에 쓰는 모든 출력은 파이프로 향하고 반대쪽의 “grep”에 의해 읽 힙니다. “command”가 FD 1 (stdout)에 쓰는 모든 출력은 / dev / null로 이동합니다.

대신 다음을 실행하십시오.

command >/dev/null 2>&1 | grep 'something'

다음과 같은 일이 발생합니다.

  1. 파이프가 작성되고 “명령 FD 1″및 “grep FD 0″이 지시됩니다.
  2. “명령 FD 1″은 / dev / null을 가리 킵니다.
  3. “명령 FD 2″는 FD 1이 현재 가리키는 위치를 가리 킵니다 (/ dev / null)

따라서 “command”의 모든 stdout 및 stderr은 / dev / null로 이동합니다. 파이프에 아무것도 들어 가지 않으므로 화면에 아무 것도 표시하지 않고 “grep”이 닫힙니다.

또한 리디렉션 (파일 설명자)은 읽기 전용 (<), 쓰기 전용 (>) 또는 읽기 / 쓰기 (<>) 일 수 있습니다.

마지막 메모. 프로그램이 FD1 또는 FD2에 무언가를 쓰는지 여부는 전적으로 프로그래머에게 달려 있습니다. 좋은 프로그래밍 방법은 오류 메시지가 FD 2로 가고 일반 출력이 FD 1로 가도록 지시하지만, 둘을 혼합하거나 규칙을 무시하는 조잡한 프로그래밍을 종종 보게 될 것입니다.


답변

Bash를 사용하는 경우 다음을 사용하십시오.

command >/dev/null |& grep "something"

http://www.gnu.org/software/bash/manual/bashref.html#Pipelines


답변

stdout 및 stderr을 파일로 영구적으로 리디렉션하려는 경우 stderr를 grep하고 stdout을 유지하여 tty에 메시지를 쓰십시오.

# save tty-stdout to fd 3
exec 3>&1
# switch stdout and stderr, grep (-v) stderr for nasty messages and append to files
exec 2> >(grep -v "nasty_msg" >> std.err) >> std.out
# goes to the std.out
echo "my first message" >&1
# goes to the std.err
echo "a error message" >&2
# goes nowhere
echo "this nasty_msg won't appear anywhere" >&2
# goes to the tty
echo "a message on the terminal" >&3