Обнаруживать, запускается ли скрипт PHP в интерактивном режиме или нет.

У меня есть сценарий, который предназначен для запуска как веб-страницы, так и через консоль.

Обнаружение того, какой метод использовался для вызова скрипта, выглядит довольно прямолинейно, но когда скрипт запускается с консоли, мне нужно знать, запускается ли сценарий в интерактивном режиме или нет (команды ввода пользователем или ввод, перенаправленный из файла) ,

php script.php и php script.php < input_file

Это возможно?

Мне также понадобилось немного более гибкое решение, чем 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 – пробег может отличаться)

posix_isatty()

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

Очевидно, что это работает только на совместимых с POSIX операционных системах, где PHP имеет posix расширение posix . Я не знаю эквивалента Windoze.