我有一个运行如下命令的应用程序:
<command> <switches> >& /dev/null
我可以配置<command>
,但我无法控制<switches>
。此命令生成的所有输出都转到/dev/null
. 我希望输出在屏幕上可见或重定向到日志文件。
我尝试使用freopen()
和相关功能重新打开/dev/null
到另一个文件,但无法使其正常工作。
你还有其他建议吗?这可能吗?
谢谢你的时间。
PS:我在Linux上工作。
可怕的黑客:
使用二进制模式的文本编辑器打开应用程序,找到'/dev/null/'并将其替换为相同长度的字符串
e.g '~/tmp/log'
由于您可以修改您运行的命令,您可以使用简单的 shell 脚本作为包装器将输出重定向到文件。
#!/bin/bash
"$@" >> logfile
如果将其保存在路径中作为 capture_output.sh,则可以将 capture_output.sh 添加到命令的开头,以将程序的输出附加到日志文件。
附加#
在命令的末尾,使其变为<command> # >& /dev/null
,从而注释掉不需要的部分。
您的应用程序可能正在运行一个 shell 并将该命令行传递给它。
您需要让它运行您编写的脚本。该脚本将>/dev/null
在命令行中替换为>>/your/log
并使用修改后的命令行调用真实的 shell。
第一步是更改应用程序使用的外壳。更改环境变量SHELL
就足够了,即,将您的应用程序运行为
SHELL=/home/user/bin/myshell theApp
如果这不起作用,请尝试暂时链接/bin/sh
到您的脚本。
myshell
将调用原始外壳,但在模式替换参数之后:
#!/bin/bash
sh ${1+"${@/\>\/dev\/null/>>\/your\/log}"}
这些方面的东西应该起作用。
您可以使用 gdb 对已运行的进程执行此操作。请参阅以下页面:http ://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/
您可以为该命令创建别名吗?如果是这样,请将其别名为将输出转储到文件的另一个命令。
编辑:这不是一个好主意,当然不值得尝试,除非你知道这会破坏什么。它对我有用,也可能对你有用。
好的,这是一个非常糟糕的 hack,可能不值得做。假设其他命令都不起作用,并且您根本无法访问二进制/应用程序(其中包含带有 的命令/dev/null
),并且您无法将输出重定向到其他文件(通过替换/dev/null
)。
然后,您可以删除 /dev/null ( $> rm /dev/null
) 并在可以引导所有数据的位置(最好使用软链接)创建您自己的文件。完成后,您可以使用以下命令再次创建 /dev/null:
$> mknod -m 666 /dev/null c 1 3
需要非常清楚的是,这是一个糟糕的hack,当然需要root权限才能工作。您的重定向文件很可能包含来自许多其他正在运行并/dev/null
用作接收器的应用程序/二进制文件的数据。
设备文件/dev/tty
引用您的应用程序的控制终端 - 如果没有改变,那么这应该可以工作:
freopen("/dev/tty", "w", stdout);
freopen("/dev/tty", "w", stderr);
或者,您可以重新打开它们以指向日志文件:
freopen("/var/log/myapp.log", "a", stdout);
freopen("/var/log/myapp.err", "a", stderr);
它可能不完全重定向,但它允许在发送的任何地方获取输出
strace -ewrite -p $PID
它不是那么干净(显示如下行: write(#,) ),但有效!(并且是单行 :D )您可能也不喜欢这样一个事实,即参数是缩写的。要控制使用 -s 参数设置显示的字符串的最大长度。
它捕获所有流,因此您可能希望以某种方式对其进行过滤。
你可以过滤它:
strace -ewrite -p $PID 2>&1 | grep "write(1"
仅显示描述符 1 调用。2>&1 是将stderr重定向到stdout,因为strace默认写入stderr。
在 perl 中,如果您只想重定向STDOUT
到更有用的东西,您可以执行以下操作:
open STDOUT, '>>', '/var/log/myscript.log';
open STDERR, '>>', '/var/log/myscript.err';
在脚本的开头,这会将其重定向到脚本的其余部分。
按照 e-t172 的回答,您能否将最后一个开关设置为(或附加到它):
; echo
如果您可以在将内容传递给 /dev/null 之前将某些内容内联(不确定您是否正在处理硬编码命令),则可以使用tee重定向到您选择的内容。
Wikipedia 中允许升级命令的示例:
echo "Body of file..." | sudo tee root_owned_file > /dev/null