2009年11月3日火曜日

source コマンドではまった

親シェルから呼び出された子シェルで export された環境変数は、呼び出し元の親シェルでは反映されない。つまり、子シェルで環境変数を設定しても、親シェルに戻った瞬間にその環境変数の設定は失われるということ。

別のスクリプトに書かれた環境変数の export を呼び出し元にも反映したいなら、そのスクリプトを子シェルで実行するのではなく、include と同じ意味を持つ source か . を利用して呼び出し元に取り込まないといけない。これだと、子シェルを作らず、親シェル上で実行される扱いになるので、別スクリプトの export が呼び出し元にも反映されるわけです。

で、その source コマンドで嵌りました。

最近の Ubuntu は dash という sh 拡張のシェルを基本にしているらしく、以前に作ってた bash スクリプトを動かすと source コマンドが存在しないエラーが発生。

ネットで調べてみると、source と . は等価変換可能、ということだったので bash で書かれた source を全て . に変換。

でも、これが上手く動作しない。

実は、bash 用コード中に

% source prog param

なんて無理やり source で呼び出したコマンド(prog)にパラメータ(param)を指定してて、bash 上ではこれでうまく行ってたんですが、

% . prog param

ってやってみたら、param が付いてこないみたい。親シェルの引数がそのまま prog に引き継がれるよ…。

どうやら source コマンドの後ろの引数の部分の仕様は未定義らしくて、実装によってその挙動が異なるみたいです。今まで使ってた bash では、引数処理まできちんとやってくれてたけど、どこでも動くわけではなかったみたい。

結局のところ、dash ではどうしても無理そうだったので

% arg=123
% . myscript

として myscript 内で変数 arg を評価するコードに…。これを見てアセンブラの push を思い出しました。しかも、このスクリプトは共有されてて今まで通り bash から読み込まれることもあるので、arg の存在の有無を判定して、無さそうなら引数を確認…とかかなり複雑に。なんか汚い…。

…まぁ、これで動作するようになったので動かないことはなくてほっとしたけどね。

0 件のコメント:

コメントを投稿