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

时间:2022-03-18 07:15:22

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 or even ./myscript.pl </dev/null >/dev/null 2>/dev/null
  • 运行./myscript.pl |时也返回true更少甚至./myscript.pl / 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 ? when running as a cron job or CGI script.

信息似乎确实可用。如果我运行ps,它会在TTY列中显示类似pts / 2的条目,即使我运行./myscript.pl / dev / null 2> / dev / null,和?作为cron作业或CGI脚本运行时。

Is there an elegant way to determine this in a Perl script? I'd rather not have to parse the output of ps.

有没有一种优雅的方法来在Perl脚本中确定这个?我宁愿不必解析ps的输出。

5 个解决方案

#1


11  

You can try to open /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.

您可以尝试打开/ dev / tty。如果您在终端(即使在远程计算机上的终端中),这将起作用。否则,如果脚本是通过at或cron运行的,则不会。

Note: this will only work on Unix systems.

注意:这只适用于Unix系统。

#2


5  

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";
    }
}

#3


1  

PS should help you out.
ps aux | grep 'filename.pl'

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

#4


0  

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...

我还是更喜欢没有外部命令的解决方案......

#5


0  

At first you must check, output is associated with terminal by -t . Of course if you want, you can look at /proc/$pid/fd/1 , it is symlink to device. You can test it, if it is a terminal.

首先你必须检查,输出与-t相关联。当然如果你想,你可以查看/ proc / $ pid / fd / 1,它是设备的符号链接。如果它是终端,你可以测试它。

But if it is not enough, you can check enviromential variables by %ENV special hash table. CGI-BIN interface sets some of them. If you run script under cron, it sets some variable. If it is not enough, you can set it in /etc/crontab file and test in your script. It is for your needs what you'll do.

但是如果还不够,你可以通过%ENV特殊哈希表来检查环境变量。 CGI-BIN接口设置了其中一些。如果你在cron下运行脚本,它会设置一些变量。如果还不够,可以在/ etc / crontab文件中设置它并在脚本中进行测试。它可以满足您的需求。

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. Only what you need, is windows incompatibilities. But if you are using windows10, then it has environment similar to linux based on ubuntu. then you cannot look out as strongly, as you do it making compatibility between win32api and unix like systems.

您不必调用任何外部命令,或者您不需要特殊的libarier。只有你需要的是Windows不兼容。但是如果你使用的是windows10,那么它的环境类似于基于ubuntu的linux。然后你不能强烈地看,就像你在win32api和unix之类的系统之间做兼容。

#1


11  

You can try to open /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.

您可以尝试打开/ dev / tty。如果您在终端(即使在远程计算机上的终端中),这将起作用。否则,如果脚本是通过at或cron运行的,则不会。

Note: this will only work on Unix systems.

注意:这只适用于Unix系统。

#2


5  

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";
    }
}

#3


1  

PS should help you out.
ps aux | grep 'filename.pl'

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

#4


0  

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...

我还是更喜欢没有外部命令的解决方案......

#5


0  

At first you must check, output is associated with terminal by -t . Of course if you want, you can look at /proc/$pid/fd/1 , it is symlink to device. You can test it, if it is a terminal.

首先你必须检查,输出与-t相关联。当然如果你想,你可以查看/ proc / $ pid / fd / 1,它是设备的符号链接。如果它是终端,你可以测试它。

But if it is not enough, you can check enviromential variables by %ENV special hash table. CGI-BIN interface sets some of them. If you run script under cron, it sets some variable. If it is not enough, you can set it in /etc/crontab file and test in your script. It is for your needs what you'll do.

但是如果还不够,你可以通过%ENV特殊哈希表来检查环境变量。 CGI-BIN接口设置了其中一些。如果你在cron下运行脚本,它会设置一些变量。如果还不够,可以在/ etc / crontab文件中设置它并在脚本中进行测试。它可以满足您的需求。

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. Only what you need, is windows incompatibilities. But if you are using windows10, then it has environment similar to linux based on ubuntu. then you cannot look out as strongly, as you do it making compatibility between win32api and unix like systems.

您不必调用任何外部命令,或者您不需要特殊的libarier。只有你需要的是Windows不兼容。但是如果你使用的是windows10,那么它的环境类似于基于ubuntu的linux。然后你不能强烈地看,就像你在win32api和unix之类的系统之间做兼容。