Linuxのwatchコマンドを正しく使う方法
watchはコマンドを2秒ごとに再実行します。間隔の選び方、差分の強調表示、変化時の終了、パイプを正しく実行するための引用方法を解説します。
watch コマンドの動作
watch コマンドは、別のコマンドを一定間隔で再実行し、出力を画面上の同じ位置に再描画します。デフォルトの間隔は 2 秒です。ディスク使用量の増加、コンテナの安定、証明書更新の反映、キューの消化など、数値の変化を待つときに使用します。
watch は procps-ng に含まれており、新しい Ubuntu または Debian VPS には procps パッケージの一部としてすでにインストールされています。以下のフラグを使用する前に、バージョンを確認してください。便利なオプションのうち 2 つは比較的新しいためです。
watch --versionUbuntu 24.04 では、次のような行が表示されます: watch from procps-ng 4.0.4。次に、最も簡単で実用的な例を示します。
watch df -h /画面がクリアされ、ヘッダー行、空行、その後に df -h / の出力が表示されます。
Every 2.0s: df -h / server1: Sun Aug 9 10:21:44 2026左側には間隔と、watch が実行している正確なコマンドが表示されます。右側にはホスト名と現在時刻が表示されます。時刻は重要です。下の数値が変化していなくても、画面の更新が続いていることを確認できるためです。終了するには Ctrl+C を押します。
watch は、端末に収まる 1 フレームを描画します。長い行は折り返されますが、-w はその代わりに行を切り詰めます。最下行より下の内容はまったく描画されません。各サイクルで前のフレームを上書きするため、フレーム内にスクロールバックはありません。この点だけで、watch が適している用途の大半が決まります。
watch はどの間隔でコマンドを再実行すべきですか?
2 秒はあくまでデフォルトです。値が変化する速さと、1 回の実行にかかる負荷に応じて間隔を選択してください。
-n 0.5は、ss -sやインターフェイスのバイトカウントなど、常に変化するカウンターに使用します。watch が受け付ける最短間隔は 0.1 秒です。- ディスクや証明書には
-n 30または-n 60を使用します。1 日かけて容量が増えるファイルシステムを、1 分間に 30 回確認する必要はありません。
watch はコマンドを実行し、完了するまで待ってから指定した間隔だけ待機します。そのため、コマンドの実行時間が間隔に加算されます。-n 2 で 8 秒かかるコマンドを実行すると、10 秒ごとに 1 回表示され、実行中は常にマシンのリソースを使用します。-p (--precise) を追加すると、watch は実行開始から次の実行開始までを計測し、指定した秒数ごとに実行を開始しようとします。
常に別のデフォルト値を使用する場合は、シェルのプロファイルで WATCH_INTERVAL を export します。明示的に指定した -n は、この値より優先されます。watch --help を実行すると、使用しているビルドがその変数を読み取ることを確認できます。
-d で変更箇所を強調する
同じようなテキストが並ぶ中から、1 つだけ移動したフィールドを探すのは大変です。-d(--differences)を使えば、自動的に確認できます。
watch -n 30 -d 'df -h / /var'直前のフレームと異なる文字は反転表示されるため、Use% のセルが移動した瞬間に点灯し、それ以外は変化しません。/var が別のファイルシステムでない場合は、root ファイルシステムが 2 回表示されます。これは、システムのパーティション構成をすぐに把握する方法です。
比較は位置ベースです。つまり、watch は新しいフレームと古いフレームを文字単位で突き合わせます。列幅が変わる出力では、ほぼ全体が点灯します。そのため、レイアウトが安定したコマンドを使用してください。現在の procps-ng は watch --differences=permanent も受け付けます。これは、直近の変更だけでなく、これまでに変更されたすべての位置を強調表示します。依存する前に、watch --help で利用できることを確認してください。
出力が変化したときに watch を終了するにはどうすればよいですか?
-g(--chgexit)を指定すると、直前の実行時と出力が異なった最初の時点で watch が終了します。プロンプトに戻るため、同じ行でその後に別のコマンドを実行できます。
watch -n 10 -g 'systemctl is-active myapp' ; echo 'state changed'このフラグを使うと、watch を「デプロイが反映されたら通知する」ためのツールとして利用できます。ただし、注意点があります。比較対象は出力全体です。そのため、出力に時刻や PID(プロセス識別子)が含まれていると、最初の更新で変化し、watch がすぐに終了します。systemctl status myapp は経過時間とメモリ使用量を表示するため、これに -g を指定しても意味がありません。待機対象である、変化しない単一の情報だけをコマンドの出力にします。これを実現するのが systemctl is-active です。
新しい procps-ng には、逆の判定を行う --equexit <cycles> もあります。指定した回数のサイクルにわたって出力が変化しなかった後に終了します。「変化が止まったら通知する」という用途に使用できます。watch --help で確認してください。古いビルドにはこのオプションがありません。
watch がパイプと glob を無視するのはなぜですか?
この問題は誰もが一度は経験します。原因は watch ではなく、シェルにあります。
watch docker compose ps | grep web対話型シェルはコマンドを実行する前に行全体を読み込み、パイプの位置で分割します。watch docker compose ps を起動し、watch 自体の画面出力を grep に接続します。watch は端末に書き込まなくなるため、表示が壊れるか空になります。また、grep はコンテナ一覧ではなく、再描画の出力をフィルタリングします。
パイプライン全体を引用符で囲み、1 つの引数として渡してください。
watch 'docker compose ps | grep web'watch はその文字列を sh -c に渡し、そのシェルが各サイクルでパイプラインを 1 回実行します。glob でも同じ規則が適用されますが、症状は気付きにくくなります。
watch ls -l /var/log/*.log
watch 'ls -l /var/log/*.log'1 行目では、Enter を押した時点でシェルが glob を 1 回展開します。watch はその後、固定されたファイル名の一覧を再実行するため、1 分後に作成されたログファイルは表示されません。2 行目では glob が watch に渡され、各サイクルで sh 内に展開されるため、新しいファイルが自動的に表示されます。
引用符は、変数やコマンド置換を評価するタイミングも決めます。watch "echo $(date)" はシェル内で date を 1 回実行し、その固定された文字列を繰り返し表示します。watch 'echo $(date)' は各サイクルで date を実行します。シングルクォートは後で評価することを意味し、ダブルクォートは今すぐ評価することを意味します。
この sh -c には、さらに 2 つの影響があります。
- エイリアスとシェル関数はその中では利用できません。
watch llはsh: 1: ll: not foundで失敗します。sh -cがあなたの.bashrcを読み込まないためです。実際のコマンドを記述するか、対話型PATHにしか存在しないバイナリのフルパスを指定してください。 - 標準エラー出力も取得すると便利です。エラーテキストを画面内に表示し、画面の外へ散らばらせたくない場合は、引用符の内側に
2>&1を入れてください。
引用符の扱いが難しい場合は、-x (--exec) を使うと sh -c を介さずにコマンドを直接実行できます。スペースを含む引数は扱いやすくなります。ただし、パイプと glob は完全に機能しなくなります。解釈するシェルが存在しないためです。
権限についても同じ考え方が当てはまります。watch は通常のプロセスだからです。watch 'sudo ss -tulpn' を実行すると、確認できず入力もできないパスワードプロンプトが表示されます。代わりに sudo watch 'ss -tulpn' を実行してください。その場合、Ctrl+C を押すまでループ全体が root として実行される点に注意してください。
VPS で監視する価値のある 4 つの項目
使用量が増え続けるディスク
watch -n 30 -d 'df -h / /var'df は、カーネルが保持している値を取得するため、何度実行しても負荷は小さいです。一方、du -sh /var/log は毎回ツリー内のすべてのファイルを走査するため、同じではありません。watch で実行するとディスクを継続的に読み取り、診断対象のマシン自体を遅くします。du を 1 回実行するか、ncdu を使用します。その後、df を watch で監視し、値が増え続けているか確認します。
再起動を繰り返すコンテナ
cd /srv/myapp
watch -n 5 -d 'docker compose ps'status 列には、各コンテナが起動してからの経過時間が表示されます。クラッシュループ中のコンテナは「Up 2 seconds」に戻り続けるため、-d を使うと一目で分かります。最初にディレクトリを変更してください。watch は、それを起動したシェルの作業ディレクトリを引き継ぎ、docker compose にはプロジェクトディレクトリが必要だからです。watch は再起動が発生していることを示します。docker compose logs -f web はその理由を示します。理由が分かったら、コンテナを自動的に再起動する Compose の healthcheck として答えを設定してください。誰かが画面を見続ける必要がなくなります。
証明書の更新
sudo -i
watch -n 60 -g 'openssl x509 -noout -enddate -in /etc/letsencrypt/live/example.com/fullchain.pem'このコマンドは notAfter=Nov 7 09:14:22 2026 GMT という 1 行だけを出力し、それ以外は何も出力しません。そのため、-g はファイルが更新後の証明書に置き換わったときだけ実行されます。/etc/letsencrypt/live 配下のファイルは root だけが読み取れるため、これは root シェルで実行します。これはディスク上の証明書を監視している点に注意してください。実行中の Web サーバーは、reload するまで古い証明書をメモリに保持します。そのため、実際に提供されている証明書は echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate で確認してください。また、公開ホストに対してこのコマンドを 2 秒間隔で実行しないでください。更新処理自体は systemd の service と timer で行い、systemctl list-timers で次回の実行時刻を確認できます。
キューの処理状況
watch -n 15 'postqueue -p | tail -n 1'これは -- 24 Kbytes in 6 Requests. のような概要行を出力し、処理が完了すると Mail queue is empty のようになります。数を取得できるキューであれば、同じ形式を使えます。watch -n 5 'find /srv/queue/incoming -type f | wc -l'。
ここで watch の限界に達します。watch は直前のフレームと現在のフレームを比較するだけで、条件をテストできません。そのため、「数が 0 になった」と判断することはできません。単純なシェルループなら、各回の処理で数を取得するために コマンド置換 を使って実現できます。
until [ "$(find /srv/queue/incoming -type f | wc -l)" -eq 0 ]; do sleep 5; done; echo 'queue drained'watch コマンドが適さない場合
watch は前回の実行結果を記憶せず、実行するコマンドの処理内容も把握しないまま、コマンドを繰り返し実行します。これは df には適しています。ただし、次の4つの状況では不適切です。
- ログ。 watch は固定された表示領域を再描画するため、2回の実行周期の間に表示されてスクロールした行は失われます。新しい行が書き込まれるたびにストリームで表示する
journalctl -fu nginxまたはtail -fを使用します。 - 負荷の高いコマンド。
du -sh /や負荷の高いデータベースへのクエリは、watch が繰り返し起動し続けるため、どの実行間隔でも恒常的なバックグラウンド負荷になります。 - 副作用のある処理。 書き込み、投稿、再起動、インストールを行うコマンドは、実行周期ごとに再度実行されます。2秒ごとに API へ
curlを実行すると、1日で 43,200 リクエストになります。その結果、無料の API key が停止されることがあります。 - 長時間実行する監視。 watch はターミナル内で動作し、セッションの終了とともに停止します。通知を送らず、ラップトップを閉じた後の履歴も保持しません。この用途には、Uptime Kuma などの実際のステータスモニター、またはサーバー上で動作するスケジュール実行のチェックを使用します。
明確な境界は時間です。watch は、特定の事象が発生するまでの10分間に使用するツールです。翌日も確認を続ける必要がある処理は、スケジュールされたタイマーまたは実際の監視システムで実行します。
SSH 接続中は tmux 内で watch を実行する
SSH 経由では、watch の継続性は接続状態に依存します。接続が切れると、シェルが SIGHUP を受け取り、watch も終了します。tmux を使えばこの問題を解決でき、リモートサーバー上で watch を実用的に使えるようになります。
tmux new -As ops
watch -n 30 -d 'df -h /'Ctrl+b を押してから d を押すと、デタッチできます。ループはサーバー上で実行され続けます。後で tmux attach -t ops を使って再接続すると、ヘッダーの時計が動作を示し、画面は更新されたままです。ウィンドウを分割すれば、一方に watch、もう一方に journalctl -f を表示できます。これは、tmux ベースのターミナル作業環境の基本的な考え方です。同じ質問を複数のサーバーに対して同時に確認する場合は、watch の画面を多数並べるよりも、複数の Linux サーバーを管理するためのツールを使うべきです。
ここに示した画面は説明用です。列の配置やバージョン文字列は、ディストリビューションや procps-ng のリリースによって異なります。そのため、自分のマシンで man watch を実行し、使用しているビルドで実際に利用できるフラグを確認してください。
FAQ
watch mycmd | grep foo でパイプが無視されるのはなぜですか?
watch が起動する前に、シェルがパイプで行を分割します。そのため、watch 自身の画面表示が grep にパイプされ、コマンドの出力はフィルタリングされません。パイプライン全体を引用符で囲んでください: watch 'mycmd | grep foo'。watch はその単一の引数を sh -c に渡し、パイプラインをサイクルごとに 1 回実行します。同じ規則は glob とコマンド置換にも適用されます。
watch ではどの間隔を使うべきですか?
値が変化する速さと、1 回の実行にかかる負荷に合わせてください。高速なカウンターには 0.5 秒が適しています。watch が受け付ける最小間隔は 0.1 秒です。ディスクや証明書には 30 秒から 60 秒が適しています。-p を指定しない場合、コマンドの実行時間が待ち時間に加わります。そのため、-n 1 で遅いコマンドを実行すると、間隔を空けずに連続実行されます。
watch でログファイルを追跡できますか?
いいえ。watch は 1 つの画面を再描画するだけで、履歴を保持しません。そのため、2 回のサイクルの間に現れてスクロールアウトした行は完全に失われます。journalctl -fu <unit> と tail -f は新しい行を到着時にストリームするため、ログにはこちらが必要です。watch は、ディスク使用率やキューの長さなど、現在の状態を持つ値に使用してください。
待機している事象が発生したときに watch を停止するにはどうすればよいですか?
-g (--chgexit) を使用し、その事象が発生するまで出力が変わらないコマンドを指定してください。時計や PID を含む出力は最初の更新で変化するため、すぐに終了します。そのため、systemctl is-active myapp は systemctl status myapp が機能しない場合に使用できます。カウントが 0 になる場合など、実際の条件を待つには、シェルの until ループを使用してください。watch は出力が変化したことしか検出できないためです。
シェルでは動作するコマンドについて、watch が command not found と表示するのはなぜですか?
watch はコマンドを sh -c に渡します。このシェルは .bashrc を読み込まないため、エイリアスやシェル関数は存在しません。通常、このメッセージは sh: 1: ll: not found です。実際のコマンドを明示するか、対話シェルの PATH にしか存在しないバイナリにはフルパスを使用してください。