通常我会像这样开始一个命令:
longcommand &;
我知道你可以通过类似以下的方式重定向:
longcommand > /dev/null;
例如,要摆脱输出或者...
longcommand 2>&1 > output.log
捕获输出。
但有时我会忘记,想知道是否有一种方法可以在事后捕获或重定向。
longcommand
ctrl-z
bg 2>&1 > /dev/null
或者类似的东西,这样我就可以继续使用终端而不会弹出终端上的消息。请参考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 中,
$ 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
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
附加到其中。如果您想关闭原始会话,您需要关闭它的所有文件句柄,打开一个可以成为控制终端的新设备,然后调用
setsid()
。
gdb
连接到正在运行的进程,然后执行'p close(1)'和'p creat("/tmp/foo3", 0600)'来重定向标准输出流,最后在程序继续运行的情况下断开gdb连接。这是一个聪明的技巧! - cjmcreat
调用是如何知道它需要覆盖文件句柄1(即stdout)的? (翻译说明:将原文中的缩写“stdout”和数字“1”翻译成了中文,其他未提及的术语按照通用惯例不翻译。) - iggy你也可以使用reredirect
(https://github.com/jerome-pouiller/reredirect/)来完成此操作。
以下命令将进程PID
的输出(标准输出和错误输出)重定向到FILE
:
reredirect -m FILE PID
reredirect
的 README
还介绍了其他有趣的功能:如何恢复进程的原始状态,如何重定向到另一个命令或仅重定向 stdout 或 stderr。
该工具还提供了 relink
,这是一个脚本,允许将输出重定向到当前终端:
relink PID
relink PID | grep usefull_content
(reredirect
似乎具有与另一个答案中描述的Dupx相同的功能,但它不依赖于Gdb)。
Dupx
Dupx是一个简单的*nix实用程序,可以重定向已经运行的进程的标准输出/输入/错误。
动机
我经常发现自己处于这样一种情况:通过SSH在远程系统上启动的进程比我预期的时间长得多。我需要中断SSH连接,但如果我这样做,如果进程试图在破损的管道的stdout/error上写入某些内容,它将会死亡。我希望我能用^Z暂停进程,然后执行
bg %1 >/tmp/stdout 2>/tmp/stderr
很遗憾,这在我所知道的Shell中不起作用。
屏幕
如果进程在屏幕会话中运行,则可以使用屏幕的日志命令将该窗口的输出记录到文件中:
切换到脚本窗口,C-a H 开始记录。
现在您可以:
$ tail -f screenlog.2 | grep whatever
来自screen手册页面:
log [on|off]
启动/停止将当前窗口的输出写入到名为“screenlog.n”的文件中,其中n是当前窗口的编号,该文件位于窗口的默认目录中。可以使用“logfile”命令更改此文件名。如果未给出参数,则切换日志记录的状态。如果文件已经存在,则会将会话日志附加到文件的前一个内容中。当前内容和回滚历史记录的内容不包括在会话日志中。默认值为“off”。
我确信tmux也有类似的东西。
disown
无效,那么你就没有办法了。 - dmckee --- ex-moderator kittenshopt huponexit
退出并重新登录。 - jimh