gpt4 book ai didi

perl - 重定向 stderr 会影响 "open FH, ' - |', $command"的输出。为什么以及如何预防?

转载 作者:行者123 更新时间:2023-12-05 00:54:40 24 4
gpt4 key购买 nike

我想获取当前终端的大小,即运行我的 perl 脚本的终端。下面应该完成这项工作:

#!/usr/bin/perl

sub getTerminalSize {
my @dimensions = (24,80);
open( my $OH, '-|', "/usr/bin/tput lines ; /usr/bin/tput cols" )
|| return @dimensions;
chomp(@dimensions = <$OH>);
close($OH);
return @dimensions;
}

open (STDERR, ">>bla.log") or die "can not create logfile";
print "Dimensions of your terminal: ". (join " x " , getTerminalSize()) ."\n";

没有最后一行代码,它就可以正常工作。但是有了这条线,我总是得到 24 x 80,所以看起来内部创建了一个新的 shell 并返回了那个 shell 的大小。只是我的猜测。那么到底发生了什么,我如何获得两者 - 重定向 STDERR 和正确的大小?

最佳答案

要使 tput 识别终端大小,(stdin,) stdout 或 stderr 的文件描述符之一必须打开并连接到终端。

在管道构造中,stdout 连接到管道;如果将 stderr 重定向到文件,则 tput 返回默认大小,因为它不分析 stdin

因此,tput 没有可使用的终端;它返回默认大小 24x80。


您可以通过将 2>/dev/tty 添加到 tput 命令来解决此问题:

open my $OH, '-|', "/usr/bin/tput lines 2>/dev/tty; /usr/bin/tput cols 2>/dev/tty"
or return @dimensions;

似乎 tput 根本不查看 stdin。 (当然,将 stdout 重定向到终端会破坏 Perl 用来读取信息的管道机制。)


$ tput lines </dev/null
65
$ tput lines </dev/null 2>/dev/null
65
$ x=$(tput lines </dev/null 2>/dev/null)
$ echo $x
24
$

我在函数中添加了一个诊断打印,以确保它正在读取 tput 的输出,事实确实如此。我将这些行添加到函数中:

open( my $OH, '-|', "fstat /dev/fd/0 /dev/fd/1 /dev/fd/2 /dev/null")
or die "horribly";
my(@data) = <$OH>;
close($OH);
print @data;

输出是:

   Mode  Inode Links   UID   GID     Size    Modtime       Dev      RDev File
0020620 623 1 503 4 0 1333369875 334992488 268435457 /dev/fd/0
0010660 590945904 0 503 20 0 1333369875 334992488 0 /dev/fd/1
0100644 111429666 1 503 20 0 1333369875 334992488 0 /dev/fd/2
0020666 304 1 0 0 0 1333359963 334992488 50331650 /dev/null

在命令行运行时,输出为:

$ fstat /dev/fd/[012] /dev/null
Mode Inode Links UID GID Size Modtime Dev RDev File
0020620 623 1 503 4 0 1333370018 334992488 268435457 /dev/fd/0
0020620 623 1 503 4 0 1333370018 334992488 268435457 /dev/fd/1
0020620 623 1 503 4 0 1333370018 334992488 268435457 /dev/fd/2
0020666 304 1 0 0 0 1333359963 334992488 50331650 /dev/null
$

所以,tput 的标准输入仍然是终端,但是tput 没有看那个。因此,tput 一定查看了 stderr(不清楚它是否尝试了 stdout,但那是一个管道)而不是 标准输入fstat 是一个自制命令,在本质上类似于 stat,但它具有不同的输出格式。

关于perl - 重定向 stderr 会影响 "open FH, ' - |', $command"的输出。为什么以及如何预防?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9976112/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com