我正在处理需要以/usr/bin/php-cgi
而不是/usr/local/bin/php
运行的脚本,而我无法检查stdin
如果我使用/usr/local/bin/php
作为翻译,我可以做类似
if defined('STDIN'){ ... }
这似乎不适用于php-cgi - 看起来总是未定义。我检查了man page for php-cgi,但没有发现它非常有帮助。另外,如果我理解正确,STDIN
常量是php://stdin
的文件句柄。我在某处读到php-cgi
#!/usr/bin/php-cgi -q
STDIN
#!/usr/bin/php-cgi -q
<?php
$stdin = '';
$fh = fopen('php://stdin', 'r');
if($fh)
{
while ($line = fgets( $fh )) {
$stdin .= $line;
}
fclose($fh);
}
echo $stdin;
这样可行:
$ echo hello | ./myscript.php
hello
这只是挂起:
./myscript.php
defined('STDIN')
//始终返回false CONTENT_LENGTH
我已将此添加到脚本中并以两种方式运行:
print_r(get_defined_constants());
print_r($GLOBALS);
print_r($_COOKIE);
print_r($_ENV);
print_r($_FILES);
print_r($_GET);
print_r($_POST);
print_r($_REQUEST);
print_r($_SERVER);
echo shell_exec('printenv');
然后我对输出进行了差异化,它是相同的。
我不知道通过stdin
检查/获取php-cgi
的任何其他方法,如果不存在则锁定脚本。
/usr/bin/php-cgi -v
收益:PHP 5.4.17 (cgi-fcgi)
答案 0 :(得分:3)
您可以使用选择功能,例如:
$stdin = '';
$fh = fopen('php://stdin', 'r');
$read = array($fh);
$write = NULL;
$except = NULL;
if ( stream_select( $read, $write, $except, 0 ) === 1 ) {
while ($line = fgets( $fh )) {
$stdin .= $line;
}
}
fclose($fh);
答案 1 :(得分:1)
关于没有输入时挂起的具体问题:默认情况下,php流读取是阻塞操作。您可以使用stream_set_blocking()
更改该行为。像这样:
$fh = fopen('php://stdin', 'r');
stream_set_blocking($fh, false);
$stdin = fgets($fh);
echo "stdin: '$stdin'"; // immediately returns "stdin: ''"
请注意this solution does not work with that magic file handle STDIN
.
答案 2 :(得分:1)
stream_get_meta_data
帮助了我:)
正如Seth Battin stream_set_blocking($fh, false);
在上一个回答中所提到的,效果很好?
如果提供的话,下一个代码从命令行读取数据,如果不提供则跳过。
例如:
echo "x" | php render.php
和php render.php
在第一种情况下,我从另一个流中提供了一些数据(我确实需要从git查看更改过的文件,类似git status | php render.php
。
以下是我的解决方案的示例:
$input = [];
$fp = fopen('php://stdin', 'r+');
$info = stream_get_meta_data($fp);
if (!$info['seekable'] && $fp) {
while (false !== ($line = fgets($fp))) {
$input[] = trim($line);
}
fclose($fp);
}
答案 3 :(得分:0)
问题是您在代码中使用while($line = fgets($fh))
部分创建无限循环。
$stdin = '';
$fh = fopen('php://stdin','r');
if($fh) {
// read *one* line from stdin upto "\r\n"
$stdin = fgets($fh);
fclose($fh);
}
echo $stdin;
如果您传递echo foo=bar | ./myscript.php
之类的参数,并且在您调用./myscript.php
时会读取一行,则上述情况会有效
如果您想阅读更多行并保留原始代码,可以发送退出信号CTRL + D
要获取像./myscript.php foo=bar
那样传递的参数,您可以检查$argv
变量的内容,其中第一个参数始终是执行脚本的名称:
./myscript.php foo=bar
// File: myscript.php
$stdin = '';
for($i = 1; $i < count($argv); i++) {
$stdin .= $argv[$i];
}
我不确定这会解决任何问题,但也许会给你一些想法。