Que pouvez-vous faire avec la eval
commande? Pourquoi est-ce utile? Est-ce une sorte de fonction intégrée dans bash? Il n'y a pas de man
page pour cela ..
help eval
obtenir la page "man" de votre shell
Que pouvez-vous faire avec la eval
commande? Pourquoi est-ce utile? Est-ce une sorte de fonction intégrée dans bash? Il n'y a pas de man
page pour cela ..
help eval
obtenir la page "man" de votre shell
Réponses:
eval
fait partie de POSIX. C'est une interface qui peut être un shell intégré.
Son décrit dans le "Manuel du programmeur POSIX": http://www.unix.com/man-page/posix/1posix/eval/
eval - construct command by concatenating arguments
Il faudra un argument et en construit une commande, qui sera exécutée par le shell. Voici l'exemple de la page de manuel:
1) foo=10 x=foo
2) y='$'$x
3) echo $y
4) $foo
5) eval y='$'$x
6) echo $y
7) 10
$foo
avec la valeur '10'
et $x
avec la valeur 'foo'
.$y
, qui consiste en la chaîne '$foo'
. Le signe dollar doit être échappé avec '$'
.echo $y
.'$foo'
eval
. Il va d'abord évaluer $x
à la chaîne 'foo'
. Nous avons maintenant la déclaration y=$foo
qui sera évaluée y=10
.echo $y
est maintenant la valeur '10'
.C'est une fonction courante dans de nombreuses langues, par exemple Perl et JavaScript. Consultez perldoc eval pour plus d'exemples: http://perldoc.perl.org/functions/eval.html
eval
est une fonction intégrée, pas une fonction. En pratique, les fonctions intégrées se comportent beaucoup comme des fonctions qui n'ont pas de définition dans le langage, mais pas tout à fait (comme cela apparaît si vous êtes assez tordu pour définir une fonction appelée eval
).
Oui, eval
est une commande interne bash, elle est donc décrite dans la bash
page de manuel.
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.
Il est généralement utilisé en combinaison avec une substitution de commande . Sans explicite eval
, le shell tente d' exécuter le résultat d'une substitution de commande et non de l' évaluer .
Dites que vous voulez coder un équivalent de VAR=value; echo $VAR
. Notez la différence dans la façon dont le shell traite les écrits de echo VAR=value
:
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR
<empty line>
Le shell tente de s’exécuter echo
et VAR=value
sous forme de deux commandes distinctes. Cela renvoie une erreur à propos de la deuxième chaîne. La mission reste inefficace.
andcoz@...:~> eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
Le shell fusionne (concatène) les deux chaînes echo
et VAR=value
analyse cette unité en fonction de règles appropriées et l'exécute.Last but not least, eval
peut être une commande très dangereuse. Toute entrée dans une eval
commande doit être soigneusement vérifiée pour éviter les problèmes de sécurité.
eval
n'a pas de page de manuel car ce n'est pas une commande externe séparée, mais plutôt un shell intégré, c'est-à-dire une commande interne à et connue uniquement du shell ( bash
). La partie pertinente de la bash
page de manuel dit:
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
De plus, la sortie if help eval
est:
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
C’est une commande puissante et si vous avez l’intention de l’utiliser, vous devez faire très attention à ne pas risquer de compromettre la sécurité .
L'instruction eval indique au shell de prendre les arguments de eval en tant que commande et de les exécuter via la ligne de commande. C'est utile dans une situation comme celle ci-dessous:
Dans votre script, si vous définissez une commande dans une variable et que vous souhaitez utiliser cette commande ultérieurement, vous devez utiliser eval:
/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
. En d'autres termes, le nom de la commande unique était composé de neuf caractères, espaces et symbole de tuyau compris. .
eval est une commande shell généralement implémentée.
Dans POSIX, il est répertorié dans "2.14. Utilitaires intégrés spéciaux" à l’entrée "eval" .
Ce qui est construit signifie:
Le terme "intégré" implique que le shell peut exécuter l'utilitaire directement et n'a pas besoin de le rechercher.
En termes simples: crée une ligne d’entrée à analyser deux fois .
Le shell a une séquence d'étapes à suivre pour "traiter" une ligne. Vous pouvez regarder cette image et vous rendre compte que eval est la seule ligne qui monte vers la première étape, à gauche. De la description POSIX :
2.1 Introduction de Shell
- Le shell lit son entrée ....
- Le shell décompose l'entrée en jetons: mots et opérateurs
- Le shell analyse les entrées en commandes simples et composées.
- Le shell effectue diverses extensions (séparément) ...
- Le shell effectue la redirection et supprime les opérateurs de redirection et leurs opérandes de la liste des paramètres.
- Le shell exécute une fonction, un fichier intégré, un fichier exécutable ou un script ...
- Le shell attend éventuellement que la commande soit terminée et recueille le statut de sortie.
A l'étape 6, une commande intégrée sera exécutée.
À l'étape 6, eval renvoie la ligne traitée à l'étape 1.
Il s'agit de la seule condition dans laquelle la séquence d'exécution revient.
C'est pourquoi je dis: Avec eval, une ligne d'entrée est analysée deux fois .
Et l'effet le plus important à comprendre. Est - ce une conséquence de la première fois qu'une ligne est soumise aux sept étapes shell ci - dessus, est cite . À l'étape 4 (extensions), il y a également une séquence d'étapes pour effectuer toutes les extensions , dont la dernière est la suppression des devis :
Le retrait des devis doit toujours être effectué en dernier.
Donc, toujours, il y a un niveau de cotation supprimé.
En conséquence de ce premier effet, des parties supplémentaires / différentes de la ligne sont exposées à l'analyse syntaxique du shell et à toutes les autres étapes.
Cela permet d’exécuter des extensions indirectes:
a=b b=c ; eval echo \$$a ### shall produce "c"
Pourquoi? Parce que sur la première boucle, la première $
est citée.
En tant que tel, il est ignoré pour les extensions du shell.
Le prochain $
avec le nom a est développé pour produire "b".
Ensuite, un niveau de citation est supprimé, ce qui rend le premier $
non cité .
Fin de la première boucle.
C'est ensuite sur la seconde boucle que la chaîne $b
est lue par le shell.
Puis étendu à "c"
et donné comme argument à echo
.
Pour "voir" ce que eval produira sur la première boucle (à réévaluer), utilisez echo. Ou toute commande / script / programme qui montre clairement les arguments:
$ a=b b=c
$ eval echo \$$a;
c
Remplacez eval par echo pour "voir" ce qui se passe:
$ echo echo \$$a
echo $b
Il est également possible d'afficher toutes les "parties" d'une ligne avec:
$ printf '<%s> ' echo \$$a
<echo> <$b>
Dans cet exemple, il ne s'agit que d'un écho et d'une variable, mais souvenez-vous-en pour vous aider à évaluer des cas plus complexes.
Il faut dire que: il y a une erreur dans le code ci-dessus, pouvez-vous le voir?.
Facile: il manque des citations.
Comment? tu peux demander. Simple, changeons les variables (pas le code):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
Voir les espaces manquants?
C'est parce que la valeur à l'intérieur a $b
été divisée par le shell.
Si cela ne vous convainc pas, essayez ceci:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list
### of all files in the present directory.
Citations manquantes. Pour que cela fonctionne correctement (ajoutez "$a"
des \"
devis internes et externes ).
Essayez ceci (est parfaitement sûr):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
Il n'y a pas de page de manuel pour cela ..
Non, il n'y a pas de page de manuel indépendante pour cela. La recherche de manuel avec man -f eval
ou même apropos eval
ne montre aucune entrée.
Il est inclus à l'intérieur man bash
. Comme est intégré.
Recherchez "SHELL BUILTIN COMMANDS" puis "eval".
Un moyen plus simple d’obtenir de l’aide est le suivant: Dans bash, vous pouvez help eval
voir l’aide de la fonction intégrée.
Parce qu'il s'agit d'un texte contraignant à coder de manière dynamique.
En d'autres termes: il convertit la liste de ses arguments (et / ou développements de tels arguments) en une ligne exécutée. Si, pour une raison quelconque, un argument a été défini par un attaquant, vous allez exécuter du code d’attaquant.
Ou encore plus simplement, avec eval, vous indiquez à quiconque a défini la valeur d'un ou plusieurs arguments:
Allez, assieds-toi ici et tape n'importe quelle ligne de commande, je l'exécuterai avec mes pouvoirs.
Est-ce dangereux? Cela devrait être clair pour tout le monde.
La règle de sécurité pour eval devrait être:
N'exécutez eval que sur les variables auxquelles vous avez attribué sa valeur.
Lire plus de détails ici .
eval
est une caractéristique des langues les plus interprétées ( TCL
, python
, ruby
...), non seulement des coquilles. Il est utilisé pour évaluer le code de manière dynamique.
Dans les shells, il est implémenté en tant que commande intégrée au shell.
Fondamentalement, eval
prend une chaîne en tant qu'argument et évalue / interprète le code qu'il contient. Dans les shells, eval
peut prendre plus d'un argument, mais il eval
suffit de les concaténer pour former la chaîne à évaluer.
C'est très puissant car vous pouvez construire du code de manière dynamique et l'exécuter, chose que vous ne pouvez pas faire dans des langages compilés comme C.
Comme:
varname=$1 varvalue=$2
eval "$varname=\$varvalue" # evaluate a string like "foo=$varvalue"
# which in Bourne-like shell language
# is a variable assignment.
Mais c’est aussi dangereux, car il est important de nettoyer les parties dynamiques (fournies de l’extérieur) de ce qui est transféré eval
car elles sont interprétées comme du code shell.
Par exemple, ci-dessus, si $1
est evil-command; var
, eval
finirait par évaluer le evil-command; var=$varvalue
code shell et ensuite l'exécuter evil-command
.
La perversité de eval
est souvent exagérée.
OK, c'est dangereux, mais au moins on sait que c'est dangereux.
Beaucoup d'autres commandes évaluera le code shell dans ses arguments , sinon aseptisé, comme ( en fonction de la coquille), [
alias test
, export
, printf
, GNU sed
, awk
et bien sûr sh
/ bash
/ perl
et tous les interprètes ...
Des exemples (ici en utilisant uname
comme evil-command
et $a
en externe fourni des données hygiénisées):
$ 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
Ces commandes sed
, export
... pourraient être considérées comme plus dangereuses car, même si c'est évident eval "$var"
, le contenu de $var
sera évalué en tant que code shell, ce n'est pas si évident avec sed "s/foo/$var/"
ou export "$var=value"
ou [ "$var" -gt 0 ]
. La dangerosité est la même, mais elle est dissimulée dans ces autres commandes.
sed
comme si eval
on passait une chaîne contenue dans une variable, et pour les deux, le contenu de cette chaîne finit par être évalué en tant que code shell, donc sed
c'est aussi dangereux que eval
, c'est ce que je dis. sed
est en train de passer une chaîne contenant uname
(uname n’a pas encore été exécuté) et par l’appel de sed
, la commande uname est exécutée. J'aime pour eval. En fait sed 's/foo/$a/g'
, vous ne transmettez pas de données non normalisées à sed
, ce n'est pas ce dont nous parlons ici.
Cet exemple peut éclairer un peu:
#!/bin/bash
VAR1=25
VAR2='$VAR1'
VAR3='$VAR2'
echo "$VAR3"
eval echo "$VAR3"
eval eval echo "$VAR3"
Sortie du script ci-dessus:
$VAR2
$VAR1
25
eval
. Pensez-vous que certains aspects fondamentaux et critiques de la fonctionnalité eval
ne sont pas abordés dans les réponses existantes? Si oui, expliquez -le et utilisez l'exemple pour illustrer votre explication. S'il vous plaît ne répondez pas dans les commentaires; éditez votre réponse pour la rendre plus claire et plus complète.
type command
pour savoir de quel type est une commande . (type eval
dans ce cas)