2012-04-02 68 views
3

我想当前终端的尺寸,即,在端子我的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和正确的大小?

+0

这是一个Perl FAQ:[我如何获得屏幕尺寸?](http://learn.perl.org/faq/perlfaq8.html#How-do-I-get-the-screen-size-) – daxim 2012-04-02 19:36:05

回答

3

对于tput来标识终端大小,其中一个文件描述符( stdin)stdout或stderr必须打开并连接到终端。

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

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


可以解决此问题通过增加2>/dev/ttytput命令:

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,但这是一个管道),而不是stdinfstat是一种自制命令,类似于stat,但它有不同的输出格式。

+0

那么,上面的脚本是完整的,即独立,所以我不知道我在哪里操纵stdin? – 2012-04-02 12:28:40

+0

迄今为止非常感谢。但作为一个相当perl新手这个问题:如何“修复”这一点。我如何使自己的日常行为按照预期行事(独立于“环境”)? – 2012-04-02 12:42:03

+1

查看更多内容 - '输入cols 2>/dev/tty'等 – 2012-04-02 12:46:52

相关问题