採用情報 お問い合わせ

BLOG

Zabbix で「Timeout while executing a shell script」が出た場合の対処法

はじめに :

Web フロントエンドから重いスクリプトを実行すると「Timeout while executing a shell script.」というエラーで失敗してしまうことがあります。これを回避するために設定ファイル(zabbix_server.conf)の Timeout 値を延長するとシステム全体(他の様々な監視処理)に影響を及ぼすため、安易に増やすことはおすすめしません。本記事では、時間が多く掛かるスクリプト実行をバックグラウンド処理に替えて非同期に実行する方法を解説します。末尾に「&」をつけるだけでいいのでは?と思われがちですが、少し気を付けるポイントがあります。

※ 本記事で使用する用語についてはこちらの用語集を参照してください。

環境 :

  • Zabbix Server 7.0.24
  • Zabbix Agent 7.0.24
  • Rocky Linux 8.10

事象の発生手順 :

今回の事象はエージェント ( パッシブ ) 上でスクリプト実行することを想定します。

1. 実行するスクリプトの配置

Zabbix エージェントが動作する OS 上に、15 秒スリープする heavy_script.sh を配置します。
スクリプトの権限と内容は以下のとおりです。

# ls -l /etc/zabbix/scripts/heavy_script.sh
-rwxr-xr-x 1 zabbix zabbix 21 May 19 02:09 /etc/zabbix/scripts/heavy_script.sh

# cat /etc/zabbix/scripts/heavy_script.sh
#!/bin/bash
sleep 15

注意:リモートスクリプト実行の許可(AllowKey の設定)が必要です

2. Zabbix サーバのタイムアウト値

Zabbix サーバのタイムアウト設定は 4 秒です。

/etc/zabbix/zabbix_server.conf

Timeout=4

3. スクリプトの登録

[ 通知 ]->[ スクリプト ] より Zabbix エージェント上で実行するスクリプトを登録します。

4. スクリプトの実行

[ 監視データ ]->[ ホスト ]-> 該当するホストをクリックして、開いたメニューから登録したスクリプトを選択します。

5. タイムアウト発生

しばらく待つと以下の様なエラーが表示されます。

原因と対処法:スクリプトのバックグラウンド実行

今回の事象では Zabbix サーバのタイムアウト 4 秒が設定されています。それに対して実行完了まで 15 秒かかるスクリプトを実行したためタイムアウトが発生しています。
これを回避するために設定ファイルの Timeout 値を延長することでも対処できます。しかしながら、このパラメータはスクリプト実行時だけでなく、様々な箇所で利用されているため、その変更はシステム全体に影響を及ぼすため安易に増やすことは推奨しません。
そこで、スクリプトをバックグラウンド実行することで、Zabbix 側から見て非同期処理(完了待ちをしない状態)にし、待たせない対処方法を紹介します。
スクリプトの設定画面のコマンド欄に以下のように記載します。

【スクリプト登録例】
/etc/zabbix/scripts/heavy_script.sh > /dev/null 2>&1 &
【解説】
  • &: プロセスをバックグラウンドで実行する
  • > /dev/null 2>&1: 標準出力と標準エラー出力の両方を /dev/null に切り替える。

なぜ & だけではダメなのか?

末尾に & をつけるだけではタイムアウトは回避できません。プロセスがバックグラウンドに回っても以下の理由で親プロセス(Zabbix)が待ち続けてしまうからです。なお、エージェントで実行したスクリプトはサーバから渡された Timeout 値の上限に達すると、単にエラーを返すだけでなくプロセス自体が SIGTERM で強制終了されてしまいます。

  • 「標準出力」と「標準エラー出力」の接続先は、親プロセスからそのまま引き継がれる。
  • 親プロセスは子プロセスがパイプを閉じるのを待ってしまう。


これを回避するために、> /dev/null 2>&1 を使ってプロセスの出力先(パイプの接続先)を別の場所へ切り替えます。接続先を切り替えることで親とのパイプが閉じられるため、Zabbix を待機状態から解放できます。

上記の方法では Web フロントエンド上に何も出力されなくなります。運用者が成功したか失敗したかを確認できるようにするため、即時応答用のラッパースクリプトを挟む設計が実用的です。また、切り替える先を /dev/null ではなく、/var/log/script.log のようにファイルを指定することでスクリプトの実行結果をログに残すこともできます。更に出力したログを監視することや zabbix sender を利用してスクリプトの実行結果を監視することもできます。

【ラッパースクリプトの例】
#!/bin/bash
echo " バックグラウンドで処理を開始しました "
/etc/zabbix/scripts/heavy_script.sh >/var/log/script.log 2>&1 &
exit 0
【ラッパースクリプトの実行例】

スクリプトの実行方法や実行場所による動作の違い

実は、スクリプトを「アクション」として「エージェント側」で実行する場合、上記の対処は不要です。
この場合は、内部的には system.run[] の nowait モードと同等の処理が行われます。Zabbix 側で自動的にプロセスを切り離してバックグラウンド実行するため、わざわざ「> /dev/null 2>&1 &」 を付与しなくてもタイムアウトする心配がありません。
一方、同じアクション実行でも「Zabbix サーバ(またはプロキシ)側」で実行する場合は、手動実行と同じように zabbix が実行完了を待ってしまうため、タイムアウトの対策が必要になります。
ちなみに、実行場所によってタイムアウト判定に使用されるパラメータ値が異なります。エージェント上で実行する場合は Timeout が使われますがサーバ / プロキシ上で実行する場合は TrapperTimeout が使用される実装になっています。
このように、スクリプトの実行方法や実行場所によって異なりややこしいため、以下の表にまとめました。

実行方法 スクリプトの実行場所 スクリプト実行完了
の待機
タイムアウトパラメータ
手動 サーバ / プロキシ あり TrapperTimeout(zabbix_server.conf)
手動 エージェント ( パッシブ / アクティブ ) あり Timeout(zabbix_server.conf)
アクション サーバ / プロキシ あり TrapperTimeout(zabbix_server.conf)
アクション エージェント ( パッシブ / アクティブ ) なし -

アクティブエージェントでのスクリプト実行の注意点

Zabbix 7.0 ではアクティブチェックでもスクリプト実行が可能です。
アクティブチェックでスクリプト実行を利用する場合は、7.0.18 以降のバージョンを使用することを推奨します。以下の問題が Zabbix 7.0.18 で修正されており、それ以前のバージョンでは意図しないタイムアウトやエラーが発生します。

ZBX-26723 Agent active remote command executes with wait instead of nowait when used in action

スクリプトを「アクション」としてアクティブエージェント側で実行する際、本来は非同期(nowait モード・タイムアウトなし)で動作すべきところを、誤って同期(wait モード・タイムアウトあり)として処理してしまっていた問題の修正。

ZBX-26510 Zabbix Agent active remote command execution in an action

Zabbix エージェントにおけるアクション操作や手動でのスクリプト実行時、事前のパッシブステータスが有効でないと、アクティブチェックでの処理に回されていた問題の修正。事前のステータスにかかわらず、まずはパッシブチェックでの処理を試行し、失敗した場合はアクティブチェックの処理にフォールバックするようになりました。

ZBX-24799 Cannot execute script. timeout while retrieving result for remote command

アクティブチェックでのスクリプト実行時、サーバが実行指示をセットしてからエージェントが取得しに来るまでの待ち時間がサーバ側の短い Timeout 設定値に依存してエラーとなっていた問題の修正。サーバ側が最大で 60 秒間エージェントの取得を待機するようになりました。

重要:Zabbix 7.0 から RefreshActiveChecks が 5 秒(デフォルト)になりましたが、60 秒以上に設定している場合は注意が必要です。エージェントが実行指示を取得する前にタイムアウトしてしまう場合があります。

まとめ

本記事では、Zabbix のスクリプト実行時に発生するタイムアウトエラーの原因と回避策を解説しました。
Timeout 値の延長はシステム全体の遅延を招くため、コマンドの非同期化によるアプローチを紹介しました。なお、今回は「Zabbix サーバのタイムアウト設定」に起因する事象を扱いましたが、「Zabbix エージェント側のタイムアウト」や「Web フロントエンド側のタイムアウト」も存在します。それらについてはエラーの内容や対処も異なりますので、また機会があれば別途調査してみたいと思います。

免責事項

本記事で紹介しているスクリプトや設定内容は、動作の仕組みを解説するためのサンプルです。実際の運用環境に適用する際は、ご自身の環境に合わせて十分にテストを行い、自己責任にてご活用ください。本記事の内容によって生じたいかなる損害についても、筆者は責任を負いかねます。

商標について

※ Zabbix は、ラトビア共和国およびその他の国における Zabbix LLC の登録商標です。
※ その他、本記事に記載されている会社名および製品名は、各社の商標または登録商標です。
本記事に関連するリンク