bashのちょっとしたバグと環境変数の話
- angel_p_57
- 2049
- 7
- 0
- 0
シェル自身が変数を管理しているし、処理もシェル内部で完結しているわけだから、わざわざ環境変数にする意味がないのである。処理のたびに環境変数のチェック→シェル変数のチェックとする意味がない。シェル変数だけを見れば済むのだから。
2021-02-23 19:07:35起動時にbash自身に引き継がれた環境変数は、というと、起動時に「エクスポート属性のついたシェル変数」として取り込んでいる。それで一元管理ができている。
2021-02-23 19:07:47なお、外部コマンド実行時には「bash自身の環境変数」を引き渡すわけだけども、その時にシェル変数の状況を都度反映してあげれば良い。つまり環境変数は情報のコピーとしてしか意味を持たず、二重管理にはなっていない。
2021-02-23 19:08:01逆に言えば、環境変数を設定すればそれで済む問題なら、喜んで環境変数で管理すれば良かったのに(仮定法)、ということである。
2021-02-23 19:08:27なぜかというと、環境変数の一部 or 大部分は、「プログラム起動時に、引き渡されてきた値に応じて設定を調整する」という扱いがされている。環境変数を「常に変化するもの」と見て、処理のたびに追うのは面倒だからだろう。
2021-02-23 19:08:48LANG, LC_XX系もその扱いになっていて、プログラム起動時の初期化処理の中で setlocale というAPIを呼ぶときに参照される。なので、途中でただ値を変更するだけでは意味がない。再度同じAPIを呼ぶ必要がある。
2021-02-23 19:08:59しかも、setlocale を呼ぶ時には、敢えて環境変数を経由させる意味がない。APIに直接値を渡すことも可能だからだ。…ってことを考えると、環境変数変更→setlocale なんて、とても面倒なことになる。
2021-02-23 19:09:13そういう観点で bash の挙動を追ってみると、export LANG=xxx 等で値を変更した場合、然るべきタイミングで setlocale を呼び直すだけで、環境変数への反映には頼ってないことが分かる。( 外部コマンド実行時には反映してるけど )
2021-02-23 19:09:28他は調べてないけど、おそらく必要に応じて、「変数の変化」に必要なフックを管理するようにしてるのではないだろうか。
2021-02-23 19:09:40…ただ、後から気付いたけど、環境変数に頼らないといけない場面もありそう。典型的なのは時刻に関わる TZ (タイムゾーン) 環境変数。
2021-02-23 19:10:01これは実を言うと、時刻関連の処理のたびに変化してないかチェックされる、LANG等とは真逆の性格の環境変数で、しかも API の tzset で陽に設定を行うときも環境変数を経由しなければならない。
2021-02-23 19:10:12で、bash に時刻処理なんてあったっけ? と考えてみると、コマンド履歴(history)記録時の時刻だとか、printf での T 書式だとかがあった。果たして、bash の挙動を追ってみたところ、TZ だけは即座に環境変数に反映するようだ。あらら。
2021-02-23 19:10:35実はこれは簡単。デバッガの gdb で bash のプロセスを attach すれば良い。"p __environ[数字]" で、持っている環境変数を見ることができる。デバッグシンボルがないバイナリでも問題ない。後は適当にブレークポイントを考えるだけの話。
2021-02-23 19:11:02Linuxの /proc/プロセスID/environ ファイルのことを知ってる人もいるかも知れないけど、あっちは「起動時に引き渡された環境変数」なので、見ても環境変数の変化を追うことはできないので要注意。
2021-02-23 19:11:15昔記事を書いたとき、environファイルのことは言ってたけど、gdb の方法は言ってなかった。これは単純に初心者向けではないから。 qiita.com/angel_p_57/ite…
2021-02-23 19:12:19