2012-07-04 2 views
10

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

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

php script.php против php 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' возвращает истину? – 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.

Смежные вопросы