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

Ian*_*ing 120 linux bash shell

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

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

vla*_*adr 119

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

  • 使用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
Run Code Online (Sandbox Code Playgroud)

您还可以考虑:

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

  • 如果你正在重定向stdout/stderr(显然除了/ dev/null之外的任何东西),你需要用write access打开文件 - `open("/ path/to/new/stdout",O_WRONLY)`.但是,O_WRONLY可能无法使用; 它在Linux/glibc上的值是"1". (12认同)
  • 需要注意的是:附加到gdb中的进程会暂停该进程,直到您从中分离为止. (12认同)

nau*_*tur 57

这样做:

strace -ewrite -p $PID
Run Code Online (Sandbox Code Playgroud)

这不是那么干净(显示如下的线条write(#,<text you want to see>)),但有效!


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

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

strace -ewrite -p $PID 2>&1 | grep "write(1" 
Run Code Online (Sandbox Code Playgroud)

仅显示描述符1调用.2>&1是将STDERR重定向到STDOUT,strace默认情况下写入STDERR.

  • 这不是OP所要求的.OP要求重新远离TTY,而不是拦截.此外,在某些平台上,strace/truss将在截获的流字符之间插入空格和/或转义非ASCII,您还必须处理这些处理. (6认同)
  • 是的,这可以部分地解决问题 - 但是对于一些人来说,阅读这个问题就是他们所需要的 - 看看程序中发生了什么错误地写入null或在另一个控制台上.我在发现这个问题后发现了这个问题,并认为这是一个很好的黑客(至少对我而言).如果我的眼睛不解除我的话,很多人会觉得很有帮助;) (4认同)

jco*_*ctx 20

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

在同一目录中创建以下两个文件,路径中的内容,比如说$ HOME/bin:

silence.gdb,包含(来自vladr的回答):


p dup2(open("/dev/null",0),1)
p dup2(open("/dev/null",0),2)
detach
quit
Run Code Online (Sandbox Code Playgroud)

和沉默,包含:


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

chmod +x ~/bin/silence  # make the script executable
Run Code Online (Sandbox Code Playgroud)

现在,下次你忘记重定向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
Run Code Online (Sandbox Code Playgroud)

如果您不想看到它,也可以将gdb的输出重定向到/ dev/null.

  • 我的gdb(v7.2)有一个方便的选项--batch-silent,它抑制输出,并且如果出现问题(例如缺少进程),则不会将您转储到gdb控制台中。顺便说一句,`$!`指的是最新的后台作业,但是我认为它不能在脚本本身中使用。我使用别名:'alias silencebg ='silence $!'` (2认同)

小智 17

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

tty
ls -l /proc/20818/fd
gdb -p 20818
Run Code Online (Sandbox Code Playgroud)

gdb里面:

p close(1)
p open("/dev/pts/4", 1)
p close(2)
p open("/tmp/myerrlog", 1)
q
Run Code Online (Sandbox Code Playgroud)

bash终端分离正在运行的进程并使其保持活动状态:

[Ctrl+z]
bg %1 && disown %1
[Ctrl+d]
Run Code Online (Sandbox Code Playgroud)

说明:

20818 - 只是运行进程pid的一个例子
- gdb命令的打印结果
close(1) - 关闭标准输出
/ dev/pts/4 - 写入
关闭的终端(2) - 关闭错误输出
/ tmp/myerrlog - 文件到写入
q - 退出gdb
bg%1 - 在后台
异步%1 上运行stoped job 1 - 从终端分离作业1

  • 如果关闭“ stdin”(文件描述符“ 0”),则此功能将无效。 (2认同)
  • 这救了我的命。我在 ssl 会话中运行 make,前 10% 需要一个小时,我真的不想让我的笔记本电脑再运行 10 个小时。但是我是否正确地假设您的 stderr 重定向应该读取 `p open("/tmp/myerrlog", 2)` ? (2认同)

Jér*_*ler 5

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

类型

reredirect -m FILE PID
Run Code Online (Sandbox Code Playgroud)

输出(标准和错误)将写入文件中。

reredirect README 还解释了如何恢复进程的原始状态,如何重定向到另一个命令或仅重定向 stdout 或 stderr。

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

relink PID
relink PID | grep useful_content
Run Code Online (Sandbox Code Playgroud)

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