【问题标题】:Not possible to get bash output to file无法将 bash 输出写入文件
【发布时间】:2019-04-11 05:01:27
【问题描述】:

我正在运行 Vowpal Wabbit 守护程序,我从以下命令开始:

vw -i X_b123.model -t --quiet --daemon --port 26542 -r /dev/stdout

然后我尝试向守护进程发送一些东西:

echo 'somedataforwovpal' | netcat localhost 26542 -q1

我得到答案,像这样(两行都是答案):

1:-0.0268077 2:-0.0990701 3:-0.154975
2

目前,一切都完美无缺。 我想要的只是将此输出发送到文件。这就是让我发疯的地方。为什么?通常我会做的很简单,通过发送 stdout 到这样的文件:

echo 'somedataforwovpal' | netcat localhost 26542 -q1 > myfile.txt

嗯,这只是部分起作用。该文件已创建,但它仅包含输出的第二行(仅数字 2)和第一行 1:-0.0268077 2:-0.0990701 3:-0.154975仍在打印到控制台。

所以我的想法是,第二部分将转到 stderr,所以我尝试了以下几种方法来保存 stderr/stdout 输出:

echo 'somedataforwovpal' | netcat localhost 26542 -q1 2> myfile.txt
echo 'somedataforwovpal' | netcat localhost 26542 -q1 2>&1 >  myfile.txt
echo 'somedataforwovpal' | netcat localhost 26542 -q1 &>  myfile.txt
echo 'somedataforwovpal' | netcat localhost 26542 -q1 > myfile.txt 2>&1
echo 'somedataforwovpal' | netcat localhost 26542 -q1 >> myfile.txt
script -c "echo '1 |w auto_t dum_qt |f auto_t dum_qt |m qm_pos_2' | netcat localhost 26542 -q1" myfile.txt

没用,还是一样。如您所见,这些方法都没有,我什至尝试过脚本,但仍然相同。真的快把我逼疯了,请问有没有人能救我?

【问题讨论】:

  • 第三和第四行将同时捕获标准输出和标准错误。如果它们不起作用,那么还有其他问题。
  • 你试过了吗:>> myfile.txt ...只是看到netcat没有调用两次,擦除了进程中的第一行?
  • 是的,我试过了,但没有帮助,对不起
  • 附加的输出行来自vw,而不是来自netcat。当您第一次启动守护程序时,我会尝试将vwstderr 重定向到您感兴趣的文件:vw -i X_b123.model -t --quiet --daemon --port 26542 -r /dev/stdout >& myfile.txt
  • arielf,谢谢,这就是问题所在(我只是不能将其作为解决方案,因为它不是答案,而是评论)

标签: bash shell unix stdout vowpalwabbit


【解决方案1】:

如果您想将所有输出(stdout + stderr + 显式 tty)保存到文件中,您可以使用 script 实用程序:

$ script /tmp/session.log
Script started, file is /tmp/session.log

$ some_command args...
... output of some_command args ...

$ exit
Script done, file is /tmp/session.log

现在/tmp/session.log 包含会话期间在屏幕上捕获的所有内容。

script 的手册页警告:

script 将所有内容都放在日志文件中,包括换行符和退格符。 这不是天真的用户所期望的。

您可以使用如下所示的 perl 脚本从不需要的垃圾中去除最终输出(不是很科学,但对我有用)

#!/usr/bin/perl -w
#
# Filter to clean script (and other terminal/interactive) junk output
#
while (<>) {
    # ANSI terminal sequences (empirical)
    s/\033\[\??(?:\d*(?:;\d*)*)?[hlmHJKL]//g;
    s/\033[=>]//g;

    # Backspace/delete sequences, slow/safe way from the inside out
    s/[^\010]\010//g;

    # Other CTRL & non-wanted ASCII chars
    tr/\000-\010\013-\037\177//d;

    print;
}

【讨论】:

    【解决方案2】:

    为什么追加新行不起作用?

    echo 'somedataforwovpal' | netcat localhost 26542 -q1 >> myfile.txt
    

    来自 bash 手册页:

    附加重定向输出

    以这种方式重定向输出会导致打开其名称来自 word 扩展的文件以附加到文件描述符 n 上,如果未指定 n,则打开标准输出(文件描述符 1)。如果文件不存在,则创建它。

    附加输出的一般格式是:

    [n]>>单词

    这有什么线索吗?

    echo 'somedataforwovpal' | netcat localhost 26542 -q1 | cat -net
    

    【讨论】:

    • 您是否考虑在其间添加三通管?
    • 感谢您的回答,我试过这个,认为这可以工作,但它仍然是一样的。第一行还是直接做 bash
    【解决方案3】:

    可以绕过正常的重定向,但通常不是一个好主意。例如:

    #! /bin/env bash
    echo $* >> $(tty)
    

    运行它可以工作。

    $: bypass foo >log 2>&1
    foo
    

    日志中也没有任何内容。

    $: ls -l log
    -rw-r--r-- 1 P2759474 1049089 0 Nov  7 12:16 log
    

    很抱歉,我没有适合您的好解决方案,但这至少可以帮助您了解这是如何发生的。

    【讨论】:

    • 这只是为了表明程序如何在内部绕过您对标准 I/O 的控制并直接写入您的终端,或其他一些类似的令人发指的骗局(我承认在极少数情况下会感到内疚...)我没有实际的解决方案,但也许一些聪明的年轻人会慢慢融入其中?
    猜你喜欢
    • 1970-01-01
    • 2012-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-26
    • 1970-01-01
    • 2021-02-26
    • 2013-03-18
    相关资源
    最近更新 更多