且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

检测PHP脚本是否正在以交互方式运行

更新时间:2023-12-04 21:40:40

I also needed a slightly more flexible solution than posix_isatty that could detect:

  • 该脚本是否正在从终端运行
  • 脚本是通过管道还是从文件接收数据
  • 输出是否被重定向到文件

经过一些libc标头的试验和挖掘之后,我想到了一个非常简单的类,可以完成上述所有操作以及更多操作.

After a bit of experimenting and digging around through libc headers, I came up with a very simple class that can do all of the above and more.

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;

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

Some example usage, to show what it can detect.

输入:

$ 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

我没有提供链接,套接字或块设备的示例,但是没有理由它们不起作用,因为它们的设备模式掩码在类中.

I've not included examples for links, sockets, or block devices, but there's no reason they shouldn't work, as the device mode masks for them are in the class.

(未在Windows上进行测试-里程可能会有所不同)

(Not tested on Windows - mileage may vary)