2016-04-29 11 views
4

Ich habe etwas ähnliches wie dies in einem PHP-Skript:Shell heredoc innerhalb php heredoc

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

Wie Sie sehen können, die beiden Heredocs (BASH ist PHP und EOF ist Shell) Ende, wie man denken würde, richtig ist, aber wenn ich lese, erstellt das Protokoll das Protokoll so etwas wie dieses hat:

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

und ich überprüfen sie die apache-Log und es hat die folgenden Einträge:

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

Was mache ich falsch?

Bitte beachten Sie, dass es viele andere Implementierungen gibt, z. B. die Verwendung von PHP-Funktionen oder die Verwendung von Anführungszeichen anstelle von Heredocs. Aber ich bin neugierig, warum das in diesem speziellen Fall nicht funktioniert.

BEARBEITEN. Ich klärte den Code, so dass es klarer ist, dass ich über php running Shell-Befehle spreche.

+0

'<<< BASH' ist eine Here-String und kein' Here-Doc'. 'Here-String' benötigt kein Trennzeichen, um sein Ende zu markieren. – sjsam

Antwort

2

Aktualisiert Antwort für PHP Fall

Angenommen, wir haben test.php-Datei mit folgendem Inhalt:

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

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

mylog(); 

Dann erzeugt php test.php das Richtige (!):

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

Ausgabe:

test 

Jetzt wollen wir den Bash Teil einrücken:

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

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

mylog(); 

Jetzt php test.php produziert genau das, was Sie in Ihrer Frage geschrieben haben:

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

Ausgang:

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

Anscheinend haben Sie Ihren Bash-Teil eingerückt, was eine ungültige Bash-Syntax ist. Sie müssen also nur den Einzug für den Bash-Teil entfernen. Zumindest EOF sollte nicht eingerückt werden.

Original-Antwort, wo ich die OP dachte bedeutete reine Bash

exec einen Befehl ausführt, aber Sie müssen bash Ausdruck auszuwerten. Sie brauchen also eval statt.

eval "$(
cat <<'EOF' 

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

EOF 
)" 

So wir eine Bash Variable mit "$( konstruiert und )":

Um den Befehl eval verwenden Sie die folgende Konstruktion.Innerhalb der Variable haben wir eine here-doc-Zeichenkette mit cat <<'EOF' und EOF erstellt, wobei einfache Anführungszeichen die Parameterersetzung deaktivieren, sodass wir literalen Text eingeben können (keine Auswertung). Dann haben wir log contents mittels einer anderen Here-Doc-Zeichenfolge geschrieben, die mit <<EOF2 und EOF2 erstellt wurde.

könnten Wir speichern die Bash Variablen speichern, es dann so oft nutzen, wie wir wollen:

cmd="$(
cat <<'EOF' 

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

EOF 
)" 

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

Ausgang:

log contents 
log contents 
log contents 

docs für here documents See.

+0

der [tldp] (http://www.tldp.org/LDP/Bash-Beginners-Guide/html/Bash-Beginners-Guide.html) Bash Guide ist veraltet und in einigen Fällen einfach falsch. Ich empfehle stattdessen [Bash Guide] (http://mywiki.wooledge.org/BashGuide). –

+0

habe ich etwas vermisst oder gibt es überhaupt kein PHP in dieser Antwort? –

+0

@ santiagoarizti, ah, ja. Irgendwie dachte ich an Pure Bash. Ich werde meine Antwort reparieren. –