シェルスクリプトと書いてみたけど、ほとんどbashの話題。FreeBSDだと一般ユーザーではbashでないshが、スーパーユーザーではcsh(tcsh)が立ち上がったりするけど、使いにくいので真っ先にportsからbashを入れて置き換えてしまう・・・。最新のは追いかけてないけど今でもそうなのかなぁ。シェル起動時のスクリプト以前メモ帳にまとめたんだけどな。bashの場合、インタラクティブシェルかどうか、ログインシェルかどうかで読み込む起動スクリプトが違う。リンクを張ってshとして起動されるとまた違う動作になる。●定義ログインシェルとは、argv[0][0]=='-'であるか、--loginオプションと共に起動されたシェルのことである。いうコマンド名で起動した場合、である。(exec系の関数は実際に実行するプログラムのパスと、そのプログラムに渡す「最初の引数」=argv[0]=「通常はコマンド名」を別々に指定できる)。インタラクティブ(対話)シェルとは、入力とエラー出力が端末に接続されていて、-cオプションが指定されておらず、オプション以外の引数が指定されていない状態で起動されたシェルのことである。キーボードから入力できて、出力は端末画面に表示されて、シェルスクリプトを実行するために起動されたシェルではない、ということ。上の条件を満たさなくても-iオプションを指定して起動すると強制的にインタラクティブ扱いになる。インタラクティブ扱いだと環境変数PS1(プロンプト指定)がセットされ、変数$-にiが含まれる。$-としてみれば意味が分かるだろう。うち最初に見つかったものを実行。--noprofileを付けるとこの挙動が抑制される。◆ログインシェルが終了するとき:~/.bash_logoutを実行。◆ログインシェルではないインタラクティブシェルとして起動された場合:~/.bashrcを実行。-norcでこの挙動を抑制、--rcfileでファイル名を指定できる。◆非インタラクティブシェルとして起動された場合:BASH_ENV環境変数に指定されたファイルを実行。あとで実験するが、インタラクティブでなければログインシェルでもBASH_ENVに指定されたファイルが実行される。●shとして起動された場合に実行されるスクリプト◆ログインシェルの場合:/etc/profileを実行。~/.profileを実行。--noprofileを付けるとこの挙動が抑制される。◆インタラクティブシェルとして起動された場合:ENV環境変数で指定されたファイルを実行。bashと違って、インタラクティブならばログインシェルの場合でもこの動作が行われる。◆インタラクティブではない場合:何も実行されない。sshdがbashをexecしたような場合。.bashrcを実行。-norcでこの挙動を抑制、--rcfileでファイル名を指定できるが、rshdやsshdから指定できなければならない。あとで実験するが、ログインシェルではなく、ネットワークから接続された場合はインタラクティブ扱い、ということらしい。ログインシェルならば非インタラクティブ扱いのまま。●UIDとEUIDが一致しない場合-pオプションをつけない限り、スタートアップファイルは実行されず、環境からシェル関数を引き継がない。他にも若干違いがある。-pを付けると通常と同じ動作になるが、EUIDはそのままらしい。マニュアルの受け売りで深く考えたわけではないのでよく分からん。BASH_ENVで指定されたファイルbashでログインすると~/.bash_profileが読み込まれるので、こんなのを書いておく。fiすると、bashでもshでもログインすると~/.profileが読み込まれる。~/.profileにはこんなのを書いておく。FreeBSDではデフォルトでこうなっていた。ENV=~/.shrcshの場合にはインタラクティブならログインシェルでも$ENVが読み込まれるので、これで~/.shrcが読み込まれる。fiとすることで、~/.shrcが読み込まれる。以後、shをインタラクティブに起動するとENVで指定した~/.shrcが読み込まれ、bashをインタラクティブに起動すると~/.bashrc経由でENVで指定した~/.shrcが読み込まれる。システムワイドな設定(PRINTERとかかねぇ)は/etc/profileに書く。常駐モノ(ssh-agentとかだな)や共通の環境(CVS_RSHとかだな)は~/.profileに書く。bashじゃないと怒られるものは~/.bash_profileに書く。shを起動したときに設定したい環境変数は~/.shrcに、bashを起動したときに設定したい環境変数は~/.bashrcで$ENVを読み込んだ後に書く。shでログインした後、bashを起動したらPS1を再設定とかね。・・・っていうことでいいのかな。実験してみる.bash_profileと.bashrcにechoを入れて実験してみる。Inc.ちょっと古いな。Cygwinのは4.1.10だった。read]普通にインタラクティブログインシェル。~/.bashrc]の部分がそう)、そのおかげで.bashrcが実行されている。read]普通にインタラクティブシェル。/proc/3651/fd非ログイン・非インタラクティブなので、BASH_ENV環境変数で指定したファイルが実行される。%s'となっていて、lesspipe.shが実行されるときに.bash_environが実行されてechoが出てしまい、これが原因でlessの動作が台無しに。これは標準エラー出力もファイルに出したいときによく使う2>&1の逆だね。/proc/3888/fdログインシェルに対する.bashrcと違って、ログインでも非インタラクティブならBASH_ENVで指定されたスクリプトが読み込まれるようだ。あと、CentOS5.6では.bash_logoutに/usr/bin/clearが書いてあって、ログアウトすると画面がクリアされるのだが、この場合はクリアされなかった。Cygwinのbash-4.1.10でも.bash_logoutが実行されなかった。/dev/pts/1当然インタラクティブログインシェル。xsshdがハイフン付きでbashを起動していてログインシェルとして扱われていることが分かる。入出力は端末ではなく、-iも指定されていないのでインタラクティブではない。したがってPS1が設定されず、プロンプトが出ない。細かいことを言うとプロンプトはシステムのbashrcスクリプトが設定していたりするが、PS1が設定されているときのみPS1を再設定する形になっていて、PS1が元々設定されていないとこの例のようにプロンプトが出ない。-ixoffが書いてあるから。非インタラクティブなので.bash_environも実行されている。/proc/4611/fd.bash_profileが実行されていないのでログインシェルではない。コマンドが指定されているのでインタラクティブシェルでもない。sshは後ろにコマンドを指定するとログイン扱いにせず、端末も割り当てないようだ。この結果、ネットワーク越しのルールが適用されて、インタラクティブではないが.bashrcが実行され、マニュアルには書いてないがBASH_ENVは無視されて.bash_environは実行されていない。「インタラクティブ扱い」ということらしい。-なんてやるときに.bashrcが変なものを表示してると、ゴミが混ざるということか・・・。強制的に端末を割り当てるこの場合、.bashrcが実行されないはずなので環境変数BASH_ENVを設定するにはsshd側に若干の設定が必要。楽なのはsshd_configでPermitUserEnvironmentをyesに設定してsshdに-HUPを送り、~/ssh/.environmentにBASH_ENV=~/.bash_environと書いておく方法。実験したら元に戻しておくのを忘れないように。closed.コマンドが指定されているのでsshはbashを非ログインシェルとして起動し、bashは非インタラクティブと判断する。入力が端末なのでネットワーク越しのルールも適用されない。よって.bash_profileも.bashrcも実行されず、.bash_environだけが実行される。aliasBASH_ALIASESという連想配列があるが、これもexportできないようだ。found最初のaliasでは定義しているのに見つからず、次のunaliasでは抹消したのにまだ実行できている。hoge'fugaaliasの定義と実行の行は別にしないといけないので、コマンド文字列の途中で改行している。この挙動のため、たとえBASH_ENVを使ってaliasを定義したとしても、シェルスクリプトなどから呼ばれた場合はaliasは実行されない。この挙動は変更できて、expand_aliasesシェルオプションを有効にするとaliasが解釈されるようになる。hoge'fugaどちらも意味は同じ。前者はbash起動時のコマンドラインオプションで指定、後者はbash起動後にshoptコマンドで設定。Subversionを最新のものに変えたときにこの挙動に気づいた。うちのSubversionはコミットログ入力の際に秀丸が立ち上がるようになっている。非対話的にログメッセージを取得するためのエディタを呼び出せませんと言われてコミットできなくなった。この訳だと何が原因でエディタが呼び出せないのかいまひとつはっきりしない。non-interactiveなので、「非対話モードの場合は、ログメッセージを取得するためにエディタを起動できません」が正しいっぽい。秀丸のコマンド実行は入出力がリダイレクトされた状態になっているので、Subversionが対話モードではない、と判断したようだ。CygwinのminttyからSlikSVNを起動するような場合も引っかかる(CygwinのSubversionなら当然大丈夫のはず)。svnのオプションとして--force-interacitveを付ければ動くというのは分かったが、シェルスクリプトやシェル関数にするのも面倒なので、bashのaliasにしてみた。すると、minttyからはうまく動くのに、秀丸からbash経由で実行してもうまく動かない。秀丸からbashを立ち上げると、bashは非対話モードで動くのでaliasが解釈されず、生のsvnがそのまま実行されていた。expand_aliasesを渡して解決することにした。w4221が親のbashで、先頭がハイフンなのでログインシェル。psを一回だけ指定すると子bashがない。forkせずにexecしたようだ。それに対してpsを2回実行すると5242として子bashが現れる。wx.bashrcが実行されるのでシェルが介在しているにもかかわらず、forkせずにpsがexecされて子bashが出てこない。wx子bashが出る(5438)。$foo'シングルクオートは変数を展開しない。その後親シェルでfooを調べると、fugaになる。