なぜbashは解析/実行のものも環境変数に入れるのですか?


9

bash のshellshockバグは、環境変数を介して機能します。正直なところ、次のような機能があることに驚きました。

「env varsによる関数定義の受け渡し」

したがって、この質問は完全に定式化されていない可能性がありますが、この機能が必要になる例またはケースを尋ねることですか?

ボーナス。他のシェルzsh、ダッシュなどにもこの機能がありますか?


これは、env varsを使用して関数定義を渡します。「なぜ環境変数を利用可能/アクセス可能に保つだけではないのですか」とはどういう意味ですか??
Anthon 2014

@Anthonコメントありがとうございます。たぶん、私はより明確に言い換えるべきです。env varsを介して関数定義を渡すことができる必要があるのはどのような理由からですか?
humanityANDpeace 14

1
100%確信はありませんが、たとえばparallel、それが複数のbashインスタンスを呼び出す場合にGNU が関数定義を配布する方法であると思います。そうでなければ、それらをファイルに書き込む必要があり、呼び出された各インスタンスがそれを読み取り、そのファイルを削除できる場合などの問題に対処する必要があります。
Anthon 2014

2
このスレッドにはいくつかの歴史があります。ただし、エクスポートされた関数は非常識です。新しいシェルが古いシェルの実行可能コマンドを継承するようにしたい場合は.dot、古いシェルが行ったのと同じファイルを入手します。それがどのように行われるか-そしてそれは理にかなっています-または、新しいシェルに入力時にファイルを入力としてフィードしますexec。とにかく、ファイルがカーネルによってキャッシュされると、読み込まれます。
mikeserv 2014

@mikeserv私はそれを正しく理解していますか?シェルショックの大部分は、とにかくそれほど重要ではないこの機能に関連しているのですか?
humanityANDpeace 14

回答:


4

スクリプトが別のスクリプトを呼び出すと、親スクリプトの変数をエクスポートして、子スクリプトに表示することができます。関数のエクスポートは明白な一般化です。親から関数をエクスポートし、子で可視にします。

環境は、プロセスが任意のデータをその子に渡すことができる唯一の便利な方法です。データはnullバイトを含まない文字列にマーシャリングする必要がありますが、これはシェル関数にとっては困難ではありません。共有メモリブロックやファイル記述子を介して渡される一時ファイルなどの他の潜在的な方法がありますが、これらは、それらをどうするかわからない、またはそれらを閉じる中間プログラムで問題を引き起こす可能性があります。プログラムは、自分が知らないか気にしない変数を含む環境で実行することを期待しているため、それらを上書きしたり消去したりすることはありません。

関数名を環境変数の名前として使用するという選択は奇妙なものです。1つには、エクスポートされた変数が、同じ名前のエクスポートされた関数と競合することを意味します。

エクスポートされた関数は古い機能です。関数はSVR2のBourneシェル追加され、同じ年にリリースされたバージョン8シェルのエクスポートされた関数(1984)です。そのシェルでは、変数と関数は同じ名前空間を使用していました。関数のエクスポートがどのように機能したかわかりません。家宝シェルは機能を持っていますが、それらをエクスポートしませんボーンバリアントに基づいています。

ATT kshはエクスポート機能をサポートしていると思われますが、ソースを確認したり、ソースを操作したりすると、ksh93uのように、そうすることがわかりません。

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

Kshのパブリックドメインクローン(pdksh、mksh)、dash、およびzshは、エクスポート機能をサポートしていません。


1
ありがとうございました!したがって、関数をエクスポートしないと機能の機能は失われますが、ダッシュ、zsh、pdkshなど、この機能性に欠けているシェルがあります。これを正しく読みますか?
humanityANDpeace 14

しかし、bashで関数をエクスポートすると、のような変数に入りますBASH_FUNC_f%%=() { echo hi }。bashが他の環境変数を解析するのはなぜですか?私がBASH_FUNC_g%%電話しているだけなのに、なぜ解析さえするのfですか?(どうやら、前2014年シェルショック脆弱性は、環境変数がちょうどと呼ばれていたfg-私はまだ、なぜ思ったんだけどg、私が今までに呼び出していない場合は解析されていたであろうg私のスクリプトで)
変成岩

@Metすべての環境変数を調べて、関数定義であるものを特定する必要があります。それはその事実を記憶し、最初に必要になるまで関数のコードを解析することを避けることができますが、それはほとんど利益を得るための追加の複雑さになるでしょう。2つではなく1つのタイプの関数を使用する方が簡単です(「通常の関数」と「少し解析が必要な環境変数からの関数」)。
Gilles「SO-邪悪なことをやめ

定かでない。私がやるべきことは明白だったことを示唆しています、と呼ばれるものを実行するときf、(1)と呼ばれるシェル関数を確認しf、(2)と呼ばれる環境変数を確認し、fそれを解析しようとします、(3)チェックPATHと呼ばれる実行可能ファイルの各コンポーネントf。シェルの起動時に、すべての環境変数をシェルコードとして解析すると、それほど複雑でない設計のように見えますか?
変成期

@Metamorphicすべてのコマンドで実行する必要がある別のステップを追加することを提案しています。関数を定義または未定義にするとき(unset -f foobash fooは環境内での関数定義をもう探す必要はありません)、関数をリストするとき(declare -fすべての環境変数を読み取る以外にどのように処理しますか?) 、そして私が考えていない他のものは何でも。ほとんどのデザインを省略したので、デザインは簡単に思えます。対照的に、起動時にすべてを行うことは単一のコードであり、その後はすべてが機能します。
Gilles「SO-邪悪なことをやめ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.