10

detach.sh次のようなプログラムを端末から安全にデタッチするために、おそらくbashという名前のLinuxシェルスクリプト(できればbash)を作成しようとしています。

  1. 呼び出し:./detach.sh prog [arg1 arg2 ...]

  2. 可能ですexec、例えば。シェルでこれを実行することによって:

    exec ./detach.sh prog [arg1 arg2 ...]
    
  3. 適切な引用符付き(主に空白を含む引数の処理)。

  4. 出力を破棄します(不要なため)。

  5. screen、などを使用しませんtmux(4と同じ理由に加えて、追加のベビーシッタープロセスは必要ありません)。

  6. (合理的に)ポータブルなコマンドとプログラムを使用し、start-stop-daemonディストリビューション固有のものはありません。

#!/bin/bash私はいくつかの方法を考えました(簡潔にするためにシバンの線は無視されています):

  1. nohup

    nohup "$@" >& /dev/null &
    
  2. disown

    "$@" >& /dev/null &
    disown
    
  3. setsid

    setsid "$@" >& /dev/null &
    
  4. サブシェルの使用:

    ("$@" >& /dev/null &)
    
  5. nohup/setsidサブシェルと組み合わせる:

    # Or alternatively:
    # (nohup "$@" >& /dev/null &)
    (setsid "$@" >& /dev/null &)
    

geditテストプログラムとして(部品を代用して)使用する場合"$@"、条件1は上記のすべての方法で満たすことができますが、条件2はなしで満たすことができます。

ただし、任意のプログラム(シェルビルトインではない)がスクリプト5に追加された場合、すべての条件が満たされているように見えます(少なくとも私にとってはgedit)。例えば:

(setsid "$@" >& /dev/null &)
# Not just `true' because it is also a shell builtin.
/bin/true

上記の現象の説明と要件を正しく実装する方法についてのアイデアを持っている人はいますか?

編集:

条件2では、プログラムを端末から切り離す必要がありますが、それ以外の場合は通常どおり実行されます。たとえば、この場合、スクリプトのプロセスが終了した直後に終了するgeditと、条件は失敗します。gedit

4

3 に答える 3

4

詳細な調査により、これらの以前は気付かれなかった事実が明らかになりました。

  1. aがスクリプトに追加されている場合、スクリプト 3 と 5 の両方 (setsidバリアントのみ) はすべての条件を満たします。/bin/true

  2. /bin/true実際に 1 で変更されたこれらのスクリプトは、 をに置き換えても同様に機能 しfor i in {0..9999}; do :; doneます。

したがって、次のように結論付けることができます。

  • (事実1より)

    複数レベルのデタッチ (スクリプト 5 のように) は不要であり、重要なのは適切なユーティリティ ( setsid) を使用することです。

  • (事実2より)

    スクリプトを正常に実行するには、bash が終了する前に適切な遅延が必要です。/bin/true(純粋な bash 時間コンシューマーと同様に、外部プログラムの呼び出しには時間がかかりfor i in {0..9999}; do :; doneます。)

    setsidソースコードを見ていませんが、適切な遅延が適用されていない場合、実行するプログラムの実行環境の構成が完了する前に bash が終了する可能性があると考えられます。

そして最後に、最適解は

#!/bin/bash
setsid "$@" >& /dev/null &
sleep 0.01

編集1

遅延の必要性はここで説明されています。@wilxに感謝します!

編集2

(@MateiDavidのおかげで)標準入力をリダイレクトするのを忘れていたようです。より良い方法は次のとおりです。

#!/bin/bash
setsid "$@" >& /dev/null < /dev/null &
于 2014-03-30T08:08:49.047 に答える
1

子をフォークするsetsid "$@" >& /dev/null & wait前に制御端末が消えないようにする必要があると思います。setsid

アップデート

これは、コマンドラインと引数の両方で機能するようです-c

(setsid tail -F /var/log/messages >& /dev/null) & disown
于 2016-05-10T09:46:33.693 に答える
0

UNIX デーモン プロセス (つまり、制御端末を持たず、独自のセッションリーダーであるプロセス) を作成しようとしています。コマンドはこれsetsidを行う必要がありますが、放棄する端末で開いているすべてのファイル記述子を閉じる必要があります。これは、それらをリダイレクトする/dev/nullか、ファイル記述子を閉じるためのシェルの構文を使用することで実行できます (たとえば、2>&-Bash0<&-で)。

于 2012-05-01T19:15:20.370 に答える