有没有办法检索重定向到 /dev/null 的标准输出?我试过了tail -f /proc/{PID}/fd/1
,除了重定向到/dev/null
.
IE
tail -f /proc/${cmd_pid}/fd/1
工作cmd > log.txt
但不cmd > /dev/null
- - - - - - 更新 - - - - - -
事实上,log.txt
如果总是记录标准输出,我的问题将会非常大。如果我可以控制何时记录或停止日志(而不停止进程cmd
本身),那将是最好的。
所以如果可以将标准输出重定向到某个tmp
不占用资源的文件系统,当我需要时我可以检索标准输出?
不,您不能更改文件句柄。
不,如果不将数据存储在某处,就无法存储数据。
可能有人写了一个循环缓冲区——它可以让你看到(比如说)最后 100k 的数据。或者,如果程序通常无头运行,您可以将输出发送到屏幕并通过
screen
.这可以通过将输出通过管道传输到 shell 脚本来完成,如下所示:
请注意,重定向是在循环内完成的,特别是为了在每次迭代中重新打开输出文件。然后,开始:
然后当你想要日志时:
循环的下一次迭代将开始写入
/some/log/file
而不是写入到/dev/null
。如果您的命令大量记录,这可能会导致严重的性能损失。
当你这样做时
cmd > /dev/null
,shell 在一个新的子进程中打开 fd 1/dev/null
并执行cmd
。cmd
执行一些操作write(1, "output"...)
以将数据写入 stdout(或者可能是其他写入系统调用,例如send
,sendmsg
或pwrite
),而不管 fd 是在什么上打开的。在 Linux 上,
/proc/$pid_of_cmd/fd/1
将只是一个神奇的符号链接/dev/null
,文件 fd 1 在其中打开,因此tail -f that
与tail -f /dev/null
.您可以拦截这些
write()
系统调用strace
并解码结果:或者:
仅用于
write()
标准输出 (fd 1) 的 s。或者:仅用于
write()
stdout (fd 1) 的 s 并且仅当 stdout 在/dev/null
.请注意,如果您将 的输出重定向
perl
到 tty 设备以外的其他设备,它将开始按块而不是按行进行缓冲,因此您只会看到几千字节的批量输出。$|
您可以通过将变量设置为来禁用该缓冲1
:cmd > /dev/null
或者,不要做,而是做cmd | cat > /dev/null
。Then
cmd
的标准输出将是一个管道,在 Linux 上,/proc/$pid_of_cmd/fd/1
它的行为就像一个命名管道,所以如果你这样做:您实际上会将管道重定向到您的新
cat
命令。如果你终止那个新的
cat
,你会想要恢复另一个 (kill -s CONT "$pid_of_cat"
) 以重新打开/dev/null
那个管道上的水龙头。要实际更改进程的标准输出位置,您可以附加一个调试器:
然后在 gdb 中:
(O_WRONLY|O_TRUNC|O_CREAT 为 0x241)
检查是否
open()
返回 fd 1。如果没有,您可能需要调用dup2()
和一个额外的close()
.