【问题标题】:Does PHP support process substitution?PHP 是否支持进程替换?
【发布时间】:2016-08-08 13:58:14
【问题描述】:

我正在尝试以下示例,例如:

$ php -r 'require_once($argv[1]);' <(echo "hello")

或:

$ php -r 'file_get_contents($argv[1]);' <(echo "hello")

都失败了:

PHP 警告:require_once(/dev/fd/63):打开流失败:第 1 行的命令行代码中没有这样的文件或目录

PHP 警告:file_get_contents(/dev/fd/63):未能打开流:第 1 行的命令行代码中没有此类文件或目录

或:

$ php -r 'file_get_contents($argv[0]);' < <(echo "hello")

失败:

PHP 致命错误:require_once(): Failed opening required '-' (include_path='.:/usr/share/pear:/usr/share/php') 在第 1 行的命令行代码中

以上尝试的灵感来自drush命令,例如:

$ drush --early=<(echo print 123';') ""
[warning] require_once(/dev/fd/63): failed to open stream: No such file or directory preflight.inc:58

我可以从文件描述符中注入动态 PHP 代码(无需每次都创建单独的文件),以便在引导主代码之前执行代码。


其他类似的命令工具也能正常工作:

$ cat <(echo "hello")
hello

或:

$ python -c "import sys; print sys.stdin.readlines()" < <(echo "hello")
['hello\n']

我找到了这个PHP bugthis one,但这些早就修复了,我使用的是 5.6.22。

当从 CLI 调用时,我有什么方法可以欺骗 PHP 从进程替换中读取数据(从文件描述符中读取,例如/dev/fd),通过使用一些简单的单线?

【问题讨论】:

    标签: php shell command-line-interface stdin process-substitution


    【解决方案1】:

    错误信息给出了一个很好的提示:PHP 找不到给定的文件。

    但是等等,什么文件?好吧,让我们记住 process substitution 是什么:

    进程替换是一种重定向形式,其中进程的输入或输出(某些命令序列)显示为临时文件。

    所以当你打印你以这种方式提供的参数时,你会看到:

    $ php -r 'print $argv[1];' <(echo "a")
    

    对我来说,它返回以下临时文件:

    /dev/fd/63
    

    所以是的,您可以使用 PHP 进行进程替换,但不能用于此。

    如果您想要使用命令的输出作为参数,只需使用$() 来扩展它:

    $ php -r 'print $argv[1];' "$(echo "hello man")"
    hello man
    

    【讨论】:

    • $argv[1] 正在返回文件描述符(/dev/fd/63),所以这是正确的,但我不知道为什么它无法读取它。您的最后一个示例是使用命令替换,而不是进程替换。所以我很想看看带有进程替换的示例。
    • @kenorb 问题是这里的进程替换提供了一个文件描述符,它从中读取字符串“a”。您无法预先确定文件描述符的内容,以便它包含您想要的数据。你到底想做什么?提供变量文件名?
    • 我在玩 drush:drush --early=&lt;(echo print 123) "" 这给了我require_once(/dev/fd/63) 错误,所以我想知道是否可以使用其他语法,因为在这种情况下使用命令替换不起作用。可能是另一个问题,但另一方面与此太相似了。基本上不是专门去催的,但我想知道PHP是否可以支持文件描述,无论是bug还是设计。
    • @kenorb 我明白了。我认为在这里使用进程替换没有多大意义,因为它通常是一种绕过管道的方法。检查Process substitution 以获得很好的例子。我会关注为什么--early="$(echo 123)" 不起作用,因为命令替换似乎更方便这种情况:您希望将命令的输出用作参数。
    • 是的,拜托,$(echo 123) 将在该语法中查找文件 123,而不是内容。
    猜你喜欢
    • 2011-04-28
    • 2014-01-11
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    • 2014-03-10
    • 2020-09-06
    • 1970-01-01
    相关资源
    最近更新 更多