Nextcloudのアップデートは、それほど頻繁に行う作業ではありません。しかし、だからこそ毎回「あれ、このコマンド実行したっけ?」となりがちです。
筆者自身も、メンテナンスモードの切り替えやデータベースのバックアップなど、手順を一つひとつ確認しながら作業していました。そこで「毎回やることはスクリプトに任せよう」と考え、更新前のバックアップから updater.phar の実行までを一通り補助する Bash スクリプトを作成しました。
今回は、そのスクリプトの仕組みを紹介します。
動作環境
動作を想定している環境は以下の通りです。
- Ubuntu 20.04 LTS / 22.04 LTS / 24.04 LTS
- MySQL または MariaDB
- PHP / Bash
- root 権限(sudo)
- Apache実行ユーザ:
www-data
Ubuntu系で一般的な構成であれば、そのまま利用できるようになっています。
スクリプト本体
最初に環境に合わせて、スクリプト冒頭の変数だけ変更します。
NC_DIR="/var/www/html/nextcloud"
NC_USER="www-data"
DB_NAME="nextcloud"
DB_USER="nextcloud"
BACKUP_DIR="/var/backups/nextcloud"
続いて実行権限を付与します。
chmod +x nextcloud_update.sh
最後に sudo で起動します。
sudo ./nextcloud_update.sh
途中では
- データベースパスワード
- 各ステップへ進むかどうか
を対話形式で確認します。
確認しながら進められるので、完全自動化というより「操作ミスを減らすための半自動化」という位置付けです。
Bashで自動化というと「全部ワンコマンドで終わらせる」方向へ行きがちですが、個人的にはサーバーの更新作業はそこまで割り切らない方が安心だと考えています。
特に Nextcloud のアップデートは、途中で状況を確認したくなる場面も少なくありません。
そのため、このスクリプトでは各工程ごとに確認を挟み、「人が判断するところ」と「機械に任せるところ」を分ける構成にしました。
毎回同じ手順を思い出しながら実行するより、確認すべきポイントだけに集中できるので、更新作業はかなり気楽になります。
以下がスクリプト全文です。
#!/bin/bash
# ==============================================================================
# Nextcloud Update & Database Backup Script
# ==============================================================================
set -euo pipefail
# --- 変数定義(環境に合わせて変更してください) ---
NC_DIR="/var/www/html/nextcloud"
NC_USER="www-data"
PHP_BIN="php"
# DB設定
DB_NAME="nextcloud"
DB_USER="nextcloud"
DB_HOST="localhost"
BACKUP_DIR="/var/backups/nextcloud"
# --- ユーティリティ関数 ---
log_info() {
echo -e "\n\e[34m[INFO]\e[0m $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_warn() {
echo -e "\e[33m[WARN]\e[0m $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
log_error() {
echo -e "\e[31m[ERROR]\e[0m $(date '+%Y-%m-%d %H:%M:%S') - $1" >&2
}
ask_proceed() {
local prompt_msg="${1:-次のステップに進みますか?}"
while true; do
read -rp "👉 ${prompt_msg} [y/N]: " answer
case "${answer}" in
[yY]|[yY][eE][sS])
return 0
;;
[nN]|[nN][oS]|"")
log_warn "ユーザーにより処理が中断されました。"
exit 1
;;
*)
echo "'y' または 'n' を入力してください。"
;;
esac
done
}
# --- 前提チェック ---
# root 権限チェック(sudo 経由を含む root 以外は即時終了)
if [ "${EUID}" -ne 0 ]; then
log_error "このスクリプトは root 権限で実行する必要があります。(例: sudo $0)"
exit 1
fi
log_info "前提条件と実行権限を確認しています..."
if [ ! -d "${NC_DIR}" ]; then
log_error "Nextcloudディレクトリが見つかりません: ${NC_DIR}"
exit 1
fi
if ! command -v mysqldump &> /dev/null && ! command -v mariadb-dump &> /dev/null; then
log_error "mysqldump または mariadb-dump コマンドが見つかりません。"
exit 1
fi
mkdir -p "${BACKUP_DIR}"
# ==============================================================================
# Step 1: データベースパスワードの取得と認証確認
# ==============================================================================
log_info "【Step 1】データベース情報の入力"
read -rsp "🔑 DBユーザー (${DB_USER}) のパスワードを入力してください: " DB_PASS
echo
# パスワードの疎通確認
if ! MYSQL_PWD="${DB_PASS}" mysqladmin -h "${DB_HOST}" -u "${DB_USER}" ping &>/dev/null; then
log_error "データベースへの接続に失敗しました。パスワードまたはホスト設定を確認してください。"
exit 1
fi
log_info "データベースへの接続を確認しました。"
# ==============================================================================
# Step 2: メンテナンスモードの有効化
# ==============================================================================
log_info "【Step 2】メンテナンスモードの有効化"
ask_proceed "メンテナンスモードをONにしますか?"
sudo -u "${NC_USER}" "${PHP_BIN}" "${NC_DIR}/occ" maintenance:mode --on
log_info "メンテナンスモードを有効化しました。"
# スクリプト異常終了時にメンテナンスモード解除を促すトラップを設定
cleanup() {
if [ $? -ne 0 ]; then
log_warn "エラーが発生したため処理を停止しました。"
log_warn "必要に応じてメンテナンスモードを解除してください:"
log_warn "sudo -u ${NC_USER} ${PHP_BIN} ${NC_DIR}/occ maintenance:mode --off"
fi
}
trap cleanup EXIT
# ==============================================================================
# Step 3: DBバックアップの実行(インラインパスワード処理)
# ==============================================================================
log_info "【Step 3】DBバックアップの実行"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/${DB_NAME}_backup_${TIMESTAMP}.sql.gz"
ask_proceed "DBバックアップを開始しますか? (保存先: ${BACKUP_FILE})"
# dumpコマンドの判定(MariaDB/MySQL互換)
DUMP_CMD="mysqldump"
command -v mariadb-dump &> /dev/null && DUMP_CMD="mariadb-dump"
# MYSQL_PWD環境変数を使用することで、psコマンド等へのパスワード露出を防止
if MYSQL_PWD="${DB_PASS}" ${DUMP_CMD} -h "${DB_HOST}" -u "${DB_USER}" --single-transaction --quick "${DB_NAME}" | gzip > "${BACKUP_FILE}"; then
log_info "バックアップが正常に完了しました: ${BACKUP_FILE}"
else
log_error "バックアップ処理中にエラーが発生しました。"
exit 1
fi
# ==============================================================================
# Step 4: updater.phar によるアップデート実行
# ==============================================================================
log_info "【Step 4】updater.phar の実行"
log_warn "updater自体の対話プロンプトが表示されます。画面の指示に従って操作してください。"
ask_proceed "updater.phar を起動しますか?"
cd "${NC_DIR}"
sudo -u "${NC_USER}" "${PHP_BIN}" "${NC_DIR}/updater/updater.phar"
# ==============================================================================
# Step 5: 状態の確認とメンテナンスモードの調整
# ==============================================================================
log_info "【Step 5】最終確認とメンテナンスモードの解除"
current_mode=$(sudo -u "${NC_USER}" "${PHP_BIN}" "${NC_DIR}/occ" maintenance:mode)
echo "現在の状態: ${current_mode}"
if echo "${current_mode}" | grep -q "enabled"; then
read -rp "👉 メンテナンスモードをOFF(解除)にしますか? [y/N]: " unfreeze
if [[ "${unfreeze}" =~ ^[yY]$ ]]; then
sudo -u "${NC_USER}" "${PHP_BIN}" "${NC_DIR}/occ" maintenance:mode --off
log_info "メンテナンスモードを解除しました。"
else
log_warn "メンテナンスモードを維持したまま終了します。"
fi
fi
# ==============================================================================
# Step 6: バージョン確認
# ==============================================================================
log_info "【Step 6】バージョンの確認"
sudo -u "${NC_USER}" "${PHP_BIN}" "${NC_DIR}/occ" status
log_info "すべての更新手順が完了しました。"
trap - EXIT
このスクリプトで重視したこと
単にコマンドを並べるだけではなく、「途中で失敗しても致命傷にならないこと」を意識しています。
set -euo pipefail
Bashスクリプトでは定番ですが、非常に重要です。
- コマンドが失敗した
- 未定義変数を参照した
- パイプラインの途中でエラーが発生した
このような場合は、その時点で処理を停止します。
「バックアップに失敗したのに、そのままアップデートが続く」といった事故を防ぐためです。
root権限の確認
EUID を利用して、root 権限以外では実行できないようにしています。
sudo ./nextcloud_update.sh
以外の実行方法では即座に終了します。
パスワードをコマンドラインへ残さない
昔ながらの
mysqldump -pPASSWORD
という書き方は、ps コマンドなどからパスワードが見えてしまいます。
そこで本スクリプトでは
MYSQL_PWD
環境変数を利用しています。
賛否のある方法ではありますが、少なくともコマンドライン引数へ平文パスワードを残すより安全です。(なお筆者は別スクリプトを利用していますが、それはまた別のお話)
trapによる復旧案内
一番怖いのは
- メンテナンスモードON
- エラー発生
- そのまま終了
というパターンです。
そこで trap cleanup EXIT を利用し、異常終了した場合は
occ maintenance:mode --off
を案内するようにしています。
「解除方法を忘れた」という事態を防ぐための保険です。
実行の流れ
処理は次の順番で進みます。
1. 前提条件の確認
まずは
- root権限
- Nextcloudディレクトリ
mysqldumpまたはmariadb-dump
の存在を確認します。
ここで問題があれば、それ以上処理は進みません。
2. データベース接続の確認
パスワードを入力したあと、
mysqladmin ping
で接続テストを行います。
アップデート直前になって認証エラーが発覚するより、最初に確認してしまった方が安心です。
3. メンテナンスモードを有効化
occ maintenance:mode --on
を実行します。この操作の前にも確認プロンプトを表示するため、誤操作を防げます。
4. データベースをバックアップ
バックアップには
mysqldumpmariadb-dump
のどちらか利用可能な方を自動で選択します。
取得したSQLは、そのまま gzip 圧縮して保存します。
nextcloud_backup_20260821_153000.sql.gz
のように日時付きファイルになるため、履歴も管理しやすくしています。
5. updater.phar を起動
Nextcloud標準の
updater.phar
を実行します。ここから先はNextcloud側の対話画面になりますので、画面の案内に従って更新を進めます。
6. 最終確認
更新後は
- メンテナンスモードの状態確認
- 必要ならOFFへ変更
occ status
まで実行します。最後に現在のバージョンが表示されれば、一通りの更新は完了です。
さっくりとしたまとめ
サーバー運用では「バックアップを取ってから更新する」は当たり前ですが、人間は当たり前ほど慣れてしまうものです。だから私は、忘れない仕組みを作るようにしています。
「運用者は呼吸するかのようにできる。だが、第三者に任せられるか? すっごく焦ってるときに緊急アップデートをした時は?」のためにも、確実に動く仕組みは大切というお話でした。
コメントを残す