使用命令行redirect进程启动后的STDERR / STDOUT?

在shell中你可以做redirect, > <等等,但是在程序启动后怎么样?

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

closures并重新打开你的tty(即注销和重新打开,这也可能会终止你的后台进程),你只剩下一个select:

  • 使用gdb附加到有问题的进程,然后运行:
    • p dup2(open(“/ dev / null”,0),1)
    • p dup2(open(“/ 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 ; 屏幕提供了多个虚拟TTY,您可以在不必打开新的SSH / Telnet /等会话之间进行切换
  • 使用nohup ; 这使您可以closures并重新打开您的会话,而不会丢失…进程中的任何后台进程。

这将做到:

 strace -ewrite -p $PID 

这不是那么干净(显示行如: write(#,<text you want to see>) ),但工程!


你也可能不喜欢参数被缩写的事实。 要控制使用-s参数来设置显示的string的最大长度。

它捕捉所有的stream,所以你可能想要以某种方式过滤:

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

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

掀起了vladr(和其他人)的优秀研究:

在同一目录中创build以下两个文件,path中的内容为$ 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 

现在,下一次你忘记redirectfirefox,例如,你的terminal开始变得混乱不可避免的“(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的输出redirect到/ dev / null。

将正在运行的进程的输出redirect到另一个terminal,文件或屏幕:

 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 

bashterminal上分离正在运行的进程并保持活动:

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

说明:

20818 – 只是运行进程pid的一个例子
gdb命令的打印结果
closures(1) – closures标准输出
/ dev / pts / 4 – terminal写入
closures(2) – closures错误输出
/ tmp / myerrlog – 要写入的文件
q – 退出gdb
bg%1 – 在后台运行停止的作业1
拒绝%1 – 从terminal卸下工作1

不是你的问题的直接答案,但这是一个我在过去几天发现有用的技术:使用“屏幕”运行初始命令,然后分离。

这是bash脚本部分根据以前的答案,它是在一个打开的进程执行期间redirect日志文件,它被用作logrotate进程中的postscript

 #!/bin/bash pid=$(cat /var/run/app/app.pid) logFile="/var/log/app.log" reloadLog() { getStatus if [ "$pid" = "" ]; then showStatus 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