2012-07-04 101 views
10

我有一个脚本,可以作为网页运行,也可以通过控制台运行。检测一个PHP脚本是否正在交互运行

检测使用哪种方法来调用脚本看起来非常简单,但是当从控制台运行脚本时,我需要知道脚本是否以交互方式运行(用户键入命令或输入重定向从一个文件)。

php script.phpphp script.php < input_file

这可能吗?

回答

25

我还需要比posix_isatty稍微更灵活的解决方案,可以检测:

  • 从终端
  • 正在运行该脚本是对脚本经由管道或从文件中接收数据
  • 是输出被重定向到一个文件

经过一些实验和挖掘libc头后,我想出了一个非常简单的类,可以做以上所有和更多。

class IOMode 
{ 
    public $stdin; 
    public $stdout; 
    public $stderr; 

    private function getMode(&$dev, $fp) 
    { 
     $stat = fstat($fp); 
     $mode = $stat['mode'] & 0170000; // S_IFMT 

     $dev = new StdClass; 

     $dev->isFifo = $mode == 0010000; // S_IFIFO 
     $dev->isChr = $mode == 0020000; // S_IFCHR 
     $dev->isDir = $mode == 0040000; // S_IFDIR 
     $dev->isBlk = $mode == 0060000; // S_IFBLK 
     $dev->isReg = $mode == 0100000; // S_IFREG 
     $dev->isLnk = $mode == 0120000; // S_IFLNK 
     $dev->isSock = $mode == 0140000; // S_IFSOCK 
    } 

    public function __construct() 
    { 
     $this->getMode($this->stdin, STDIN); 
     $this->getMode($this->stdout, STDOUT); 
     $this->getMode($this->stderr, STDERR); 
    } 
} 

$io = new IOMode; 

一些示例用法,显示它可检测到的内容。

输入:

$ php io.php 
// Character device as input 
// $io->stdin->isChr == true 

$ echo | php io.php 
// Input piped from another command 
// $io->stdin->isFifo == true 

$ php io.php < infile 
// Input from a regular file (name taken verbatim from C headers) 
// $io->stdin->isReg == true 

$ mkdir test 
$ php io.php < test 
// Directory used as input 
// $io->stdin->isDir == true 

输出:

$ php io.php 
// $io->stdout->isChr == true 

$ php io.php | cat 
// $io->stdout->isFifo == true 

$ php io.php > outfile 
// $io->stdout->isReg == true 

错误:

$ php io.php 
// $io->stderr->isChr == true 

$ php io.php 2>&1 | cat 
// stderr redirected to stdout AND piped to another command 
// $io->stderr->isFifo == true 

$ php io.php 2>error 
// $io->stderr->isReg == true 

我已经不包含的链接,插座,或块设备的例子,但我们没有理由他们不应该工作,因为设备模式掩盖他们在课堂上。

(在Windows未测试 - 里程可能会发生变化)

+1

非常好,+1 - 在什么情况下会'S_IFLNK'和'S_IFSOCK'返回true? – DaveRandom

+1

@DaveRandom:我从来没有真正发现过(或者需要它们),当我从C头文件中获取掩码时,我将它们包括在内以获得完整性。他们显然是相关的链接和套接字,但是当我尝试时,我无法触发任何东西。 – Leigh

+0

非常感谢。这正是我想要的! :) – Fania

4

posix_isatty()

if (posix_isatty(0)) { 
    // STDIN is a TTY 
} else { 
    // STDIN is a pipe or has no associated TTY 
} 

显然对POSIX兼容的操作系统,其中PHP有posix扩展安装这仅适用。我不知道Windoze等价物。

相关问题