저는 티셔츠에 대한 경험이 많지 않기 때문에 이것이 매우 기본적인 것이 아니기를 바랍니다.
답변 중 하나를 확인한 후이 문제이상한 동작이 발생했습니다 tee
.
첫 번째 줄과 찾은 줄을 출력하려면 다음 명령을 사용할 수 있습니다.
ps aux | tee >(head -n1) | grep syslog
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
syslog 806 0.0 0.0 34600 824 ? Sl Sep07 0:00 rsyslogd -c4
그러나 처음으로 이것을 (zsh에서) 실행했을 때 grep 결과 아래에 열 헤더가 있는 결과의 순서가 잘못되었으므로(그러나 이 문제는 다시 발생하지 않았습니다) 명령을 바꿔 보았습니다.
ps aux | tee >(grep syslog) | head -n1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
첫 번째 줄만 인쇄되고 다른 것은 인쇄되지 않습니다! tee를 사용하여 grep으로 리디렉션할 수 있습니까? 아니면 잘못된 방식으로 수행하고 있습니까?
두 번째 명령은 실제로 이 질문을 입력했을 때 한 번 작동했고, 다섯 번 더 실행했는데 한 줄의 결과가 반환되었습니다. 이게 나만의 시스템인가요? (저는 tmux에서 zsh를 실행하고 있습니다).
마지막으로, 첫 번째 명령 "grep syslog"가 결과로 표시되지 않는 이유는 무엇입니까(단 하나의 결과)?
여기서 제어하려면 grep 없이tee
ps aux | grep syslog
syslog 806 0.0 0.0 34600 824 ? Sl Sep07 0:00 rsyslogd -c4
henry 2290 0.0 0.1 95220 3092 ? Ssl Sep07 3:12 /usr/bin/pulseaudio --start --log-target=syslog
henry 15924 0.0 0.0 3128 824 pts/4 S+ 13:44 0:00 grep syslog
고쳐 쓰다: head로 인해 전체 명령이 잘린 것으로 보이며(아래 답변 참조) 이제 다음 명령은 다음을 반환합니다.
ps aux | tee >(grep syslog) | head -n1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
syslog 806
답변1
$ ps aux | tee >(head -n1) | grep syslog
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
syslog 806 0.0 0.0 34600 824 ? Sl Sep07 0:00 rsyslogd -c4
grep
및 명령은 head
거의 같은 시간에 시작되며 둘 다 유휴 상태일 때 동일한 입력 데이터를 받지만 일반적으로 데이터를 사용할 수 있을 때 수신됩니다. 예를 들어 다음과 같은 문제로 인해 "동기화되지 않음" 출력이 발생할 수 있습니다.
다중화된 데이터는
tee
실제로 다른 프로세스보다 먼저 한 프로세스로 전송되며 대부분 구현에 따라 다릅니다tee
. 간단한tee
구현에서는read
일정량의 입력을 받은 다음write
이를 두 번 제공합니다. 한 번은 표준 출력으로, 한 번은 인수로 제공합니다. 이는 이러한 대상 중 하나가 먼저 데이터를 가져옴을 의미합니다.그러나 파이프는 버퍼링됩니다. 이러한 버퍼는 각각 한 줄일 가능성이 높지만 더 클 수도 있습니다. 이로 인해
grep
다른 명령이head
데이터(예: ped 라인)를 수신하기 전에 수신 명령 중 하나가 필요한 모든 출력(예: ped 라인)을 볼 수 있습니다. 모두.그러나 이러한 명령 중 하나가 데이터를 수신하지만 시간 내에 아무 작업도 수행할 수 없으며 다른 명령이 더 많은 데이터를 수신하여 신속하게 처리할 수도 있습니다.
예를 들어, 데이터가 한 번에 한 행씩 전송되더라도
head
어떻게 해야 할지 알 수 없는 경우(또는 커널 스케줄링으로 인해 지연되는 경우) 기회가 생기기 전에 결과가 표시될 수 있습니다. 시연하려면 지연을 추가해 보십시오. 이렇게 하면 거의 확실하게 출력이 먼저 인쇄됩니다.grep
head
grep
head
ps aux | tee >(sleep 1; head -n1) | grep syslog
grep
$ ps aux | tee >(grep syslog) | head -n1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
head
나는 입력의 첫 번째 줄이 수신되고 표준 입력이 닫히고 종료되기 때문에 여기서는 일반적으로 한 줄만 얻는다고 생각합니다. tee
stdout이 닫힌 것을 확인하면 자체 stdin(의 출력 ) 을 닫고 ps
종료됩니다. 이는 구현에 따라 달라질 수 있습니다.
실제로 ps
전송되는 유일한 데이터는 첫 번째 줄(물론 제어되기 때문에)이고 head
표준 입력 설명자 앞뒤의 다른 줄일 수도 있습니다.head
tee
두 번째 줄에 나타나는 불일치는 타이밍에 의해 발생합니다. head
stdin은 닫혀 있지만 ps
데이터는 계속 전송됩니다. 두 이벤트가 제대로 동기화되지 않았으므로 포함된 행이 여전히 매개변수( 명령) syslog
가 될 가능성이 있습니다 . 이는 위의 설명과 유사합니다.tee
grep
stdin/exit를 닫기 전에 모든 입력을 기다리는 명령을 사용하면 이 문제를 완전히 피할 수 있습니다. 예를 들어 awk
대신 을 사용 head
하면 모든 행을 읽고 처리합니다(출력이 발생하지 않더라도).
ps aux | tee >(grep syslog) | awk 'NR == 1'
그러나 위에서 언급한 것처럼 행이 여전히 순서 없이 나타날 수 있으며 이는 다음을 통해 확인할 수 있습니다.
ps aux | tee >(grep syslog) | (sleep 1; awk 'NR == 1')
너무 자세한 내용은 아니길 바라지만, 동시에 서로 상호작용하는 많은 일들이 일어나고 있습니다. 별도의 프로세스는 동기화 없이 동시에 실행되므로 특정 실행에 대한 작업이 다를 수 있습니다. 때로는 기본 프로세스를 자세히 살펴보고 그 이유를 설명하는 데 도움이 됩니다.
답변2
grep syslog
시기에 따라 다르기 때문에 항상 표시되는 것은 아닙니다. 셸 파이프를 사용하면 거의 동시에 명령을 실행합니다. 하지만 여기서 핵심은 "거의"라는 단어입니다. grep을 시작하기 전에 모든 프로세스에 대한 검사가 완료 되면 ps
목록에 나타나지 않습니다. 시스템 부하 등에 따라 무작위 결과를 얻을 수 있습니다.
티셔츠에서도 비슷한 일이 일어납니다. 서브셸의 백그라운드에서 실행되며 grep 전후에 트리거될 수 있습니다. 이것이 출력 순서가 일관되지 않는 이유입니다.
티 문제는 이상하게 작동합니다. 이는 일반적인 방법으로 사용되지 않기 때문입니다. 이는 인수 없이 실행됩니다. 즉, 표준 입력에서 표준 출력으로 데이터를 복사해야 함을 의미합니다. 그러나 표준 출력은 헤더(첫 번째 경우) 또는 grep(두 번째 경우)을 실행하는 서브셸로 리디렉션됩니다. 그러나 다음 명령에도 파이프됩니다. 이 경우 어떤 일이 일어나는지는 실제로 구현에 달려 있다고 생각합니다. 예를 들어, 내 bash 4.2.28에서는 하위 쉘 stdin에 아무 것도 기록되지 않습니다. zsh에서는 시도할 때마다 원하는 방식으로 안정적으로 작동합니다(ps의 첫 번째 줄과 검색된 줄을 인쇄합니다).
답변3
약간 해킹적이지만 여기에 내가 사용하는 쉘 함수 형태의 솔루션이 있습니다 psgrep()
.
헤더 줄을 ps
로 리디렉션 STDERR
한 다음 grep
으로 리디렉션하되, 자체에서 발생하는 "노이즈" 줄을 방지하려면 STDOUT
먼저 grep
명령 자체를 제거하십시오.grep
psgrep() { ps aux | tee >(head -1>&2) | grep -v " grep $@" | grep "$@" -i --color=auto; }