web-dev-qa-db-ja.com

bashで「exec echo some; echo test」を実行しても、「some test」が出力されませんか?

Bashでexec echo "some "; echo "test"を実行しても、「何らかのテスト」が出力されませんか?

小さなシェルスクリプトを書いていて、execコマンドが呼び出された後に何も続かないようにしたいので、この質問の確認を求めます。

相談後、私の理解として、心配する必要はないと思います。

  • man 3 exec
  • man 1p exec

シェルスクリプトは、シェルによって実行されると、

  1. シェルはプログラムexecを実行します。
  2. これにより、スクリプトを実行していたシェル/ bashを置き換えるexec***ファミリーシステムコールを使用しますimpedingシェルのさらなるアクション(「置き換えられた」)

前に説明したように、この質問の主な目的は、execの後に発生するスクリプト内のすべて(echo testなど)が実行されないようにするための私の推論を確認することです。

可能な限り一般的な回答(POSIX)をいただければ幸いですが、具体的に言えば、GNU/LinuxとGNU/Bashに最も興味があります。

5

execは常にスクリプトを終了しますifコマンドを実行し、正常に実行します(コマンドの終了コードとは関係なく、それを開始するため)。

execは、コマンドなしで非常に便利な方法で実行できます。ファイル記述子を永続的にリダイレクトするには:

exec 3>/path/to/file

コマンドを開始できない場合、シェルの動作は構成によって異なります。 bashはデフォルトで終了します。

代わりに関数を使用することをお勧めします。

safe_exec () {
    cmd="$1"
    if test -z "$cmd" || ! test -f "$cmd" || ! test -x "$cmd"; then
        exit 1
    else
        exec "$@"
    fi
}

safe_exec echo "some "; echo "test"
3
Hauke Laging

そうです、execが成功すると、現在のシェルが置き換えられるため、次のコマンドは実行されません。

ただし、 少なくともBashではexecが失敗した場合にもシェルは終了します

exec [-cl] [-a name] [command [arguments]]

commandを指定すると、新しいプロセスを作成せずにシェルを置き換えます。 [...]commandが何らかの理由で実行できない場合、execfail Shellオプションが有効。その場合、失敗を返します。

したがって、bash -c 'exec /bin/nosuchfile; echo foo'は、不足しているプログラムファイルに関するエラーメッセージを出力するだけです。スクリプトのエラーを処理するには、次のようなものが必要です

#!/bin/bash
shopt -s execfail
exec /someprogram
echo whoops, it failed

ただし、execからエラーメッセージが表示されます。 execにリダイレクトを行った場合、([== --- ==)execが失敗した後にスクリプトが続行すると、それが有効になります

6
ilkkachu

execビルトイン(コマンド引数付き)は、シェルプロセス²を置き換えます。シェルプロセスの後続のコードは実行されません。

したがって、exec echo "some "; echo "test"some textを出力する唯一の方法は、PATHにechoという実行可能コマンドがあり、この実行可能ファイルがsomeではなくsome textを出力した場合です。これは、echo実行可能ファイルがechoというコマンドから期待されるとおりに動作する通常の状況では発生しません。

PATHにechoという実行可能ファイルがない場合、または実行に失敗した場合、execはエラーメッセージを表示してシェルを終了します。その場合でも、echo "test"は実行されません。

¹ コマンド引数なしのexecは別の獣です。シェルプロセスに代わるものではなく、リダイレクトを適用するだけです。
² サブシェルでは、影響を受けるのはサブシェルだけで、親シェルは通常どおり実行を続けます。