Могу ли я определить, действительно ли Perl-скрипт запускается из терминала? - PullRequest
0 голосов
/ 03 ноября 2018

Могу ли я определить, действительно ли Perl-скрипт запускается из терминала?

Я бы предпочел по умолчанию предположить, что он был запущен из браузера, если я не уверен. Но если есть способ убедиться, что он запущен на 100% из терминала, я был бы счастлив (для целей отладки).

Большое спасибо

Ответы [ 3 ]

0 голосов
/ 04 ноября 2018

Файл устройства /dev/tty представляет управляющий терминал для процесса. Если ваш процесс не подключен к терминалу (демон, из cron / at и т. Д.), Он не может «открыть» это специальное устройство. Так

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

/dev/tty может представлять виртуальное консольное устройство (/dev/ttyN), pty (xterm, ssh), последовательный порт (COM1) и т. Д. И не зависит от перенаправлений, поэтому это должно быть надежно .

Если это выполняется очень часто, возможно, используйте эту версию

use feature qw(state);

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

, который должен быть более эффективным (на порядок выше в моем простом тесте).

Они работают только в системах Unix-y (или в приложении POSIX, работающем поверх Windows, или в подсистеме POSIX Windows).

0 голосов
/ 04 ноября 2018

Это взято непосредственно из исходного кода функции prompt ExtUtils :: MakeMaker. Возможно, я предполагаю, что кто-то может пойти на все, чтобы обмануть это. Но в какой-то момент поломка должна принадлежать выключателю.

Для большинства целей этого должно быть достаточно:

 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 состоит в том, что они, по-видимому, активно поддерживаются и будут получать только отчеты и возможные обновления, если они окажутся неадекватными их объявленной цели. .

0 голосов
/ 03 ноября 2018

Используйте оператор проверки файлов -t, который проверяет, прикреплен ли дескриптор файла к терминалу. Например:

if (-t STDIN) {
  print "Running with a terminal as input."
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...