나는 종종 다음과 같은 간단한 명령 때문에 좌절감을 느낍니다.
find / | fgrep somestuff.ext
사용하지 않을 때 sudo
권한이 거부된 줄이 계속해서 나타납니다. 이는 공평하지만 grep이 파이프에서 읽을 때 이 출력이 무시되지 않는 이유는 무엇입니까?
이 형식의 출력이 파이프로 전달되는 대신 터미널 창으로 직접 전송되고(이런 일이 발생했을 것으로 의심됨) 이후에 grep에 의해 무시되는 이유는 무엇입니까? cat에 의해 동일한 행이 생성되는 반면(권한 거부 메시지가 저장되어 있다고 가정) text) 파일)이 파이프에 올바르게 들어가고 내 grep 패턴에서 무시됩니까?
STDIN/STDOUT 프로세스에 내가 이해하지 못하는 뭔가가 있는 것 같습니다.
답변1
권한 거부 메시지는 stdout이 아닌 find
stderr로 전송됩니다. 전체 stderr를 비트 버킷으로 리디렉션할 수 있습니다.
find 2>/dev/null | fgrep somestuff.ext
또한 특정 파일을 찾으려면 grep이 필요하지 않습니다.
find . -name somestuff.ext
여전히 신청할 수 있습니다 2>/dev/null
.
권한 거부 메시지만 표시하지 않으려면 다음을 사용할 수 있습니다.
2> >(grep -v 'Permission denied' >&2)
배쉬에서.
답변2
choroba의 좋은 답변이 문제를 해결하는 동안 발견한 동작의 이유는 bash의 기본 파이프 동작입니다(그리고 대부분의 쉘에서도 상상합니다).
파이프라인 섹션에서 언급한 대로 man bash
:
명령의 표준 출력은 명령2의 표준 입력으로 파이프됩니다. 이 연결은 명령으로 지정된 리디렉션 전에 수행됩니다(아래 리디렉션 참조).
이는 stderr 링크가 기본적 stderr
으로 파이프를 통해 공급되지 않고 기본 stderr 링크인 tty로 구동된다는 것을 의미합니다 .command1
command2
Bash 매뉴얼에는 다음과 같이 나와 있습니다.
|&를 사용하면 명령의 표준 오류가 표준 출력 외에도 command2의 표준 입력으로 파이프됩니다. 이는 2>&1 |의 약어입니다.
따라서 귀하의 경우 grep 명령으로 파이프하려면 기본적으로 /dev/stderr
전송되는 find 명령 오류는 다음 두 가지 형식 중 하나여야 합니다.
find / |& fgrep somestuff.ext
find / 2>&1 | fgrep somestuff.ext
질문 제목은 "파이프가 표준 오류를 무시하는 이유"일 수도 있습니다.
대답은 bash와 Linux가 stdout
기본적으로 이를 다르게 처리하여 stderr
사용자가 두 출력을 다르게 기록/처리할 수 있기 때문입니다.
예를 들어 stdout
명령 1을 stdin
명령 2 로 파이프하고 stderr
.을 사용하여 명령 1을 로그 파일로 보낼 수 있습니다 2>errorlog.txt
.
실제로 다음과 같이 리디렉션을 지정하지 않고 명령을 실행하면
find /
그것은 동등하다
find / 1>/dev/stdout 2>/dev/stderr
최종 해결책은 다음과 같습니다.
find / 1>/dev/tty1 2>/dev/tty1 #assuming that you are logged in tty1
단일 검증이 가능합니다 ls
:
ls -all /dev/st*
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Nov 25 15:36 /dev/stdout -> /proc/self/fd/1
ls -all /proc/self/fd/2
lrwx------ 1 root root 64 Nov 28 02:46 /proc/self/fd/2 -> /dev/tty1
ls -all /proc/self/fd/1
lrwx------ 1 root root 64 Nov 28 02:46 /proc/self/fd/1 -> /dev/tty1
어떤 이유로든 stdout
명령을 "결합"하려면 (파이프의 경우) 또는 (모든 종류의 출력 리디렉션의 경우) 사용 목적을 stderr
명시적으로 선언해야 합니다.bash
|&
2>&1