Bashスクリプト、パート5:シグナル、バックグラウンドタスク、スクリプト管理

Bashスクリプト:開始
Bashスクリプト、パート2:ループ
Bashスクリプト、パート3:オプションとコマンドラインスイッチ
Bashスクリプト、パート4:入力と出力
Bashスクリプト、パート5:シグナル、バックグラウンドタスク、スクリプト管理
Bashスクリプト、パート6:関数とライブラリーの開発
Bashスクリプト、パート7:sedとワープロ
Bashスクリプト、パート8:awkデータ処理言語
Bashスクリプトパート9:正規表現
Bashスクリプト、パート10:ケーススタディ
Bashスクリプト、パート11:対話型ユーティリティの期待と自動化

画像

前回、bashスクリプトの入力、出力、エラーストリーム、ファイル記述子、スレッドリダイレクトの操作について説明しました。 今、あなたはすでにあなた自身を書くのに十分知っています。 bashをマスターするこの段階では、作業スクリプトの管理方法とその起動を自動化する方法について質問があるかもしれません。



これまでのところ、コマンドラインでスクリプト名を入力してEnterキーを押すと、プログラムがすぐに起動しましたが、これがスクリプトを呼び出す唯一の方法ではありません。 今日は、Linuxシグナルでスクリプトがどのように機能するか、作業中にスクリプトを実行してスクリプトを管理するさまざまなアプローチについて説明します。

Linuxシグナル


Linuxでは、システムまたはアプリケーションが生成する30以上のシグナルがあります。 以下に、コマンドラインスクリプトを開発する際に役立つと思われる、最も一般的に使用されるもののリストを示します。
信号コード
役職
説明
1
シグアップ
ターミナル閉鎖
2
シギント
ユーザーは端末からプロセスを停止します(CTRL + C)
3
SIGQUIT
ユーザーは、メモリダンプを使用して端末(CTRL + \)からプロセスを停止します
9
シグキル
無条件のプロセス終了
15
シグターム
プロセス完了要求信号
17
シグストップ
プロセスの強制停止、ただしその作業の終了ではない
18
SIGTSTP
端末からのプロセスの一時停止(CTRL + Z)、ただしシャットダウンしない
19
SIGCONT
以前に停止したプロセスを継続する

ターミナルを閉じたときにbashシェルがSIGHUPシグナルを受信すると、シャットダウンします。 終了する前に、実行中のスクリプトを含む、実行中のすべてのプロセスにSIGHUPシグナルを送信します。

SIGINTシグナルは一時的なシャットダウンを引き起こします。 Linuxカーネルは、プロセッサー時間をシェルに割り当てなくなります。 これが発生すると、シェルはプロセスにSIGINTシグナルを送信して通知します。

Bashスクリプトはこれらのシグナルを制御しませんが、シグナルを認識して特定のコマンドを実行し、シグナルによって引き起こされる結果に備えてスクリプトを準備できます。

スクリプトへのシグナルの送信


bashシェルを使用すると、キーボードショートカットを使用してスクリプトに信号を送信できます。 これは、実行中のスクリプトを一時的に停止したり、作業を終了したりする必要がある場合に非常に役立ちます。

プロセスのシャットダウン


CTRL + Cキーの組み合わせは、 SIGINTシグナルを生成し、シェルで実行されているすべてのプロセスに送信します。これにより、作業が完了します。

シェルで次のコマンドを実行します。

 $ sleep 100 

その後、 CTRL + Cキーの組み合わせで作業を完了しますCTRL + C


キーボードのシャットダウン

一時的なプロセスのシャットダウン


CTRL + Zキーの組み合わせにより、 SIGTSTPシグナルを生成できます。シグナルはプロセスを一時停止しますが、実行は完了しません。 そのようなプロセスはメモリに残り、その作業を再開できます。 シェルでコマンドを実行します。

 $ sleep 100 

そして、 CTRL + Zキーの組み合わせで一時的に停止します。


一時停止プロセス

角括弧内の数字は、シェルがプロセスに割り当てるジョブ番号です。 シェルは、そこで実行されるプロセスを一意の番号を持つタスクと見なします。 最初のプロセスには番号1、2番目のプロセスには2、というように割り当てられます。

シェルにバインドされたタスクを一時停止して終了しようとすると、bashは警告を発行します。

次のコマンドを使用して、中断されたタスクを表示できます。

 ps –l 


タスクリスト

プロセスの状態を表示する列Sには、中断されたプロセスのTが表示されます。 これは、コマンドが一時停止されているか、トレース状態にあることを示します。

一時停止したプロセスをシャットダウンする必要がある場合は、 killコマンドを使用できます。 詳細については、 こちらをご覧ください

彼女の呼び出しは次のようになります。

 kill processID 

信号傍受


スクリプトでLinux信号追跡を有効にするには、 trapコマンドを使用します。 スクリプトは、このコマンドが呼び出されたときに指定されたシグナルを受け取ると、それを独立して処理しますが、シェルはそのようなシグナルを処理しません。

trapコマンドは、スクリプトがシグナルに応答できるようにします。そうでない場合、それらの処理はシェルが関与せずにシェルによって実行されます。

trapコマンドが呼び出されたときに、実行するコードと、インターセプトするスペースで区切られたシグナルのリストがどのように指定されるかを示す例を考えてみましょう。 この場合、これは1つのシグナルにすぎません。

 #!/bin/bash trap "echo ' Trapped Ctrl-C'" SIGINT echo This is a test script count=1 while [ $count -le 10 ] do echo "Loop #$count" sleep 1 count=$(( $count + 1 )) done 

この例で使用されるtrapコマンドは、キーボードでCtrl + Cを押すことで生成できるSIGINTシグナルを検出するたびにテキストメッセージを表示します。


信号傍受

CTRL + Cを押すたびに、スクリプトは、シェルを終了させるのではなく、 traceを呼び出すときに指定されたechoコマンドを実行します。

スクリプト信号傍受


trapコマンドを呼び出すときにEXITシグナル名を使用して、スクリプトからの終了シグナルをインターセプトできます。

 #!/bin/bash trap "echo Goodbye..." EXIT count=1 while [ $count -le 5 ] do echo "Loop #$count" sleep 1 count=$(( $count + 1 )) done 


スクリプト信号傍受

スクリプトを終了するとき、その作業が正常に終了したか、 SIGINTシグナルによって終了したかにかかわらず、インターセプトは機能し、シェルはechoコマンドを実行します。

傍受信号の変更と傍受のキャンセル


スクリプトによってインターセプトされたシグナルを変更するには、新しいパラメーターを使用してtrapコマンドを実行できます。

 #!/bin/bash trap "echo 'Ctrl-C is trapped.'" SIGINT count=1 while [ $count -le 5 ] do echo "Loop #$count" sleep 1 count=$(( $count + 1 )) done trap "echo ' I modified the trap!'" SIGINT count=1 while [ $count -le 5 ] do echo "Second Loop #$count" sleep 1 count=$(( $count + 1 )) done 


信号傍受の変更

変更後、信号は新しい方法で処理されます。

シグナルの傍受をキャンセルすることができます。このため、 trapコマンドを実行し、二重ダッシュとシグナル名を渡すだけで十分です。

 #!/bin/bash trap "echo 'Ctrl-C is trapped.'" SIGINT count=1 while [ $count -le 5 ] do echo "Loop #$count" sleep 1 count=$(( $count + 1 )) done trap -- SIGINT echo "I just removed the trap" count=1 while [ $count -le 5 ] do echo "Second Loop #$count" sleep 1 count=$(( $count + 1 )) done 

インターセプトがキャンセルされる前にスクリプトが信号を受信した場合、現在のtrapコマンドで指定されたtrap処理します。 スクリプトを実行します。

 $ ./myscript 

そして、キーボードのCTRL + Cを押します。


キャンセル前に傍受された信号

CTRL + Cの最初の押下は、スクリプトが実行されたときに発生し、シグナルインターセプトが有効であったため、スクリプトはシグナルに割り当てられたechoコマンドを実行しました。 実行がインターセプトをキャンセルするコマンドに到達した後、 CTRL + Cコマンドは通常の方法で機能し、スクリプトを終了しました。

バックグラウンドでコマンドラインスクリプトを実行する


bashスクリプトがタスクを完了するのに時間がかかる場合があります。 この場合、スクリプトの完了を待たずに、コマンドラインで正常に機能する必要があります。 これを実装することはそれほど難しくありません。

psコマンドによって表示されるプロセスのリストを見た場合、バックグラウンドで実行されており、端末に関連付けられていないプロセスに気付く場合があります。
次のようなスクリプトを作成しましょう。

 #!/bin/bash count=1 while [ $count -le 10 ] do sleep 1 count=$(( $count + 1 )) done 

名前の後にアンパサンド( & )文字を指定して実行します。

 $ ./myscipt & 

これにより、バックグラウンドプロセスとして開始されます。


バックグラウンドでスクリプトを実行する

スクリプトはバックグラウンドプロセスで起動され、その識別子がターミナルに表示され、実行が完了すると、これに関するメッセージが表示されます。

スクリプトはバックグラウンドで実行されますが、ターミナルを使用してSTDOUTおよびSTDERRメッセージを表示し続けることに注意してください。つまり、表示されるテキストまたはエラーメッセージはターミナルで見ることができます。


プロセスリスト

このアプローチでは、ターミナルを終了すると、バックグラウンドで実行されているスクリプトも作業を完了します。

ターミナルを閉じた後でもスクリプトが動作し続ける必要がある場合はどうなりますか?

ターミナルを閉じるときに終了しないスクリプトの実行


スクリプトは、ターミナルセッションを終了した後でもバックグラウンドプロセスで実行できます。 これを行うには、 nohupコマンドを使用できます。 このコマンドを使用すると、プロセスに送信されるSIGHUPシグナルをブロックして、プログラムを開始できます。 その結果、プロセスは、それが開始された端末を離れる場合でも実行されます。

スクリプトを実行するときにこの手法を適用します。

 nohup ./myscript & 

これは端末に出力されるものです。


ノーフチーム

nohupコマンドは、端末からプロセスのバインドを解除します。 これは、プロセスがSTDOUTおよびSTDERRへの参照を失うことを意味しSTDOUT 。 スクリプトによるデータ出力が失われないように、 nohupSTDOUTおよびSTDERRに到着するメッセージをファイルnohup.out自動的にリダイレクトします。

同じディレクトリから複数のスクリプトを実行すると、それらの出力は1つのnohup.outファイルに分類されることに注意してください。

課題を見る


jobsコマンドを使用すると、シェルで実行されている現在のジョブを表示できます。 次のようなスクリプトを作成しましょう。

 #!/bin/bash count=1 while [ $count -le 10 ] do echo "Loop #$count" sleep 10 count=$(( $count + 1 )) done 

実行してください:

 $ ./myscript 

そして、キーの組み合わせCTRL + Z一時的に停止します。


スクリプトの実行と一時停止

画面に何も表示されないように、スクリプト出力をファイルにリダイレクトしながら、バックグラウンドで同じスクリプトを実行します。

 $ ./myscript > outfile & 

jobsコマンドが完了すると、中断されたスクリプトとバックグラウンドで動作するスクリプトの両方に関する情報が表示されます。


スクリプト情報の取得

jobsコマンドを呼び出すときの-lスイッチは、プロセスIDに関する情報が必要であることを示します。

一時停止したジョブを再開する


バックグラウンドでスクリプトを再起動するには、 bgコマンドを使用できます。

スクリプトを実行します。

 $ ./myscript 

CTRL + Z押すと、実行が一時的に停止します。 次のコマンドを実行します。

 $ bg 


BGコマンド

これで、スクリプトはバックグラウンドで実行されます。

複数の一時停止ジョブがある場合、 bg番号を渡して特定のジョブを再開できます。

タスクを通常モードで再起動するには、 fgコマンドを使用します。

 $ fg 1 

スクリプトを実行する計画


Linuxには、特定の時間にbashスクリプトを実行する方法がいくつかあります。 これはatコマンドとcronジョブスケジューラです。

atへの呼び出しは次のようになります。

 at [-f filename] time 

このコマンドは、多くの時間形式を認識します。


タスクの開始時刻を指定する機能に加えて、 atコマンドには、サポートされている形式のいずれかを使用して日付を指定することもできます。


このトピックについては詳しく説明しませんが、コマンドの簡単な使用例を考えてみましょう。

 $ at -f ./myscript now 


atコマンドを使用したタスクのスケジューリング

at呼び出すときの-M at 、システムが適切に構成されている場合にスクリプトが出力する内容を電子メールで送信するために使用されます。 電子メールを送信できない場合、このキーは単に出力を抑制します。

完了待ちのタスクのリストを表示するには、 atqコマンドを使用できます。

 $ atq 


保留中のジョブのリスト

保留中のジョブの削除


atrmコマンドを使用するとatrmatrmできます。 呼び出されると、タスク番号が示されます。

 $ atrm 18 


ジョブを削除

スケジュールされたスクリプト


atコマンドを使用して1回限りのスクリプト実行を計画すると、多くの状況で作業が楽になります。 しかし、毎日同じ時間に、または週に1回、または月に1回、スクリプトを実行する場合はどうでしょうか。

Linuxには、スクリプトを定期的に実行するようにスケジュールできるcrontabユーティリティがあります。

Crontabはバックグラウンドで実行され、いわゆるcronテーブルのデータに基づいて、スケジュールされたジョブを実行します。

既存のcronジョブテーブルを表示するには、次のコマンドを使用します。

 $ crontab –l 

スケジュールに基づいてスクリプトを実行することを計画している場合、 crontabは次の形式でタスクをいつ完了するかに関するデータを受け取ります。

 , ,  , ,  . 

たとえば、 commandと呼ばれる特定のスクリプトを毎日10:30に実行command 、これはタスクテーブルのそのようなエントリに対応します。

 30 10 * * * command 

ここで、月、月、曜日を指定するフィールドに使用されるユニバーサルシンボル「 * 」は、 cronが毎月10:30にコマンドを実行することを示します。

たとえば、毎週月曜日の4:30PMスクリプトを実行する場合は、タスクテーブルに次のエントリを作成する必要があります。

 30 16 * * 1 command 

曜日の番号は0で始まり、0は日曜日、6は土曜日を意味します。 別の例を示します。 ここでは、コマンドは毎月1日の正午に実行されます。

 00 12 1 * * command 

月の番号は1から始まります。
テーブルにエントリを追加するには、 -eスイッチを-eしてcrontabを呼び出す必要があります。

 crontab –e 

次に、スケジュール生成コマンドを入力できます。

 30 10 * * * /home/likegeeks/Desktop/myscript 

このコマンドのおかげで、スクリプトは毎日10:30に呼び出されます。 「リソースが一時的に利用できません」というエラーが発生した場合は、ルート権限で次のコマンドを実行します。

 $ rm -f /var/run/crond.pid 

いくつかの特別なディレクトリを使用して、 cronを使用してスクリプトの定期的な起動を整理するのがさらに簡単です。

 /etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly 

スクリプトファイルをそれらの1つに配置すると、それぞれ、毎時、毎日、毎週、または毎月の起動につながります。

ログインおよびシェルの起動時に実行されるスクリプト


ユーザーのログインやシェルの起動など、さまざまなイベントに基づいてスクリプトの起動を自動化できます。 ここでは、そのような状況で処理されるファイルについて読むことができます。 たとえば、これらは次のファイルです。

 $HOME/.bash_profile $HOME/.bash_login $HOME/.profile 

ログイン時にスクリプトを実行するには、その呼び出しを.bash_profileファイルに入れます。

ターミナルを開くときにスクリプトを実行するのはどうですか? .bashrcファイルは、これを整理するのに役立ちます。

まとめ


今日は、スクリプトのライフサイクル管理に関連する問題を調査し、バックグラウンドでスクリプトを実行する方法と、スケジュールに従って実行を計画する方法について説明しました。 次回は、bashスクリプトの機能とライブラリ開発について読んでください。

親愛なる読者! スケジュールされたスケジューリングコマンドラインスクリプトを使用していますか? もしそうなら、それらについて教えてください。

Source: https://habr.com/ru/post/J326826/


All Articles