質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

bashでsourceコマンドで実行した先でexportした変数がブランクになってしまう

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,358

kk123

score 151

 困っていること

下記のようなスクリプトAを実行し、スクリプトA内で
スクリプトBをsourceコマンドで実行しているのですが、exportした変数がブランクになってしまいます。

 スクリプトA
#!/bin/bash
echo ${var} ←ブランク
source スクリプトB
echo ${var} ←VAR=AAAAAAAAAAAA が表示されてほしいがブランク
 スクリプトB
#!/bin/bash
var="VAR=AAAAAAAAAAAA"
export var
 参考サイト

https://qiita.com/shinyashikis@github/items/294766d75c2ac633e22d

 追記

すいません...記載内容ですが、自己判断で勝手に省略してしまった部分があるのでしっかりすべて記載いたします。
(質問にお答えしていただいた方々すいません...)

  1. 下記parent.shをcronで実行
  2. parent.sh内でchildA.shを呼び出しし、変数に代入
  3. parent.sh内でchildB.shを呼び出しし、変数を表示
    を実行しています。
    具体的なコードは下記です。
 parent.sh
#!/bin/bash
echo ${var} ←ブランク
(source childA 2 > $1 ) | awk '{print strftime("%Y/%m/%d %H:%M:%S",systime())" "$0;fflush()}' >> parent.log ←parent.logに対してchildA.shでechoしたものをログ形式で出力
(source childB 2 > $1 ) | awk '{print strftime("%Y/%m/%d %H:%M:%S",systime())" "$0;fflush()}' >> parent.log ←parent.logに対してchildB.shでechoしたものをログ形式で出力
echo ${var} ←ブランク
 childA.sh
#!/bin/bash
var="VAR=AAAAAAAAAAAAA"
echo ${var} ← parent.logを確認するとVAR=AAAAAAAAAAAAAが出力されている
 childB.sh
#!/bin/bash
echo ${var} ← parent.logを確認するとブランクが出力されている

以上となります。
不備があり大変申し訳ございませんが、よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mattn

    2018/01/23 18:58

    実際のコードやファイル名が質問の通りなのであれば動くと思います。

    キャンセル

  • kk123

    2018/01/23 19:19

    自己判断で一部プログラムを省略してしまいましたので、追記させていただきました...申し訳ございませんでした。

    キャンセル

回答 4

checkベストアンサー

+1

(source childA 2 > $1 ) | awk '{print strftime("%Y/%m/%d %H:%M:%S",systime())" "$0;fflush()}' >> parent.log ←parent.logに対してchildA.shでechoしたものをログ形式で出力
(source childB 2 > $1 ) | awk '{print strftime("%Y/%m/%d %H:%M:%S",systime())" "$0;fflush()}' >> parent.log ←parent.logに対してchildB.shでechoしたものをログ形式で出力

この部分、サブシェルと言って、子プロセスとして起動されています。ですので childA や childB でいくら export しても呼び出し元には反映されません。() を取ってみて下さい。

source childA 2> $1 | awk '{print strftime("%Y/%m/%d %H:%M:%S",systime())" "$0;fflush()}' >> parent.log ←parent.logに対してchildA.shでechoしたものをログ形式で出力
source childB 2> $1 | awk '{print strftime("%Y/%m/%d %H:%M:%S",systime())" "$0;fflush()}' >> parent.log ←parent.logに対してchildB.shでechoしたものをログ形式で出力

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/24 09:35

    パイプの後をコメントアウトしたら可能になりました!ありがとうおございました!
    パイプで接続されたプロセスは別プロセスで、その別プロセスに対して、パイプ元のプロセスが標準出力した内容を標準入力しているために、sourceパイプ元を実行しても変数${var}の引き継ぎができなかったということでしょうか...!

    キャンセル

  • 2018/01/24 09:48

    source は実行コマンドではなく、bash の組み込みコマンドなので、プロセス実行ではないのです。source コマンドは起動している bash 上で実行されます。リダイレクトがどの様に動くかは bash のソース見てみないと分かりませんが、おそらく動かないと思います。(実行プロセスの標準出力をファイルディスクリプタに割り当ててると思うので)

    キャンセル

  • 2018/01/25 13:57

    なるほど…お助けしていただきましてありがとうございました!
    bashの組み込みコマンドがプロセスを生成しない等の自分にはまだ理解できていない点も発見でき、とてもよかったです…!><

    キャンセル

+1

(source childA 2 > $1 )
(source childB 2 > $1 )

括弧の中のコマンドはサブシェルで実行されますので、その中で設定した環境変数は消えて無くなります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/23 20:12

    ご回答ありがとうございます。
    ご指摘していただいた通りに()を除外したのですが、childA.shで定義した変数がchildB.shではブランクのままでした(childAからparent.shに戻った際にechoしてもブランクでした...)

    キャンセル

+1

パイプで処理すると、子シェルで実行されますので、子シェルでいくら変数を変更しても親シェルには無関係です。

子シェルから親シェルに文字列を伝えるのであれば、ファイルに書き込んで、親シェルで読み込んで下さい。

すいません自己判断で不要そうなスクリプトを排除した内容で質問してしまいました。

部分省略は全然かまわないのですが、省略後のコードで現象が発生することを確認してから書かないと、「質問と全然関係ないことを書いた」と言うことになります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

動くはずに思えますが・・・

どのような手順で動かしたか正確に記載されてはどうかと思います。

$ echo $SHELL
/bin/bash
$ cat a.sh
#!/bin/bash
echo ${var}
source b.sh
echo ${var}
$ cat b.sh
var="VAR=AAA"
$ ls -l [ab].sh
-rwxrwxrwx 1 ksoh ksoh 48 Jan 23 18:51 a.sh
-rw-rw-rw- 1 ksoh ksoh 27 Jan 23 18:53 b.sh
$ ./a.sh

VAR=AAA
$

なにかが違うはずです。


なお、sourceは実行中のプロセス内でそのまま指定スクリプトを実行するビルトインコマンドですので変数をいちいちexportする必要はありません。

exportというのは「この変数を環境変数として子供へ引き継がせてね」とシェルへ伝えるための構文です。子供プロセスへ伝える必要がない単なる変数の場合は一々exportしなくてよいです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/23 19:16

    ご回答していただきましてありがとうございます。
    すいません自己判断で不要そうなスクリプトを排除した内容で質問してしまいました。
    追記という形ではありますが、詳細に記載しましたので、アドバイスいただけないでしょうか...
    申し訳ございませんが、よろしくお願いいたします。
    (sourceで呼び出していればexportしなくても問題ないのですね...)

    キャンセル

  • 2018/01/23 19:22

    うーむ。sourceをつかってもそれをカッコで囲むと子供プロセスになってしまいますね。
    詳しくはmattnさんの回答をご覧ください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る