【问题标题】:How to redirect output away from /dev/null如何从 /dev/null 重定向输出
【发布时间】:2010-03-24 12:28:27
【问题描述】:

我有一个运行如下命令的应用程序:

<command> <switches> >& /dev/null

我可以配置<command>,但我无法控制<switches>。此命令生成的所有输出都转到/dev/null。我希望输出在屏幕上可见或重定向到日志文件。

我尝试使用freopen() 和相关函数将/dev/null 重新打开到另一个文件,但无法正常工作。

您还有其他想法吗?这可能吗?

感谢您的宝贵时间。

PS:我在 Linux 上工作。

【问题讨论】:

  • 这和 Perl 有什么关系?
  • 除非您可以更改脚本中的命令,否则我认为您不走运。一旦它被重定向到 null 你就无法取回它,因为你可能与它共享的所有文件描述符(stdin、stdout、stderr)都消失了。
  • 所以你可以控制命令,但不能控制它的重定向?如果是这样,我会说 e-t172 是正确的,或者至少与您将要得到的一样正确:stackoverflow.com/questions/2507569/… 如果不是,请更新以澄清。
  • 我可以配置 ,但无法控制 <command> # <switches> >& /dev/null 将运行不带开关的命令! :( 我已经编辑了我的问题以使其更清晰。
  • 这个问题不是更适合ServerFault吗?跟C有什么关系?您是否正在考虑编写一个 C 程序来替换 ?一种会捕获参数然后调用命令但将 ITS 输出重定向到日志文件的方法?

标签: c redirect stdio


【解决方案1】:

可怕的黑客攻击:

使用二进制模式的文本编辑器打开应用,找到'/dev/null/'并替换为相同长度的字符串

e.g '~/tmp/log'
  • 先备份
  • 小心
  • 小心点
  • 我提到了备份吗?

【讨论】:

  • 澄清:用文本编辑器打开二进制可执行文件。在二进制文件的乱码中应该有“/dev/null”,这就是你上面建议的替换。
  • @lexu:我之前做过。将 /dev/null 替换为一串等长的空格。这行得通,但是对于应用程序的每个版本,破解可执行文件都很乏味......我正在考虑编写一个程序来执行一些重定向破解并调用 。这将是一次性的努力。
  • @Gowtham:(替代方法)(1)编写一个执行“替换”的程序......(2)去找应用程序的开发人员并(礼貌地)要求一个配置选项允许您重定向到日志文件 ..
  • @Gowtham:该命令被称为 Perl 脚本,您可以修改吗?如果是,您可以重新打开 stdio 到另一个文件。
【解决方案2】:

由于您可以修改运行的命令,因此可以使用简单的 shell 脚本作为包装器将输出重定向到文件。

#!/bin/bash
"$@" >> logfile

如果您在路径中将其保存为 capture_output.sh,那么您可以将 capture_output.sh 添加到命令的开头,以将程序的输出附加到日志文件中。

【讨论】:

    【解决方案3】:

    在命令末尾附加#,使其变为<command> # >& /dev/null,从而注释掉不需要的部分。

    【讨论】:

    • @e-t172:好主意。我忘了提到 。该命令称为<command> <switches> >& /dev/null
    【解决方案4】:

    您的应用程序可能正在运行一个 shell 并将该命令行传递给它。

    您需要让它运行您编写的脚本。该脚本会将命令行中的>/dev/null 替换为>>/your/log,并使用修改后的命令行调用真正的shell。

    第一步是更改应用程序使用的外壳。更改环境变量 SHELL 就足够了,即,将您的应用程序运行为

    SHELL=/home/user/bin/myshell theApp
    

    如果这不起作用,请尝试暂时将 /bin/sh 链接到您的脚本。

    myshell 将调用原始 shell,但在模式替换参数之后:

    #!/bin/bash
    sh ${1+"${@/\>\/dev\/null/>>\/your\/log}"}
    

    按照这些思路应该可以工作。

    【讨论】:

      【解决方案5】:

      您可以使用 gdb 对已运行的进程执行此操作。请参阅以下页面:http://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/

      【讨论】:

        【解决方案6】:

        你能为那个命令创建一个别名吗?如果是这样,请将其别名为另一个将输出转储到文件的命令。

        【讨论】:

          【解决方案7】:

          设备文件/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);
          

          【讨论】:

            【解决方案8】:

            编辑:这不是一个好主意,当然不值得尝试,除非你知道这会破坏什么。它对我有用,也可能对你有用。

            好的,这是一个非常糟糕的 hack,可能不值得做。假设其他命令都不起作用,并且您根本无法访问二进制/应用程序(其中包含带有 /dev/null 的命令)并且您无法将输出重定向到其他文件(通过替换 /dev/null)。

            然后,您可以删除 /dev/null ($> rm /dev/null) 并在其位置创建您自己的文件(最好使用软链接),所有数据都可以被定向到该位置。完成后,您可以使用以下命令再次创建 /dev/null:

            $> mknod -m 666 /dev/null c 1 3

            非常清楚,这是一个 糟糕的 hack,当然需要 root 权限才能工作。您重定向的文件很可能包含来自许多其他正在运行并使用/dev/null 作为接收器的应用程序/二进制文件的数据。

            【讨论】:

            • 补充一下,我在运行 2.6.30 的 Fedora 机器上进行了尝试。此信息之所以如此,是因为 mknod 在其他平台/环境上的主要和次要编号可能不同。
            • 如果 'why-my-answer-was-voted-down' 被解释为评论,那就太好了。我知道这是一个 hack(清楚地提到了),这明确是发帖者正在寻找的“......但我无法控制......”。
            • 删除 /dev/null 不仅仅是一个 hack。这是一个完全错误的想法。它影响整个系统(路径名上的任何新打开),而不仅仅是目标脚本/程序。完成后必须“修复”它。它需要root访问权限。这里的答案不是“重定向 /dev/null”,而是重新打开最初从 /dev/null 打开的现有描述符。
            • @Chris 好吧,这正是我所提到的,这不值得做。作为一个“坏”的黑客更多的是观点 - 对于任何生产环境,这肯定是不正确的 - 但是,如果我有我的调试环境并且我需要输出来查看某些东西 - 我可能会很好更喜欢这个黑客。不过,感谢 cmets - 我已经编辑了帖子。
            【解决方案9】:

            它可能不完全重定向,但它允许在任何发送的地方获取输出

            strace -ewrite -p $PID

            它不是那么干净(显示如下行: write(#,) ),但有效! (并且是单行 :D )您可能也不喜欢这样一个事实,即参数是缩写的。要控制使用 -s 参数设置显示的字符串的最大长度。

            它捕获所有流,因此您可能希望以某种方式对其进行过滤。

            你可以过滤它:

            strace -ewrite -p $PID 2>&1 | grep "write(1"

            仅显示描述符 1 调用。 2>&1是将stderr重定向到stdout,因为strace默认写入stderr。

            【讨论】:

              【解决方案10】:

              在 perl 中,如果您只想将 STDOUT 重定向到更有用的东西,您可以执行以下操作:

              open STDOUT, '>>', '/var/log/myscript.log';
              open STDERR, '>>', '/var/log/myscript.err';
              

              在脚本的开头,这会将其重定向到脚本的其余部分。

              【讨论】:

                【解决方案11】:

                按照 e-t172 的回答,您能否将最后一个开关设置为(或附加到它):

                ; echo 
                

                【讨论】:

                  【解决方案12】:

                  如果您可以在将内容传递给 /dev/null 之前将某些内容内联(不确定您是否正在处理硬编码命令),您可以使用 tee 重定向到您选择的内容。

                  来自 Wikipedia 的允许升级命令的示例:

                  echo "Body of file..." | sudo tee root_owned_file > /dev/null
                  

                  http://en.wikipedia.org/wiki/Tee_(command)

                  【讨论】:

                    猜你喜欢
                    • 2023-03-06
                    • 2012-01-04
                    • 2019-10-11
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-04-14
                    • 1970-01-01
                    • 2012-01-03
                    • 2023-04-08
                    相关资源
                    最近更新 更多