我是否可以确定是否从终端运行Perl脚本?

时间:2018-11-03 17:06:54

标签: perl environment-variables

我可以确定是否从终端运行Perl脚本吗?

如果不确定,我宁愿默认假定它是从浏览器运行的。但是,如果有办法确保它已经从终端运行了100%,我会很高兴(出于调试目的)。

非常感谢

3 个答案:

答案 0 :(得分:3)

使用file test operator -t测试文件句柄是否已附加到终端。例如:

if (-t STDIN) {
  print "Running with a terminal as input."
}

答案 1 :(得分:3)

这直接来自ExtUtils :: MakeMaker的prompt函数的源代码。我想,有人可能会竭尽全力去欺骗它。但是在某些时候,破损必须归破碎者所有。

对于大多数目的,这应该足够了:

 my $isa_tty = -t STDIN && (-t STDOUT || !(-f STDOUT || -c STDOUT)) ;

首先,它检查STDIN是否已打开到TTY。如果是这样,请检查STDOUT是否。如果不是STDOUT,则也不能将其打开为文件或字符特殊文件。

更新:

IO :: Prompt :: Tiny使用以下内容:

# Copied (without comments) from IO::Interactive::Tiny by Daniel Muey,
# based on IO::Interactive by Damian Conway and brian d foy

sub _is_interactive {
    my ($out_handle) = ( @_, select );
    return 0 if not -t $out_handle;
    if ( tied(*ARGV) or defined( fileno(ARGV) ) ) {
        return -t *STDIN if defined $ARGV && $ARGV eq '-';
        return @ARGV > 0 && $ARGV[0] eq '-' && -t *STDIN if eof *ARGV;
        return -t *ARGV;
    }
    else {
        return -t *STDIN;
    }
}

然后IO :: Interactive :: Tiny添加注释以解释发生了什么事情:

sub is_interactive {
    my ($out_handle) = (@_, select);    # Default to default output handle

    # Not interactive if output is not to terminal...
    return 0 if not -t $out_handle;

    # If *ARGV is opened, we're interactive if...
    if ( tied(*ARGV) or defined(fileno(ARGV)) ) { # IO::Interactive::Tiny: this is the only relavent part of Scalar::Util::openhandle() for 'openhandle *ARGV'
        # ...it's currently opened to the magic '-' file
        return -t *STDIN if defined $ARGV && $ARGV eq '-';

        # ...it's at end-of-file and the next file is the magic '-' file
        return @ARGV>0 && $ARGV[0] eq '-' && -t *STDIN if eof *ARGV;

        # ...it's directly attached to the terminal 
        return -t *ARGV;
    }

    # If *ARGV isn't opened, it will be interactive if *STDIN is attached 
    # to a terminal.
    else {
        return -t *STDIN;
    }
}

并且我已经验证了IO :: Interactive中的逻辑与IO :: Interactive :: Tiny的逻辑相同。因此,如果您的目标是在适当时提示,请考虑使用IO :: Prompt :: Tiny。而且,如果您的需求比IO :: Prompt :: Tiny所支持的需求更加细微,则可以使用IO :: Interactive :: Tiny提供此特定功能。

虽然您使用自己的解决方案可能最安全,但是使用其中一个CPAN模块的一个优点是,它们大概处于主动维护状态,并且如果结果证明不符合其广告目的,则会收到报告和最终更新。

答案 2 :(得分:1)

设备文件/dev/tty代表该过程的控制终端。如果您的进程未连接到终端(守护程序,cron / at中的守护程序等),则它无法“打开”此特殊设备。所以

use feature qw(state);

sub isatty { 
    no autodie; 
    state $isatty = open(my $tty, '+<', '/dev/tty'); 
    return $isatty;
}

/dev/tty可以代表虚拟控制台设备(/dev/ttyN),pty(xtermssh),串行端口(COM1)等,并且不受影响通过重定向,所以这应该可靠。

上面的代码仅比simple(r)

有效
sub isatty {
    no autodie;
    return open(my $tty, '+<', '/dev/tty');
}

因此,如果不经常使用该版本,第二个版本就可以了。

仅在Unix-y系统上(或在Windows之上运行的POSIX应用程序中,或在Window的POSIX子系统中)工作。