在php heredoc里面的壳heredoc

我在php脚本中有类似的东西:

<?php
...
function log() {
    // saving the log into a file.
    exec(<<<BASH
cat >> $logFile <<EOF
$log
EOF
BASH
    );
}
...

你可以看到两个heredocs(BASH是php和EOF是shell)结束,因为人们认为是正确的,但当我读到创建的日志时,日志有这样的东西:

...
my logged string of an important event
EOF
my logged string of another important event
EOF
...

我检查apache日志,它有以下条目:

sh: line 1: warning: here-document at line 0 delimited by end-of-file (wanted `EOF')

我究竟做错了什么?

请注意,我知道有许多其他实现,例如使用php函数或使用引号而不是heredocs.但我很好奇为什么在这种特殊情况下这不起作用.

编辑.
我澄清了代码,所以我更清楚的是我在谈论php运行shell命令.

最佳答案 更新了PHP案例的答案

假设我们有test.php文件,其中包含以下内容:

<?php
function mylog() {
  $logFile = 'test.log';
  $log = 'test';

  exec(<<<BASH
cat >> $logFile <<EOF
$log
EOF
BASH
     );
}

mylog();

然后php test.php生成正确的东西(!):

rm -f test.log
php test.php
cat test.log

输出:

test

现在让我们缩进Bash部分:

<?php
function mylog() {
  $logFile = 'test.log';
  $log = 'test';

  exec(<<<BASH
  cat >> $logFile <<EOF
  $log
  EOF
BASH
     );
}

mylog();

现在php test.php产生了你在你的文章中所写的内容
题:

rm -f test.log
php test.php
cat test.log

输出:

sh: line 2: warning: here-document at line 0 delimited by end-of-file (wanted `EOF')
  test
  EOF

显然,你的Bash部分是缩进的,这是一种无效的Bash语法.所以你只需要删除Bash部分的缩进.至少,EOF不应缩进.

原来的答案,我认为OP意味着纯粹的Bash

exec执行命令,但您需要评估bash表达式.所以你需要eval代替.

要使用eval构造命令,请使用以下命令:

eval "$(
cat <<'EOF'

cat >> test.log <<EOF2
log contents
EOF2

EOF
)"

所以我们用“$(和)”构造了一个Bash变量.在变量中,我们使用cat<<‘EOF’和EOF创建了一个here-doc字符串,其中单引号禁用参数替换,因此我们可以输入文字文本.(无评估).然后我们通过另一个用<<<< EOF2和EOF2创建的here-doc字符串写入日志内容. 我们可以保存保存Bash变量,然后根据需要多次使用它:

cmd="$(
cat <<'EOF'

cat >> test.log <<EOF2
log contents
EOF2

EOF
)"

rm test.log
eval "$cmd"; eval "$cmd"; eval "$cmd"
cat test.log

输出:

log contents
log contents
log contents

请参阅here documents的文档.

点赞