명령 행을 사용하여 시작된 후 프로세스의 STDERR / STDOUT을 리디렉션 하시겠습니까?


127

쉘에서 리디렉션 > <등을 수행 할 수 있지만 프로그램을 시작한 후에는 어떻습니까?

다음은이 질문을하는 방법입니다. 터미널 백그라운드에서 실행되는 프로그램은 계속 성가신 텍스트를 출력합니다. 중요한 과정이므로 텍스트를 피하기 위해 다른 쉘을 열어야합니다. 할 수 있기를 원합니다>/dev/null같은 쉘에서 계속 작업 할 수 있도록 다른 리디렉션이나 다른 리디렉션 .


STDOUT / STDERR을 리디렉션하는 가장 쉬운 방법은 포크 전에 파일 설명자를 DUP2하는 것입니다. 이것은 상당히 표준적인 관행이며, 아마도 쉘이 지금 성취하는 방식 일 것입니다. 그 대답이 있는지 확실하지 않지만 좋은 답변이 될 가능성이 줄어 듭니다.
Stefan Mai

답변:


124

tty를 닫았다가 다시 열지 못하는 경우 (즉, 로그 오프했다가 다시 로그온하면 프로세스의 일부 백그라운드 프로세스가 종료 될 수 있음) 한 가지만 선택할 수 있습니다.

  • gdb를 사용하여 해당 프로세스에 연결하고 다음을 실행하십시오.
    • p dup2 (열기 ( "/ dev / null", 0), 1)
    • p dup2 (열기 ( "/ dev / null", 0), 2)
    • 떼다
    • 떠나다

예 :

$ tail -f /var/log/lastlog &
[1] 5636

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/pts/0
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog

$ gdb -p 5636
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Attaching to process 5636
Reading symbols from /usr/bin/tail...(no debugging symbols found)...done.
Reading symbols from /lib/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib/librt.so.1
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
[New Thread 0x7f3c8f5a66e0 (LWP 5636)]
Loaded symbols for /lib/libpthread.so.0
Reading symbols from /lib/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2

(no debugging symbols found)
0x00007f3c8eec7b50 in nanosleep () from /lib/libc.so.6

(gdb) p dup2(open("/dev/null",0),1)
[Switching to Thread 0x7f3c8f5a66e0 (LWP 5636)]
$1 = 1

(gdb) p dup2(open("/dev/null",0),2)
$2 = 2

(gdb) detach
Detaching from program: /usr/bin/tail, process 5636

(gdb) quit

$ ls -l /proc/5636/fd
total 0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 0 -> /dev/pts/0
lrwx------ 1 myuser myuser 64 Feb 27 07:36 1 -> /dev/null
lrwx------ 1 myuser myuser 64 Feb 27 07:36 2 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 3 -> /var/log/lastlog
lr-x------ 1 myuser myuser 64 Feb 27 07:36 4 -> /dev/null
lr-x------ 1 myuser myuser 64 Feb 27 07:36 5 -> /dev/null

다음을 고려할 수도 있습니다.

  • 사용하여 screen; 화면은 새로운 SSH / telnet / etc, 세션을 열지 않고도 전환 할 수있는 여러 가상 TTY를 제공합니다.
  • 사용하여 nohup; 이를 통해 프로세스의 백그라운드 프로세스를 잃지 않고 세션을 닫았다가 다시 열 수 있습니다.

1
gdb 응답은 tail -f 파일에서 작동하지 않았으며 gcc -ggdb로 컴파일 된 c의 테스트 프로그램에서는 작동하지 않았습니다. 또한 cont를 사용하면 더 많은 gdb 명령을 실행할 수 없으므로 명령이 분리 된 다음 종료됩니다.
Ian Kelling

분리에 대한 올바른, 오전 2시입니다. :) gdb 솔루션에서 정확히 작동하지 않은 것은 무엇입니까?
vladr 2012

12
stdout / stderr를 / dev / null 이외의 것으로 리디렉션하는 경우 쓰기 권한으로 파일을 열어야합니다- open("/path/to/new/stdout",O_WRONLY). 그러나 O_WRONLY는 아마도 사용할 수 없을 것입니다. 그 가치는 1Linux / glibc에 있습니다.
Jander

13
주의 사항 : gdb에서 프로세스에 연결하면 프로세스가 분리 될 때까지 프로세스가 일시 중지됩니다.
Marty B

1
사용 @Jander의 코멘트에 추가 1025을 활성화을 O_APPEND뿐만 아니라 O_WRONLY같은 파일에 모두 표준 에러와 표준 출력을 리디렉션하면 편리합니다.
스펙트럼

57

이것은 할 것이다 :

strace -ewrite -p $PID

그것은 깨끗하지는 않지만 (와 같은 줄을 보여줍니다 write(#,<text you want to see>)) 작동합니다!


또한 인수가 생략된다는 사실을 싫어할 수도 있습니다. 그것을 사용하여 제어하려면-s표시되는 최대 문자열 길이를 설정 매개 변수 .

모든 스트림을 포착하므로 어떻게 든 필터링 할 수 있습니다.

strace -ewrite -p $PID 2>&1 | grep "write(1" 

설명자 1 호출 만 표시합니다. STDERR에 기본적 2>&1으로 strace쓰듯이 STDERR 을 STDOUT으로 리디렉션 하는 것입니다.


6
이것은 OP가 요구 한 것이 아닙니다. OP는 가로 채지 말고 TTY에서 벗어나도록 요청했습니다. 또한 일부 플랫폼에서 strace / truss는 인터셉트 된 스트림 문자 사이에 공백을 삽입하거나 비 ASCII를 이스케이프 처리하므로 해당 문자도 처리해야합니다.
vladr

4
예, 이것은 부분적으로하는 일이지만 일부 사람들은이 질문을 읽는 것이 프로그램에서 실수로 null 또는 다른 콘솔에 쓰려고 실행되는 것을 확인하기 위해 필요한 전부입니다. 나는 프로세스 에서이 질문을 찾은 후에 그것을 발견했고 그것이 좋은 해킹이라고 생각했습니다 (적어도 나를 위해). 그리고 내 눈이 나를
속이지

sudo필요할 수도 있습니다 .
colidyre 2014 년

21

vladr (및 다른 사람들)의 훌륭한 연구를 수행 :

동일한 디렉토리에 다음 두 파일을 작성하십시오 (예 : $ HOME / bin).

silence.gdb, (vladr의 답변에서) :


p dup2(open("/dev/null",0),1)
p dup2(open("/dev/null",0),2)
detach
quit

그리고 침묵 :


#!/bin/sh
if [ "$0" -a "$1" ]; then
 gdb -p $1 -x $0.gdb
else
 echo Must specify PID of process to silence >&2
fi

chmod +x ~/bin/silence  # make the script executable

이제 다음에 파이어 폭스를 리디렉션하는 것을 잊어 버렸을 때 터미널은 피할 수없는 "(firefox-bin : 5117) : Gdk-WARNING ** : XID 충돌, 문제가 발생했습니다"라는 메시지로 인해 혼란스럽게 시작합니다.


ps  # look for process xulrunner-stub (in this case we saw the PID in the error above)
silence 5117  # run the script, using PID we found

보고 싶지 않은 경우 gdb의 출력을 / dev / null로 리디렉션 할 수도 있습니다.


3
내 gdb (v7.2)에는 --batch-silent출력을 억제하고 무언가 잘못되었을 때 (예 : 프로세스 누락) gdb 콘솔에 덤프하지 않는 편리한 옵션 이 있습니다. BTW $!는 가장 최근의 백그라운드 작업을 말하지만 스크립트 자체에서 사용할 수 있다고 생각하지 않습니다. 나는 별칭을 사용한다 : alias silencebg='silence $!'
seanf

18

실행중인 프로세스에서 다른 터미널, 파일 또는 화면으로 출력을 리디렉션하십시오.

tty
ls -l /proc/20818/fd
gdb -p 20818

내부 gdb :

p close(1)
p open("/dev/pts/4", 1)
p close(2)
p open("/tmp/myerrlog", 1)
q

bash 터미널 에서 실행중인 프로세스를 분리하고 활성 상태로 유지하십시오.

[Ctrl+z]
bg %1 && disown %1
[Ctrl+d]

설명:

20818-프로세스 pid
p 실행 예-gdb 명령의 인쇄 결과
close (1)-표준 출력 닫기
/ dev / pts / 4-
닫기 에 쓸 터미널 (2)-닫기 오류 출력
/ tmp / myerrlog-파일
q에 쓰기 -종료 gdb
bg % 1-백그라운드 제거 % 1에서 중지 된 작업 1 실행
-터미널에서 작업 1 분리


2
stdin(file descriptor 0)가 닫히면 작동하지 않습니다 .
pabouk

이것은 나의 하루를 구했다. 처음 10 % 동안 1 시간 동안 ssl-session에서 실행중인 제품을 만들었고 실제로 10 시간 동안 랩톱을 계속 실행하고 싶지 않았습니다. 하지만 stderr에 대한 리디렉션을 읽어야한다고 가정 p open("/tmp/myerrlog", 2)합니까?
GerardV

CentOS 6에서 실행시 매우 작은 문제가 발생했습니다. "/ tmp / myerrlog"파일이 이미 존재해야합니다. 물론 터치로 만드는 것은 사소한 일이었습니다.
ebneter

3

귀하의 질문에 대한 직접적인 대답은 아니지만 지난 며칠 동안 유용하다고 생각한 기술입니다. 'screen'을 사용하여 초기 명령을 실행 한 다음 분리하십시오.


2

이것은 오픈 프로세스 실행 중 로그 파일을 리디렉션하는 이전 답변을 기반으로하는 bash 스크립트 부분이며 logrotate프로세스 에서 포스트 스크립트로 사용됩니다

#!/bin/bash

pid=$(cat /var/run/app/app.pid)
logFile="/var/log/app.log"

reloadLog()
{
    if [ "$pid" = "" ]; then
        echo "invalid PID"
    else
        gdb -p $pid >/dev/null 2>&1 <<LOADLOG
p close(1)
p open("$logFile", 1)
p close(2)
p open("$logFile", 1)
q
LOADLOG
        LOG_FILE=$(ls /proc/${pid}/fd -l | fgrep " 1 -> " | awk '{print $11}')
        echo "log file set to $LOG_FILE"
    fi
}

reloadLog


0

reredirect ( https://github.com/jerome-pouiller/reredirect/ )를 사용할 수 있습니다 .

유형

reredirect -m FILE PID

출력 (표준 및 오류)이 FILE에 기록됩니다.

reredirect README는 원래 프로세스 상태를 복원하는 방법, 다른 명령으로 리디렉션하거나 stdout 또는 stderr 만 리디렉션하는 방법도 설명합니다.

reredirect또한 relink현재 터미널로 리디렉션 할 수 있는 스크립트를 제공하십시오 .

relink PID
relink PID | grep usefull_content

(리디렉션은 다른 답변에서 설명한 Dupx과 동일한 기능을 가진 것으로 보이지만 Gdb에 의존하지 않습니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.