Open7

(ラズパイ4)ffmpeg #monit

Hidden comment
はとりんはとりん
if cpu > 80% for 2 cycles then alert
if cpu > 95% for 5 cycles then restart
if 3 restarts within 5 cycles then timeout
  1. if cpu > 80% for 2 cycles then alert
  • cpu > 80%:ffmpegプロセスのCPU使用率が80%を超えた場合。
  • for 2 cycles:Monitが2回連続してチェックを行った結果、80%を超え続けている場合。Monitの1サイクルはデフォルトで2分です(このサイクル時間は設定で変更可能です)。
  • then alert:CPU使用率が80%以上を2回連続で超えたらアラート(メール通知やログへの書き込み)を行う。
  1. if cpu > 95% for 5 cycles then restart
  • cpu > 95%:CPU使用率が95%を超えた場合。
  • for 5 cycles:Monitが5回連続でチェックを行い、95%を超えている場合。
  • then restart:この条件が満たされた場合、ffmpegプロセスを再起動する。
  1. if 3 restarts within 5 cycles then timeout
  • 3 restarts:プロセスが再起動された回数が3回に達した場合。
  • within 5 cycles:Monitが5回チェックを行うサイクル内で、3回再起動されていた場合。
  • then timeout:Monitがプロセスの自動再起動を停止し、タイムアウトを発動します。これにより、無限に再起動し続けることを防ぎます。たとえば、根本的な問題がある場合に、無限ループに入るのを避けます。
はとりんはとりん

グローバル設定と個別設定を分けたほうが良いらしい(GTP4o先生)

  • グローバル設定ファイル:/etc/monit/monitrc
  • 個別の設定ファイル:/etc/monit/conf.d/ ディレクトリ内に個別設定ファイルを作成可能

(グローバル)

sudo micro /etc/monit/monitrc
#Monitがどの頻度で監視を行うか
 set daemon 600
#監視対象のプロセス設定は個別ファイルで設定する
 include /etc/monit/conf.d/*

(個別)

sudo micro /etc/monit/conf.d/ffmpeg.conf
check process ffmpeg matching "ffmpeg"
  start program = "/usr/home/XXXX/procstart.sh"
  stop program  = "/usr/home/XXXX/ffkill.sh"
#  if cpu > 80% for 2 cycles then alert
#  if cpu > 95% for 5 cycles then restart
#  if 3 restarts within 5 cycles then timeout

(monitの手動起動、リロード、自動起動設定)

sudo monit reload
sudo systemctl start monit

↓ffmpegプロセスはcronで起動したいのでmonitもcronで起動

sudo systemctl enable monit

↑monit.service is not a native service, redirecting to systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable monit

(デバッグ)

sudo journalctl -u monit
sudo tail -f /var/log/monit.log
sudo monit status
sudo systemctl status monit
はとりんはとりん

if does not exist for 5 cycles then exec "/path/to/restart_ffmpeg.sh" の意味は次の通りです:

if does not exist for 5 cycles は、Monitが設定されたポーリングサイクル(デフォルトでは60秒)ごとにFFmpegプロセスをチェックし、5回連続でプロセスが存在しない(ダウンしている)状態が続いた場合にアクションを実行する、という意味です。

exec "/path/to/restart_ffmpeg.sh" は、FFmpegプロセスが5サイクル(300秒間)ダウンした状態が続いた場合に指定されたシェルスクリプト(restart_ffmpeg.sh)を実行するという動作になります。

つまり、この設定は次のように動作します:

MonitがFFmpegプロセスの存在を監視し、5サイクル連続でプロセスが存在しない(FFmpegがダウンしている)ことを検出します。
5サイクル目に、FFmpegがまだダウンしている場合、Monitは指定されたシェルスクリプト(/path/to/restart_ffmpeg.sh)を実行します。
誤解を避けるための説明
この設定は、FFmpegがダウンした瞬間から5サイクル(300秒間)経過後にシェルスクリプトを1度だけ実行するというものです。つまり、「5回シェルの起動を試みる」という意味ではなく、「5サイクルの間プロセスが存在しない状態が続いたら1度だけシェルスクリプトを実行する」という動作です。

ポイント
1サイクルごとにプロセスの存在を確認します(デフォルトは60秒ごと)。
5回連続でダウンしているときにのみ、シェルスクリプトが実行されます。
したがって、MonitがFFmpegプロセスのダウンを検知してから5サイクル(300秒間)の遅延後に1回だけシェルスクリプトが実行される設定になります。

はとりんはとりん

if 3 restarts within 5 cycles then timeout の意味は、Monitが指定されたプロセスを5サイクルの間に3回再起動させた場合、そのプロセスをタイムアウト(停止状態)にするという設定です。

詳細な意味:
5 cycles:Monitのポーリングサイクルです。例えば、グローバル設定で300秒ごとにポーリングするようにしている場合、5サイクルは300秒×5 = 1500秒(25分)になります。
3 restarts:Monitがプロセスを再起動する回数です。ここでは、5サイクルの間に3回再起動が行われた場合を指します。
timeout:Monitがそのプロセスの再起動を諦めて、監視から除外したり、他のアクションを実行しないようにする状態を意味します。タイムアウト後は、手動で再起動するなどの操作が必要になる場合があります。
実際の動作:
Monitはプロセス(ここではFFmpeg)を監視しています。
もしプロセスがダウンしてMonitが再起動を試みると、その回数がカウントされます。
5サイクル(例えば1500秒)以内に3回再起動が行われた場合、Monitはそのプロセスの再起動を諦め、タイムアウト状態にします。この状態では、Monitはそのプロセスを再起動しなくなります。
タイムアウト状態になった場合、手動でプロセスを再起動するか、他の監視ツールや管理者が介入する必要があるかもしれません。
なぜこの設定が有効か:
短期間にプロセスが何度もダウンする場合は、根本的な問題(設定の誤り、リソース不足、システムの不具合など)がある可能性が高いです。
Monitが無限に再起動を試みるのを防ぎ、システムの安定性を確保します。多くの再起動が失敗する場合は、手動での介入やさらなる調査が必要です。
この設定により、プロセスの再起動が3回行われても改善されない場合、Monitはタイムアウトして自動の再起動を止めることになります。

はとりんはとりん

https://zenn.dev/hatorin/scraps/f2e39e2ae8be72
の対策に、それまではcrontabでプロセスの下げ上げをしていたが、monitで自動化。

  • グローバル設定ファイル:/etc/monit/monitrc
    メール通知と個別設定ファイルの指定
set daemon 60
set log /var/log/monit.log
set mailserver www(数字).sakura.ne.jp
    username "送信元メールアドレス" password "パスワード"
    using tls
    with timeout 30 seconds
set mail-format {
   from:    (送信元メールアドレス)
   subject: monit alert --  $EVENT $SERVICE
   message: $EVENT Service $SERVICE
                 Date:        $DATE
                 Action:      $ACTION
                 Host:        $HOST
                 Description: $DESCRIPTION
 }
set alert (送信先メールアドレス1) 
set alert (送信先メールアドレス2) 
set httpd port 2812 and
allow (BASIC認証ユーザ):(同パスワード)
include /etc/monit/conf.d/*


  • 個別設定ファイル /etc/monit/conf.d/ffmpeg.conf
    • プロセス起動、cpu利用率、アップロード速度について監視
    • プロセス再起動はprocrestart.shを叩いているが、本体再起動のsaikidou.shでもよいかも。目的はストリームの長期間維持で、ラズパイ本体の長時間稼働ではないから。
    • cpu利用率が80%を超えるとメール通知(のみ)
    • アップロード速度が350kB/sを下回るとsaikidou.shでラズパイ再起動
# process
check process ffmpeg matching "ffmpeg"
  start program = "/home/xxx/procrestart.sh" as uid 1000 and gid 1000
  stop program  = "/home/xxx/ffkill.sh" as uid 1000 and gid 1000
   if does not exist for 3 cycles then exec "/home/xxx/procrestart.sh" as uid 1000 and gid 1000
   if does not exist for 3 cycles then alert
   if 3 restarts within 5 cycles then exec "/home/xxx/saikidou.sh" as uid 1000 and gid 1000
   if 3 restarts within 5 cycles then alert
#  if cpu > 80% for 2 cycles then alert
#  if cpu > 95% for 5 cycles then restart
#  if 3 restarts within 5 cycles then timeout

# CPU usage
check system RaspberryPi4
    if cpu usage > 80% for 2 cycles then alert

# network upload
check program network_upload with path "/usr/local/bin/nw_monitor.sh"
    if status != 0 for 10 cycles then exec "/home/xxx/saikidou.sh" as uid 1000 and gid 1000
    if status != 0 then    alert
  • アップロード速度監視用 nw_monitor.sh
    • アップロード速度 350kB/s
#!/bin/bash

THRESHOLD=350
UPLOAD=$(ifstat -i eth0 1 1 | awk 'NR==3 {print $2}')
echo "Current upload: $UPLOAD kB/s"
if [ -z "$UPLOAD" ]; then
    echo "Error: No upload data retrieved."
    exit 1
fi

if (( $(echo "$UPLOAD < $THRESHOLD" | bc -l) )); then
    echo "Upload below threshold. Triggering alert."
    exit 1  
else
    echo "Upload above threshold. All is well."
    exit 0  
fi
はとりんはとりん

monit導入に併せ、crontabも変更
@rebootでffmpegを起動するのではなく、monitから起動するように