我在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。但我很好奇为什么在这种特殊情况下这不起作用。
EDIT。 我澄清了代码,所以我更清楚的是我在谈论php运行shell命令。
答案 0 :(得分:2)
更新了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字符串,其中单引号禁用参数替换,因此我们可以输入文字文本。(无评估)。然后,我们通过使用log contents
和<<EOF2
创建的另一个here-doc字符串编写了EOF2
。
我们可以保存保存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的文档。