バックグラウンドで実行されているシェルスクリプトの終了

バックグラウンドで実行されているシェルスクリプトの終了

inotifyt-toolsのinotifywaitユーティリティを使用してディレクトリを監視するシェルスクリプトを作成しました。スクリプトがバックグラウンドで実行され続けたいのですが、必要に応じて停止することもできます。

引き続き実行するには、while true次のように使用しました。

while true;
do #a set of commands that use the inotifywait utility
end

ファイルとして保存して/bin実行可能にしました。バックグラウンドで実行するためにnohup <script-name> &端末を使用して閉じました。

このスクリプトを停止する方法がわかりません。私は答えを見たここそして非常に密接に関連する質問ここ

アップデート1: 以下の@InfectedRootの答えに基づいて、次の戦略を使用して問題を解決できました。初めて使用

ps -aux | grep script_name

sudo kill -9 <pid>プロセスを終了するために使用されます。その後、返されたIDを再pgrep inotifywait利用する必要がありました。sudo kill -9 <pid>

これはうまくいきますが、混乱したアプローチだと思い、より良い答えを探しています。

アップデート2: 回答には以下が含まれます2つのプロセスを終了。コマンドラインからスクリプトを実行すると2つのプロセスが開始されるため、これは重要です。スクリプト自体2、inotifyプロセス

答え1

コマンドを改善、使用、killall結合するには、次のようにします。

ps -aux | grep script_name
killall script_name inotifywait

または、1行ですべて実行してください。

killall `ps -aux | grep script_name | grep -v grep | awk '{ print $1 }'` && killall inotifywait

答え2

以下を使用してバックグラウンドタスクを一覧表示する

# jobs

次に、前のジョブ番号を選択して実行します。

はい

# fg 1 

ここに画像の説明を入力してください。

フロントデスクでお迎えいたします。

次にCTRL + Cを使用して終了するか、簡単な方法でスクリプトのPIDを見つけます。

ps -aux | grep script_name

ここに画像の説明を入力してください。

それからpidを使って殺します。

sudo kill -9 pid_number_here

答え3

ご存知のように、これを行う方法はいくつかあります。

「更新#2」関連 - 通常、上位階層でプロセスを終了すると、通常、関連するすべてのプロセスが終了します。しかし、多くの例外があります。理想的には、プロセスツリーの最後の「サブプロセス」を終了し、子プロセスに実行する他の操作がない場合は、子プロセスの親プロセスを終了する必要があります。ただし、親プロセスを終了すると、親プロセスが終了するとシグナルが子プロセスに転送され、子プロセスも終了する必要があります。しかし、場合によっては、サブプロセスはトラップまたは同様のメカニズムを介して信号を無視することがあります。 )実行し続けることができ、「init」プロセス(または同様のプロセス)によって継承されます。ただし、プロセスの動作に関するこのトピックは複雑になる可能性があるため、そのままにします。

制御スクリプト(以下の説明)を使用したくない場合は、私が好む1つの方法は、「スクリーン」ユーティリティを使用してプロセスを開始して管理することです。 「screen」コマンドは機能が豊富なため、習得に時間がかかる場合があります。完全な説明については、「screen」のマニュアルページをお読みください。バックグラウンドでプロセスを開始する簡単な例は、次のコマンドです。

画面 -d -m /パス/to/プログラム

これにより、「screen」セッション内で「/path/to/program」が開始されます。

次のコマンドを使用して、実行中のセッションを表示できます。

スクリーン-ls

次のコマンドを使用すると、いつでも実行中のプログラムに再接続できます。

スクリーン-R

その後、^Cまたは他のもので終了します。

プロセスに勝手に再接続して切断できるという利点に加えて、「スクリーン」はプログラムが生成できるすべてのstdout()をキャプチャします。


しかし、この問題で私が個人的に好むのは、プロセスの開始と停止を管理する制御プログラムを持つことです。これは少し複雑になる可能性があり、間違いなく複雑なスクリプトが必要です。すべてのスクリプトと同様に、これを実装する良い方法がたくさんあります。アプリケーションの起動と停止によく使用する方法の bash の例を提供しました。操作が簡単な場合は、制御スクリプトに直接挿入するか、制御スクリプトに別の外部プログラムを呼び出すことができます。この例は、管理プロセスの面では決して包括的ではないことに注意してください。私は次のシナリオの可能性を無視しています。 「開始」オプションを使用するときは、スクリプトがすでに実行されていないことを確認し、実行中のPIDが実際に起動したプロセスであることを確認してください(スクリプトが終了していないこと、他のPIDが終了していないことを確認してください)。プロセスはすでに同じPID起動を使用しています)スクリプトが最初の「終了」要求に実際に応答(終了)していることを確認してください。これらすべての検査を実行することは複雑になる可能性があるため、例が長すぎて複雑になることは望ましくありません。シェルスクリプトを練習するために例を変更したい場合があります。

次のコードを「programctl」というファイルに保存し、次のコマンドを使用して実行可能にします。

chmod 755プログラム制御

次に、ファイルを編集し、「myscript」で始まるケースセクションにコード/スクリプトを追加します。

すべてが準備されたら、「programctl」が現在のディレクトリにあると仮定し、次のようにプログラムを起動できます。

./programctl 開始

やめてください。

./programctl 停止

乾杯。

#!/bin/bash
# Description:  A wrapper script used to stop/start another script.

#--------------------------------------
# Define Global Environment Settings:
#--------------------------------------

# Name and location of a persistent PID file

PIDFILE="/tmp/tmpfile-$LOGNAME.txt"

#--------------------------------------
# Check command line option and run...
# Note that "myscript" should not
# provided by the user.
#--------------------------------------

case $1
in
    myscript)
        # This is where your script would go.
        # If this is a routine 'bash' shell script, you can enter
        # the script below as illustrated in the example.  
        # Or you could simply provide the path and parameters
        # to another script such as /dir/name/command -options

        # Example of an embedded script:

        while true
        do
            # do something over and over...
            sleep 1
        done

        # Example of an external script:

        /usr/local/bin/longrun -x
    ;;

    start)
        # Start your script in the background.
        # (Note that this is a recursive call to the wrapper
        #  itself that effectively runs your script located above.)
        $0 myscript &

        # Save the backgound job process number into a file.
        jobs -p > $PIDFILE

        # Disconnect the job from this shell.
        # (Note that 'disown' command is only in the 'bash' shell.)
        disown %1

        # Print a message indicating the script has been started
        echo "Script has been started..."
    ;;

    stop)
        # Read the process number into the variable called PID
        read PID < $PIDFILE

        # Remove the PIDFILE
        rm -f $PIDFILE

        # Send a 'terminate' signal to process
        kill $PID

        # Print a message indicating the script has been stopped
        echo "Script has been stopped..."
    ;;

    *)
        # Print a "usage" message in case no arguments are supplied
        echo "Usage: $0 start | stop"
    ;;
esac

答え4

ps+grepまたはを使用してpgrepプロセスを取得できます名前/PID;後でkillall/ を使用してpkillプロセス名を削除するか、killpid を削除します。以下のすべてが機能するはずです。

killall $(ps aux | grep script_name | grep -v grep | awk '{ print $1 }') && killall inotifywait
(ps -ef | grep script_name | grep -v grep | awk '{ print $1 }' | xargs killall) && killall inotifywait
(ps -ef | grep script_name | grep -v grep | awk '{ print $2 }' | xargs kill) && killall inotifywait
(pgrep -x script_name | xargs kill) && pkill -x inotifywait
pkill -x script_name && pkill -x inotifywait

最も重要なのは、人だけを殺さなければならないということです。正確なプロセスあなたが殺したいもの。

pkill/ pgrep1に一致模様代わりに正確な名前したがって、-x正確な名前と一致するようにここに追加されました。

また、pgrep/ を使用する場合にpkill必要な場合があります。

  • -fコマンドライン全体と一致します(このようにps aux)。
  • -aプロセス名を印刷することもできます。

関連情報