【问题标题】:how to redirect this perl script's output to file?如何将此 perl 脚本的输出重定向到文件?
【发布时间】:2018-06-04 20:29:02
【问题描述】:

我在 perl 方面没有太多经验,如果有任何/所有反馈,我将不胜感激......

[开始之前:我无权更改现有的 perl 脚本。]

我每天多次运行几个 perl 脚本,但我想开始将它们的输出捕获到一个文件中。

第一个 perl 脚本不带任何参数,我可以毫无问题地“输出”它的输出:

/asdf/loc1/rebuild-stuff.pl 2>&1 | tee $mytmpfile1

第二个 perl 脚本用这个命令挂起:

/asdf/loc1/create-site.pl --record=${newsite} 2>&1 | tee $mytmpfile2

仅供参考,以下命令不会挂起:

/asdf/loc1/create-site.pl --record=${newsite} 2>&1

我想知道 /asdf/loc1/create-site.pl 是否正在尝试将 | tee $mytmpfile2 处理为额外的命令行参数?我不允许分享整个脚本,但这是其主要例程的开始:

...
my $fullpath = $0;
$0 =~ s%.*/%%;

# Parse command-line options.
...
Getopt::Long::config ('no_ignore_case','bundling');
GetOptions ('h|help'               => \$help,
            'n|dry-run|just-print' => \$preview,
            'q|quiet|no-mail'      => \$quiet,
            'r|record=s'           => \$record,
            'V|noverify'           => \$skipverify,
            'v|version'            => \$version) or exit 1;
...

上面的代码是否提供了任何线索?除了修改脚本之外,您还有什么技巧可以让我将其输出捕获到文件中吗?

【问题讨论】:

  • 不,您在此处提供的代码没有提供任何线索。请在询问您是否提供 minimal reproducible example 之前进行测试 - 尽可能短的代码,让其他人在不更改运行时直接看到问题。
  • 要清楚,你的脚本不可能自己处理| tee ...;该操作甚至在脚本启动之前由 shell 执行,因此 perl 脚本无法更改 tee 调用。它确实能够检查其 stdout 和 stderr 是针对 TTY 还是 FIFO 并在此基础上更改其行为,但是您在此处提供的代码都没有进行该检查。
  • 另外值得注意的是,默认缓冲行为可以根据 FIFO / TTY 的确定而改变;请参阅BashFAQ #9 进行一些介绍性讨论。

标签: linux shell perl


【解决方案1】:

它没有挂。您正在“遭受缓冲”。像大多数程序一样,Perl 的 STDOUT 默认是缓冲的。像大多数程序一样,Perl 的 STDOUT 在连接到终端时由换行符刷新,否则被块缓冲。当 STDOUT 未连接到终端时,在累积 4 KiB 或 8 KiB 的输出(取决于您的 Perl 版本)或程序退出之前,您不会得到任何输出。

您可以在脚本中添加$| = 1; 以禁用STDOUT 缓冲。如果您的程序以真值结束或使用exit 退出,您可以在不更改.pl 文件的情况下执行此操作。只需使用以下包装器:

perl -e'
   $| = 1;
   $0 = shift;
   do($0);
   my $e = $@ || $! || "$0 didn\x27t return a true value\n";
   die($e) if $e;
' -- prog args | ...

或者您可以欺骗程序,使其认为它已使用unbuffer 连接到终端。

unbuffer prog args | ...

【讨论】:

  • unbuffer 是一个更糟糕的解决方案——以至于我倾向于建议不要为它提供一个简单的 Perl-native 修复程序。它需要 Expect,因此需要一个 TCL 解释器才能运行——因此您正在大幅扩展依赖链,影响启动时间和内存使用等等。
  • Re "unbuffer 是一个更糟糕的解决方案",你为什么这么说?比什么更糟?我不知道有任何其他类似的工具。
  • 这个解释出现在我的评论中——尝试重新加载?简短的回答是依赖链; unbuffer 是用 expect 编写的,因此当您在 unbuffer 下运行 Perl 脚本时,您将启动两个单独的脚本解释器,否则您只需要一个。
  • 您自己已经提供了替代方案 -- $| = 1。我建议加倍下注。 :)
  • 这需要更改程序,因此无法替代。
猜你喜欢
  • 1970-01-01
  • 2011-11-18
  • 1970-01-01
  • 2017-08-11
  • 1970-01-01
  • 2018-01-11
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多