UPS/NUT(ネットワーク UPS ツール)#
NUT#
NUT(ネットワーク UPS ツール)は、一連の便利な操作と通知の UPS ツールを統合しています。
Nut は主に 3 つのコアサービスを含んでいます:
- nut-driver: このサービスは特定のドライバを介して UPS と通信します。
- nut-server: このサービスは nut-driver を利用して UPS と通信し、UPS の状態をネットワークサービスを通じて公開します。
- nut-monitor(nut-client): このサービスは nut-server に接続し、UPS の状態に応じて特定の応答を行います。
注意: nut-client は実際には systemd のソフトリンクファイルであり、本質的には nut-monitor です。
┌─────────────┐ ┌────────────┐
┌──── │ nut-monitor │ ───────────────► │ nut-server │
│ └─────────────┘ └────────────┘
│
│ │
│ │
▼ ▼
┌─────────────┐ ┌────────────┐
│ upssched │ │ nut-driver │
└─────────────┘ └────────────┘
│ │
│ │
│ │
▼ ▼
┌────────────────┐ ┌─────────────┐
│ user scripts │ │ UPS │
└────────────────┘ └─────────────┘
NUT のインストール#
pve コンソールから直接インストール
apt install -y nut
UPS に接続するには、次のコマンドを使用します:
# nut-scanner -U
SNMPライブラリが見つかりません。SNMP検索は無効です。
Neonライブラリが見つかりません。XML検索は無効です。
IPMIライブラリが見つかりません。IPMI検索は無効です。
USBバスをスキャン中。
[nutdev1]
driver = "blazer_usb"
port = "auto"
vendorid = "0665"
productid = "5161"
product = "USB to Serial"
vendor = "INNO TECH"
bus = "001"
または
/bin/upsc nutdev1@localhost
SSLを証明書データベースなしで初期化
battery.charge: 100
battery.voltage: 13.50
battery.voltage.high: 13.00
battery.voltage.low: 10.40
battery.voltage.nominal: 12.0
...
UPS の状態を確認します。
NUT Server の設定#
Nut のインストールが完了すると、自動的に /etc/nut ディレクトリに設定ファイルが生成されます。次の設定作業は、このディレクトリ内のさまざまな設定ファイルを調整することです。
nut.conf#
この設定は主に nut の実行モードを定義します。設定フィールドは MODE=xxxx のみで、選択可能な値とその意味は以下の通りです:
- none: Nut が設定されていないか、外部システムで Nut サービスを起動している場合、"何もしない" と理解できます。
- standalone: 独立モード、一般的に UPS が 1 台のみで、ローカルシステムのみを担当する場合(ネットワークサービスを提供しない)に使用します。
- netserver: 独立モードに似ていますが、driver、upsd、upsmon サービスを起動し、ネットワークサービスを提供できる点が異なります。他のマシンの nut-monitor はネットワークを介して Nut Server に接続できます。
- netclient: クライアントモードのみで、nut-monitor のみを起動し、リモートの Nut サービスに接続します。
ここで私が使用している SANTAK TG-BOX 850 は USB で私の pve に接続されており、pve には NUT ツールがインストールされているため、pve はサーバーとして機能し、他のマシンはサーバーの状態を確認するだけです。
# cat /etc/nut/nut.conf
MODE=netserver
ups.conf#
この設定は nut-driver が物理 UPS にどのように接続するかを定義します。この設定ファイルの構成形式は以下の通りです:
# 注意が必要なのは、群晖またはQNAPがネットワークを介してUPSに接続できるようにするには、
# UPSの名前に特別な要件があることです(群晖はupsと名付ける必要があり、QNAPはテストしていないため、qnapupsと呼ばれる可能性があります);
[ups]
driver = usbhid-ups
port = auto
desc = "TG-BOX 850"
upsd.conf#
この設定ファイルは nut-server のネットワークサービスを制御します。たとえば、リスニングポート、最大接続数、証明書設定などです。私は内部ネットワークで使用しているため、ネットワークリスニングのみを設定し、他のパラメータはデフォルトのままで大丈夫です:
LISTEN 0.0.0.0 3493
upsd.users#
upsd.users 設定ファイルは、ネットワークを介して nut-server に接続するためのユーザー名とパスワードを定義します。この設定のサンプルは以下の通りです:
[monuser]
password = secret
upsmon master
群晖と QNAP ユーザーについて:これらの 2 つの NAS が Nut Server に直接接続できることを期待する場合、群晖にはユーザー名が monuser でパスワードが secret のユーザーが存在することを確認する必要があります。QNAP については確認していませんが、オンラインでの情報によれば、ユーザー名が admin でパスワードが 123456 のユーザーが存在する必要があります。
NUT 監視設定#
基本設定に比べて、Nut のコア処理は監視設定を適切に行うことにあります。Nut は監視戦略を大きく 2 つサポートしています:
- 1、
upsmon.conf
で直接設定し、すべてのイベントをユーザー指定のスクリプトが処理します。タイマーなどの高度な機能はありません。 - 2、
upsmon.conf
で実行スクリプトをupssched
に設定し、すべてのイベントを最初にupssched
が処理します。upssched
を利用することで、選択的にシャットダウンをトリガーするなどの高度な機能を実現できます。
upsmon.conf#
この設定は主に nut-monitor が UPS をどのように監視するかを設定し、UPS にどのようなイベントが発生した場合にどのような処理を行うかを定義します。以下にコア設定を詳しく説明します。
MONITOR 指令#
MONITOR 指令は監視する UPS の接続アドレスを定義します。 その形式は以下の通りです:
MONITOR <system> <powervalue> <username> <password> ("master"|"slave")
<system>
: nut-server の接続アドレス、形式は "UPS 名" + "@" + "nut-server アドレス"、例えばmyups@192.168.1.2
<powervalue>
: UPS の数、大多数の場合、UPS 電源は 1 つだけなので、1 と書けば大丈夫です。<username>/<password>
:upsd.users
で定義されたユーザー名とパスワードmaster/slave:
master
はこのシステムが最後にシャットダウンし、従属システムが先にシャットダウンすることを示します。slave
はこのシステムが即座にシャットダウンすることを示します。
以下は私の設定サンプルです:
MONITOR ups@localhost 1 monuser secret master
SHUTDOWNCMD#
SHUTDOWNCMD 指令は UPS の電力が不足している場合や手動でシャットダウンする必要がある場合のシャットダウンコマンドを定義します。完全なパスを記入することをお勧めします。
SHUTDOWNCMD "/usr/sbin/poweroff"
NOTIFYCMD#
NOTIFYCMD
指令は非常に重要な指令で、特定のイベント(市電中断、UPS が低電量など)が発生した場合に、nut-monitor
が実行するコマンドを設定します。 簡単に言えば、NOTIFYCMD
は具体的な実行コマンドを定義し、ここで自分で作成したスクリプトを設定できます。UPS にイベントが発生した場合、このスクリプトが呼び出されます。
NOTIFYCMD
指令には大きく 2 つの設定方法があります。1 つは自分のスクリプトを設定する方法で、スクリプトには実行権限が必要で、スクリプト内でNOTIFY
環境変数を使用してイベントタイプを取得し、自分で処理します。 この方法は「シンプルで直接的」な意味合いがあり、カスタマイズの程度はスクリプトの書き方に完全に依存します。具体的に使用できる変数は自分でテストしてください。バージョンによって環境変数名が異なる可能性があります。
もう 1 つの方法は、NOTIFYCMD
を内蔵のupssched
コマンドを実行するように設定することです。upssched
は Nut が提供する特定の戦略を持つスケジューラです。簡単に言えば、一般的な機能を抽象化したもので、upssched
には独自の設定があり、「市電が 180 秒以内に復旧した場合はシャットダウンしない」といった高度なスケジューリング戦略を実現できます。
ここでは 2 つ目の方法を選択します。
NOTIFYCMD /usr/sbin/upssched
NOTIFYFLAG#
NOTIFYFLAG
も重要な設定で、NOTIFYCMD
と連携して使用する必要があります。NOTIFYFLAG
指令は、UPS の一連のイベントがどのような操作をトリガーすべきかを指定します。この指令の形式は以下の通りです:
NOTIFYFLAG <notify type> <flag>[+<flag>][+<flag>] ...
ここではイベントタイプを示し、選択可能なタイプは以下の通りです:
- ONLINE: UPS がオンライン、つまり市電が復旧したときにトリガーされます。
- ONBATT: UPS がバッテリー電源を使用している、つまり市電が中断したときにトリガーされます。
- LOWBATT: UPS が低電量のときにトリガーされます。
- FSD: UPS がシャットダウン中(強制シャットダウン)。
- COMMOK: nut-server との接続が成功したときにトリガーされます。
- COMMBAD: nut-server との接続が失敗したとき(接続が切れた)にトリガーされます。
- SHUTDOWN: UPS がシャットダウン指令を発したときにトリガーされます。
- REPLBATT: UPS がバッテリーの交換を必要とするときにトリガーされます。
- NOCOMM: UPS との接続ができない(UPS が準備できていない)ときにトリガーされます。
flag フラグには通常 4 種類あり、複数の組み合わせはプラス(+)で接続します:
- SYSLOG: syslog にのみ印刷します。
- WALL: ターミナルにメッセージを表示します(/bin/wall)。
- EXEC:
NOTIFYCMD
で指定されたコマンドを呼び出し、関連するイベントを渡します。 - IGNORE: 何もしない、無視します。
もし NOTIFYCMD がカスタムスクリプトを使用している場合、ここでは実際にスクリプトが処理する必要があるイベントを設定してください。NOTIFYCMD が upssched を使用するように設定されている場合、すべてのイベントを EXEC として設定し、具体的なフィルタリングは upssched で処理できます。
例えば、NOTIFYCMD
で設定されたスクリプトが市電中断と復旧イベントのみを処理し、同時に syslog に印刷する場合、次のように設定できます:
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
私がNOTIFYCMD
で設定したのはupssched
なので、ここではすべてのイベントを upssched に渡します:
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC
NOTIFYFLAG REPLBATT SYSLOG+EXEC
NOTIFYFLAG NOPARENT SYSLOG+EXEC
その他の設定#
上記のコア設定に加えて、他の設定は特に問題がない限り、通常はデフォルトのままで大丈夫です。具体的な設定については公式ドキュメントを参照してください:UPSMON.CONF(5)。
upssched.conf#
この設定を使用する前提は、upsmon.conf の NOTIFYCMD が upssched を指しており、NOTIFYFLAG が関連イベントに EXEC を設定していることです。 この設定の主な目的は、特定のイベントの処理方法を制御するために upssched の内蔵の高度な構文を使用することです。upssched.conf の設定は主に 2 つの部分から構成されます:ヘッダーのオプション設定と末尾のルール設定。
4.2.1、オプション設定#
ヘッダーオプション設定には 3 つの設定のみが含まれます:
- CMDSCRIPT: この設定は最初の行に配置する必要があります(推奨、実際には AT 指令の前であれば大丈夫です)。この指令はイベントの処理スクリプトを定義します。スクリプトは一般的にユーザーが自分で作成します。
upssched
はルールに基づいて指定されたパラメータをこのスクリプトに渡して実行します。 - PIPEFN: プロセス間通信のためのパイプファイルで、AT 指令の前に配置する必要があります。
- LOCKFN: 排他ロックファイルで、upsmon が同時に複数のファイルをスケジュールするのを防ぐために、AT 指令の前に配置する必要があります。
CMDSCRIPT 設定のスクリプトのサンプルは以下の通りです:
#!/usr/bin/env bash
set -ex
exec >> /var/log/upssched-cmd.log 2>&1
# システムをシャットダウンする主な関数
function xpoweroff(){
logger -t upssched-cmd 'XPEnologyをシャットダウンする準備中...'
logger -t upssched-cmd 'TProxy Gatewayをシャットダウンする準備中...'
logger -t upssched-cmd 'すべての必要なシステムが正常にシャットダウンしました...'
}
# upsschedがトリガーしたイベントを判断
case $1 in
onbattwarn)
logger -t upssched-cmd 'UPSがバッテリー電源に切り替わりました。システムを安全にシャットダウンする準備中...'
xpoweroff
;;
ups-back-on-line)
logger -t upssched-cmd '市電が復旧しました...'
;;
lowbatt)
logger -t upssched-cmd 'UPSの電量が不足しています。システムを直ちにシャットダウンします...'
xpoweroff
;;
*)
logger -t upssched-cmd "認識できないコマンド: $1"
;;
esac
注意が必要なのは、CMDSCRIPT 設定のスクリプトはデフォルトで nut ユーザーとして実行されるため、nut ユーザーの権限問題を適切に処理する必要があります。
PIPEFN と LOCKFN については、公式に推奨されているのは upssched という名前のディレクトリを別に作成し、その中にファイルを配置することですが、Ubuntu Server 22.04 などの一部のシステムでは、/run/nut/ が tmpfs であり、再起動時にディレクトリが失われて権限の問題が発生する可能性があります。そのため、独立したディレクトリを作成せずに直接設定することをお勧めします:
CMDSCRIPT /opt/scripts/upssched-cmd.sh
PIPEFN /run/nut/upssched.pipe
LOCKFN /run/nut/upssched.lock
4.2.2、ルール設定#
upssched を使用する利点は、内蔵のルールエンジンがあり、簡単な構文を使用して複雑なルールを設定できることです。upssched のルール構文は以下の通りです:
AT notifytype upsname command
ルールは AT で始まり、notifytype は注目するイベントタイプを指定します。upsname は UPS 名を指定し、1 つだけの場合や区別したくない場合は * と書けば大丈夫です。command 部分は実行するアクションを指定し、command には大きく 3 つのタイプがあります:
- START-TIMER: タイマーを開始します。
- CANCEL-TIMER: タイマーをキャンセルします。
- EXECUTE: 即座に実行します。
この部分は一見複雑に見えますが、実際には非常にシンプルです。以下のルールは、市電が切れたとき(UPS がバッテリー電源を使用しているとき)にonbattwarn
という名前のタイマーを 180 秒後に実行し、このタイマー内で市電が復旧した場合はスクリプトを実行しないようにキャンセルします。
AT ONBATT * START-TIMER onbattwarn 180
AT ONLINE * CANCEL-TIMER onbattwarn
もちろん、即座に実行する必要があるイベントもあります。例えば、市電中断時に即座に通知を送信します。
# `CMDSCRIPT`で指定されたスクリプトを即座に実行し、`onbattnoti`をスクリプトに渡します。
AT ONBATT * EXECUTE onbattnoti
NUT Server の設定ファイル#
完全な設定は以下の通りです:
nut.conf
MODE=netserver
ups.conf
# 名前は最初に群晖と互換性を持たせるためにUPSとしました。
[ups]
driver = "usbhid-ups"
port = "auto"
upsd.conf
LISTEN 0.0.0.0 3493
upsd.users
[monuser]
password = secret
upsmon master
[qnapups]
password = 123456
upsmon master
upsmon.conf
MONITOR ups@localhost 1 monuser secret master
MINSUPPLIES 1
SHUTDOWNCMD "/usr/sbin/poweroff"
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 30
DEADTIME 15
POWERDOWNFLAG /etc/killpower
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC
NOTIFYFLAG REPLBATT SYSLOG+EXEC
NOTIFYFLAG NOPARENT SYSLOG+EXEC
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
upssched.conf
CMDSCRIPT /opt/scripts/upssched-cmd.sh
PIPEFN /run/nut/upssched.pipe
LOCKFN /run/nut/upssched.lock
AT ONBATT * START-TIMER onbattwarn 180
AT ONLINE * CANCEL-TIMER onbattwarn
upssched-cmd.sh
#!/usr/bin/env bash
set -ex
exec >> /var/log/upssched-cmd.log 2>&1
echo "実行ID: $(id)"
SSH_CMD='ssh -o StrictHostKeyChecking=no'
case $1 in
onbattwarn)
logger -t upssched-cmd 'UPSがバッテリー電源に切り替わりました。システムを安全にシャットダウンする準備中...'
;;
ups-back-on-line)
logger -t upssched-cmd '市電が復旧しました...'
;;
lowbatt)
logger -t upssched-cmd 'UPSの電量が不足しています。システムを直ちにシャットダウンします...'
;;
*)
logger -t upssched-cmd "認識できないコマンド: $1"
;;
esac
NUT Server の再起動#
systemctl restart nut-server.service
systemctl restart nut-driver.service
systemctl restart nut-monitor.service
NUT Client の設定#
nut クライアントの設定#
/etc/nut/nut.conf ファイルを編集し、MODE を netclient モードに設定します。
MODE=netclient
upsmon の設定#
/etc/nut/upsmon.conf ファイルを編集し、以下の設定項目を追加します:
MONITOR UPSの名前@UPSのIPアドレス 1 ユーザー名 パスワード slave
MINSUPPLIES 1
SHUTDOWNCMD "/usr/sbin/poweroff"
NOTIFYCMD /usr/sbin/upssched
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 30
DEADTIME 15
POWERDOWNFLAG /etc/killpower
NOTIFYFLAG ONLINE SYSLOG+EXEC
NOTIFYFLAG ONBATT SYSLOG+EXEC
NOTIFYFLAG LOWBATT SYSLOG+EXEC
NOTIFYFLAG FSD SYSLOG+EXEC
NOTIFYFLAG COMMOK SYSLOG+EXEC
NOTIFYFLAG COMMBAD SYSLOG+EXEC
NOTIFYFLAG SHUTDOWN SYSLOG+EXEC
NOTIFYFLAG REPLBATT SYSLOG+EXEC
NOTIFYFLAG NOPARENT SYSLOG+EXEC
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 5
RUN_AS_USER root
ここで注意が必要なのは RUN_AS_USER で、upsmon.conf ファイル内では通常 upsmon が実行されるユーザーが定義されます。特定のシステムでは、upsmon がデフォルトで一般ユーザーとして実行されるため、シャットダウンコマンドを実行できない可能性があるため、root が必要です。
upssched の設定#
wall コマンドは、システム内で全てのログインユーザーにメッセージをブロードキャストするために使用されます。upsmon のデフォルト設定では、wall コマンドを使用して全てのユーザーに通知メッセージを送信します。
ここで wall ツールをインストールする必要があります。Gentoo のインストールプロセスは以下の通りです:
echo "sys-apps/util-linux tty-helpers" >> /etc/portage/package.use
sudo emerge -v sys-apps/util-linux
# インストールされているか確認
which wall
upssched ツールは、特定の条件下でスクリプトを実行することを許可します。/etc/nut/upssched.conf ファイルを編集し、以下の内容を追加します:
CMDSCRIPT /etc/nut/upssched-cmd.sh
PIPEFN /run/nut/upssched.pipe
LOCKFN /run/nut/upssched.lock
AT ONBATT * START-TIMER onbattwarn 600
AT ONLINE * CANCEL-TIMER onbattwarn
AT ONLINE * EXECUTE ups-back-on-line
AT LOWBATT * EXECUTE lowbatt
これにより、UPS が供電を開始してから 600 秒後に onbattwarn イベントがスクリプトに送信され、その後スクリプトで定義されたコマンドが実行されます。
/etc/nut/upssched-cmd.sh の内容は以下の通りです:
#!/usr/bin/env bash
set -ex
exec >> /var/log/upssched-cmd.log 2>&1
echo "実行ID: $(id)"
function xpoweroff(){
/sbin/shutdown -h +0 "UPSが1分間バッテリーで動作しています。シャットダウンします。"
}
case $1 in
onbattwarn)
logger -t upssched-cmd 'UPSがバッテリー電源に切り替わりました。システムを安全にシャットダウンする準備中...'
xpoweroff
;;
ups-back-on-line)
logger -t upssched-cmd '市電が復旧しました...'
;;
lowbatt)
logger -t upssched-cmd 'UPSの電量が不足しています。システムを直ちにシャットダウンします...'
xpoweroff
;;
*)
logger -t upssched-cmd "認識できないコマンド: $1"
;;
esac
実行権限を付与します。
sudo chmod +x /etc/nut/upssched-cmd.sh
NUT Client の再起動#
systemctl enable nut-monitor.service
systemctl restart nut-monitor.service
systemctl status nut-monitor.service
設定の検証#
以下のコマンドを使用して UPS の状態をテストできます:
upsc <UPS名>@IP