シェルスクリプトでのexecコマンドの用途は何ですか?


249

誰でも簡単な例でシェルスクリプトでのexecコマンドの使用法を説明できますか?


31
linux.about.comへのリンクは役に立ちません。それらは、「exec」を使用してコマンドまたはコマンドのパイプラインを実行することが、通常のコマンドを実行することとどのように異なるかをリモートで明確にしません。したがって、OPの質問は「execの使用とは何ですか?」
ジョナサンハートレー

2
Stack Overflowは、プログラミングと開発に関する質問のためのサイトです。この質問はプログラミングや開発に関するものではないため、トピックから外れているようです。ヘルプセンターで、どのようなトピックについて質問できますかをご覧ください。おそらく、スーパーユーザーまたはUnix&Linux Stack Exchangeのほうがよいでしょう。
jww

回答:


281

execカーネル内の組み込みコマンドミラー機能に基づいて、それらの家族がありexecve、通常はCから呼ばれ、

execfork新しいプロセスを実行せずに、現在のプロセスの現在のプログラムを置き換えます。作成するすべてのスクリプトで使用するものではありませんが、場合によっては役立ちます。以下に、私が使用したいくつかのシナリオを示します。

  1. ユーザーがシェルにアクセスせずに特定のアプリケーションプログラムを実行することを望みます。/ etc / passwdのサインインプログラムを変更することもできますが、環境設定を起動ファイルから使用したい場合があります。したがって、(たとえば).profileでは、最後のステートメントは次のようになります。

     exec appln-program

    ですから、戻るシェルはありません。appln-programクラッシュしても、エンドユーザーはシェルにアクセスできません。シェルが存在しないため、exec置き換えられました。

  2. / etc / passwdにあるシェルとは異なるシェルを使用したい。馬鹿げているように思われるかもしれませんが、一部のサイトでは、ユーザーがサインインシェルを変更することを許可していません。私が知っている1つのサイトでは、すべてのユーザーがで始まりcsh、誰もが.login(csh起動ファイル)への呼び出しを入力しましたksh。それが機能している間、それは浮遊cshプロセスを実行したままにし、ログアウトは混乱を招く可能性がある2つのステージでした。そこでexec ksh、cシェルプログラムをkornシェルに置き換えたものに変更し、すべてをより単純にしました(これにkshは、ログインシェルではないという事実など、他の問題があります)。

  3. プロセスを保存するだけです。prog1 -> prog2 -> prog3 -> prog4etc を呼び出して元に戻らない場合は、各呼び出しをexecにします。リソースが節約され(繰り返されない限り、確かに多くはありません)、シャットダウンが単純になります。

あなたは明らかにexecどこかで使用されているのを見ました、おそらくあなたがあなたを悩ませているコードを示したなら、私たちはその使用を正当化できます。

編集:私は上記の私の答えが不完全であることを認識しました。あり2つの用途execのようなシェルでkshbashファイルディスクリプタを開くために使用が- 。ここではいくつかの例を示します。

exec 3< thisfile          # open "thisfile" for reading on file descriptor 3
exec 4> thatfile          # open "thatfile" for writing on file descriptor 4
exec 8<> tother           # open "tother" for reading and writing on fd 8
exec 6>> other            # open "other" for appending on file descriptor 6
exec 5<&0                 # copy read file descriptor 0 onto file descriptor 5
exec 7>&4                 # copy write file descriptor 4 onto 7
exec 3<&-                 # close the read file descriptor 3
exec 6>&-                 # close the write file descriptor 6

ここでは間隔が非常に重要であることに注意してください。fd番号とリダイレクト記号の間にスペースexecを入れると、元の意味に戻ります。

  exec 3 < thisfile       # oops, overwrite the current program with command "3"

これらを使用する方法はいくつかあります。たとえば、kshでの使用、read -uまたはprint -uでの使用bashです。

read <&3
echo stuff >&4

22
Pythonウェブアプリケーションに関連し、あなたの(素晴らしい)回答2と3の間にあるように見えるので、ここで言及する価値のある別の使用法もあります。私は通常、スーパーバイザーからgunicornを呼び出すwsgi Webアプリ(たとえば、ジャンゴまたはフラスコ)を実行しますアプリ:後者はかなり多くの環境変数を必要とすることで有名ですが、すべてを設定し、最終的exec gunicornに正しいpidをスーパーバイザーに返すシェルスクリプトからgunicornを実行する方がはるかに簡単で保守しやすくなっています。
gru

1
ドキュメントはexecリダイレクトに使用できると言っています:>コマンドが指定されていない場合、リダイレクトは現在のシェルで有効になり、戻りステータスは0です。リダイレクトエラーがある場合、戻りステータスは1ですが、どのようにしてexec実際にファイル記述子を変更するのですか?この特定のコマンドがこのタスクに選択されるのはなぜですか?(値下げが今失敗している?)
レイ

@Ray:私ができる最善の方法:pubs.opengroup.org/onlinepubs/009604599/utilities/exec.html 。方法を知る必要がある場合は、シェルのソースコードを確認してください。
cdarke 2015年

7
別の用途:スクリプトのすべての出力をログファイルにリダイレクトexec >.\logfilename.log 2>&1
Hogan

1
@Carmageddon: &>bash拡張機能(を参照man bash)であり、例はと同等exec >/var/log/userdata.log 2>&1です。つまり、stdoutとstderrをそのファイルにリダイレクトします。以下のコマンドは、リセットされない限りこれらのリダイレクトを継承しますが、実行されます。
cdarke

41

受け入れられた回答を初心者向けの簡単な短い回答で補強するために、おそらく必要ありませんexec

あなたがまだここにいるのであれば、次の議論でその理由が明らかになるはずです。あなたが走ると、言う、

sh -c 'command'

shインスタンスを実行し、commandそのshインスタンスの子として開始します。いつcommand終了すると、shインスタンスも終了します。

sh -c 'exec command'

shインスタンスを実行し、次に置き換えますそのshインスタンスをcommandバイナリでそれを実行します。

もちろん、これらはどちらもこの限られた状況では役に立ちません。あなたは単に欲しい

command

シェルに構成ファイルを読み取らせるか、実行の準備として何らかの方法で環境を設定したい場合がありますcommand。これは、exec command役に立つ唯一の状況です。

#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command

これは、必要なものが含まれるように環境を準備するためにいくつかのことを行います。それが完了すると、shインスタンスは不要になるため、shインスタンスを子プロセスとして実行して待機commandするのではなく、インスタンスをプロセスに置き換えるだけの(マイナーな)最適化shであり、終了したらすぐに終了します。

同様に、シェルスクリプトの最後にある重いコマンドのために、できるだけ多くのリソースを解放したい場合は、execそのコマンドを最適化として使用できます。

何かがあなたに実行を強制したshが、本当に何か他のものを実行したい場合exec something elseは、もちろん、望ましくないshインスタンスを置き換えるための回避策です(たとえばgoshshがリストされてい/etc/shellsない場合など)ログインシェルとして指定しないでください)。

execファイル記述子を操作するためのの2番目の使用法は、別のトピックです。受け入れられた答えはそれをうまくカバーしています。この自己完結型を維持するためexecに、コマンド名の代わりにリダイレクトが続く箇所については、マニュアルを参照します。


2
あなた自身の気の利いたシェルを呼び出す誘惑に抵抗しますbush。もちろん、これはbash一般的なUnixシェルにも適用されます。@anishsaneが指摘しているように、Bashはbash -c 'command'実際に実行することで密かに最適化しexec commandます。
Tripleee

1
シェルの終了コードは通常、最後に実行したコマンドの終了コードです。もちろん、シェルの実行やコマンドの実行に失敗した場合、シェルの終了ステータスには適切なエラーコードが表示されます。
Tripleee

2
@JonathanLeffler私は、初心者の質問で目にするアンチパターンを意図的に文書化しています。これはこの重複ましたが、以前に見たことがあるので、具体的に説明したいと思います。
Tripleee

2
@JonathanLefflerマイナーな表現の微調整。これで十分ですか?フィードバックをお寄せいただきありがとうございます。
Tripleee

2
ありがとう-この最適化についての短い段落をもう1つ追加しました。他に異論があるかどうか、または別の角度から説明したいだけなのかどうかは、はっきりしません。
Tripleee
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.