Programming

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

procodes 2020. 7. 18. 23:24
반응형

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


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

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


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

You may also consider:

  • using screen; screen provides several virtual TTYs you can switch between without having to open new SSH/telnet/etc, sessions
  • using nohup; this allows you to close and reopen your session without losing any background processes in the... process.

This will do:

strace -ewrite -p $PID

It's not that clean (shows lines like: write(#,<text you want to see>) ), but works!


You might also dislike the fact that arguments are abbreviated. To control that use the -s parameter that sets the maximum length of strings displayed.

It catches all streams, so you might want to filter that somehow:

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

shows only descriptor 1 calls. 2>&1 is to redirect STDERR to STDOUT, as strace writes to STDERR by default.


riffing off vladr's (and others') excellent research:

create the following two files in the same directory, something in your path, say $HOME/bin:

silence.gdb, containing (from vladr's answer):


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

and silence, containing:


#!/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

Now, next time you forget to redirect firefox, for example, and your terminal starts getting cluttered with the inevitable "(firefox-bin:5117): Gdk-WARNING **: XID collision, trouble ahead" messages:


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

You could also redirect gdb's output to /dev/null if you don't want to see it.


Redirect output from a running process to another terminal, file or screen:

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

Inside gdb:

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

Detach a running process from bash terminal and keep it alive:

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

Explanation:

20818 - just an example of running process pid
p - print result of gdb command
close(1) - close standard output
/dev/pts/4 - terminal to write to
close(2) - close error output
/tmp/myerrlog - file to write to
q - quit gdb
bg %1 - run stoped job 1 on background
disown %1 - detach job 1 from terminal


Not a direct answer to your question, but it's a technique I've been finding useful over the last few days: Run the initial command using 'screen', and then detach.


this is bash script part based on previous answers, which redirect log file during execution of an open process, it is used as postscript in logrotate process

#!/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

Dupx is a simple *nix utility to redirect standard output/input/error of an already running process.

https://www.isi.edu/~yuri/dupx/


You can use reredirect (https://github.com/jerome-pouiller/reredirect/).

Type

reredirect -m FILE PID

and outputs (standard and error) will be written in FILE.

reredirect README also explains how to restore original state of process, how to redirect to another command or to redirect only stdout or stderr.

reredirect also provide a script called relink that allows to redirect to current terminal:

relink PID
relink PID | grep usefull_content

(reredirect seems to have same features than Dupx described in another answer but, it does not depends on Gdb).

참고URL : https://stackoverflow.com/questions/593724/redirect-stderr-stdout-of-a-process-after-its-been-started-using-command-lin

반응형