/dev/null로 리디렉션된 std 출력 검색

/dev/null로 리디렉션된 std 출력 검색

/dev/null로 리디렉션된 std 출력을 검색하는 방법이 있습니까? 시도해 보았는데 tail -f /proc/{PID}/fd/1리디렉션을 제외하고는 작동하는 것 같습니다 /dev/null.

tail -f /proc/${cmd_pid}/fd/1

유효 cmd > log.txt하지만 유효하지 않음cmd > /dev/null

- - - - - - 갱신 - - - - - -

사실, log.txtstdout이 항상 기록된다면 큰 문제가 생길 것입니다. 프로세스 자체를 중지하지 않고 로깅 또는 로깅 중지 시기를 제어할 수 있다면 cmd가장 좋을 것입니다 .

tmp그렇다면 stdout을 리소스 집약적이지 않은 일부 파일 시스템으로 리디렉션하고 필요할 때 stdout을 검색할 수 있습니까 ?

답변1

이렇게 하면 cmd > /dev/null쉘은 새 하위 프로세스에서 fd 1을 열고 /dev/null이를 실행합니다 cmd.

cmdfd가 무엇에 열려 있는지에 관계없이 stdout(또는 , 또는 write(1, "output"...)와 같은 다른 쓰기 시스템 호출)에 데이터를 쓰는 작업을 수행합니다 .sendsendmsgpwrite

Linux에서는 fd 1 파일이 열리는 매직 /proc/$pid_of_cmd/fd/1심볼릭 링크만 있으므로 ./dev/nulltail -f thattail -f /dev/null

이러한 write()시스템 호출을 가로채서 strace결과를 디코딩할 수 있습니다.

strace -zqqs99999 -xxa0 -o /dev/stdout -e write -p "$pid" |
   perl -ne 'print chr(hex($_)) for /\\x(..)/g'

또는:

strace -zqqs99999 -xxa0 -o /dev/stdout -e write -p "$pid" |
   perl -ne 'if (/^write\(1,/) {print chr(hex($_)) for /\\x(..)/g}'

write()s에서 stdout(fd 1)에만 적용됩니다 . 또는:

strace -yzqqs99999 -xxa0 -o /dev/stdout -e write -p "$pid" |
   perl -ne 'if (/^\Qwrite(1<\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c>,\E "(.*)"/) {
     print chr(hex($_)) for $1 =~ /\\x(..)/g}'

s에서 stdout(fd 1) 에만 적용 write()되고 stdout이 에서 열려 있는 경우에만 적용됩니다 /dev/null.

출력을 tty 장치가 아닌 다른 장치로 리디렉션하면 perl라인 대신 블록 단위로 버퍼링이 시작되므로 대량으로 몇 KB의 출력만 표시됩니다. $|변수를 다음으로 설정하여 이 버퍼링을 비활성화 할 수 있습니다 1.

strace -zqqs99999 -xxa0 -o /dev/stdout -e write -p "$pid" |
   perl -ne 'BEGIN{$| = 1}
             print chr(hex($_)) for /\\x(..)/g' > file

아니면 그렇게 하는 대신에 cmd > /dev/null그렇게 하십시오 cmd | cat > /dev/null.

그러면 cmdstdout은 파이프가 되고 Linux에서는 /proc/$pid_of_cmd/fd/1명명된 파이프처럼 동작합니다. 그렇게 하면 다음과 같습니다.

kill -s STOP "$pid_of_cat"
cat "/proc/$pid_of_cmd/fd/1"

실제로 파이프를 새 cat명령으로 리디렉션하게 됩니다.

새 파이프를 종료한 경우 cat해당 파이프의 탭을 다시 열려면 다른 파이프( )를 복원해야 합니다 kill -s CONT "$pid_of_cat"./dev/null

프로세스의 표준 출력 위치를 실제로 변경하려면 디버거를 연결할 수 있습니다.

gdb --pid "$pid_of_cmd"

그런 다음 gdb에서:

call close(1)
p open("/path/to/some/file", 0x241, 0600)
detach

(0x241은 O_WRONLY|O_TRUNC|O_CREAT를 의미합니다)

open()fd 1이 반환되는지 확인하십시오 . 그렇지 않은 경우 몇 번의 통화 dup2()와 추가 가 필요할 수 있습니다 close().

답변2

아니요, 파일 핸들을 변경할 수 없습니다.

그러면 stdout을 리소스 집약적이지 않은 일부 tmp 파일 시스템으로 리디렉션하고 필요할 때 stdout을 검색할 수 있습니까?

아니요, 데이터를 저장하지 않으면 데이터를 저장할 수 없습니다.어딘가에.

누군가가 순환 버퍼를 작성했을 수도 있습니다. 이를 통해 마지막 100,000개의 데이터를 볼 수 있습니다. 또는 프로그램이 일반적으로 헤드 없이 실행되는 경우 출력을 화면으로 보내고 를 통해 실행할 수 있습니다 screen.

답변3

검색하지 않으면 stdout이 삭제될 수 있으며, 검색을 시작하면 stdout이 로그 파일로 리디렉션될 수 있습니다.

이는 다음과 같이 출력을 쉘 스크립트로 파이프하여 수행할 수 있습니다.

#! /bin/sh
# a-script.sh
while IFS= read -d input
do
  printf "%s\n" input >> /some/file
done 

특히 각 반복에서 출력 파일을 다시 열기 위해 리디렉션이 루프 내에서 수행됩니다. 그런 다음 시작하십시오.

ln -s /dev/null /some/file
cmd | a-script.sh

그런 다음 로그를 원할 때:

ln -sf /some/log/file /some/file

루프의 다음 반복은 /some/log/fileto 대신 에 쓰기 시작합니다 /dev/null.

명령이 많이 기록하면 심각한 성능 저하가 발생할 수 있습니다.

관련 정보