/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.txt
stdout이 항상 기록된다면 큰 문제가 생길 것입니다. 프로세스 자체를 중지하지 않고 로깅 또는 로깅 중지 시기를 제어할 수 있다면 cmd
가장 좋을 것입니다 .
tmp
그렇다면 stdout을 리소스 집약적이지 않은 일부 파일 시스템으로 리디렉션하고 필요할 때 stdout을 검색할 수 있습니까 ?
답변1
이렇게 하면 cmd > /dev/null
쉘은 새 하위 프로세스에서 fd 1을 열고 /dev/null
이를 실행합니다 cmd
.
cmd
fd가 무엇에 열려 있는지에 관계없이 stdout(또는 , 또는 write(1, "output"...)
와 같은 다른 쓰기 시스템 호출)에 데이터를 쓰는 작업을 수행합니다 .send
sendmsg
pwrite
Linux에서는 fd 1 파일이 열리는 매직 /proc/$pid_of_cmd/fd/1
심볼릭 링크만 있으므로 ./dev/null
tail -f that
tail -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
.
그러면 cmd
stdout은 파이프가 되고 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/file
to 대신 에 쓰기 시작합니다 /dev/null
.
명령이 많이 기록하면 심각한 성능 저하가 발생할 수 있습니다.