9

我试图在 Linux 上的 Perl 脚本中确定它是否在终端中运行。

也就是说,我需要这样的代码:

  • 仅在命令行上运行时返回 true
  • ./myscript.pl | less运行时甚至返回 true./myscript.pl </dev/null >/dev/null 2>/dev/null
  • 在 cron 作业中运行或作为 CGI 脚本运行时返回 false

特别是因为第二个子弹,我不能使用-t STDOUT和变化,而且IO::Interactive也没用。

信息似乎是可用的。如果我 run ,它会在列中ps显示一个条目,即使当我 run以及作为 cron 作业或 CGI 脚本运行时也是如此。pts/2TTY./myscript.pl </dev/null >/dev/null 2>/dev/null?

有没有一种优雅的方法可以在 Perl 脚本中确定这一点?我宁愿不必解析ps.

4

5 回答 5

12

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

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

于 2011-08-05T11:36:08.243 回答
5

我自己的问题的另一个答案。我研究了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";
    }
}
于 2011-08-05T14:28:35.293 回答
1

PS应该可以帮到你。
ps aux | grep 'filename.pl'

于 2011-08-05T11:31:52.797 回答
0

为了部分回答我自己的问题,以下方法可以解决问题:

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

如果有则返回 TTY 名称(为真),如果没有则返回“”(假)。

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

于 2011-08-05T11:40:22.810 回答
0

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

但如果还不够,可以通过 %ENV 特殊哈希表查看环境变量。CGI-BIN 界面设置了其中的一些。如果您在 cron 下运行脚本,它会设置一些变量。如果还不够,你可以在 /etc/crontab 文件中设置它并在你的脚本中测试。你会做什么是为了你的需要。

您应该只调用一次完整的过程。你不能迭代它,因为脚本环境在它工作之前不会改变。

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

于 2018-06-15T12:31:44.010 回答