【发布时间】:2012-07-04 20:33:00
【问题描述】:
我有一个脚本,它既可以作为网页运行,也可以通过控制台运行。
检测用于调用脚本的方法似乎很简单,但是当从控制台运行脚本时,我需要知道脚本是否以交互方式运行(用户键入命令,或从一个文件)。
php script.php
相对
php script.php < input_file
这可能吗?
【问题讨论】:
标签: php
我有一个脚本,它既可以作为网页运行,也可以通过控制台运行。
检测用于调用脚本的方法似乎很简单,但是当从控制台运行脚本时,我需要知道脚本是否以交互方式运行(用户键入命令,或从一个文件)。
php script.php
相对
php script.php < input_file
这可能吗?
【问题讨论】:
标签: php
我还需要一个比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 上测试 - 里程可能会有所不同)
【讨论】:
S_IFLNK 和 S_IFSOCK 会返回 true?
STD* 流,这些不应该是正确的,它们适用于“正确的”文件流。块设备(通常是某种类型的硬盘)也是如此。
if (posix_isatty(0)) {
// STDIN is a TTY
} else {
// STDIN is a pipe or has no associated TTY
}
显然这只适用于 POSIX 兼容的操作系统,其中 PHP 安装了 posix 扩展。我不知道 Windoze 等价物。
【讨论】:
对于 Windows,您可以使用:
$b = stream_isatty(STDIN);
if ($b) {
echo "php script.php\n";
} else {
echo "php script.php < input_file\n";
}
【讨论】: