スクリプトとログのスケジューリング

ShellBeginner
オンラインで実践に進む

はじめに

あなたが眠っている間に家を掃除してくれるロボットを想像してください。眠っているので、ロボットが動いている様子は見えません。朝起きたとき、ロボットが本当に掃除を終えたのか、それともソファの下で動けなくなったのか、どうすれば分かるでしょうか。

答えは、ロボットに日記を付けさせることです。

Linux では、自動化されたスクリプトがバックグラウンドやスケジューラーから実行されることが多く、端末を見ている人がいない場合があります。そのため、画面への出力だけでは十分ではありません。何が起きたかを追跡できるように、出力をログファイルに書き込みます。

これは、最も簡単でありながら非常に価値の高い自動化の習慣の一つです。ログのないスクリプトは、何も知らせずに失敗する可能性があります。ログのあるスクリプトは、実行された証拠を残します。

この実験では、次のことを行います。

  1. 出力を切り替える:画面ではなくファイルに書き込むよう、スクリプトを設定します。
  2. 履歴を保持する:Append 演算子を使い、古い内容を削除せずに新しいエントリを追加します。
  3. タイムスタンプを追加する:すべての日記のエントリに日付と時刻を付けます。

出力をログファイルに追記する

通常のスクリプトは、出力をすぐに画面へ表示します。これは、誰かと対面で話すようなものです。しかし、誰も聞いていない場合(自動化されたスクリプトではよくあります)、その内容は永久に失われます。

そこで、出力をファイルに保存します。そのためにリダイレクト演算子を使います。

これは、以前学んだシェルの考え方に直接つながります。コマンドは通常、標準出力に書き込みますが、リダイレクトを使うと出力先を変更できます。ログ記録は、この仕組みを自動化で実用的に利用する方法です。

  • >(上書き):「日記を消去して、新しいページから始める」。履歴の保存には不向きです。
  • >>(追記):「次の空白行へ移動して、そこに書き込む」。履歴の保存に適しています。

準備されている簡単なスクリプトを確認しましょう。

cat myscript.sh

このスクリプトは、「The script is running」と表示するだけです。今の状態で実行すると(./myscript.sh)、画面にメッセージが表示されます。

これを変更して、script.log という日記ファイルに書き込むようにします。

スクリプトを開きます。

nano myscript.sh

行を変更し、>> 演算子を使います。

ヒント:ログを書き込むときは、/home/labex/project/script.log のような絶対パス(完全なパス)を必ず使ってください。スクリプトが別の場所から実行された場合でも、日記ファイルが予期しないフォルダーに作成されるのを防げます。

この習慣が重要なのは、スケジュールされたジョブが、対話型シェルで想定している場所とは異なる作業ディレクトリで実行されることが多いためです。パスを指定せずに script.log へ書き込むスクリプトでは、ファイルが間違った場所に作成される可能性があります。

ファイルの内容は次のようにします。

#!/bin/bash
echo "The script is running" >> /home/labex/project/script.log

保存して終了します。

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

./myscript.sh

何も表示されません。

スクリプトは実行されましたが、画面には何も表示しませんでした。その代わり、日記にそっと書き込んでいます。

日記の内容を確認します。

cat script.log

メッセージがファイル内に正しく保存されていることを確認できます。

タイムスタンプを追加する

「何が起きたか」を記録した日記に、「いつ起きたか」が書かれていなければ役に立ちません。スクリプトを 1 年間毎日実行すると、ログファイルには「The script is running」という同じ行が 365 行並ぶだけになってしまいます。

そこで、タイムスタンプを追加します。Linux には現在の時刻を表示する date コマンドがあります。このコマンドの出力もログファイルにリダイレクトします。

これは可観測性の基本です。後から人間が何が起きたかを再現できるよう、十分な証拠を残します。非常に簡単なタイムスタンプでも、自動化されたジョブのトラブルシューティング能力は大きく向上します。

myscript.sh を開きます。

nano myscript.sh

メッセージの前に date コマンドを追加します。これにより、ログには時刻が先に記録され、その後に動作内容が記録されます。

#!/bin/bash
date >> /home/labex/project/script.log
echo "The script is running" >> /home/labex/project/script.log

保存して終了します。

スクリプトをもう一度実行します。

./myscript.sh

ログを確認します。

cat script.log

次のような内容が表示されます。

The script is running
Fri Oct 27 10:00:00 UTC 2023
The script is running

(最初の行は、前のテストで記録されたものです)。

これで、すべての動作に正確な時刻が付きます。自動バックアップが午前 3 時に本当に実行されたことを、上司に示せるようになります。

大規模なシステムでは、ログによって、スクリプトが 2 回実行されたか、途中で停止したか、実行と実行の間にどれくらい時間がかかったかといった、より難しい疑問にも答えられます。適切なログがあれば、見えない自動化の動作を確認できるようになります。

ログの履歴を確認する

「追記」の仕組みを確認しましょう。>>(追記)の代わりに >(上書き)を使うと、ログファイルは増えません。実質的に、最後の実行結果だけが残ります。

この違いは、スクリプトを繰り返し実行する場合に重要です。上書きは現在の状態を示すスナップショットには便利ですが、追記はイベントの順序を保持できるため、通常は履歴の記録に適しています。

スクリプトが何度も実行される忙しい 1 日を再現します。

続けて 3 回実行します。

./myscript.sh
./myscript.sh
./myscript.sh

次に、日記を読み取ります。

cat script.log

タイムスタンプ付きのエントリが増えていることを確認できます。各エントリには、それぞれのタイムスタンプがあります。この履歴は、トラブルシューティングで非常に役立ちます。サーバーが昨日クラッシュした場合、ログを昨日のタイムスタンプまでさかのぼれば、その時点でスクリプトが何をしていたかを正確に確認できます。

まとめ

これで、スクリプトに日記を付けさせることができました。

この実験では、次のことを学びました。

  1. リダイレクト(>>):出力をファイルに送り、失われないようにする方法。
  2. 追記:既存の履歴を消去せず、新しい内容を追加する方法。
  3. タイムスタンプ:date を追加して、処理がいつ行われたかを確認する方法。

これは、Linux 上で動作するプロフェッショナルなサービスで一般的に使われる標準的な方法です。Web サーバーでもデータベースでも、今行ったのと同じようにログファイルへ書き込みます。