🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
bash

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

Linux

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

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

Q&A

解決済

1回答

1269閲覧

bashファイルでwhile文の途中で意図しないbreakが発生する。

man_

総合スコア45

bash

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

Linux

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

while

Whileは多くの言語で使われるコントロール構造であり、特定の条件が満たされる限り一連の命令を繰り返し実行します。

0グッド

1クリップ

投稿2021/02/04 18:23

編集2021/02/05 03:43

#やりたいこと
linux上で動作するCoCo-Beholderというネットワークエミュレーションツールがあります。CoCo-Beholderのリンクを以下に示します。
https://github.com/ZhenyaKh/coco-beholder

本ツールでは様々な輻輳制御手法が提供されており、pythonファイルを実行することで、エミュレーションを行います。
そこで、bashファイルで、様々な輻輳制御手法を一度に実行するプログラムを作成したいと考えています。

#困っている点
現在作成したプログラムを以下に示します。
本プログラムでは、テキストファイルから輻輳制御手法の名前を取り出し、CoCo-Beholderのrun.pyというプログラムを実行します。また。run.pyの"-sc"というオプション引数は私が追加した引数で、実行する輻輳制御手法を選択します。

そこで、困っている点として、"ledbat"という輻輳制御手法で"run.py"を実行し、"echo"でコマンドプロンプト上に"ledbat"と表示した後にwhile文を抜けてしまいます。他の輻輳制御手法ではwhile文を抜けることはありません。

そこで、何故while文から抜けてしまうのでしょうか?
有識者の方々、ご助力お願いします。

<bashファイル>

#!/usr/bin/env bash while read line do ./run.py -p ~/pantheon -t 10 -r 10 -q 800 -l layout/layout.yml -sc $line #./run.py -p ~/pantheon -t 10 -r 10 -q 800 -l layout/layout.yml echo $line done < cc.txt

<cc.txt>

ledbat bbr copa cubic fillp fillp_sheep indigo pcc pcc_experimental quic scream sprout taova vegas verus vivace

#追記
set -oを追加した際に出力される設定内容

allexport off braceexpand on emacs off errexit off errtrace off functrace off hashall on histexpand off history off ignoreeof off interactive-comments on keyword off monitor off noclobber off noexec off noglob off nolog off notify off nounset off onecmd off physical off pipefail off posix off privileged off verbose off vi off xtrace off

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

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

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

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

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

takasima20

2021/02/04 21:17

つづり "ledbat" が間違ってるとか?
otn

2021/02/04 23:14

> while文を抜けてしまいます。 というのはどういう現象でしょう?実際に目にしたものを主観を交えず書いてください。
t_obara

2021/02/05 00:19

シェル経由でなく、-sc ledbatを指定して直接起動した場合、動作するのですか?例外が発生する場合whileから抜けますよ。
man_

2021/02/05 00:43

takashima20さん質問ありがとうございます。 つづりは"ledbat"であっています。
man_

2021/02/05 00:47

otnさん質問ありがとうございます。 ”while文を抜けてしまいます。”というのは、ledbatのエミュレーションを行い、echoでコマンドプロンプト上に"ledbat"と表示された後に、bbrのエミュレーションを行わずプログラムが終了してしまうという意味です。
man_

2021/02/05 00:48

t_obaraさん質問ありがとうございます。 シェル経由でなく、直接pythonファイルを実行した場合にも正常に動作します。
otn

2021/02/05 00:52

> 例外が発生する場合whileから抜けますよ。 例外でも、Bashから見ると単なる「ステータスが0で無い終了」なので、それは無いです。
otn

2021/02/05 00:56

> echoでコマンドプロンプト上に"ledbat"と表示された後に、 cc.txt側に問題がある可能性もあるので、./run.py をコメントにして、全行echoされるか確認ください。
man_

2021/02/05 01:09

ontさん質問ありがとうございます。 ./run.pyをコメントアウトし、while文の中をechoのみで実行した場合は、cc.txtの全行が表示されます。
otn

2021/02/05 01:19

質問のコードには書いてないけど、実は set -e を書いていると言うことは無いですよね?
man_

2021/02/05 02:03

otnさん質問ありがとうございます。 "set -e"は書いていません。
68user

2021/02/05 02:42

ほんとうにこれだけのコードでその事象が再現しますか? って感じですね。 なぜかデフォルトで set -e 相当になっていたりというのは疑わしいので、run.py の終了ステータスを echo $? で表示するとか、set -o で現在の設定を出力してみる。 また、サブシェルでやっていることに起因するなら、下記のようにカレントシェルで実行してみる。 exec < cc.txt while read LINE do あとは set -vx でデバッグ情報を表示するなど。
otn

2021/02/05 03:30

そうですね。念のため、whileの前に、set -o を入れてみてください。現在の設定が表示されます。 errexit がoffであるのが普通です。errexit がonだと終了ステータスがゼロでないとスクリプトが終了します。
man_

2021/02/05 03:44

otnさんコメントありがとうございます。 追記にset -oで出力される内容を記載しました。 errexitはoffでした。
man_

2021/02/05 03:48

68userさんコメントありがとうございます。 run.pyの後にecho $?を追加したところ、echo $?の出力は0でした。 また、set -vxでデバック情報を出力しましたが、ledbatの出力は他の輻輳制御手法を実行した際と同様の出力であり、プログラムが終了される要因を確認することができませんでした。
takasima20

2021/02/05 11:40

なるほど!そういう流れでしたか!!勉強になるなあ。(^_^)
guest

回答1

0

ベストアンサー

わかった。
run.pyの中で、標準入力を読んじゃっているので、ledbat以降のデータがPythonに読まれてしまい、while readで読もうとしたがすでにccc.txtはEOFになっている。

何故もっと早くこの可能性に気づかなかったのか。

ということで、そもそもどういう処理をするのか、見直しましょう。
run.pyは、標準入力で何を読みたいのか?

参考:同様の例。

sh

1while read line # 1行目はこれで読まれるが、 2do 3 wc # 2行目以降はこのコマンドが読んでしまう 4 echo line=$line 5done < ccc.txt

投稿2021/02/05 04:06

編集2021/02/05 04:38
otn

総合スコア85882

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

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

man_

2021/02/05 04:22

上手く理解できていないです。 何が原因で、どう変更すべきなのでしょうか? また、ledbat以外の輻輳制御手法ではループするのに,ledbatではプログラムが終了する理由は何でしょうか?
otn

2021/02/05 04:25

> run.pyの中で、標準入力を読んじゃっているので、 というのが理解できないと言うことでしょうか? 参考のスクリプトの意味はわかりますか? なお、wc コマンドは、標準入力を読んで、「行数、単語数、バイト数」を表示するコマンドです。
man_

2021/02/05 04:37

分からないことは以下の2点です。 ・標準入力を読んじゃっているということは、どういう意味でしょうか?run.pyでは、cc.txtを参照することはありません。 ・bbrやcopaなど他の輻輳制御手法を選択し、run.pyを実行した際はwhile文でループして、cc.txtに記載されている次の輻輳制御手法でrun.pyを実行するのですが、ledbatを選択し、run.pyを実行した場合にはwhile文が終了し、プログラムが終了してしまいます。そこで、他の輻輳制御手法を選択した場合とledbatを選択した際の違いを教えていただきたいです。 よろしくお願いします。
68user

2021/02/05 04:40

とりあえず下記でやってみては。これで動くなら otn さんのおっしゃるとおり run.py が標準入力を食べているのでしょう。 lines=(ledbat bbr copa) for line in ${lines[@]} do ./run.py ... done
man_

2021/02/05 04:46

68userさん 提示していただいたコードで実行したところ、プログラムが途中で終了せずに、最後まで実行することができました。 質問に記載したbashファイルと何が違うのでしょうか?
otn

2021/02/05 04:46

違いとしては、ledbatの場合は標準入力を読んで、それ以外の場合は標準入力を読まないと言うことだと思います。 > un.pyでは、cc.txtを参照することはありません。 cc.txtじゃなくて標準入力です。input関数とか、sys.stdinとか。あるいは他の方法もあり得ます。
otn

2021/02/05 04:51

「標準入力が端末なら何もしないが、標準入力が端末でなければ標準入力を読む」という仕様なんですかね。 プログラムを作った人に聞いてみましょう。 そういう仕様で、それでいいのなら、 for line in `cat ccc.txt` do ./run.py ~~ echo $line done ですね。
man_

2021/02/05 04:51

otnさん、回答ありがとうございます。 while文でcc.txtの行数文ループしたい場合はどう変更すべきでしょうか?
man_

2021/02/05 04:57

otnさんに提示いただいたコードだと、㏄.txtが$lineとして渡されエラーが出力されました。
otn

2021/02/05 05:04

ちゃとコピペしていますか? ` ` が漏れているのでは?
man_

2021/02/05 05:05

追記で echo $lineでcat cc.txtと出力されてしまいます。
man_

2021/02/05 05:10

シングルクォーテーションも抜けていません
otn

2021/02/05 05:15 編集

シングルクォーテーションじゃないです。 ちゃんとコピペしていますか?
man_

2021/02/05 05:15

何の記号でしょうか?
man_

2021/02/05 05:16

コピペしたら上手く動きました。
otn

2021/02/05 05:16

バッククォートです。 ちゃんとコピペしていますか?
otn

2021/02/05 05:21

for line in `cat cc.txt`だと、ファイルを行単位に読んでいるわけじゃなくて、単語単位(空白文字で区切られた非空白文字の塊)で読むので、空白文字を含んだ行があると違いが出ます。あと、* などシェルの特殊文字とかも駄目です。 元のコードでも、./run.py 行に </dev/tty とリダイレクトを付ければ行けるかも。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問