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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1323956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:38:13  来源:igfitidea点击:

How to redirect output of an already running process

linuxbash

提问by Sheldon Ross

Normally I would start a command like

通常我会启动一个命令

longcommand &;

I know you can redirect it by doing something like

我知道你可以通过做类似的事情来重定向它

longcommand > /dev/null;

for instance to get rid of the output or

例如摆脱输出或

longcommand 2>&1 > output.log

to capture output.

捕获输出。

But I sometimes forget, and was wondering if there is a way to capture or redirect after the fact.

但我有时会忘记,并想知道是否有办法在事后捕获或重定向。

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

or something like that so I can continue using the terminal without messages popping up on the terminal.

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

采纳答案by user37875

See Redirecting Output from a Running Process.

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

Firstly I run the command cat > foo1in one session and test that data from stdin is copied to the file. Then in another session I redirect the output.

Firstly find the PID of the process:

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

Now check the file handles it has open:

$ 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

Now run 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)
 = 0
(gdb) p creat("/tmp/foo3", 0600)
 = 1
(gdb) q
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: /bin/cat, process 6760

The pcommand in GDB will print the value of an expression, an expression can be a function to call, it can be a system call… So I execute a close()system call and pass file handle 1, then I execute a creat()system call to open a new file. The result of the creat()was 1 which means that it replaced the previous file handle. If I wanted to use the same file for stdout and stderr or if I wanted to replace a file handle with some other number then I would need to call the dup2()system call to achieve that result.

For this example I chose to use creat()instead of open()because there are fewer parameter. The C macros for the flags are not usable from GDB (it doesn't use C headers) so I would have to read header files to discover this – it's not that hard to do so but would take more time. Note that 0600 is the octal permission for the owner having read/write access and the group and others having no access. It would also work to use 0 for that parameter and run chmod on the file later on.

After that I verify the result:

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

Typing more data in to catresults in the file /tmp/foo3being appended to.

If you want to close the original session you need to close all file handles for it, open a new device that can be the controlling tty, and then call setsid().

首先,我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)
 = 0
(gdb) p creat("/tmp/foo3", 0600)
 = 1
(gdb) q
The program is running. Quit anyway (and detach it)? (y or n) y
Detaching from program: /bin/cat, process 6760

pGDB中的命令会打印一个表达式的值,一个表达式可以是一个要调用的函数,也可以是一个系统调用……所以我执行一个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().

回答by blah

Dupx

Dupx is a simple *nix utility to redirect standard output/input/error of an already running process.

Motivation

I've often found myself in a situation where a process I started on a remote system via SSH takes much longer than I had anticipated. I need to break the SSH connection, but if I do so, the process will die if it tries to write something on stdout/error of a broken pipe. I wish I could suspend the process with ^Z and then do a

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

Unfortunately this will not work (in shells I know).

双倍

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

动机

我经常发现自己处于这样一种情况:我通过 SSH 在远程系统上启动的进程比我预期的要长得多。我需要断开 SSH 连接,但是如果我这样做了,如果它尝试在损坏的管道的 stdout/error 上写一些东西,这个过程就会终止。我希望我可以用 ^Z 暂停这个过程,然后做一个

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

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

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

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

回答by Krzysztow

I collected some information on the internet and prepared the script that requires no external tool: See my response here. Hope it's helpful.

我在网上搜集了一些资料,准备了不需要外部工具的脚本:看我的回复这里。希望它有帮助。

回答by Jér?me Pouiller

You can also do it using reredirect (https://github.com/jerome-pouiller/reredirect/).

您也可以使用 reredirect ( https://github.com/jerome-pouiller/reredirect/)来做到这一点。

Type

类型

reredirect -m FILE PID

and outputs (standard and error) will be written in FILE.

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

reredirect README also explains how to restore original state of process, how to redirect to another command or to redirect only stdout or stderr.

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

reredirect also provide a script called relinkthat allows to redirect to current terminal:

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

relink PID
relink PID | grep usefull_content

(reredirect seems to have same features than Dupx described in another answer but, it does not depends on Gdb).

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

回答by lemonsqueeze

Screen

屏幕

If process is running in a screen session you can use screen's log command to log the output of that window to a file:

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

Switch to the script's window, C-aHto log.
Now you can :

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

$ tail -f screenlog.2 | grep whatever

From screen's man page:

从屏幕的手册页:

log [on|off]

Start/stop writing output of the current window to a file "screenlog.n" in the window's default directory, where n is the number of the current window. This filename can be changed with the 'logfile' command. If no parameter is given, the state of logging is toggled. The session log is appended to the previous contents of the file if it already exists. The current contents and the contents of the scrollback history are not included in the session log. Default is 'off'.

登录 [开|关]

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

I'm sure tmux has something similar as well.

我确定 tmux 也有类似的东西。