68user's page 掲示板

Prev< No. 5069〜5091> Next  [最新発言に戻る] [過去ログ一覧]
No. 5071 # Mods [E-mail] 2010/05/13 (木) 10:22:57
はじめまして、Mod's(マスター・オブ・ドヘン○イ)と申します。
困った時に参考にさせて頂いております。

Bシェルスクリプトを独学中です。と言いつつBashの環境設定ファイルとサブシェル
(詰まる所はプロセスの理解不足)について質問させてください。

利用環境:MacOSX 10.6
ログインシェル:Bash
    bash-3.2$ bash --version
    GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)


元々はログインシェルがBashの利用環境にてログイン過程のシェル起動や以降のシェル起動による
環境設定ファイルの読み込み順序などを調べる為に/etc/profile、/etc/bashrc、~/.bash_profile、
~/.bashrcの4つにそれぞれechoコマンドを仕込んで実際にそれらログインスクリプトが起動した
時に任意のファイルへ「読み込みました」的な内容の出力をするようにしました。

結果、ログイン時にはそれら全ての環境設定から出力されその後のBashの起動では~/.bashrcから
のみ出力があり、ここまでは予想通りでした。
グローバル環境設定ファイル、およびローカル環境設定ファイルのいずれもprofile側からrc側を
sourceしています。

ここまでは良いのですが、カレントシェルからシェルスクリプトを実行した際、私の予想では
~/.bashrcから出力を得られるつもりでいました。シェルスクリプトを実行する際にサブシェルを
起動すると「されている(←私の中で未確定)」わけですから。

従いまして下記のように2つ推測を立ててみました(どちらも外れているかもしれませんが:笑)。
<推測>
    推測&#9312; :新たにシェルは起動している、しかし。
    スクリプト実行によるサブシェルはあくまでスクリプトを実行するシェルであって対話シェル
    として起動しているわけではないのでローカル環境設定ファイルを読み込む必要がない。
    言い換えると環境設定ファイルはあくまでログインスクリプトだから。

    推測&#9313; :新たにシェルは起動していない。
    あくまでスクリプトを解釈するのはカレントシェルであって解釈後の実際の処理はシェルの
    起動を伴わない子プロセスが実行するから。

推測&#9313;を書いていてふと思ったのですが、1つのプロセスというのは同時に一つの事しか出来ない
「はず」で、カーネル視点から考えるとシェルとしてプロセスを起動した以上は入力されたコマンド
を自身が理解出来る命令へ翻訳して受け取るための1プロセス。
そして翻訳された命令を受け取ったカーネルは実際のデータ処理実行でまた次の1プロセスを育成。
つまり、こちらはカーネル上のデータ処理のプロセスであってシェルの起動ではない。

よってカレントシェルからのスクリプト実行の処理というのはカレントシェルがスクリプト内の
コマンドを翻訳してカーネルが翻訳された命令を受け取って子プロセスが育生されるので~/.bashrcは
読み込まれない。

つまり、「サブシェルが起動する」というのはカレントシェルのプロセス上でデータ処理が行われる
訳ではないということを便宜的に説明するための「考え方」でしかないのか?

と、以上までのような推測を立ててみました。
個人的にはこのように考えるとcronからのスクリプト実行でも環境変数を~/.bashrcから読み込ま
ない事にも合点がいくのですが。。。
もっともcronプロセスはログインプロセスとは全くべつのプロセスなので環境変数で引き継ぐも
なにもないのですがシェルが起動するということを中心に考えると、むぅ〜ん、という感じです。

どちらにせよ、~/.bashrcをシェルスクリプト実行時に起動させたければsourceすれば良いだけの
ことですが、一般的な説明としてスクリプト実行には新たにシェルが起動しているという説明と
~/.bashrcが起動しない結果が自分の中で噛み合ないので質問させて頂きました。

psコマンドを使いこなせていれば良いのだろうなぁと思いつつ。いきなりの長文で失礼しました。

http://x68000.q-e-d.net/~68user/unix/pickup?keyword=%A5%B5%A5%D6%A5%B7%A5%A7%A5%EB&target=command

No. 5072 # 68user 2010/05/14 (金) 13:19:29
>>5071 Mods
bash(1) 曰く、
    ~/.bash_profile
            個人用の初期化ファイル。ログインシェルが実行します。
    ~/.bashrc
            対話シェルごとに実行される、個人用の起動ファイル。
です。

対話的シェルの定義は、同じく bash(1) 曰く
      対話的なシェルとは、オプションでない引数がなく、標準入力と
      標準出力がいずれも端末に接続されていて (これは isatty(3)
      で調べられます)、 -c オプションが指定されていない状態で起動
      されたシェル、または -i オプション付きで起動されたシェル
      のことです。
です。

シェルスクリプトは
    http://x68000.q-e-d.net/~68user/unix/pickup?%A5%B7%A5%A7%A5%D0%A5%F3%A5%B0
にあるように、結果的には
    /bin/bash ./foo.sh
などと起動されるので、
    「オプションでない引数がなく」
に該当しないため、対話的シェルではありません。よって、
    ~/.bashrc
            対話シェルごとに実行される、個人用の起動ファイル。
は読み込まれません。

また、シェルスクリプト起動の場合はログインシェルでもないので、
    ~/.bash_profile
            個人用の初期化ファイル。ログインシェルが実行します。
も読み込まれません。

以上が仕様上の話です。

で、なぜそういう仕様かと言うと、シェルスクリプトが個人用の
設定を参照してしまうと都合が悪いからです。例えばこちらの手元の
CentOS 5.3 において /usr/bin/* のうちシェルスクリプトである
ものは、以下のようにかなりあります。

/usr/bin/apr-config
/usr/bin/apropos
/usr/bin/apu-config
/usr/bin/at
/usr/bin/atq
/usr/bin/atrm
/usr/bin/bashbug-32
/usr/bin/build-classpath
/usr/bin/build-classpath-directory
/usr/bin/build-jar-repository
/usr/bin/bzcmp
/usr/bin/bzdiff
/usr/bin/bzgrep
/usr/bin/bzless
/usr/bin/bzmore
/usr/bin/c89
/usr/bin/c99
(略)

これらが実行されるたびに ~/.bash_profile などを呼んでしまうと、
alias・シェル変数・関数などがプログラム作成者の意図に反したもの
であった場合、おかしな挙動をしてしまうでしょう。それを避けるために
こういう仕様になっているものと思います。

上記のプログラムの挙動をカスタマイズしたい場合は、アプリ個別の
設定ファイル (~/.*rc) や、環境変数で指示すべき、ということですね。

> 個人的にはこのように考えるとcronからのスクリプト実行でも
> 環境変数を~/.bashrcから読み込まない事にも合点がいくのですが。。。
cron 経由だと端末を持たないので対話的シェルではないから、
~/.bashrc を読まない、です。この結果、
      ログインシェル・対話的シェルと、cron 経由のシェルで
      共通の環境変数を設定する方法がない
となってしまい、仕様としてはイマイチだと個人的には思っていますが、
世の人達は cron で
      HOGE=fuga
      * * * * * $HOME/bin/foo.sh
としたり、
      * * * * * . $HOME/.bash_profile && $HOME/bin/foo.sh
としたり、
      $HOME/bin/foo.sh 内で必要な環境変数を設定する
などの方法で乗り切っています。

環境変数であれば FreeBSD だと /etc/login.conf で設定する方法
もありますが、Mac OS X だとどうなのかはわかりません。

> 一般的な説明としてスクリプト実行には新たにシェルが起動しているという説明と
> ~/.bashrcが起動しない結果が自分の中で噛み合ないので質問させて頂きました。
シェルは起動していますが、~/.bashrc などを読むべき条件が
揃っていない、ということですね。

No. 5073 # Mods [E-mail] 2010/05/14 (金) 17:19:22
>>5072 管理人様

早速のご回答を頂きましてありがとうございます!
cronの説明も含め非常にスッキリいたしました。

スクリプト実行によるシェル起動プロセスが~/.bashrcを読み込まない件に関しては最初の
推測が近かったものの「ローカル環境設定ファイルを読み込む必要がない。」のではなく
むしろ「読み込んではまずい。」ということだったのですね。
その理由も言われてみれば非常に納得です。

この度は詳細な解説をして頂き、まことにお世話になりました(感謝感激です)。

No. 5078 # BAVO 2010/05/26 (水) 21:59:38
はじめまして
以前『User-Agent 統計』を参考にさせていただいていたのですが
最近トップページから『User-Agent 統計』に進んでもエラーになり
うまく動いてないようですが、他の方からは正常に動いているのでしょうか?
できれば動作確認していただければと思います。
よろしくお願いします。

No. 5079 # 68user 2010/05/26 (水) 23:00:37
>>5078 BAVO
以前サーバの負荷が上昇した際、User-Agent 統計が負荷上昇の
一因であるように見えたので、実行不可としておりました。
その後別アプローチから負荷軽減を図ったので、とりあえず
さきほど実行可能にしてみました。
    http://x68000.q-e-d.net/~68user/cgi-bin/view-browser.cgi

>>5045 h.maruwa
同じご指摘をいただいていたにも関わらず、スルーしており
申し訳ありませんでした。

No. 5080 # abb 2010/06/03 (木) 18:58:08
>FollowSymLinks
>シンボリックリンクを許可するかどうか。
>シンボリックリンクをたどるかどうかを設定します。
>なお、シンボリックリンク自体は OS の機能ですから、いつでも使えます。
>ここでは web 経由でシンボリックリンクを辿るかどうかを決めるわけなので、
>CGI プログラムの中ではいつでもシンボリックリンクを使うことができます。

なんだか日本語が変ですよ。設定がどう働くのかこれじゃわからないです。。。

No. 5084 # h.maruwa 2010/08/13 (金) 07:56:50
>>5079 68user
User-Agent統計のページが閲覧可能となっているのを確認しました。
対応有難うございました。

日本国内でのUser-Agentを多数・長期間分網羅したサイトは稀少なので
アクセスが集中しやすいのかもしれませんね。

No. 5091 # jagio 2010/09/26 (日) 11:03:36
UNIX情報Web公開、ありがとうございました。
下記の部分がとても、役に立ちました。

http://x68000.q-e-d.net/~68user/unix/pickup?tee
UNIXの部屋 コマンド検索:tee (*BSD/Linux)
...(snip)...
make >make-log 2>&1 (sh・bash の場合)
...(snip)...


C言語バッチ処理のlog出力先を下記のように(×)から(○)へ変えたら、
標準入力を要求する、フィルタ系pgmテストがやりやすくなりました。
(×)./"$PGM1" >>"$LOG1" 2>&1
(○)./"$PGM1" 2>&1 | tee -a "$LOG1"

pgmには、
標準エラー出力に下記のようなメッセージを表示させ、
    fprintf(stderr, "*** %s needs stdin ! ***\n", pgm_id);
    fprintf(stderr, "*** if end of input ,then press ctrl+d. ***\n");
標準出力と標準エラー出力をログ出力させると、
画面表示で何をすれば良いか分かり、
データ入力時の操作がしやすいです。


以上です。////////

Prev< No. 5069〜5091> Next  [最新発言に戻る] [過去ログ一覧]