web-dev-qa-db-ja.com

スクリプトからバックグラウンドプロセスを開始し、スクリプトが終了したときに管理する

スクリプトからデーモンのようにプロセスを実行して構成したいと思います。
私のシェルはCygwinでエミュレートされたzshで、デーモンは基本的なFTPサーバーである [〜#〜] sfk [〜#〜] です。

ここで重要なのは、スクリプトstartserv.shを次のように作成することです。

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
$cmd &

スクリプトstartserv.shを実行した後、プロンプトを表示せずに停止(終了?)します。

  • CTRL+C スクリプトとバックグラウンドジョブプロセスの両方を終了します。

  • ヒッティング Enter スクリプトはプロセスを終了し、バックグラウンドのままです。

とにかくpsではなくjobs経由でしか表示されないので、プロセスを閉じるときに、残忍なkill -9信号を送信する必要があります。 dを避けるために避けたい CTRL+C

代替は、スクリプト全体をバックグラウンドで実行することになります。 「する」でしょうが、スクリプトをstartserv.sh &として実行すると、readコマンドはユーザー入力を取得できません。

本当のdaemonではなく、短命なサーバーが必要であることに注意してください。つまり、スクリプトが終了した後、サーバープロセスをバックグラウンドで実行します。 (仮想マシンゲストを使用して)単純な対話型シェルタスクを実行しますが、シェルを生き残るためのプロセスは必要ありません。したがって、Nohupは適切ではないようです。

15
antonio

ヒッティング Enter スクリプトはプロセスを終了し、バックグラウンドのままです。

ほとんど!実際、このスクリプトは、押すまでにすでに終了しています。 Enter。ただし、これはプロンプトを元に戻す方法です(シェルが$PS1を繰り返し出力するため)。

打つ理由 CtrlC それらの両方が終了するのは、それらの2つがリンクされているためです。スクリプトを実行すると、シェルはそれを実行するサブシェルを開始します。このサブシェルを終了すると、おそらくSIGHUPシグナルによってバックグラウンドプロセスが終了します。

スクリプト、バックグラウンドプロセス、サブシェルを分離する

Nohupを使用すると、この小さな不便さを解消できる可能性があります。

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
Nohup $cmd &

disown代替

/bin/shから/bin/bashに切り替えることができる場合は、disownを試すこともできます。詳細については、bashインスタンスにhelp disownと入力してください。

disown -h $cmd &

バックグラウンドプロセスを「適切に」終了する

今、あなたのプロセスを殺すことになると、あなたは完全に行うことができます "CtrlC"killを使用します。残忍なSIGKILLを送信しないでください。代わりに、以下を使用できます。

$ kill -2 [PID]
$ kill -15 [PID]

これにより、Nice SIGINT(2)またはSIGTERM(15)がプロセスに送信されます。プロセスの開始後にPID値を印刷することもできます。

...
Nohup $cmd &
echo $!

...またはそれ以上に、スクリプトがSIGINTを待機するようにして、バックグラウンドプロセスに送り返します(これにより、スクリプトがフォアグラウンドに保持されます)

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
Nohup $cmd &

# Storing the background process' PID.
bg_pid=$!

# Trapping SIGINTs so we can send them back to $bg_pid.
trap "kill -2 $bg_pid" 2

# In the meantime, wait for $bg_pid to end.
wait $bg_pid

SIGINTでは不十分な場合は、代わりにSIGTERMを使用してください(15):

trap "kill -15 $bg_pid" 2 15

これにより、スクリプトがSIGINTCtrlCkill -2)またはSIGTERMバックグラウンドプロセスをwaitingしている間、信号を中継するだけです。これらのシグナルがsfkインスタンスを強制終了する場合、wait呼び出しが返されるため、スクリプトも終了します:)

18
John WH Smith