17

Webページとしてもコンソール経由でも実行できるように設計されたスクリプトがあります。

スクリプトを呼び出すために使用されたメソッドの検出は非常に簡単に思えますが、スクリプトがコンソールから実行されている場合、スクリプトがインタラクティブに実行されているかどうかを知る必要があります(ユーザー入力コマンド、またはファイルからリダイレクトされた入力) 。

php script.phpphp script.php < input_file

これは可能ですか?

4

3 に答える 3

36

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ではテストされていません-マイレージは異なる場合があります)

于 2012-07-04T10:40:47.980 に答える
5

posix_isatty()

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

posix明らかに、これは、PHPに拡張機能がインストールされているPOSIX準拠のオペレーティングシステムでのみ機能します。Windozeに相当するものを私は知りません。

于 2012-07-04T10:39:37.777 に答える