このeval
コマンドで何ができますか?なぜ便利なのですか?それはbashの組み込み関数の一種ですか?そのためのman
ページはありません。
help eval
あなたのシェルから「男」ページを取得する
このeval
コマンドで何ができますか?なぜ便利なのですか?それはbashの組み込み関数の一種ですか?そのためのman
ページはありません。
help eval
あなたのシェルから「男」ページを取得する
回答:
eval
POSIXの一部です。シェルの組み込みが可能なインターフェイス。
「POSIX Programmer's Manual」に記載されています:http : //www.unix.com/man-page/posix/1posix/eval/
eval - construct command by concatenating arguments
引数を取り、そのコマンドを作成します。コマンドはシェルによって実行されます。これはマンページの例です:
1) foo=10 x=foo
2) y='$'$x
3) echo $y
4) $foo
5) eval y='$'$x
6) echo $y
7) 10
$foo
で、値'10'
と値を定義し$x
ます'foo'
。$y
、文字列で構成されるdefineを定義します'$foo'
。ドル記号はでエスケープする必要があります'$'
。echo $y
。'$foo'
eval
ます。最初に$x
文字列に評価されます'foo'
。これで、y=$foo
評価されるステートメントができましたy=10
。echo $y
は現在値'10'
です。これは、PerlやJavaScriptなど、多くの言語で一般的な機能です。他の例については、perldoc evalをご覧ください:http : //perldoc.perl.org/functions/eval.html
eval
は、は組み込み関数であり、関数ではありません。実際には、組み込み関数は、言語内定義を持たない関数のように動作しますが、完全ではありません(呼び出される関数を定義するほどひねられている場合に明らかになりますeval
)。
はい、eval
bashの内部コマンドなので、bash
manページで説明されています。
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.
通常、コマンド置換と組み合わせて使用されます。明示的に指定しないeval
と、シェルはコマンド置換の結果を評価するのではなく、実行しようとします。
と同等のコードを作成するとしVAR=value; echo $VAR
ます。シェルが以下の記述を処理する方法の違いに注意してくださいecho VAR=value
。
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR
<empty line>
シェルは、実行しようecho
とVAR=value
二つの別々のコマンドとして。2番目の文字列に関するエラーをスローします。割り当ては無効のままです。
andcoz@...:~> eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
シェルは2つの文字列echo
をマージ(連結)し、VAR=value
適切なルールに従ってこの単一ユニットを解析して実行します。最後にeval
なりましたが、非常に危険なコマンドになる可能性があります。eval
セキュリティの問題を回避するために、コマンドへの入力は慎重に確認する必要があります。
eval
別個の外部コマンドではなく、シェル組み込みコマンドであるため、manページはありません。これは、シェルの内部コマンドであり、シェルのみが知っているコマンドbash
です()。bash
マニュアルページの関連部分には次のように書かれています。
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
さらに、出力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
は強力なコマンドであり、使用する場合は、それに伴う可能性のあるセキュリティリスクを回避するように注意する必要があります。
evalステートメントは、シェルにevalの引数をコマンドとして受け取り、コマンドラインで実行するように指示します。以下のような状況で役立ちます。
スクリプトで変数にコマンドを定義し、後でそのコマンドを使用する場合は、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
。つまり、スペースとパイプ記号を含む9文字。
evalは、組み込みコマンドとして通常実装されるシェルコマンドです。
POSIXでは、エントリ"eval"の "2.14。Special Built-In Utilities"の一部としてリストされています。
組み込みの意味は次のとおりです。
「ビルトイン」という用語は、シェルがユーティリティを直接実行でき、検索する必要がないことを意味します。
簡単に言うと、入力行を2回解析します。
シェルには、行を「処理」するために従う一連のステップがあります。あなたは可能性があり、この画像を見てとevalは左側に、ステップ1に戻って、上がるだけの行であることを認識しています。POSIXの説明から:
2.1シェルの紹介
- シェルはその入力を読み取ります...
- シェルは入力をトークンに分割します:単語と演算子
- シェルは、入力を単純なコマンドと複合コマンドに解析します。
- シェルはさまざまな展開を(別々に)実行します...
- シェルはリダイレクトを実行し、パラメーターリストからリダイレクト演算子とそのオペランドを削除します。
- シェルは、関数、組み込み、実行可能ファイル、またはスクリプトを実行します...
- シェルは、オプションでコマンドの完了を待機し、終了ステータスを収集します。
ステップ6で、ビルトインが実行されます。
ステップ6で、evalは処理された行をステップ1
に送り返します。これは、実行シーケンスが戻る唯一の条件です。
それが私が言う理由です:evalでは入力行が2回解析されます。
そして、理解する最も重要な効果。ある行が上記の7つのシェルステップの対象となる最初の結果の1つは、引用です。ステップ4(拡張)の中には、すべての拡張を実行するための一連のステップも あります。最後はQuote Removalです:
引用の削除は常に最後に実行されるものとします。
したがって、常に、引用の1つのレベルが削除されます。
その最初の効果の結果として、行の追加/異なる部分がシェル解析およびその他のすべてのステップにさらされます。
これにより、間接展開を実行できます。
a=b b=c ; eval echo \$$a ### shall produce "c"
どうして?最初のループでは、最初のループ$
が引用されているためです。
そのため、シェルによる展開では無視されます。名前がaである
次のもの$
は、「b」を生成するために展開されます。
次に、1レベルの引用が削除され、最初の引用が解除され$
ます。
最初のループの終わり。
次に、2番目のループで$b
、シェルが文字列を読み取ります。
次に「c」に展開し
、の引数として指定しecho
ます。
最初のループでevalが生成する(再評価される)ものを「見る」には、エコーを使用します。または、引数を明確に示すコマンド/スクリプト/プログラム:
$ a=b b=c
$ eval echo \$$a;
c
evalをechoに置き換えて、何が起こっているのかを「見る」:
$ echo echo \$$a
echo $b
行のすべての「部分」を表示することもできます:
$ printf '<%s> ' echo \$$a
<echo> <$b>
この例では、これは1つのエコーと1つの変数のみですが、より複雑なケースの評価に役立つように覚えておいてください。
それは言わなければならない:上記のコードに間違いがある、それを見ることができるか。
簡単:引用符が欠落しています。
どうやって?あなたが尋ねることができます。簡単です、変数を変更しましょう(コードではありません):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
不足しているスペースを確認しますか?
これは、内部の値$b
がシェルによって分割されたためです。
それでも納得できない場合は、これを試してください:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list
### of all files in the present directory.
引用符がありません。正しく機能させるために(内部引用符"$a"
と外部\"
引用符を追加します)。
これを試してください(完全に安全です):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
マニュアルページはありません。
いいえ、これに関する独立したマニュアルページはありません。エントリを含む、man -f eval
またはapropos eval
エントリを表示しないマニュアルの検索。
内部に含まれていman bash
ます。すべてのビルトインです。
「SHELL BUILTIN COMMANDS」を検索してから、「eval」を検索します。
ヘルプを取得する簡単な方法は次のとおりです。bashではhelp eval
、組み込みのヘルプを表示できます。
テキストをコードに動的にバインドしているためです。
つまり、引数のリスト(および/またはそのような引数の展開)を実行された行に変換します。何らかの理由で、攻撃者によって引数が設定されている場合、攻撃者コードを実行します。
またはさらに簡単に、evalを使用すると、1つまたは複数の引数の値を定義した人に通知することができます。
さあ、ここに座ってコマンドラインを入力してください、私は自分の力でそれを実行します。
それは危険ですか?それがすべてであることを明確にする必要があります。
評価のための安全規則は次のようになります
だけ先の変数にはevalを実行しますが、それは価値です与えています。
eval
ほとんどのインタプリタ言語(の特徴であるTCL
、python
、ruby
...)、だけでなく、シェルが。コードを動的に評価するために使用されます。
シェルでは、シェル組み込みコマンドとして実装されています。
基本的に、eval
引数として文字列を取り、その中のコードを評価/解釈します。シェルでeval
は、複数の引数を取ることができますが、eval
それらを連結して評価する文字列を形成するだけです。
コードを動的に構築して実行できるため、非常に強力です。Cのようなコンパイルされた言語では実行できません。
好む:
varname=$1 varvalue=$2
eval "$varname=\$varvalue" # evaluate a string like "foo=$varvalue"
# which in Bourne-like shell language
# is a variable assignment.
しかし、渡されるものの動的な(外部から提供される)部分をサニタイズすることが重要であるため、危険です eval
、シェルコードとして解釈されるまさにその理由で、です。
例えば、上記の場合$1
でevil-command; var
、eval
エンドアップでしょう評価evil-command; var=$varvalue
シェルコードを、その後、それを実行evil-command
。
の悪 eval
はしばしば誇張されすぎています。
OK、それは危険ですが、少なくとも私たちはそれが危険であることを知っています。
他のコマンドの多くは、サニタイズされていない場合、(シェルによって異なります)のように、その引数にシェルコードを評価します[
別名test
、export
、printf
、GNU sed
、awk
、そしてもちろんsh
/ bash
/perl
およびすべての通訳...
例(ここでuname
はevil-command
、$a
外部から提供される非サニタイズデータとして使用):
$ 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
これらの...コマンドはsed
、export
より危険であると見なされる可能性があります。なぜなら、明らかなeval "$var"
ことにより、コンテンツが$var
シェルコードとして評価される一方で、sed "s/foo/$var/"
or export "$var=value"
またはor ではそれほど明白ではないから[ "$var" -gt 0 ]
です。危険性は同じですが、それらの他のコマンドでは隠されています。
sed
同じようにeval
、両方の場合、その文字列の内容は最終的にシェルコードとして評価されるため、sed
と同じくらい危険eval
です。(unameはまだ実行されていない)sed
を含む文字列が渡さuname
れsed
、unameコマンドが呼び出されると、unameコマンドが実行されます。evalが好きです。ではsed 's/foo/$a/g'
、サニタイズされていないデータをsed
に渡していないので、ここでは説明していません。
この例はいくらか光を放つかもしれません:
#!/bin/bash
VAR1=25
VAR2='$VAR1'
VAR3='$VAR2'
echo "$VAR3"
eval echo "$VAR3"
eval eval echo "$VAR3"
上記のスクリプトの出力:
$VAR2
$VAR1
25
type command
タイプを知るために使用します。(この場合)type eval