Bashスクリプトのソース-終了の代わりにエラーで戻りますか?


15

私はターミナルbashスクリプトを調達しているので、エラーで終了します

set -o errexit

ターミナルを閉じ、別のターミナルを開いて、いくつかの変数をリセットする必要があるため、非常に迷惑です。

これまでのところ、使用して

command || return

スクリプト内の行は、まさに私が望むことをしています

set -o errexit

すること...しかし、スクリプト全体に対してそれを実行したいのです。1行/コマンドだけではありません

サイトを設定するためのコマンドがいっぱいのファイルがありますが、コマンドを実行したくない|| 帰る

ファイル内のすべての行に対して

別の設定オプション、またはターミナルを終了する代わりに単に「戻る」何か他のものがありますか?

- わかりやすくするために、スクリプトを強制終了し、ctrl + Cを押してターミナルで実行中のサービスを強制終了するのと同じ状態のままにします。command || returnそれをします。しかし|| return、ファイル内のすべての行に手を加えたくありません。だからset -o errexit、端末をシャットダウンさせないに似たものを探しています

---注: 2行のダムスクリプト(super.sh)の作成:

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

そして置くset -o errexitcreate.shの上部に、

期待どおりに動作します。ただし、ターミナルから呼び出すのではなく、別のbashスクリプトを呼び出すために、2行のファイルを作成する必要があるのは本当に愚かなことです。うーん

以下に例を示します。

super.shで

#!/bin/bash

create_path=~/Desktop/site_builder/create.sh
source $create_path blah

create.shで

#!/bin/bash
set -o errexit
#line below this is a line that fails and will cause the script to stop and return to the terminal as expected 
sed "s/@@SITE_NAME@@/$dirname" 
~/Desktop/site_builder/template_files/base.html > ~/Desktop/$dirname/templates/base.html # a line with a stupid error

ターミナルで:

 $ bash super.sh

期待どおりの出力:

my-mac$

これは動作します。なんて面倒な解決策でしょう。

私が欲しい私の端末シャットダウンを持たずに、D:端末から愚かsuper.shファイルではなく、super.shファイルに何を実行するために、理想的には、。これは私がやろうとしていることで起こります:

端末コマンド:

my-mac$ source $create_path blah

create.shにはまだあります set -o errexit

これが端末の出力です

    sed: 1: "s/@@SITE_NAME@@/blah": unterminated substitute in regular expression
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

[Process completed]

そして、ターミナルはフリーズします。Ctrl + Cは機能せず、Ctrl + Dも機能しません

の代わりにset -o errexitcommand || returncreate.shファイルのすべての場所でステートメントを使用する場合、(端末からsuper.shを呼び出す代わりに)supser.shの行を直接端末で実行しているときに、必要なものを取得します。しかし、それは実際的な解決策でもありません。

注:私は、子シェルを生成するだけの@terdonの回答が好きだったので、端末( )全体ではなくスクリプトを介してサブシェルを生成することになりました。も動作します。


これをスクリプトで実行していますか、それとも手動で実行していますか?
テルドン

ターミナルでソースを使用してファイルを呼び出しています。のように:source $file_path argumentスクリプトは、呼び出し元と同じシェルで実行されています(実際source、そう言われています...そして、そのように動作command || returnします)ステートメントは、ターミナルで実行しているファイルにあります

OK、セットはどこで実行されますか?これはソーススクリプト内にありますか、それとも手動で実行しますか?コピーして試すことができる簡単な例を追加できれば、答えははるかに簡単です。アイデアはありますが、動作することを確認するためのテスト方法が必要です。
テルドン

それを助けるかもしれないメモを元の投稿に追加しました。しかし、私もあなたが提案したようにします。

回答:


4

フェイルセーフでファイルをソースするだけです:

source the-source-file || true

...その場合でも、全体的なコマンドは失敗しませんsource


実際、これは私が望んでいたものだと思っていましたが、私の端末はただ遅いだけであることがわかりました...実際にエラーで端末に戻りたいです(つまり、トラック内のスクリプト全体を停止することを意味します).. source file || true これを行わずsource file || return 、端末にこれを入力しても

ファイルを入手してもシェルプロンプトに戻りませんか??
ジェフシャラー

これが私の端末Jills-MBP:~ jillr$ source ~/Desktop/site_builder/create.sh blah || trueの内容です。失敗した場合にスクリプトの次の部分を実行するだけなので、trueではなくreturnします。唯一機能しているのはcommand || return、すべてのコマンドの実際のファイル内のステートメントであり、これはばかげています。関数ですべてを投げてfunction || return、ファイルの最後で呼び出すのが良いかどうかはわかりません。

まあ、|| return失敗したコマンドを明示的に付けた場合、はい、戻ります。あなたのメイン/親シェルが終了しないようにしようと思っていましたか?
ジェフシャラー

はい、端末が実際に終了しないようにします。ターミナルを終了したくないからです。スクリプトを終了します。スクリプト内の個々のコマンドで戻ると、スクリプトが終了し、Ctrl + Cを押してプロセスを強制終了するのと同じ状態になります(ターミナルからサーバーを実行するなど)。コマンドを書くのを避けたい|| ファイル内のすべての行に戻る:D

2

これは、私が達成するために必要なもの(仮想環境を作成し、それをアクティブにし、bashスクリプトから要件をインストールする)で機能する唯一のことです:

次のように、スクリプトからサブシェル/子シェルを生成します。

stupid_file.sh

(
set -o errexit
#bunch of commands
#one line fails
)

次を使用してstupid_fileを実行します。

source stupid_file.sh <file arguments here> || true

終わり。

**お辞儀をします**

(クレジットはジェフとタードンに送られます)


1
これは、実際にスクリプトを実行するのではなく、単に実行することと何の違いもありません。
-chepner

@chepnerうーん。涼しい。私はちょうど呼び出してみてbash $create_path blah、それがまだ終了し、同じ方法で実行され、まだ仮想環境に正しくインストールされているかどうかを確認する必要があります。時間切れです。

時間を節約します:( "installs stuff"で現在のシェルに環境変数を設定することを意味する場合)、(...)括弧内のすべての割り当てはそのサブシェルのみに影響するため、どちらも実行しません。foo=3; (foo=5); echo "$foo"5ではなく3を出力します
。– chepner

@chepnerは正確ではありません。source file端末から呼び出すことはできず、同じ結果を期待できません。うまくいかなかったからです。同じ結果が得られるのは、端末経由またはスクリプトからサブシェルを明示的に作成するときだけです。ただし、bash代わりにsourceスクリプトを実行して同じ結果を得ることができますが、

@chepnerのインストールでは、実際には仮想環境を作成し、その仮想環境をアクティブにしてpip install -r $apath/requirements.txtから、そのアクティブな環境で実行します。そもそも私がスクリプトを呼び出すためにソースを使用した理由

0

簡単な回避策として、現在のシェルでシェルを実行し、そこでソースを作成できます。何かのようなもの:

  1. 新しいターミナルを開き、すべてを希望どおりに設定します。環境変数などに言及しました。ここで設定します。

  2. そのターミナルで、新しいシェルを起動します。たとえば、bash

  3. 自分のことをしてください。スクリプトを入手します。終了すると、最初のシェルにスローされ、すべてがセットアップされます。bashもう一度実行するだけで、ビジネスに戻ります。

説明のために、ソースを取得しようとすると失敗するこのスクリプトを作成しました。

$ cat /home/terdon/scripts/bar.sh
set -o errexit
var='bar

ネストされたシェルセッションを開始してからソースを取得した場合にどうなるかを見てみましょう(sourceコマンドにポータブルな名前を使用していることに注意してください.; sourceはbashismです)。

parent-shell $ bash      ## start a new shell
child-shell $ . ~/scripts/bar.sh
bash: /home/terdon/scripts/bar.sh: line 2: unexpected EOF while looking for matching `''
parent-shell $ 

ご覧のとおり、構文エラーによりソーススクリプトが終了し、シェルセッションが終了しましたが、ネストされたセッションであったため、すべての変数が設定された元の親シェルに戻りました。ここで、もう一度新しいシェルを実行するだけで、スクリプトのソースに戻ることができます。


私はこれを本当に素早く試してみるつもりです

これには意図した効果があります...欠点は、親シェル用に作成した変数が子シェルでアクセスできないことです。子シェルには、子シェルでの実行に必要な変数の1つが含まれます。実行中のファイルからサブシェルを生成する方法はありますか?そうすれば、親シェルでスクリプトを呼び出すことができ、必要な変数にアクセスできますか?私はcreate_path=~/Desktop/site_builder/create.sh 頻繁に行うので、文字通り親シェルに設定しています。そして、スクリプトを実行するためにsource $ create_path [argument]を呼び出す必要があります。

1
@JillRussekは、変数が子シェルに渡されていない場合、exportそれらを実行していません。しかし、あなたが説明することは本当にほとんど意味がありません。それはますますXY問題のように聞こえています。あなたの最終目標が何であるかを説明する新しい質問を投稿したいと思うかもしれません。この奇妙なソースをすべて解決するより良いソリューションを提供できると思います。
テルドン

うーん。私もそれを試してみるかもしれません。現時点では、ターミナルからではなくスクリプトから子シェルを生成するだけで、私が望んでいることを正確に実行できます。スクリプトで仮想環境を作成し、その中にpipをインストールするために、ターミナルからスクリプトを入手する必要があります。現在、意図したとおりに機能しています。

しかし、あなたは正しいです。変数をエクスポートしていませんでした。(以前に子シェルを生成したことはありません)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.