[英]Can a Perl test script detect whether it's being run from a harness in parallel?
[英]Can I detect if a Perl script is being run from a terminal for sure?
我可以確定是否正在從終端運行 Perl 腳本嗎?
如果我不確定,我寧願默認假設它是從瀏覽器運行的。 但是,如果有辦法確保它 100% 從終端運行,我會很高興(出於調試目的)。
非常感謝
這是直接取自 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 模塊之一的優勢在於,它們可能是積極維護的,並且如果結果證明它們不足以達到其宣傳的目的,則會收到報告和最終更新。
使用文件測試運算符-t
來測試文件句柄是否附加到終端。 例如:
if (-t STDIN) {
print "Running with a terminal as input."
}
設備文件/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 系統(或在 Windows 之上運行的 POSIX 應用程序,或在 Window 的 POSIX 子系統中)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.