如何在shell脚本中处理输出到STDOUT或STDERR的PHP脚本的输出?

6qfn3psc  于 2023-03-24  发布在  Shell
关注(0)|答案(2)|浏览(183)

假设我在PHP CLI上的shell脚本中运行以下PHP脚本:

<?php
# foo.php

$a = rand(1,5);

if ($a == 1) {
    fwrite(STDOUT, 'normal condition');
} else {
    fwrite(STDERR, 'error condition');
}

脚本在shell中运行如下:

php foo.php

如何根据输出是STDERR还是STDOUT在shell中处理PHP脚本的输出?例如,如果PHP脚本的输出是STDOUT,则将其写入CSV文件,但如果输出是STDERR,则将输出写入错误日志文件。

tpxzln5u

tpxzln5u1#

您可以将每个流重定向到不同的位置。
php file.php > outfile.csv 2> errorlog.txt
有关详细信息,请参见https://askubuntu.com/questions/625224/how-to-redirect-stderr-to-a-file

iyr7buue

iyr7buue2#

产生单个输出文件的一些可能性。
选项1 -将stdoutstderr重定向到单独的文件,然后删除空文件:

php file.php > ./data.csv 2> ./error.txt
[[ ! -s ./data.csv ]] && rm ./data.csv
[[ ! -s ./error.txt ]] && rm ./error.txt

如果文件长度为零,则! -s测试将为true。这个版本使用了一些相当常见的shell习惯用法,并且应该可以在zshbash中工作。这些操作可以组合成一个函数:

phpPost() {
    php ${1:?script required} > ${2:?csv required} 2> ${3:?err required}
    [[ ! -s $2 ]] && rm $2
    [[ ! -s $3 ]] && rm $3
}
phpPost file.php data.csv error.txt

选项2 -将stdoutstderr保存在shell变量中,只有在有输出时才创建文件:

php file.php \
    >  >(d=$(<&0) && [[ -n $d ]] && <<<$d >data.csv) \
    2> >(e=$(<&0) && [[ -n $e ]] && <<<$e >error.txt)

部分作品:

  • >2>-重定向stdoutstderr
  • >(...)- process substitution。shell创建一个子进程(类似于-见下文)并将我们重定向到该进程的输出发送给该进程。
  • t=$(<&0)-将子进程的stdin存储在变量t中。
  • [[ -n ... ]]-测试字符串是否为非空。
  • <<<... > ...-使用here-string将变量内容写入文件。

此版本带有一些警告:

  • 它是特定于zsh的(或者更准确地说,在我对bash进行的非常简短的测试中,它没有工作)。
  • 这不是一个常见的shell习惯用法。
  • 文件不会每次都被覆盖。
  • 进程替换可以由shell异步运行,这意味着在某些情况下,初始命令可能在输出文件完全写入之前完成。在本例中,进程替换中的命令都是zsh内置的,因此shell在单个进程中同步运行它们。此模式的其他变体可能会有不同的行为-如果这是一个问题,则zsh文档描述了一个解决方法。

这也可以写成一个函数:

phpVars() {
    rm ${2:?} ${3:?} 2>/dev/null
    php ${1:?} \
        >  >(d=$(<&0) && [[ -n $d ]] && <<<$d >${2}) \
        2> >(e=$(<&0) && [[ -n $e ]] && <<<$e >${3})
}
phpVars file.php data.csv error.txt

替代解决方案:

  • 通过测试shell return code而不是查看输出文件,可以更容易地检测php命令是否成功。
  • 如果可以更新php代码,则该脚本可以直接写入数据和错误文件,而不是通过shell传递信息。

相关问题