Detect if a PHP script is being run interactively or not

前端 未结 3 435
-上瘾入骨i
-上瘾入骨i 2020-12-13 03:14

I have a script that is designed to be run both as a web page, and via the console.

Detecting which method was used to invoke the script seems pretty straight forwar

相关标签:
3条回答
  • 2020-12-13 03:18

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

    • Is the script being run from the terminal
    • Is the script receiving data via a pipe or from a file
    • Is the output being redirected to a file

    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.

    Input:

    $ 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
    

    Output:

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

    Error:

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

    (Not tested on Windows - mileage may vary)

    0 讨论(0)
  • 2020-12-13 03:21

    For Windows, you can use this:

    $b = stream_isatty(STDIN);
    if ($b) {
       echo "php script.php\n";
    } else {
       echo "php script.php < input_file\n";
    }
    

    https://php.net/function.stream-isatty

    0 讨论(0)
  • 2020-12-13 03:39

    posix_isatty()

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

    Obviously this only works on POSIX compliant operating systems, where PHP has the posix extension installed. I am not aware of a Windoze equivalent.

    0 讨论(0)
提交回复
热议问题