端末を終了せずにbashスクリプトを終了する方法


183

exitシェルスクリプトでコマンドを使用すると、スクリプトによってターミナル(プロンプト)が終了します。スクリプトを終了してターミナルにとどまる方法はありますか?

私のスクリプトrun.shは、直接ソースされるか、別のスクリプトからソースされることによって実行されることが期待されています。

EDIT:具体的には、2つのスクリプトがあるrun2.shとしては、

...
. run.sh
echo "place A"
...

そして、run.shなど

...
exit
...

私がそれを実行したとき. run2.sh、それがでexitコードラインにヒットした場合run.shは、ターミナルに停止してそこに留まるようにします。しかし、を使用するexitと、ターミナル全体が閉じられます。

PS:を使用しようとしましたreturnが、echoコードラインはまだ実行されます...


5
私は本当に、本当に、本当に尋ねなければなりません。なぜ、ソーススクリプトでexitを使用しているのですか。
Ignacio Vazquez-Abrams

3
exitコマンドは、ターミナルセッション/ログインを終了させないでください。exit 0成功後にスクリプトを終了するために使用する場合、スクリプトexを実行すると./test.sh、出力が表示されますが、コンソールは開いたままになります。
ベンアシュトン

shell実際にシェルターミナルを開くコマンドを使用できます。しかし、私自身の経験では、これはで発生しませんexit。通常、Exitは親スクリプトにコントロールを返します。
Willem Van Onsem 2012年

回答:


258

「問題」は、実際には、スクリプトを調達して実行していないことです。ファイルをソースすると、その内容はサブシェルを生成するのではなく、現在のシェルで実行されます。したがって、exitを含むすべてが現在のシェルに影響します。

を使用する代わりに、を使用exitする必要がありますreturn


2
ここに私が役に立ったと思った別の説明があります:askubuntu.com/a/53179/148337
3cheesewheel

正解ですが、これは良い答えではありません。呼び出し元のスクリプトがアクセスする必要がある変数または関数を呼び出し元のスクリプトが宣言する可能性があることは無視されます。戻りコードを設定し、それをruns.sh@ruakhで処理する方法を説明する方が、この質問に対するより良い回答になります。
MikeSchinkel

5
関数がネストされた呼び出しである場合はどうなりますか?つまり、aがbを呼び出し、bがcを呼び出し、cはすぐにaおよびbを終了したいと考えています。
マイケル

ソースはコピーペーストとほぼ同じです。使用するsh <script>bash <script>、スクリプトを実行してある時点で終了したい場合
peterchaula 2017

42

はい; のreturn代わりに使用できますexit。その主な目的はシェル関数から戻ることですが、source-dスクリプト内で使用すると、そのスクリプトから戻ります。

「ボーンシェル組み込み関数」§4.1 バッシュリファレンスマニュアルプットこと:

     return [n]

シェル関数を戻り値nで終了させます。nが指定されていない場合、戻り値は、関数で最後に実行されたコマンドの終了ステータスです。これは、組み込みで.(またはsource)組み込みで実行されているスクリプトの実行を終了するためにも使用でき、nまたはスクリプト内で実行された最後のコマンドの終了ステータスをスクリプトの終了ステータスとして返します。RETURNトラップに関連付けられているコマンドは、関数またはスクリプトの後で実行が再開される前に実行されます。またはreturnによるスクリプトの実行中ではなく、関数の外で使用される場合、戻りステータスはゼロ以外です。.source


3
return関数からのみ使用できます。returnシェルスクリプト(例:)として使用して実行するとsh run.sh、bashはエラーを報告します- return: can only 関数またはソーススクリプトからの戻り値 '
Tzunghsing David Wong

@TzungsingDavidWong:この回答の大部分が公式リファレンスマニュアルの引用であることをご存知ですか?そして、あなたが引用したエラーメッセージはあなたの主張ではなくこの答えに同意しますか?
ruakh 2018

私はあなたに反対していません。returnスクリプトがシェルスクリプトとして実行され、によって実行されない場合は機能しないことを指摘しておきます。(またはsource)。ところで、ドキュメントはsource -dどこにありますか?
Tzunghsing David Wong 2018

9

を使用してスクリプトを実行する代わりに、またはを使用してスクリプトを. run2.sh実行できますsh run2.shbash run2.sh

スクリプトを実行するために新しいサブシェルが開始され、スクリプトの最後で閉じられ、他のシェルは開いたままになります。


もしそうなら、なぜ2番目のパラメータsh "." run2.shですか?
CHAN

@ H0WARD私はドットを削除するのを忘れていたそうです。回答を編集しました。
Viorel Mirea、2015年

1
OPは、ソースを要件として明示的に示しています。
ジョナサンノイフェルト2016

4

returnステートメント/コマンドの後に追加のexitコマンドを追加して、コマンドラインからスクリプトを実行するか、ターミナルからソースするかの両方で機能するようにすることができます。

スクリプトの終了コードの例:

   if [ $# -lt 2 ]; then
     echo "Needs at least two arguments"
     return 1 2>/dev/null
     exit 1
   fi

コマンドのexit後にスクリプトを読み込む場合、コマンドを含む行は呼び出されませんreturn

スクリプトを実行すると、returnコマンドはエラーになります。そのため、エラーメッセージをに転送して抑制します/dev/null


3

実は、どういうふうに戸惑うかもしれませんねrun a script

を使用shしてスクリプトを実行すると、たとえば、sh ./run2.sh埋め込まれたスクリプトがで終わっていてもexit、ターミナルウィンドウは残ります。

ただし、.またはを使用するsourceと、添え字が終了するとターミナルウィンドウも終了/終了します。

詳細については、を参照してください使用しての違いは何shsource


2

これは、スクリプトrun2.sh内にrun関数を配置するのと同じです。run2.shファイルをbash ttyにソースしながら、run内で終了コードを使用します。run関数にスクリプトを終了する権限を与え、run2.shにターミネーターを終了する権限を与えた場合。次に、実行機能には、あなたの害虫駆除業者を終了する力があります。

    #! /bin/sh
    # use . run2.sh

    run()
    {
        echo "this is run"
        #return 0
        exit 0
    }

    echo "this is begin"
    run
    echo "this is end"

とにかく、私はKazにデザインの問題だと認めます。


この答えが何をしようとしているのかはテキストからはわかりませんが、それは確かに目前の質問を解決しません。
ルイス・デ・スーザ

2

私は同じ問題を抱えており、上記の回答から、そして最終的に私のために働いたことが理解したことから、

  1. たとえば、目的のスクリプトを呼び出すシバン行があります。

    #!/bin/bashbashスクリプトを実行するために使用します

私は両方の種類のシバンのスクリプトを持っています。このため、誤用につながるため(またはスクリプトが不完全に実行された場合にスクリプトが停止する場合など)、使用するshか、.信頼性がありませんでした。

したがって、答えは

    • スクリプトにシバンが含まれていることを確認します。これにより、意図されたハンドラーに疑いがないようになります。
    • .shファイルをchmodして、実行できるようにします。 (chmod +x file.sh)
    • どんなずにそれを直接呼び出しますshか、.

      (./myscript.sh)

これが同様の質問または問題を持つ誰かを助けることを願っています。


1

これは、ドット付きのソースモードで実行しているために発生すると思います

. myscript.sh

サブシェルで実行する必要があります:

/full/path/to/script/myscript.sh

「ソース」http://ss64.com/bash/source.html


機能する場合は、スクリプトへのフルパスは必要ありません. myscript.sh。せいぜい、必要になるかもしれません./myscript.sh
アルバロゴンサレス

1

他の人が指摘しているように、ソースから実行されたスクリプトは、returnvs。exitを使用して同じセッションを開いたままにすることは正しいことです。

ソースがあるかどうかに関係なく、セッションを開いたままにしておくスクリプトが必要な場合は、関連するヒントを次に示します。

次の例はfoo.sh. foo.sh/のように直接実行することも、ソースを指定して実行することもできますsource foo.sh。どちらの方法でも、「終了」後もセッションを開いたままにします。$@文字列は、関数が外部スクリプトの引数へのアクセス権を持っているように渡されます。

#!/bin/sh
foo(){
    read -p "Would you like to XYZ? (Y/N): " response;
    [ $response != 'y' ] && return 1;
    echo "XYZ complete (args $@).";
    return 0;
    echo "This line will never execute.";
}
foo "$@";

最終結果:

$ foo.sh
$ XYZにしますか?(はい/いいえ):n
$。foo.sh
$ XYZにしますか?(はい/いいえ):n
$ |
(ターミナルウィンドウは開いたままで、追加の入力を受け入れます)

これは、作業中にメインexit/ 下に一連のスクラップコードを保持しながら、単一の端末でスクリプトの変更をすばやくテストするのに役立ちreturnます。(あなたがまたは別の方法で呼び出されてもしなくてもよいのスクリプトのトンを持っている場合)、それだけで使用することにはるかに少ない不格好だけれどもそれはまた、意味のコードの移植性を高めることができreturn、およびexit適切な場合には。


0

端末エミュレータにない場合 -hold場合は、ソーススクリプトをサニタイズして、ターミナルを次のように保持できます。

#!/bin/sh
sed "s/exit/return/g" script >/tmp/script
. /tmp/script
read

それ以外の場合は使用できます $TERM -hold -e script


0

また、期待される戻り値で返されることを確認してください。または、exitが発生したときにexitを使用すると、ソースが別のプロセス(インスタンス)を作成しないため、ベースシェルから終了します。


0

シェルスクリプトとして実行するか、rcファイルとしてソースを設定して安全に実行できるスクリプトを作成するために、スクリプトはチェックして比較$0$BASH_SOURCEexit安全に使用できるかどうかを判断できます。

これはそのための短いコードスニペットです

[ "X$(basename $0)" = "X$(basename $BASH_SOURCE)" ] && \
    echo "***** executing $name_src as a shell script *****" || \
    echo "..... sourcing $name_src ....."

-1

1)成功すると、exit 0がスクリプトから出てきます。

2)失敗の場合、exit 1はスクリプトから抜けます。

ur reqに基づいて、上記の2つを試すことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.