使用命令行重定向进程启动后的STDERR / STDOUT?

时间:2009-02-27 06:26:25

标签: linux bash shell

在shell中你可以进行重定向,> <等等,但程序启动后怎么样?

以下是我如何提出这个问题,在终端后台运行的程序不断输出恼人的文字。这是一个重要的过程,所以我必须打开另一个shell来避免文本。我希望能够>/dev/null或其他一些重定向,这样我就可以继续在同一个shell中工作。

8 个答案:

答案 0 :(得分:111)

如果没有关闭并重新打开您的tty(即注销和重新开启,这也可能会终止您在此过程中的一些后台进程),您只剩下一个选择:

  • 使用gdb附加到相关进程,然后运行:
    • p dup2(open(“/ dev / null”,0),1)
    • p dup2(open(“/ dev / null”,0),2)
    • 分离
    • 退出

e.g:

$ 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; screen提供了几个虚拟TTY,您无需打开新的SSH / telnet / etc会话
  • 即可切换
  • 使用nohup;这允许您关闭并重新打开会话,而不会丢失...过程中的任何后台进程。

答案 1 :(得分:56)

这样做:

strace -ewrite -p $PID

它不是那么干净(显示像write(#,<text you want to see>)这样的行),但有效!


您可能也不喜欢参数缩写的事实。要控制它,请使用-s参数设置显示的字符串的最大长度。

它会捕获所有流,因此您可能希望以某种方式过滤:

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

仅显示描述符1调用。 2>&1是将STDERR重定向到STDOUT,因为strace默认写入STDERR。

答案 2 :(得分:18)

对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,例如,你的终端开始变得混乱不可避免的“(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 :(得分:15)

将正在运行的进程的输出重定向到另一个终端,文件或屏幕:

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 - 要写入的终端 close(2) - 关闭错误输出
/ tmp / myerrlog - 要写入的文件 q - 退出gdb
bg%1 - 在背景上运行停止作业1 disown%1 - 从终端分离作业1

答案 4 :(得分:3)

不能直接回答你的问题,但这是我过去几天发现有用的技巧:使用'screen'运行初始命令,然后分离。

答案 5 :(得分:2)

这是基于先前答案的bash脚本部分,它在执行打开过程期间重定向日志文件,在 logrotate 过程中用作postscript

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

答案 6 :(得分:1)

  

Dupx 是一个简单的* nix实用程序,用于重定向已经运行的进程的标准输出/输入/错误。

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

答案 7 :(得分:0)

您可以使用重定向(https://github.com/jerome-pouiller/reredirect/)。

类型

reredirect -m FILE PID

和输出(标准和错误)将写入FILE。

重定向自述文件还说明了如何还原进程的原始状态,如何重定向到另一个命令或仅重定向stdout或stderr。

reredirect还提供了一个名为relink的脚本,该脚本允许重定向到当前终端:

relink PID
relink PID | grep usefull_content

(重定向似乎与另一个答案中描述的Dupx具有相同的功能,但是,它不依赖于Gdb)。