如何重定向已经运行的进程的输出

通常我会启动一个命令,比如

longcommand &;

我知道你可以重新定向,比如

longcommand > /dev/null;

例如,去掉输出或

longcommand 2>&1 > output.log

来捕捉输出。

但是我有时候会忘记,并且想知道是否有一种方法可以在事后捕捉或者重定向。

longcommand
ctrl-z
bg 2>&1 > /dev/null

或者类似的东西,这样我就可以继续使用终端而不会在终端上弹出消息。

135135 次浏览

参见 重定向正在运行的进程的输出

首先,我在一个会话中运行命令 cat > foo1,并测试来自 stdin 的数据是否被复制到文件中。然后在另一个会话中重定向输出。

首先找出过程的 PID:

$ ps aux | grep cat
rjc 6760 0.0 0.0 1580 376 pts/5 S+ 15:31 0:00 cat

现在检查它打开的文件句柄:

$ ls -l /proc/6760/fd
total 3
lrwx—— 1 rjc rjc 64 Feb 27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 Feb 27 15:32 1 -> /tmp/foo1
lrwx—— 1 rjc rjc 64 Feb 27 15:32 2 -> /dev/pts/5

现在运行 GDB:

$ gdb -p 6760 /bin/cat
GNU gdb 6.4.90-debian


[license stuff snipped]


Attaching to program: /bin/cat, process 6760


[snip other stuff that's not interesting now]


(gdb) p close(1)
$1 = 0
(gdb) p creat("/tmp/foo3", 0600)
$2 = 1
(gdb) q
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: /bin/cat, process 6760

GDB 中的 p命令将打印一个表达式的值,一个表达式可以是一个要调用的函数,也可以是一个系统调用... 所以我执行一个 close()系统调用并传递文件句柄1,然后执行一个 creat()系统调用来打开一个新文件。creat()的结果是1,这意味着它替换了以前的文件句柄。如果我想为 stdout 和 stderr 使用相同的文件,或者如果我想用其他号码替换文件句柄,那么我需要调用 dup2()系统调用来实现这个结果。

对于这个示例,我选择使用 creat()而不是 open(),因为参数较少。用于标志的 C 宏不能从 GDB 中使用(它不使用 C 头文件) ,所以我必须读取头文件才能发现这一点——这并不难,但需要更多的时间。注意,0600是拥有读/写访问权限的所有者以及组和其他没有访问权限的八进制权限。它还可以对该参数使用0,并在以后的文件中运行 chmod。

之后我验证了结果:

ls -l /proc/6760/fd/
total 3
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 0 -> /dev/pts/5
l-wx—— 1 rjc rjc 64 2008-02-27 15:32 1 -> /tmp/foo3 <====
lrwx—— 1 rjc rjc 64 2008-02-27 15:32 2 -> /dev/pts/5

cat中键入更多数据将导致文件 /tmp/foo3被追加到。

如果要关闭原始会话,则需要关闭该会话的所有文件句柄,打开一个可以作为控制 tty 的新设备,然后调用 setsid()

Dupx

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

动机

我经常遇到这样的情况: 通过 SSH 在远程系统上启动一个进程所需的时间比我预期的要长得多。我需要断开 SSH 连接,但是如果我这样做,如果进程试图在断开的管道的 stdout/error 上写入一些内容,那么进程就会死亡。我希望可以使用 ^ Z 暂停该过程,然后执行

bg %1 >/tmp/stdout 2>/tmp/stderr

不幸的是,这不会工作(在我知道的 shell 中)。

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

我在网上搜集了一些信息,编写了一个不需要外部工具的脚本: 看看我的反应,希望对大家有所帮助。

您也可以使用 reredirect(https://github.com/jerome-pouiller/reredirect/)进行此操作。

下面的命令将过程 PID的输出(标准和错误)重定向到 FILE:

reredirect -m FILE PID

reredirectREADME还解释了其他有趣的特性: 如何恢复进程的原始状态,如何重定向到另一个命令,或者仅重定向 stdout 或 stderr。

该工具还提供 relink脚本,该脚本允许将输出重定向到当前终端:

relink PID
relink PID | grep usefull_content

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

屏幕

如果进程在 screen 会话中运行,可以使用 screen 的 log 命令将该窗口的输出记录到文件中:

切换到脚本窗口,C-a H记录日志。
现在你可以:

$ tail -f screenlog.2 | grep whatever

来自 screen 的手册页:

登录[注销]

开始/停止将当前窗口的输出写入窗口默认目录中的文件“ screen log.n”,其中 n 是当前窗口的编号。可以使用“ logfile”命令更改此文件名。如果没有给出参数,则切换日志记录的状态。如果会话日志已经存在,则会将其追加到文件的前一个内容。会话日志中不包括回滚历史记录的当前内容和内容。默认是“关闭”。

我相信 Tmux 也有类似的东西。