通常我会开始像
这样的命令longcommand &;
我知道您可以通过执行类似
的操作来重定向它longcommand > /dev/null;
例如摆脱输出或
longcommand 2>&1 > output.log
捕获输出。
但我有时会忘记,并且想知道是否有办法在事后捕获或重定向。
longcommand
ctrl-z
bg 2>&1 > /dev/null
或类似的东西,所以我可以继续使用终端而不会在终端上弹出消息。
答案 0 :(得分:118)
请参阅 Redirecting Output from a Running Process 。
首先,我在一个会话中运行命令
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()
。
答案 1 :(得分:16)
您也可以使用重新定向(https://github.com/jerome-pouiller/reredirect/)来完成此操作。
类型
reredirect -m FILE PID
和输出(标准和错误)将写入文件。
reredirect README还解释了如何恢复原始进程状态,如何重定向到另一个命令或仅重定向stdout或stderr。
(reredirect似乎具有与Dupx在另一个答案中描述的相同的功能,但它不依赖于Gdb)。
答案 2 :(得分:13)
Dupx
Dupx是一个简单的* nix实用程序,用于重定向已经运行的进程的标准输出/输入/错误。
动机
我经常发现自己处于这样一种情况,即我通过SSH在远程系统上启动的进程所花费的时间比我预期的要长得多。我需要打破SSH连接,但如果我这样做,如果它试图在stdout上写一些东西/破坏管道的错误,那么进程就会死掉。我希望我可以用^ Z暂停这个过程,然后再做一个
bg %1 >/tmp/stdout 2>/tmp/stderr
不幸的是,这不起作用(在我知道的炮弹中)。
答案 3 :(得分:7)
<强>屏幕强>
如果进程在屏幕会话中运行,您可以使用screen的log命令将该窗口的输出记录到文件中:
切换到脚本窗口, C-a H 进行记录。
现在你可以:
$ tail -f screenlog.2 | grep whatever
从屏幕的手册页:
log [on | off]
启动/停止将当前窗口的输出写入窗口默认目录中的文件“screenlog.n”,其中n是当前窗口的编号。可以使用'logfile'命令更改此文件名。如果未给出参数,则切换日志记录的状态。会话日志将附加到文件的先前内容(如果已存在)。回滚历史记录的当前内容和内容不包括在会话日志中。默认为“关闭”。
我确信tmux也有类似的东西。
答案 4 :(得分:0)
我在互联网上收集了一些信息,并准备了不需要外部工具的脚本:See my response here。希望它有用。