📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

818行目: 818行目:
シャットダウンを実行する時、ホストOSがロックアップすることが知られている。<br>
シャットダウンを実行する時、ホストOSがロックアップすることが知られている。<br>
<br>
<br>
===== 方法 1 =====
これを回避する方法は、libvirtフックスクリプトとsystemdユニットを使用して、<br>
これを回避する方法は、libvirtフックスクリプトとsystemdユニットを使用して、<br>
ゲストOSの実行中にホストOSがスリープ状態になることを防ぐ。<br>
ゲストOSの実行中にホストOSがスリープ状態になることを防ぐ。<br>
867行目: 868行目:
上記で作成したデーモンを停止する。<br>
上記で作成したデーモンを停止する。<br>
  sudo systemctl stop libvirt-nosleep.service
  sudo systemctl stop libvirt-nosleep.service
<br>
ゲストOSを起動して、スリープが抑制されているかどうかを確認する。<br>
systemd-inhibit --list
<br>
===== 方法 2 =====
同様に、libvirtフックスクリプトとシェルスクリプトを使用して、ゲストOSの実行中にホストOSがスリープ状態になることを防ぐ方法もある。<br>
<br>
libvirtフックから呼び出す場合、仮想マシンが起動する瞬間に呼び出されるため、確実に仮想マシンが起動し終わるまで待機することが可能である。<br>
sudo vi /usr/local/bin/libvirt-inhibit-sleep.sh
<br>
<syntaxhighlight lang="sh">
# /usr/local/bin/libvirt-inhibit-sleep.shファイル
#!/bin/bash
# KVMドメインの実行中にスリープを抑制するスクリプト(フック用)
# 引数として仮想マシン名を受け取る
DOMAIN="$1"
# 引数が指定されていない場合はエラー
if [ -z "$DOMAIN" ]; then
    echo "Error: No domain name specified" >&2
    exit 1
fi
# ログファイルの設定(デバッグ用)
LOG_FILE="/var/log/libvirt/hooks/nosleep-${DOMAIN}.log"
mkdir -p /var/log/libvirt/hooks
# ログ関数
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}
log_message "Sleep inhibit started for domain: $DOMAIN"
# 仮想マシンが完全に起動するまで少し待機
# フックはVMの起動処理の初期段階で呼ばれるため
sleep 5
# 指定されたドメインが存在するか確認
if ! virsh dominfo "$DOMAIN" &>/dev/null; then
    log_message "Error: Domain '$DOMAIN' does not exist"
    exit 1
fi
# スリープを抑制しながら、ドメインの状態を監視
# ドメインが停止したら、このコマンド全体が終了する
log_message "Starting systemd-inhibit for domain: $DOMAIN"
systemd-inhibit --what=sleep \
                --why="Libvirt domain $DOMAIN is running" \
                --who="libvirt-hook" \
                --mode=block \
                /bin/bash -c "
                    while virsh domstate '$DOMAIN' 2>/dev/null | grep -q 'running'; do
                      sleep 60
                    done
                "
log_message "Domain '$DOMAIN' has stopped, releasing sleep inhibit"
exit 0
</syntaxhighlight>
<br>
このシェルスクリプトに実行権限を付加する。<br>
sudo chmod u+x /usr/local/bin/libvirt-inhibit-sleep.sh
<br>
次に、libvirtフックスクリプトを作成する。<br>
libvirtフックスクリプトは、libvirtは仮想マシンの状態が変わるたびに、このスクリプトを呼び出す。<br>
その時、仮想マシンの名前、何が起きたか (start, stopped等)、それがbegin (開始) なのか end (終了) なのかという情報を引数として渡す。<br>
libvirtフックスクリプトは、「仮想マシンが起動を開始した」というイベント (started / begin) を検知すると、libvirt-inhibit-sleep.shをバックグラウンドで起動する。<br>
<br>
フックスクリプト自体は短時間で終了する必要があるため、nohupコマンドを使用する。<br>
スリープ抑制は長時間実行され続ける必要があるため、バックグラウンドプロセスとして独立させる。<br>
<br>
sudo vi /etc/libvirt/hooks/qemu
<br>
<syntaxhighlight lang="sh">
# /etc/libvirt/hooks/qemuファイル
#!/bin/bash
# Libvirt QEMU hook script
# 仮想マシンの起動・停止時にスリープ抑制を制御する
# このスクリプトは以下の引数で呼ばれます:
# $1 = 仮想マシン名(guest name)
# $2 = 動作(operation): start, stopped, など
# $3 = サブ動作(sub-operation): begin, end
# $4 = 追加引数(あれば)
GUEST_NAME="$1"
OPERATION="$2"
SUB_OPERATION="$3"
# ログファイルの設定
HOOK_LOG="/var/log/libvirt/hooks/qemu-hook.log"
mkdir -p /var/log/libvirt/hooks
# ログ関数
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $GUEST_NAME - $OPERATION/$SUB_OPERATION - $1" >> "$HOOK_LOG"
}
log_message "Hook called"
# 仮想マシンが起動した時
if [ "$OPERATION" = "started" ] && [ "$SUB_OPERATION" = "begin" ]; then
    log_message "VM starting, launching sleep inhibit script"
    # スリープ抑制スクリプトをバックグラウンドで実行
    # nohupを使用して、このフックスクリプトが終了しても継続実行させる
    nohup /usr/local/bin/libvirt-inhibit-sleep.sh "$GUEST_NAME" >> /var/log/libvirt/hooks/nosleep-${GUEST_NAME}.log 2>&1 &
    # プロセスIDをファイルに保存(将来的な管理用)
    echo $! > "/var/run/libvirt-nosleep-${GUEST_NAME}.pid"
    log_message "Sleep inhibit script launched with PID: $!"
fi
# 仮想マシンが停止した時
# スリープ抑制スクリプトは自動的に終了するはずだが、念のため確認
if [ "$OPERATION" = "stopped" ] && [ "$SUB_OPERATION" = "end" ]; then
    log_message "VM stopped"
    # PIDファイルが存在すれば削除
    if [ -f "/var/run/libvirt-nosleep-${GUEST_NAME}.pid" ]; then
      rm -f "/var/run/libvirt-nosleep-${GUEST_NAME}.pid"
      log_message "Cleaned up PID file"
    fi
fi
exit 0
</syntaxhighlight>
<br>
ログファイルを配置するディレクトリを作成する。<br>
sudo mkdir -p /var/log/libvirt/hooks
<br>
ゲストOSを起動して、スリープが抑制されているかどうかを確認する。<br>
systemd-inhibit --list
<br><br>
<br><br>