简体   繁体   English

如何检查Perl脚本是否在终端中运行?

[英]How do I check if a Perl script is running in a terminal?

I'm trying to determine, within a Perl script on Linux, whether it's running in a terminal. 我试图在Linux上的Perl脚本中确定它是否在终端中运行。

That is, I need code that: 也就是说,我需要以下代码:

  • returns true when simply running on the command-line 只需在命令行上运行即返回true
  • also returns true when running ./myscript.pl | less 运行./myscript.pl | less时也返回true ./myscript.pl | less or even ./myscript.pl </dev/null >/dev/null 2>/dev/null ./myscript.pl | less甚至./myscript.pl </dev/null >/dev/null 2>/dev/null
  • returns false when running in a cron job, or as a CGI script 在cron作业中运行时返回false,或作为CGI脚本返回false

Especially because of the second bullet, I can't use -t STDOUT and variations, and also IO::Interactive is of no use. 特别是因为第二个子弹,我不能使用-t STDOUT和变体,而且IO :: Interactive也没用。

The information does appear to be available. 信息似乎确实可用。 If I run ps , it shows an entry like pts/2 in the TTY column, even when I run ./myscript.pl </dev/null >/dev/null 2>/dev/null , and ? 如果我运行ps ,它会在TTY列中显示类似pts/2的条目,即使我运行./myscript.pl </dev/null >/dev/null 2>/dev/null ,和? when running as a cron job or CGI script. 作为cron作业或CGI脚本运行时。

Is there an elegant way to determine this in a Perl script? 有没有一种优雅的方法来在Perl脚本中确定这个? I'd rather not have to parse the output of ps . 我宁愿不必解析ps的输出。

You can try to open /dev/tty. 您可以尝试打开/ dev / tty。 This will work if you are in a terminal (even in a terminal on a remote computer). 如果您在终端(即使在远程计算机上的终端中),这将有效。 Otherwise, if the script is run via at or cron, it won't. 否则,如果脚本是通过at或cron运行的,则不会。

Note: this will only work on Unix systems. 注意:这只适用于Unix系统。

Another answer to my own question. 我自己的问题的另一个答案。 I studied the ps source to see how it determined the TTY, and it uses /proc/[pid]/stat . 我研究了ps源代码,看看它是如何确定TTY的,它使用/proc/[pid]/stat

use strict;
use warnings;
use 5.010;
use autodie;

sub isatty()
{
    # See http://www.kernel.org/doc/man-pages/online/pages/man5/proc.5.html
    open(my $stat, '<', "/proc/$$/stat");
    if (<$stat> =~ m{^\d+\s+\(.*\)\s+\w\s+\d+\s+\d+\s+\d+\s+(\d+)}) {
        return $1 > 0;
    }
    else {
        die "Unexpected format in /proc/$$/stat";
    }
}

PS应该帮助你。
ps aux | grep 'filename.pl'

At first you must check, output is associated with terminal by -t . 首先你必须检查,输出与-t相关联。 Of course if you want, you can look at /proc/$pid/fd/1 , it is symlink to device. 当然如果你想,你可以查看/ proc / $ pid / fd / 1,它是设备的符号链接。 You can test it, if it is a terminal. 如果它是终端,你可以测试它。

But if it is not enough, you can check enviromential variables by %ENV special hash table. 但是如果还不够,你可以通过%ENV特殊哈希表检查环境变量。 CGI-BIN interface sets some of them. CGI-BIN接口设置了其中一些。 If you run script under cron, it sets some variable. 如果你在cron下运行脚本,它会设置一些变量。 If it is not enough, you can set it in /etc/crontab file and test in your script. 如果还不够,可以在/ etc / crontab文件中设置它并在脚本中进行测试。 It is for your needs what you'll do. 这是你的需要,你会做什么。

You should call that complete procedure only once. 您应该只调用一次完整的过程。 You cannot iterate it, because script environment won't change, until it is working. 你不能迭代它,因为脚本环境不会改变,直到它工作。

You don't have to call any external commands, or you don't need special libarier. 您不必调用任何外部命令,或者您不需要特殊的libarier。 Only what you need, is windows incompatibilities. 只有你需要的是Windows不兼容。 But if you are using windows10, then it has environment similar to linux based on ubuntu. 但是如果你使用的是windows10,那么它的环境类似于基于ubuntu的linux。 then you cannot look out as strongly, as you do it making compatibility between win32api and unix like systems. 然后你不能强烈地看,因为你在win32api和unix之类的系统之间做兼容。

To partially answer my own question, the following does the trick: 为了部分回答我自己的问题,以下是诀窍:

sub isatty()
{
    my $tty = `/bin/ps -p $$ -o tty --no-headers`;
    $tty =~ s{[\s?]}{}g;
    return $tty;
}

Returns the TTY name if any (which is true), or "" if none (false). 返回TTY名称(如果有)(如果为true),或者如果没有则返回(false)。

I'd still prefer a solution without an external command... 我还是更喜欢没有外部命令的解决方案......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM