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

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

新規登録して質問してみよう
ただいま回答率
85.48%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

4回答

4268閲覧

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

sabx

総合スコア200

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

1クリップ

投稿2018/01/23 09:39

編集2018/01/23 10:14

困っていること

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

スクリプトA

bash

1#!/bin/bash 2echo ${var} ←ブランク 3source スクリプトB 4echo ${var} ←VAR=AAAAAAAAAAAA が表示されてほしいがブランク
スクリプトB

bash

1#!/bin/bash 2var="VAR=AAAAAAAAAAAA" 3export var
参考サイト

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

追記

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

  1. 下記parent.shをcronで実行
  2. parent.sh内でchildA.shを呼び出しし、変数に代入
  3. parent.sh内でchildB.shを呼び出しし、変数を表示

を実行しています。
具体的なコードは下記です。

parent.sh

bash

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

bash

1#!/bin/bash 2var="VAR=AAAAAAAAAAAAA" 3echo ${var} ← parent.logを確認するとVAR=AAAAAAAAAAAAAが出力されている
childB.sh

bash

1#!/bin/bash 2echo ${var} ← parent.logを確認するとブランクが出力されている

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mattn

2018/01/23 09:58

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

2018/01/23 10:19

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

回答4

0

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

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

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

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

投稿2018/01/23 11:54

編集2018/01/23 11:58
otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

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

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

投稿2018/01/23 10:19

hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sabx

2018/01/23 11:12

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

0

ベストアンサー

(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/23 10:19

編集2018/01/23 10:32
mattn

総合スコア5030

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mattn

2018/01/23 10:32 編集

ちなみに source childA 2 > は(標準エラーをリダイレクトしたいのであれば) 2> と詰めて書くべきです。
sabx

2018/01/23 11:09

ご回答ありがとうございます。 ()を除外しても変数の引き渡しができませんでした... pstreeコマンドを実行した所、 init - sshd - sshd - bash - bash - aws | - awk といったようなツリーになっていました。 左から3番目のbashから4番目のサブシェルを呼び出してしまっているということでしょうかね…
mattn

2018/01/23 11:16

変数とはどれのことでしょうか?
sabx

2018/01/23 11:21

変数は${var}です。 (childAで「VAR=AAAAAAAAAAAAA」が代入されている変数です)
mattn

2018/01/23 15:07

2> $1 のあとの | 以降をコメントアウトしても同じでしょうか?
sabx

2018/01/24 00:35

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

2018/01/24 00:48

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

2018/01/25 04:57

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

0

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

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

bash

1$ echo $SHELL 2/bin/bash 3$ cat a.sh 4#!/bin/bash 5echo ${var} 6source b.sh 7echo ${var} 8$ cat b.sh 9var="VAR=AAA" 10$ ls -l [ab].sh 11-rwxrwxrwx 1 ksoh ksoh 48 Jan 23 18:51 a.sh 12-rw-rw-rw- 1 ksoh ksoh 27 Jan 23 18:53 b.sh 13$ ./a.sh 14 15VAR=AAA 16$

なにかが違うはずです。


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

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

投稿2018/01/23 09:58

編集2018/01/23 10:02
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sabx

2018/01/23 10:16

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

2018/01/23 10:22

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問