Bashのビルトインexecの使用例/実用例


12

Bashの組み込みexecのドキュメントからこれを考慮してください。

execは、新しいプロセスを作成せずにシェルを置き換えます

ユースケース/実用例を提供してください。これが理にかなっているのかわかりません。

私はグーグルでI / Oリダイレクトについて知りました。もっと説明してもらえますか?


回答:


18

exec多くの場合、主に他のバイナリを起動するためのラッパーとして機能するシェルスクリプトで使用されます。例えば:

#!/bin/sh

if stuff;
    EXTRA_OPTIONS="-x -y -z"
else
    EXTRA_OPTIONS="-a foo"
fi

exec /usr/local/bin/the.real.binary $EXTRA_OPTIONS "$@"

ラッパーの実行が終了すると、「実際の」バイナリが引き継がれ、プロセステーブルの同じスロットを一時的に占有したラッパースクリプトのトレースはなくなります。「実際の」バイナリは、孫ではなく、それを起動したものの直接の子です。

質問でI / Oリダイレクトについても言及しています。これはまったく別の使用例でexecあり、シェルを別のプロセスに置き換えることとは関係ありません。when execに引数がない場合、次のようになります。

exec 3>>/tmp/logfile

コマンドラインでのI / Oリダイレクトは現在のシェルプロセスで有効になりますが、現在のシェルプロセスは実行を続け、スクリプト内の次のコマンドに進みます。


1
2つのケースは両方とも関連していると言えexecます。シェルは、子プロセスでアクション(コマンドの実行またはリダイレクトの実行)を実行せず、同じプロセスで実行するように指示します。
ステファンシャゼラス

5

シェルのexec組み込みコマンドを使用して、JavaプログラムのプロセスID(PID)を取得しました。現在、Java内部からPIDを取得する方法があるかもしれませんが、数年前にはありませんでした。プロセスが独自のPIDを/var/run/取得すると、それをPIDファイルに書き込み(拡張子が「.pid」のファイル名を探す)、管理プログラムが実行中のプロセスのPIDを認識し、2番目のインスタンスを防止同じサーバーの実行。次のように機能します。

exec java -cp=YourServer.jar StartClass -p $$

main()クラスのメソッドのコードはStartClass引数の解析を処理し、独自のプロセスIDを見つけることができます。


2

楽しみのために、ユーザープロセスのアカウンティングと制限があるシステムでバックグラウンドで次のプログラム(選択した実装言語に翻訳されています)を実行します。

while(true) fork();

使用が許可されているプロセステーブル内のすべてのスロットが、実行中のプログラムのコピーでいっぱいになったので、どうやってそれを殺すつもりですか?kill(1)を起動するには、別のプロセススロットが必要ですが、これは使用できません。シェルを強制終了コマンドで置き換えると便利です...

exec /bin/kill -9 -1

(システムに/ bin / killにkill(1)があると仮定します。「exec `which kill` -9 -1」の方が安全である可能性があります。)これにより、可能なすべてのプロセスにSIGKILLが送信されます。

(注:プロセスの制限により、シェルのプロセススロットへの新しいログインが常に許可されない限り、起動シェルからログアウトしないでください。これを行うと、クリーンアップが少し難しくなる可能性があります。 90年代初期。いや。)


3
(1)execこの状況で役立つコマンドを実際に示した場合、この答えは少し良くなります。(2)この答えはやや古風です。killコマンドは、主な理由は、この懸念のため、長年にわたりbashで組み込みコマンドとなっています。
G-Manによる「Reinstate Monica」

@ G-Man:アイテム(2)がこの答えをOPに対する正確な応答にすることを理解していますか?
エリックタワーズ

いいえ、わかりません。説明してください。
G-Manが「Reinstate Monica」と言う

4
私はあなたをフォローしていません。この質問は、すべての bash組み込みコマンドの実用的な例を求めているわけではありません。の例を求めていますexeckillビルトインであるという事実は、ビルトインとは何の関係もありませんexec
G-Manによる「Reinstate Monica」

1
私はあなたの答えの更新を読みました。(1)何だと思う?プロセステーブルがいっぱいの場合、コマンド置換(例:)`which kill`も機能しません。(2)ところで、$(…)フォームはフォームよりも推奨され`…`ます。(3)しかし、ディレクトリを推測することは危険ではありません。誤ってを入力するexec /binn/killと、エラーメッセージが表示されるだけで、シェルは消えません。(4)しかし、あなたも、どのようなディレクトリを心配する必要はありませんkillである。  exec用途$PATH、ちょうど通常のコマンドのように、そのexec kill …(あなたが持っていると仮定すると作品/bin検索パスに)。
G-Manは「Reinstate Monica」と言います

1
  • これは、プロセスのPIDを知る必要があるブルースの例に似ています。

    (cmdpid = $ BASHPID;(sleep 300; kill "$ cmdpid")&exec long-running-command

    あなたが

    1. サブシェル(外側())を開始し、
    2. サブシェルのPIDを見つけます。($$メインシェルのPIDを提供します。)
    3. タイムアウト後にプロセスを強制終了するサブサブシェルを切り離します。
    4. 手順1で作成したサブシェルのプロセスでコマンドを実行します。

    これはを実行しますlong-running-commandが、事前に決められた限られた時間だけです。 

  • これは少し簡単ですが、ログインセッションの残りの部分でroot(または他のユーザー)になりたいと判断した場合は、できexec suます。

    実際、これが本当に役立つシナリオを想像できます。リモートシステムにログインしており、何らかの理由で接続の切断と新しい接続の開始に問題があると仮定します。たとえば、リモートシステムにスケジュールに従うファイアウォールがあるとします。接続すると接続が許可され、確立された接続は閉じられませんが、現時点では、新しい接続は受け入れられません。

    やりたいことをやり終えて、ログアウトする準備ができました。友人のボブが部屋にいて、リモートシステムで作業をしたいと思っていますが、接続できません。したがって、と入力しexec su - bob、パスワードプロンプトが表示されたら、ワークステーションを彼に引き渡します。(バックグラウンドで何かを実行していない限り)UIDを使用したプロセスはないため、Bobはファイルをいじることができません。彼は(あなたの同意と協力を得て)あなたのつながりを効果的に引き継いだでしょう。

    ノート:

    • もちろん、実行を許可されていない場合、これは機能しませんsu
    • ログに記録されるので、誰かに動機を説明する必要があるかもしれません。ポリシー(ファイアウォールスケジュール)を回避しているため、問題が発生する可能性があります。
    • 100%安全であることを保証しません。たとえば、whoおそらくまだあなたの名前が表示されます。一部の(不適切に作成された)プログラムがそれを使用してBobがあなたであると考え、彼にあなたのリソースへのアクセスを許可することは考えられます。
    • システムが監査を行う場合、ボブのアクションはあなたの名前で監査される可能性があります。

実際にはほとんどのシェルで、シェル(a;b)(a;exec b)サブシェルの最後のコマンドのフォークを最適化するのと同じであることに注意してください。唯一の例外はあるように見えるbashmksh。使用execすると、それを保証するのに役立ちます。
ステファンシャゼル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.