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



。 スクリプトによるデータ出力が失われないように、 nohup



STDOUT



および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



コマンドを使用するとatrm



atrm



できます。 呼び出されると、タスク番号が示されます。



 $ 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スクリプトの機能とライブラリ開発について読んでください。



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






All Articles