【问题标题】:Redirecting I/O in PHP在 PHP 中重定向 I/O
【发布时间】:2011-06-24 18:19:17
【问题描述】:
<?php
    fclose(STDIN);
    fclose(STDOUT);
    fclose(STDERR);

    $STDIN = fopen("/tmp/some-named-pipe", "r");
    $STDOUT = fopen("/tmp/foo.out", "wb");
    $STDERR = fopen("/tmp/foo.err", "wb");

    echo "Hello, World!";                 // goes to /tmp/foo.out, implied STDOUT
    fscanf($STDIN, "%s\n", $top_secret);  // explicit $STDIN, cant use STDIN
?>

为什么重定向到新的 STDOUT 是隐式的,而从新的 STDIN 的重定向必须显式地发生?

【问题讨论】:

标签: php


【解决方案1】:

原来的 STDIN、STDOUT 和 STDERR 是 PHP 中的系统常量。它们在 PHP 初始化时填充标准输入、输出和错误的文件描述符资源。

php.net 文档在常量中描述了以下有关资源的内容:

常量的值;只允许标量和空值。 标量值是整数、浮点数、字符串或布尔值。这是 可以定义资源常量,但不推荐 并可能导致不可预知的行为。

fclose(STDOUT) 被调用时,文件描述符资源被关闭并与STDOUT 常量分离。与常量的默认行为相反,STDOUT 常量发生了变化。

当一个字符串像echo "Hello, World!" 这样被回显时,PHP 不会使用 STDOUT 常量,但它会从操作系统实时查询当前的“标准输出”文件描述符。此外,STDOUT 常量本身一旦被 fclose 就变得不可用。即使像 fwrite(STDOUT, "hello") 这样的声明也将不起作用

当为标准输出配置新的文件描述符时,这个新的文件描述符很方便地放在$STDOUT 中。请注意,这是一个变量而不是常量。根据定义,在 PHP 中重新定义常量是不可能的,系统常量 STDOUT 在这里也不例外。目前无法将新的文件描述符重新分配给 STDOUT 常量。

最终,为了让这项工作更直观,PHP 团队应该考虑使用便利函数来重新分配这些文件描述符,或者至少让系统常量在某种意义上更像“魔术常量”,即它们会自动评估实际文件描述符。

【讨论】:

    【解决方案2】:

    这是一个多次重定向标准输出的例子。 STDOUT的关闭第一次工作,但下一次 需要关闭 $STDOUT。

    <?php
    # Redirecting 10 times ...
    # Need to close 'STDOUT' & '$STDOUT', otherwise the 2nd time
    # the redirecting fails.
    
    for ( $i = 1; $i <= 10; $i++ )
    {
      $sLogName = sprintf("reopen_%02d.log", $i);
      echo "Redirecting to '" . $sLogName . "' ...\n";
    
      fclose(STDOUT);
      fclose($STDOUT);  # Needed for reopening after the first time.
    
      $STDOUT = fopen($sLogName, "w");
      echo "Now logging in file '" . $sLogName . "' ...\n";
    }
    ?>
    

    【讨论】:

      【解决方案3】:

      这仅在类 UNIX 系统(linux 等)中发生,因为当您打开文件时 unix 使用次要文件描述符,因此在进程中 STDIN、STDOUT 和 STDERR 始终为 0,1 和 2。 当你这样做时:

      fclose(STDIN);
      fclose(STDOUT);
      fclose(STDERR);
      
      $STDIN = fopen("/tmp/some-named-pipe", "r");
      $STDOUT = fopen("/tmp/foo.out", "wb");
      $STDERR = fopen("/tmp/foo.err", "wb");
      

      您正在关闭 STDIN (0)、STDOUT (1) 和 STDERR(2),因此当您以相同的顺序打开文件时,它们会得到 0,1 和 2 作为文件描述符。如果你在 Windows 上运行相同的代码,它将无法工作。

      【讨论】:

        【解决方案4】:

        在阅读您的 sn-p 时,我首先看到的是您首先尝试关闭 STDIN、STDOUT 等常量。然后使用具有相同名称的变量打开文件;因此,您使用的值完全不同,$STDIN 与 STDIN 不同。您也许可以使用 define 函数重新定义 STDIN,但我不确定并且没有计算机 atm 无法检查..

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-26
          • 2010-10-22
          • 1970-01-01
          • 1970-01-01
          • 2020-03-08
          • 2013-11-19
          相关资源
          最近更新 更多