2011-08-05 152 views
6

我试图确定,在Linux的Perl脚本中,它是否在终端中运行。如何检查Perl脚本是否在终端中运行?

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

  • 返回true运行./myscript.pl | less甚至./myscript.pl </dev/null >/dev/null 2>/dev/null
  • 返回false时,在cron运行时,在命令行
  • 也返回true时,只需运行工作或作为CGI脚本

特别是因为第二个项目符号,我不能使用-t STDOUT和变体,还有IO::Interactive是没有用的。

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

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

+0

我觉得perl可以使用'isatty(3)'函数。 – Keith

+0

'isatty'存在于POSIX模块中,是的,但是像'-t'一样检查文件句柄是否连接到tty。不是我所需要的... – mscha

+0

函数[ctermid](http://pubs.opengroup.org/onlinepubs/009695399/functions/ctermid.html)是否可用? – Keith

回答

10

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

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

+0

谢谢。这似乎是诀窍: 'sub isatty(){no autodie; return open(my $ tty,'+','/ dev/tty'); }' – mscha

+0

@mscha - 如何再次关闭这个文件描述符 - 取决于你运行这个文件的频率,你可能会用完文件描述符。 – Ingo

+6

@Ingo,这不是必须的,因为他使用了一个词法文件句柄,并没有返回它。因此,当变量超出范围时(当'isatty'返回时),文件句柄将被自动关闭。 – cjm

1

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

+2

这正是我想要避免的... 此外,只是grepping文件名是不是很可靠。 – mscha

0

要部分地回答我的问题,以下是卓有成效的:

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

返回TTY名如果有的话(这是真的),或“”如果没有(假)。

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

4

对我自己的问题的另一个答案。我研究了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"; 
    } 
} 
相关问题