Was können Sie mit dem eval
Befehl machen? Warum ist es nützlich? Ist es eine Art integrierte Funktion in Bash? Es gibt keine man
Seite dafür ..
help eval
um "man" Seite von deiner Shell zu bekommen
Was können Sie mit dem eval
Befehl machen? Warum ist es nützlich? Ist es eine Art integrierte Funktion in Bash? Es gibt keine man
Seite dafür ..
help eval
um "man" Seite von deiner Shell zu bekommen
Antworten:
eval
ist ein Teil von POSIX. Es ist eine Schnittstelle, die eine eingebaute Shell sein kann.
Es ist im "POSIX Programmer's Manual" beschrieben: http://www.unix.com/man-page/posix/1posix/eval/
eval - construct command by concatenating arguments
Es nimmt ein Argument und erstellt daraus einen Befehl, der von der Shell ausgeführt wird. Dies ist das Beispiel der Manpage:
1) foo=10 x=foo
2) y='$'$x
3) echo $y
4) $foo
5) eval y='$'$x
6) echo $y
7) 10
$foo
mit dem Wert '10'
und $x
mit dem Wert 'foo'
.$y
, welches aus dem String besteht '$foo'
. Das Dollarzeichen muss mit maskiert werden '$'
.echo $y
.'$foo'
eval
. Es wird zuerst $x
die Zeichenfolge ausgewertet 'foo'
. Jetzt haben wir die Anweisung, y=$foo
die ausgewertet wird y=10
.echo $y
ist jetzt der Wert '10'
.Dies ist eine in vielen Sprachen übliche Funktion, z. B. Perl und JavaScript. Weitere Beispiele finden Sie in perldoc eval: http://perldoc.perl.org/functions/eval.html
eval
ist dies eine integrierte Funktion, keine Funktion. In der Praxis verhalten sich eingebaute Funktionen ähnlich wie Funktionen, die keine sprachspezifische Definition haben, aber nicht ganz (wie sich zeigt, wenn Sie so verdreht sind, dass Sie eine aufgerufene Funktion definieren eval
).
Ja, es eval
handelt sich um einen internen bash-Befehl, der in der bash
Manpage beschrieben wird.
eval [arg ...]
The args are read and concatenated together into a single com-
mand. This command is then read and executed by the shell, and
its exit status is returned as the value of eval. If there are
no args, or only null arguments, eval returns 0.
Normalerweise wird es in Kombination mit einer Befehlsersetzung verwendet . Ohne einen expliziten Befehl eval
versucht die Shell , das Ergebnis einer Befehlssubstitution auszuführen und nicht auszuwerten .
Angenommen, Sie möchten ein Äquivalent von codieren VAR=value; echo $VAR
. Beachten Sie den Unterschied in der Art und Weise, wie die Shell die folgenden Schriften verarbeitet echo VAR=value
:
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR
<empty line>
Die Shell versucht, echo
und VAR=value
als zwei separate Befehle auszuführen. Es wird ein Fehler bezüglich der zweiten Zeichenfolge ausgegeben. Die Abtretung bleibt unwirksam.
andcoz@...:~> eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
Die Shell führt die beiden Zeichenfolgen zusammen (verkettet sie) echo
und VAR=value
analysiert diese einzelne Einheit gemäß den entsprechenden Regeln und führt sie aus.Last but not least eval
kann ein sehr gefährlicher Befehl sein. Alle Eingaben in einen eval
Befehl müssen sorgfältig geprüft werden, um Sicherheitsprobleme zu vermeiden.
eval
hat keine Manpage, da es sich nicht um einen separaten externen Befehl handelt, sondern um eine integrierte Shell, dh einen internen Befehl, der nur der shell ( bash
) bekannt ist. Der relevante Teil der bash
Manpage sagt:
eval [arg ...]
The args are read and concatenated together into a single command.
This command is then read and executed by the shell, and its exit
status is returned as the value of eval. If there are no args, or only
null arguments, eval returns 0
Zusätzlich ist die Ausgabe wenn help eval
:
eval: eval [arg ...]
Execute arguments as a shell command.
Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.
Exit Status:
Returns exit status of command or success if command is null.
eval
ist ein leistungsfähiger Befehl, und wenn Sie ihn verwenden möchten, sollten Sie sehr vorsichtig sein, um die damit verbundenen möglichen Sicherheitsrisiken zu vermeiden .
Die eval-Anweisung weist die Shell an, die Argumente von eval als Befehl zu nehmen und über die Befehlszeile auszuführen. Dies ist in folgenden Situationen nützlich:
Wenn Sie in Ihrem Skript einen Befehl in einer Variablen definieren und später diesen Befehl verwenden möchten, sollten Sie eval verwenden:
/home/user1 > a="ls | more"
/home/user1 > $a
bash: command not found: ls | more
/home/user1 > # Above command didn't work as ls tried to list file with name pipe (|) and more. But these files are not there
/home/user1 > eval $a
file.txt
mailids
remote_cmd.sh
sample.txt
tmp
/home/user1 >
ls | more
. Mit anderen Worten: Der einzelne Befehlsname bestand aus neun Zeichen, einschließlich der Leerzeichen und des Pipe-Symbols .
eval ist ein Shell-Befehl, der normalerweise als eingebauter Befehl implementiert wird.
In POSIX ist es als Teil von "2.14. Special Built-In Utilities" unter dem Eintrag "eval" aufgeführt .
Was Builtin bedeutet, ist:
Der Begriff "eingebaut" impliziert, dass die Shell das Dienstprogramm direkt ausführen kann und nicht danach suchen muss.
In einfachen Worten: Lässt eine Eingabezeile zweimal analysiert werden .
Die Shell hat eine Abfolge von Schritten, die zum "Verarbeiten" einer Zeile ausgeführt werden. Sie können sich dieses Bild ansehen und feststellen, dass eval die einzige Zeile ist, die nach oben zurück zu Schritt 1 auf der linken Seite führt. Aus der POSIX-Beschreibung :
2.1 Shell Einführung
- Die Shell liest ihre Eingabe ....
- Die Shell unterteilt die Eingabe in Token: Wörter und Operatoren
- Die Shell analysiert die Eingabe in einfache und zusammengesetzte Befehle.
- Die Shell führt verschiedene Erweiterungen (separat) durch ...
- Die Shell führt eine Umleitung durch und entfernt Umleitungsoperatoren und deren Operanden aus der Parameterliste.
- Die Shell führt eine Funktion, eine eingebaute ausführbare Datei oder ein Skript aus ...
- Die Shell wartet optional auf den Abschluss des Befehls und erfasst den Beendigungsstatus.
In Schritt 6 wird eine eingebaute ausgeführt.
In Schritt 6 bewirkt eval, dass die verarbeitete Zeile zu Schritt 1 zurückgesendet wird.
Dies ist die einzige Bedingung, unter der die Ausführungssequenz zurückgeht.
Deshalb sage ich: Bei eval wird eine Eingabezeile zweimal analysiert .
Und wichtigste Wirkung zu verstehen. Ist das eine Konsequenz des ersten Males, dass eine Zeile den oben gezeigten sieben Shell-Schritten unterliegt, so wird zitiert . Innerhalb von Schritt 4 (Erweiterungen) gibt es auch eine Abfolge von Schritten, um alle Erweiterungen durchzuführen , von denen der letzte das Entfernen von Zitaten ist :
Das Entfernen des Angebots erfolgt immer zuletzt.
Es wird also immer eine Quote-Ebene entfernt.
Infolge dieses ersten Effekts werden zusätzliche / unterschiedliche Teile der Linie dem Shell-Parsing und allen anderen Schritten ausgesetzt.
Damit können indirekte Erweiterungen durchgeführt werden:
a=b b=c ; eval echo \$$a ### shall produce "c"
Warum? Denn in der ersten Schleife wird die erste $
zitiert.
Als solches wird es für Erweiterungen durch die Shell ignoriert.
Das nächste $
mit dem Namen a wird erweitert, um "b" zu erzeugen.
Dann wird eine Zitierebene entfernt, wodurch die erste $
nicht zitiert wird .
Ende der ersten Schleife.
In der zweiten Schleife wird die Zeichenfolge $b
dann von der Shell gelesen.
Dann auf "c" erweitert
und als Argument an gegeben echo
.
Um zu "sehen", was eval in der ersten Schleife erzeugt (um erneut ausgewertet zu werden), verwenden Sie echo. Oder ein Befehl / Skript / Programm, das die Argumente klar anzeigt:
$ a=b b=c
$ eval echo \$$a;
c
Ersetzen Sie eval durch echo, um zu sehen, was gerade passiert:
$ echo echo \$$a
echo $b
Es ist auch möglich, alle "Teile" einer Zeile anzuzeigen mit:
$ printf '<%s> ' echo \$$a
<echo> <$b>
Dies ist in diesem Beispiel nur ein Echo und eine Variable. Denken Sie jedoch daran, dass dies bei der Bewertung komplexerer Fälle hilfreich ist.
Es muss gesagt werden, dass: Es gibt einen Fehler im obigen Code, können Sie es sehen ?.
Ganz einfach: Es fehlen einige Anführungszeichen.
Wie? du darfst fragen. Einfach, lassen Sie uns die Variablen ändern (nicht den Code):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
Sehen Sie die fehlenden Leerzeichen?
Das liegt daran, dass der innere Wert $b
von der Shell geteilt wurde.
Wenn Sie das nicht überzeugt, versuchen Sie Folgendes:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list
### of all files in the present directory.
Fehlende Anführungszeichen. Damit es richtig funktioniert (fügen Sie interne "$a"
und externe \"
Anführungszeichen hinzu).
Versuchen Sie dies (ist absolut sicher):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
Es gibt keine Manpage dafür.
Nein, dafür gibt es keine eigenständige Manpage. Die Suche nach Handbuch mit man -f eval
oder apropos eval
ohne Eintrag.
Es ist im Inneren enthalten man bash
. Wie ist jeder eingebaut.
Suchen Sie nach "SHELL BUILTIN COMMANDS" und dann nach "eval".
Eine einfachere Möglichkeit, Hilfe zu erhalten, ist: In bash können Sie help eval
die Hilfe für das integrierte Programm anzeigen .
Weil es Text bindet, um dynamisch zu codieren.
Mit anderen Worten: Es konvertiert die Liste seiner Argumente (und / oder Erweiterungen solcher Argumente) in eine ausgeführte Zeile. Wenn ein Angreifer aus irgendeinem Grund ein Argument festgelegt hat, führen Sie Angreifercode aus.
Oder noch einfacher: Mit eval sagen Sie, wer den Wert eines oder mehrerer Argumente definiert hat:
Komm schon, setz dich hier und tippe eine beliebige Befehlszeile, ich werde sie mit meinen Kräften ausführen.
Ist das gefährlich Sollte für alle klar sein, dass es ist.
Die Sicherheitsregel für eval sollte lauten:
Führen Sie eval nur für Variablen aus, denen Sie den Wert gegeben haben.
Lesen Sie hier mehr Details .
eval
ist ein Merkmal der meisten interpretierten Sprachen ( TCL
, python
, ruby
...), nicht nur Muscheln. Es wird verwendet, um Code dynamisch auszuwerten.
In Shells wird es als eingebauter Shell-Befehl implementiert.
Nimmt im Grunde genommen eval
einen String als Argument und wertet / interpretiert den darin enthaltenen Code aus. In Shells eval
können mehrere Argumente verwendet werden, diese werden jedoch eval
nur verkettet, um die auszuwertende Zeichenfolge zu bilden.
Es ist sehr leistungsstark, da Sie Code dynamisch erstellen und ausführen können, was in kompilierten Sprachen wie C nicht möglich ist.
Mögen:
varname=$1 varvalue=$2
eval "$varname=\$varvalue" # evaluate a string like "foo=$varvalue"
# which in Bourne-like shell language
# is a variable assignment.
Aber es ist auch gefährlich , wie es ist wichtig , die dynamischen (extern zur Verfügung gestellt) Teile zu sanieren , was vergangen ist eval
aus dem Grunde , sie als Shell - Code interpretiert wird .
Zum Beispiel, wenn oben $1
ist evil-command; var
, eval
würde am Ende-up des Auswertung evil-command; var=$varvalue
Shell - Code und dann die ausgeführt evil-command
.
Die Bösartigkeit von eval
ist oft übertrieben.
OK, es ist gefährlich, aber zumindest wissen wir, dass es gefährlich ist.
Viele andere Befehle Shell - Code in ihre Argumente zu bewerten , wenn nicht desinfiziert, wie ( in Abhängigkeit von der Schale), [
auch bekannt als test
, export
, printf
, GNU sed
, awk
und natürlich sh
/ bash
/ perl
und alle Dolmetscher ...
Beispiele (hier unter Verwendung uname
der evil-command
und $a
als extern zur Verfügung gestellten nicht bereinigten Daten):
$ a='$(uname>&2)' sh -c 'eval "echo $a"'
Linux
$ a='x[0$(uname>&2)]' mksh -c 'export "$a=$b"'
Linux
$ a='x[0$(uname>&2)]' ksh93 -c 'printf "%d\n" "$a"'
Linux
0
$ a='x[0$(uname>&2)]' ksh93 -c '[ "$a" -gt 0 ]'
Linux
$ a=$'bar/g;e uname>&2\n;s//'; echo foo | sed "s/foo/$a/g"
Linux
bar
$ a='";system("uname");"'; awk "BEGIN{print \"$a\"}"
Linux
$ a=';uname'; sh -c "echo $a"
Linux
Diese sed
, export
... -Befehle könnten als gefährlicher angesehen werden, da eval "$var"
der Inhalt von zwar offensichtlich $var
als Shell-Code ausgewertet wird, aber mit sed "s/foo/$var/"
oder export "$var=value"
oder nicht so offensichtlich ist [ "$var" -gt 0 ]
. Die Gefährlichkeit ist dieselbe, aber sie ist in diesen anderen Befehlen verborgen.
sed
wie eval
wird eine Zeichenkette in einer Variablen enthalten sind vergangen, und sowohl für den Inhalt dieser Zeichenfolge endet als Shell - Code ausgewertet werden, so sed
gefährlich ist wie eval
, das ist , was ich sage. sed
wird ein String übergeben, der enthält uname
(uname wurde bisher noch nicht ausgeführt) und durch den Aufruf von sed
wird der Befehl uname ausgeführt. Wie für eval. In sed 's/foo/$a/g'
, vorbei sind Sie nicht aufpoliert Daten sed
, das ist nicht das, was wir hier reden.
Dieses Beispiel könnte etwas Licht ins Dunkel bringen:
#!/bin/bash
VAR1=25
VAR2='$VAR1'
VAR3='$VAR2'
echo "$VAR3"
eval echo "$VAR3"
eval eval echo "$VAR3"
Ausgabe des obigen Skripts:
$VAR2
$VAR1
25
eval
. Glauben Sie, dass es einen grundlegenden, kritischen Aspekt der Funktionalität eval
gibt, der in den vorhandenen Antworten nicht behandelt wird? Wenn ja, erklären Sie es und veranschaulichen Sie Ihre Erklärung anhand des Beispiels. Bitte antworten Sie nicht in Kommentaren; Bearbeiten Sie Ihre Antwort, um sie klarer und vollständiger zu gestalten.
type command
erfahren Sie, welcher Typ ein Befehl ist. (type eval
in diesem Fall)