タグ: MySQL Page 1 of 2

Ubuntu 26.04にMySQLを導入。

概要

Webアプリのお供であるDBを入れます。

環境

  • Ubuntu 26.04

※ローカル運用で実施。いわゆるLAMP環境のため、他のサーバがDBを見に行くことはないという想定です。

さっくりとした手順

  1. パッケージのアップデートを行います。
  2. MySQLをインストールします。
  3. MySQLのrootパスワードを設定します。
  4. mysql_secure_installationにより安全性を高めます。

パッケージのアップデート

sudo aptitude update

筆者の好みでaptitudeを用いています。必要に応じてaptを使ってください。

MySQLインストール

  • パッケージでインストール
sudo aptitude install mysql-server
  • インストール確認
systemctl status mysql

active(running)を確認します。

MySQL設定変更について

MySQL 8.4以降では、長年使われてきた古い認証方式(mysql_native_password)がデフォルトで無効化され、よりセキュアな caching_sha2_password が標準となっています。そのため、設定ファイル(mysqld.cnf)を書き換えて旧プラグインを強制する手順は不要となり、標準の認証方式のまま初期設定を進めます。

また、近年のバージョンではインストール直後の初期セキュリティが強化されていますが、mysql_secure_installation は以下の重要な役割を持つため実行します。

  • パスワード検証コンポーネント(VALIDATE PASSWORD)の導入
  • 匿名ユーザーアカウントを削除
  • リモートからのrootユーザーのログインを無効化
  • testデータベースを削除し、testデータベースへのアクセス権限を持つユーザーを削除

mysql rootパスワード設定

sudo mysql

初期状態ではローカルソケット認証(auth_socket)のため、sudo経由でパスワードなしでログインできます。

ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'password';

''のpasswordは任意の、強固なものを入力ください。

標準推奨の caching_sha2_password を用いて強固なパスワードを設定します。

flush privileges;
exit

mysql_secure_installation

sudo mysql_secure_installation

質問事項

Enter password for user root: 
# 上記で設定したパスワードを入力します
​
VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?
​
Press y|Y for Yes, any other key for No:
# パスワード強度チェックを有効にするためYを入力してEnter
​
There are three levels of password validation policy:
​
LOW   Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary file
​
Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG:
# ポリシーに合わせて0/1/2を入力(ローカル開発環境なら0または1を推奨)
​
Estimated strength of the password: 50
Change the password for root ? ((Press y|Y for Yes, any other key for No) :
# 既に直前の手順でパスワードを設定済みのため、ここではnを選択します。
​
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.
​
Remove anonymous users? (Press y|Y for Yes, any other key for No) :
# anonymousユーザーを削除するためY
​
Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.
​
Disallow root login remotely? (Press y|Y for Yes, any other key for No) :
# rootユーザのリモートログインを禁止するためY
​
Remove test database and access to it? (Press y|Y for Yes, any other key for No) :
# テストDBを削除するためY
​
Reload privilege tables now? (Press y|Y for Yes, any other key for No) :
# 設定を反映するためY

以上でMySQLの初期設定は完了です。

RHEL9系LinuxにMySQLを導入

RHEL9系ディストリビューション(Rocky Linux 9.7)にMySQLを導入したときのメモです。

そもそもDB(データベース)とは何なのか?

一言で言えば、「特定のルールに従って、整理整頓されたデータの集まり」です。

言うなれば「超高性能な図書館」のようなものです。
閲覧者、借りている人の帳簿を司り、膨大な本から一瞬で目的の1ページを探し出し、同時に何百人もの人が本を借りようとしても混乱が起きないように管理されています。

MySQLなどの「RDBMS」

MySQLは正確には「リレーショナルデータベース管理システム(RDBMS)」と呼ばれます。

  • リレーショナル(関係性): データを「表(テーブル)」の形式で管理し、複数の表を関連付けることができます。
  • 管理システム: データそのものではなく、データを操作・管理するためのソフトウェアのことです。

何を司るのか(役割と機能)

MySQLが担っている主な役割は、大きく分けて以下の4つです。

  • データの格納と検索(CRUD)
    • データの登録(Create)、参照(Read)、更新(Update)、削除(Delete)の4つを、膨大な量の中から高速に行います。
  • 整合性の維持(つじつまを合わせる)
    • 「注文データはあるのに、注文したユーザーのデータがない」といった矛盾(バグの元)が起きないよう、データの整合性を厳しく見張ります。
  • 同時実行の制御(排他制御)
    • 例えば、残り1つの商品を2人が同時にクリックした際、どちらか一方が確実に買えるように調整し、「1つしかないのに2人に売れてしまった」という事故を防ぎます。
  • セキュリティと権限管理
    • 「この人は閲覧だけ」「この人は編集もOK」といった具合に、大切なデータへのアクセスをコントロールします。

なぜ大事なのか(存在理由)

なぜExcelファイルやテキストファイルで管理するのではダメなのでしょうか?

データの爆発に対応するため

テキストファイルだと、100万件のデータから1件を探すのに上から順に読み込む必要があり、時間がかかりすぎます。DBは「インデックス(索引)」という仕組みを持ち、瞬時にデータを見つけ出せます。

データの「信頼性」を保証するため(ACID特性)

銀行振込を想像してみましょう。

  1. Aさんの口座から1万円引く
  2. Bさんの口座に1万円足す

もし「1」の直後にシステムがダウンしたら、1万円が消えてしまいます。

こうならないよう、DBには「トランザクション」という仕組みがあり、「すべて成功するか、すべてなかったことにするか」のどちらかしか認めません。これが社会インフラを支える信頼性の正体です。

複数のプログラムから共有できるため

Linuxサーバー上で動く

  • Webサイト
  • スマホアプリ
  • 管理画面

など、バラバラな入り口から入ってくる要求を、一つの窓口(MySQL)が交通整理して処理してくれます。

まとめ

MySQLは、システムにおける「記憶の番人」です。

  • DBとは: 整理されたデータの基地。
  • 司るもの: データの出し入れ、矛盾の防止、アクセスの交通整理。
  • 大事な理由: 膨大なデータを「速く」「正確に」「安全に」扱うため。

LinuxにDBを入れるということは、そのサーバーに「確かな記憶力」と「厳格な管理能力」を持たせるということに他なりません。

ここまで踏まえ、LinuxにDBを入れていきましょう。

インストールとディレクトリ準備

MySQLサーバーのパッケージを導入し、MySQLサービスが利用するディレクトリの権限をあらかじめ適正化。

  • MySQLサーバのインストール
sudo dnf install -y mysql-server

サービスの起動と初期ログイン

MySQLサービスを有効化し、初期状態でのログインを確認。

  • サービスの有効化と起動
sudo systemctl enable --now mysqld
  • 初期ログイン(MySQL 8.0では初期状態はパスワードなし)
mysql -u root

rootパスワードの確定

ログイン直後にMySQLのroot顕現のパスワードを設定します。

※先ほどのDBの話に戻ります。DBは「システムのデータそのもの」を管理します。先ほどの図書館の例で言うと

  1. 利用者
  2. 所蔵されている本
  3. その本がどこにあるか(貸し出し中か、書架か)
  4. どのようなジャンルか、作者は?

まで全て記録されている状態です。ここで、例えば、悪意ある者が「『ハムレット』の作者は『クリストファー・マーロウ』である」としたい場合、悪意ある者はそのような行為ができてしまいます。

そのため、攻撃者はDBのroot権限を真っ先に奪います。それを防ぐためにも最初にrootパスワードを設定します。

  • rootユーザーに対して新パスワードを適用
ALTER USER 'root'@'localhost' IDENTIFIED BY 'Your_Strong_Password';

パスワードは自分の環境に合わせます。パスワード設定後、そのデータを適切な方法・手段・保管場所に格納してください。

  • 権限設定
FLUSH PRIVILEGES;
  • コンソールから抜ける
EXIT
  • パスワードで入れるかを確認
mysql -u root -p

設定したパスワードでログインできることを確認します。確認後、EXITで抜けます。

セキュリティの堅牢化 (mysql_secure_installation)

対話型スクリプトを用い、商用・本番環境に耐えうるセキュリティ設定を一括で適用します。 以下のように行ってください。

Enter password for user root:

で、先ほどのrootパスワードが聞かれます。

その後、いくつかの確認事項があるのでYで答えます。

設定項目内容理由
Remove anonymous usersYes誰でも接続できる穴を塞ぐため
Disallow root login remotely?Yesローカル管理に限定し攻撃経路を遮断するため
Remove test database and access to it?Yes不要なオブジェクトの排除
Reload privilege tables now?Yes設定内容を有効化するため

RHEL9系でMySQLのrootパスワードを忘れてしまったときの再設定メモ

本手順は、MySQLのrootパスワードを紛失し、通常の方法でログインできなくなった場合に実施する「非常時用」のリカバリ手順です。

作業の前に

この作業は本来ならばあってはならない作業です。パスワード失念はセキュリティ事故の筆頭。ましてやWebシステムの神に等しいDBを司る通行証が消えた。なので、

  • 事前にアカウント情報を記したファイルを保存する
  • 適切な場所、適切なアクセス権で保管する

は必須ですが

往々にしてこの事故は起きます。なので、「マジで起きてしまった。取り敢えずの迅速な復旧」を望んでいる(つまり今回の私のような)方へのメモとなります。

この手順が笑える状況

  • 構築中
  • 検証作業中

のいずれかのみ。本番稼働中だったらまず笑えませんし、許可を得るための政治力・交渉力は甚大なものになります。筆者は「構築中」のパターンです。

環境

  • RHEL9系(RockyLinux9系)
  • MySQL 8

注記:RHEL 9系での注意点

  • 従来の mysqld_safe コマンドは廃止されているため、systemctl set-environment を使用して起動オプションを制御します。
  • MySQL 8.0以降は skip-grant-tables モード中でも FLUSH PRIVILEGES を実行しない限り ALTER USER コマンドが受け付けられない仕様となっています。

作業影響

  • 作業中にMySQLが止まる

これに尽きますが、「起きてしまったことは仕方ない。潔くサパッと止めてサクッと終わらせる」を心がけます。

さっくりとした手順

  1. MySQLサービスを停止します。
  2. 認証をスキップするための環境変数をセットします。
  3. 認証スキップ状態でMySQLを起動します。
  4. rootパスワードのリセットを行います。
  5. 認証を有効化してMySQLサービスを起動します。
  6. リセットされたパスワードでMySQLに入れることを確認します。

MySQLサービスの停止

  • MySQL停止
sudo systemctl stop mysqld
  • MySQL停止確認
systemctl status mysld

inactive(dead)を確認します。

認証をスキップするための環境変数をセットします。

  • 認証スキップのオプションを環境変数に一時セット
systemctl set-environment MYSQLD_OPTS="--skip-grant-tables --skip-networking"

(--skip-networkingを付けることで、作業中の外部接続を遮断し安全を確保します。)

認証スキップ状態でMySQLを起動します。

sudo systemctl start mysqld
  • MySQL起動確認
systemctl status mysld

active(running)を確認します。

rootパスワードのリセットを行います。

認証がスキップされている状態でログインし、権限テーブルを強制ロードしてからパスワードを書き換えます。

  • パスワードなしでrootログイン
mysql -u root

これでログインできたらひとまず成功です。ここからはSQL捜査を行います。

  • 権限テーブルをリロード (ALTER USER を実行可能にするために必須)
FLUSH PRIVILEGES;
  • パスワードの変更を実施します。
ALTER USER 'root'@'localhost' IDENTIFIED BY 'your_strong_password';
  • 変更を確定して終了
FLUSH PRIVILEGES;
exit

認証を有効化してMySQLサービスを起動します。

一時的な環境変数を削除し、通常の認証が有効な状態で再起動します。

  • MySQLを一旦停止
systemctl stop mysqld
  • MySQL停止確認
systemctl status mysld

inactive(dead)を確認します。

  • セットした環境変数を必ず解除 (これを忘れると誰でも入れる状態が続くため重要)
systemctl unset-environment MYSQLD_OPTS
  • 通常どおりサービスを起動
sudo systemctl start mysqld
  • MySQL起動確認
systemctl status mysld

リセットされたパスワードでMySQLに入れることを確認します。

mysql -u root -p

新しいパスワードでログインできたことを確認します。

まとめ

「起きないことが第一」とは言いますが、本当にくだらない理由でこういう事象は発生します。なので

  • 起きてしまったことは潔く認める
  • そこから原状の復旧を目指す。
  • 責任の追及とか誰がイモを引くかはその後で考える

の三段活用。“全裸大佐”が言う

過ちを気に病むことはない。ただ認めて、次の糧にすればいい

という「大人の特権」をフル活用しましょう。

MySQLのデータベースを暗号化してバックアップするスクリプト。(2025年10月版)

本記事では、筆者が用いるバックアップスクリプトを元にして、バックアップの大切さを述べます。以前に作成した記事のリファインという形です。

『賢者の石』としてのバックアップ

LinuxのみならずとってITにおけるバックアップは、言うなれば『賢者の石/Philosopher's Stone』です。

ここまで断言できる根拠があります。筆者が前に述べたとおり、Linuxサーバは設定一つの変更、チューニング、誤操作などで全てが壊れる世界です。

そんな中、適切なバックアップを取っておくことで、失敗全てを帳消しにできる確率が飛躍的に高まります。

また、バックアップを取ることにより、他のサーバへの移し替えや「問題が発生した状況の再現」も容易になります。

筆者が手順で

sudo cp -pi /something/very/very/massive/important/file.conf /extra_sensitive_backup.conf.$(date +%Y%m%d)

等でバックアップを取り、

diff -u sudo cp -pi /extra_sensitive_backup.conf.$(date +%Y%m%d) /something/very/very/massive/important/file.conf 

と差分を取るのも、「事前のちょっとした面倒な作業」は「後に発生する大災害」を救ってくれます。

特に重要なWebアプリでのDBバックアップの重要性

翻って、Webアプリケーションの運用となると、この「賢者の石」としてのバックアップの役割は、単なるシステム設定の保護を超え、Webサイトのみならず事業の存続に直結します。

なぜなら、Webアプリにおいて最も価値があり、最も頻繁に変化し続ける情報、すなわち『データ(データベース)』こそが、そのアプリケーションの「魂」だからです。

自分を含め

  • 長年蓄積した記事
  • 画像情報
  • (商用利用の場合は)決済情報、顧客情報

これらデータベースに格納された情報は、失われた瞬間、企業の信用も収益もゼロになります。法的な責任も発生すれば、これらは簡単にマイナスになるという、筆者が前にも述べている「理不尽な非対称性」が発生します。

ファイルシステム全体が健在であっても、データベースだけが破損すれば、サイトは事実上停止します。これは、設定ファイル一つを誤った際の「システム停止」とは次元の異なる、「世界の消滅」を意味します。

だからこそ、WebアプリのDBバックアップには、以下の3つの要素が絶対的に求められます。

  1. 完全なバックアップ(データの保護): mysqldumpなどを利用し、停止時やトランザクション中のデータも漏れなくダンプすること。
  2. 確実な安全性(暗号化): 個人情報を含む機密性の高いデータであるため、保管時には必ず強固なパスワードで暗号化し、不正アクセスからデータを守ること。
  3. 信頼できる世代管理: 毎日確実にバックアップを取り続け、かつ必要な日数分だけ保持し、古すぎるバックアップは自動で削除する仕組み(世代管理)が不可欠です。これにより、ディスク容量の圧迫を防ぎつつ、「昨日の正常な時点」や「1週間前の状態」へ確実に巻き戻せる保証を得るのです。

次に紹介するスクリプトは、このWebアプリの命綱たるデータベース (MySQL) を、安全性と世代管理を両立させながら、コマンド一つで確実に守り抜くために作成したものです。

事実、筆者はこの手のバックアップにより

  1. AWS
  2. WebArena
  3. XServer

と3つのVPSからのWebサイト移行を行いました。

その前に事前確認

Prevention is better than cure.(転ばぬ先の杖)というやつです。

これはUbuntu系での手順です。

MySQL での操作です。

  • mysqldump 確認
which mysqldump

/usr/bin/mysqldumpなどと返ってくることを確認。見つからない場合は

sudo aptitude install mysql-client
  • データベースユーザーのアクセス権確認・付与(重要)

データベースユーザー(例: your_db_user)が、バックアップ対象のデータベース($DATABASE_NAME)全体に対してデータを読み取る権限(SELECT)を持っている必要があります。

MySQL/MariaDBにrootでログインし、以下のコマンドで確認します。

SHOW GRANTS FOR 'your_db_user'@'localhost'; 
  • 権限の付与:

もし権限が不足している場合は、rootでしてログインし、必要な権限を付与します。

データベースのダンプ(バックアップ)には、最低限 SELECT 権限が必要です。

また、--single-transactionオプションを使う場合、ほとんどのストレージエンジンでRELOAD(またはPROCESS)権限は必須ではありません。

ここまで来たら、いよいよスクリプトの作成です。

DBというシステムの生命線のバックアップたる「賢者の石」。パスの間違いなどで簡単に「持ってかれる」等価交換以上の代償を伴う作業。慎重にやっていきましょう。

さっくりとは言い難い手順

  1. 事前準備。DBアカウントファイルを作成します。
  2. 事前準備。バックアップなどを格納するディレクトリを作成します。
  3. 自分の環境に合わせて スクリプトを作成します。
  4. 動作の確認を行い、cron設定を行います。

必要なファイルとディレクトリ群、注意

項目説明設定値 (スクリプト内変数)
MySQLアカウントファイルmysqldump実行に使用するデータベース接続情報ファイル。パーミッションは400必須。$CREDENTIALS_FILE (/home/hoge/script/config/db_account/db_account.txt)
バックアップ保管ルート圧縮後のバックアップファイルを保管するディレクトリ。$BACKUP_ROOT_DIR (/path/to/backup/directory)
パスワード保管ディレクトリバックアップZIPファイルの解凍パスワードを保管するディレクトリ。$PASSWORD_DIR (/home/hoge/dbrestore_password)
実行ユーザースクリプトを実行するOSユーザー。/home/hogeの所有者

事前準備(ファイル・ディレクトリの作成とパーミッション設定)

スクリプトを実行する前に、以下のファイルとディレクトリを準備してください。

  • データベースアカウントファイルの作成

$CREDENTIALS_FILEで指定されたパスに、MySQLの接続情報を記述したファイルを作成します。

  1. ディレクトリの作成: mkdir -p /home/hoge/script/config/db_account
  2. アカウントファイルの作成 (/home/hoge/script/config/db_account/db_account.txt):
[mysqldump]
# [mysqldump]セクションが必要ですuser=your_db_user # ダンプ操作が可能なユーザー名 password="your_db_password" # ユーザーのパスワード

パーミッションの設定(重要):
スクリプトの実行条件であり、セキュリティ上必須です。

chmod 400 /home/hoge/script/config/db_account/db_account.txt

※重ねての注意点このDBアカウント情報はrootアカウントと同等以上のリスク管理が必要です。すなわち

「No shown, No stolen, No matter what. (見せても盗まれてもならぬ、何があっても)」

の強い覚悟が必要です。(とはいえ自分の命と天秤にかけた状態で)

バックアップディレクトリの作成

バックアップファイルとパスワードファイルを保管するディレクトリを作成します。

  1. バックアップルートディレクトリの作成:
    bash mkdir -p /path/to/backup/directory
  2. パスワード保管ディレクトリの作成:
    bash mkdir -p /home/hoge/dbrestore_password
  3. パーミッションの設定:
    スクリプトを実行するOSユーザーが、これらのディレクトリに対して書き込み・読み取り・実行権限を持っていることを確認してください。通常はchownコマンドで所有者を設定します。

スクリプトの作成

backup_mysql.shを任意の方法で、或いは自身の教義・信仰に則ったエディタを用いて作成します。変数の部分は 自分の環境に合わせて 調整します。

#!/bin/bash

# コマンドの実行中にエラーが発生した場合、スクリプトを終了します
set -e

## 変数ここから ##
# $HOMEの変数を指定します。
HOME_DIR="/home/hoge"
# SQLをバックアップする**保管先**ディレクトリを指定します。運用に合わせて指定ください。
BACKUP_ROOT_DIR="/path/to/backup/directory"
# バックアップ処理用の一時ディレクトリ名を指定します。
TMP_SUBDIR="temp_dump"
# パスワードファイルを保管するディレクトリを指定します。
PASSWORD_DIR="${HOME_DIR}/dbrestore_password"

# 保持するバックアップの世代を日数で指定します。
KEEP_DAYS=7

# ファイルに付与する日付/作業ディレクトリ名/バックアップファイル名を指定します。
CURRENT_DATE=$(date +%Y%m%d%H%M%S) # 日付に時刻を加えて一意性を高める
BACKUP_BASE_NAME="database" # バックアップ対象のデータベース名などから命名
SQL_FILE_NAME="${BACKUP_BASE_NAME}.sql"
ZIP_FILE_NAME="${BACKUP_BASE_NAME}.${CURRENT_DATE}.zip"
PASSWORD_FILE_NAME="db-restore.${CURRENT_DATE}.txt"

# 一時的なバックアップディレクトリのフルパス
TMP_BACKUP_DIR="${BACKUP_ROOT_DIR}/${TMP_SUBDIR}"
# 圧縮後のバックアップファイルのフルパス
ZIP_FILE_PATH="${BACKUP_ROOT_DIR}/${ZIP_FILE_NAME}"
# パスワードファイルのフルパス
PASSWORD_FILE_PATH="${PASSWORD_DIR}/${PASSWORD_FILE_NAME}"

# アカウントファイルを指定します。運用に合わせて指定ください。
CREDENTIALS_FILE="${HOME_DIR}/script/config/db_account/db_account.txt"
# redmineのデータベース名を指定します。
DATABASE_NAME="database"
# バックアップ時に指定するオプションを指定します。
OPTIONS="--defaults-extra-file=$CREDENTIALS_FILE --no-tablespaces --single-transaction"

# 世代管理のためのファイルパターン
BACKUP_FILE_PATTERN="${BACKUP_BASE_NAME}.*.zip"
PASSWORD_FILE_PATTERN="db-restore.*.txt"
## 変数ここまで ##

## 処理ここから ##

# 1.アカウントファイルのパーミッションが400かどうかチェックします。
# 400以外は処理そのものを終了します。
permissions=$(stat -c "%a" "$CREDENTIALS_FILE")
if [ "$permissions" != "400" ]; then
    echo "🚨 エラー: アカウントファイル(${CREDENTIALS_FILE})のパーミッションは400である必要があります。(現在: ${permissions})" >&2
    exit 1
fi

# 2. 一時的なバックアップディレクトリを作成します。
# -pで存在しない親ディレクトリも作成し、既に存在してもエラーにしない
mkdir -p "${TMP_BACKUP_DIR}" || exit 1
mkdir -p "${PASSWORD_DIR}" || exit 1

# 3. mysqldumpを実行してデータベースのバックアップを取ります。
echo "⏳ ${DATABASE_NAME}のデータベースダンプを開始..."
mysqldump $OPTIONS -h localhost "$DATABASE_NAME" > "${TMP_BACKUP_DIR}/${SQL_FILE_NAME}" || {
    echo "🚨 エラー: mysqldumpが失敗しました。" >&2
    rm -rf "${TMP_BACKUP_DIR}" # 失敗したら一時ディレクトリをクリーンアップ
    exit 1
}
echo "✅ データベースダンプ完了。"

# 4. パスワードによる暗号化を実施します。
password=$(openssl rand -base64 12)

# 【ルートディレクトリ圧縮回避のため、一時ディレクトリに移動して圧縮対象ファイルを直接指定】
echo "⏳ バックアップファイルの圧縮・暗号化を開始..."
cd "${TMP_BACKUP_DIR}" || exit 1
# zipコマンドで、SQLファイルのみを対象とし、圧縮後のzipを一つ上の階層に出力
zip -P "$password" "${ZIP_FILE_PATH}" "${SQL_FILE_NAME}" || {
    echo "🚨 エラー: zip圧縮が失敗しました。" >&2
    cd - > /dev/null # 元のディレクトリに戻る
    rm -rf "${TMP_BACKUP_DIR}" # 失敗したら一時ディレクトリをクリーンアップ
    exit 1
}
cd - > /dev/null # 元のディレクトリに戻る
echo "✅ 圧縮・暗号化完了: ${ZIP_FILE_PATH}"

# 5. 一時的なバックアップディレクトリを削除します。
echo "🗑️ 一時ディレクトリを削除: ${TMP_BACKUP_DIR}"
rm -rf "${TMP_BACKUP_DIR}"

# 6. 解凍パスワードを指定ディレクトリに保存し、権限を設定します。
echo "🔐 解凍パスワードを保存: ${PASSWORD_FILE_PATH}"
echo "$password" > "$PASSWORD_FILE_PATH"
# 7.パスワードの読み取り権限を600に変更します。
chmod 600 "$PASSWORD_FILE_PATH"

# 8. 【確実にバックアップファイルを世代管理 (古いファイルの削除)】
echo "🧹 保持期間(${KEEP_DAYS}日)より古いバックアップを削除..."
# バックアップファイル本体の削除
find "$BACKUP_ROOT_DIR" -maxdepth 1 -name "$BACKUP_FILE_PATTERN" -type f -mtime +$KEEP_DAYS -print -delete
# 対応するパスワードファイルの削除
find "$PASSWORD_DIR" -maxdepth 1 -name "$PASSWORD_FILE_PATTERN" -type f -mtime +$KEEP_DAYS -print -delete
echo "✅ 世代管理完了。"

## 処理ここまで ##
  1. スクリプトファイルの作成と配置:
    このスクリプトをファイル(例:backup_mysql.sh)として保存します。
    bash # 例 cp (修正済みスクリプトの内容) /home/hoge/backup_mysql.sh
  2. 実行権限の付与:
    bash chmod +x /home/hoge/backup_mysql.sh
  3. テスト実行:
    bash /home/hoge/backup_mysql.sh
  4. 定期実行の設定(Cronなど):
    Cronを利用して、スクリプトを定期的に実行するように設定します。
    bash # crontab -e で開き、以下の行を追加 (例: 毎日午前2時に実行) 0 2 * * * /home/hoge/backup_mysql.sh > /dev/null 2>&1

スクリプトの動き

このスクリプトは、運用者(つまり私のようなサーバ管理者)望む機能を盛り込んだ機能を持たせています。

  • 予め配備されたアカウント情報に基づき、mysqldumpで、対象DBのみのバックアップを行います。
  • バックアップと同時に圧縮&暗号化を行います。
  • 復号に必要なパスワードは同時に別ディレクトリに保管。有り体に言えば、スクリプト自身も知らないランダムパスワードなので推測される可能性はほぼありません。
  • その後、スクリプトはDBバックアップディレクトリとパスワード格納ディレクトリを精査。変数に基づいて、特定日数以上が過ぎたファイルを自動的に削除して、ディスクの容量を安定化します。

では、どうやって運用するの?

パスワードによる複合化

スクリプト実行後、対象の.zipファイルを

unzip database.20251028113148.zip

等として、スクリプト実行日時が入ったファイルを展開します。

このとき、パスワードを尋ねられるので、対になる複合化のパスワードファイルdb-restore.20251028113148.txtで開きます。database.sqlが平文で出てきます。

DBの切り戻し

こうして、DBのバックアップさえできていれば、その後の安心感はまるで異なります。

  • サーバが吹っ飛んだ
  • 別サーバに移行したい

等の場合も、

mysql -h localhost -u your_db -p your_db < /path/to/backup/directory/database.sql

とすることで、切り戻しや移行のハードルが非常に楽になります。

最後に

「何かの事故」
「故意/未必の故意/ミス」

など、「障害」という奴は予測できないからこそ「障害」です。管理者にできることは

「障害が来ないことを祈る」

ではありません。

「障害が来ても大丈夫な備え」をシステム化することです。

「汝平和を欲さば、戦への備えをせよ」/"Si vis pacem, para bellum"

は、ローマより続く言葉であるからこそ、普遍性と不変性があるのです。

Redmine5.1.4→Redmine5.1.8へのアップデート手順。

公開用Redmine

https://atelier.reisalin.com

のバージョンを5.1.4→5.1.8にアップデートしたときのメモです。

環境

  • Ubuntu 24.04
  • 動かしていたRedmine:5.1.4
  • アップデートしたRedmie:5.1.8
  • Apache 2.4 / mod-passangerでRubyアプリを使用(Ruby 3.2系)
  • MySQL 8.0.3

作業に備えての前提

  • Webサービスを止めるため、ユーザアクセスができない状況が発生します。
  • 利害関係者への事前周知・作業時間の確保は十分に行ってください。(慣れれば20分程度で完了しますが、1時間は取っておいた方が無難です)
  • また、筆者環境はfiles配下をクラウドストレージにマウントしています。手順は自身の環境に合わせてください。

さっくりとはいかない手順

  1. (強く推奨)システム全体のバックアップ
  2. DBのバックアップ
  3. redmineのディレクトリを一度mvでリネームしてバックアップ。
  4. apache停止
  5. ディレクトリを再作成し、新しい空のRedmineを作る。
  6. themesとpluginを再配置。filesのシンボリックリンクを貼り替える。
  7. themesとpluginを再配置した状態でDBマイグレーション。
  8. apache再開
  9. バージョンアップ確認

システム全体のバックアップ(スナップショット)

  • AWS
  • 仮想サーバ

などで動かしている場合は、この段階でシステム全体のバックアップ(スナップショット)を取ることを強く推奨します。

mysqlによるDBバックアップ

  • バックアップディレクトリに移動
cd /hoge && pwd

任意のディレクトリを指定します。

  • mysqldump
mysqldump -h localhost -u redmine -p --no-tablespaces --single-transaction redmine > redmine_backup.$(date +%Y%m%d).sql

DB名やDBユーザは自分の環境に合わせます。

  • mysqldump確認
view redmine_backup.$(date +%Y%m%d).sql

DBが平文で読めることを確認します。

データ退避

  • ディレクトリ移動
cd /var/lib && pwd

Redmineが格納されているディレクトリの親ディレクトリに移動します。(筆者環境は/home/www-data)

  • Redmine全体ディレクトリ確認
ls -ld redmine

退避対象のディレクトリがあることを確認します。ディレクトリ名は自分の環境に合わせます。

  • Redmine待避
sudo mv redmine redmine_$(date +%Y%m%d)
  • Redmine待避確認
ls -ld redmine_$(date +%Y%m%d)

ディレクトリがあることを確認します。

apache停止

念のため、apacheを停止します。

  • apache停止前確認
systemctl status apache2.service

active(running)を確認します。

  • apache停止
sudo systemctl stop apache2.service
  • apache停止確認
systemctl status apache2.service

inactive(dead)を確認します。

Redmineプログラムの配置

  • Redmineのディレクトリ作成
sudo mkdir /var/lib/redmine
  • Redmineディレクトリの権限変更
sudo chown -R www-data:www-data /var/lib/redmine
  • Redmineディレクトリの作成確認
ls -ld redmine

ディレクトリがあることと、所有者がwww-dataであることを確認します。

  • ソースダウンロード
sudo -u www-data svn co https://svn.redmine.org/redmine/branches/5.1-stable /var/lib/redmine

5.1系の最新安定版をダウンロードします。

退避させたディレクトリからconfigファイルコピー

  • database.ymlコピー
sudo -u www-data cp -pi /var/lib/redmine_$(date +%Y%m%d)/config/database.yml /var/lib/redmine/config/database.yml
  • database.ymlコピー確認 
cat /var/lib/redmine/config/database.yml

待避したファイルの内容であることを確認します。

  • configuration.yml コピー
sudo -u www-data cp -pi /var/lib/redmine_$(date +%Y%m%d)/config/configuration.yml /var/lib/redmine/config/configuration.yml
  • configuration.ymlコピー確認
cat /var/lib/redmine/config/configuration.yml

待避したファイルの内容であることを確認します。

退避したディレクトリからデータを再配置

  • プラグイン一式のコピー
sudo -u www-data cp -pir  /var/lib/redmine_$(date +%Y%m%d)/plugins/* /var/lib/redmine/plugins/

移行元・移行先は自分の環境に合わせます。

  • テーマ一式のコピー
sudo -u www-data cp -pir /var/lib/redmine_$(date +%Y%m%d)/public/themes/* /var/lib/redmine/public/themes/

シンボリックリンク貼り替え

これは筆者の環境がlogディレクトリとfilesディレクトリを別の場所(wasabiクラウドストレージ)にリンクを張っているための措置です。
それ以外の場合は上述した /var/lib/redmine_$(date +%Y%m%d)からfilesやlogをコピーして下さい。

  • Redmineルートディレクトリに移動
cd /var/lib/redmine && pwd

自分の環境に合わせます。

  • filesディレクトリ削除
sudo rm -rf files
  • ログディレクトリ削除
sudo rm -rf log
  • filesディレクトリにシンボリックリンクを張る
sudo ln -sf /mnt/wasabi/redmine/files files

自分の環境に合わせます。

  • filesシンボリックリンクの所有者変更
sudo chown -h www-data:www-data files
  • filesシンボリックリンク確認
ls -l files
  1. filesがシンボリックリンクになっていること
  2. 所有者がwww-dataであること

を確認します。

  • logディレクトリにシンボリックリンクを張る
sudo ln -sf /var/log/redmine log
  • logシンボリックリンクの所有者変更
sudo chown -h www-data:www-data log
  • logシンボリックリンク確認
ls -l log
  1. logがシンボリックリンクになっていること
  2. 所有者がwww-dataであること

を確認します。

DBマイグレーション

  • Redmineルートディレクトリに移動
cd /var/lib/redmine

自分の環境に合わせます。

  • bundle インストール
sudo -u www-data bundle install --without development test --path vendor/bundle
  • シークレットトークン発行
sudo -u www-data bundle exec rake generate_secret_token
  • DBマイグレーション(本体)
sudo -u www-data RAILS_ENV=production bundle exec rake db:migrate
  • DBマイグレーション(プラグイン)
sudo -u www-data bundle exec rake redmine:plugins:migrate RAILS_ENV=production
  • キャッシュクリア
sudo -u www-data RAILS_ENV=production bundle exec rake tmp:cache:clear
  • セッションクリア
sudo -u www-data RAILS_ENV=production bundle exec rake tmp:sessions:clear

apache再起動

  • apache再起動前確認
systemctl status apache2.service

inactive(dead)を確認します。

  • apache再起動
sudo systemctl start apache2.service
  • apache再起動確認
systemctl status apache2.service

active(running)を確認します。

動作確認

この状態でRedmineに管理者権限でログインします。手順通りなら

  • テーマ
  • 添付ファイル
  • プラグイン
  • チケット一覧

などが有効に動いていて、正常に稼働します。

バージョンアップ後の作業

  • 待避したファイルの削除/バックアップ

/var/lib/redmine_$(date +%Y%m%d)一式を削除、または任意の方法でバックアップします。

トラブルシューティング

bundle install が終わらない

Installing... の表示で止まっているように見えても、実際にはCPUを消費して動作していることがある(ネイティブ拡張機能のコンパイル)。topコマンドでcc1plusなどのプロセスが動いていないか確認する。

"Something went wrong" エラー

Redmineのアプリケーション起動エラー。原因はログに記録されている。

  1. まず /var/lib/redmine/log/production.log を確認する。
  2. 上記にログがなければ、/var/log/apache2/error.log を確認する。

ログから見る主な原因の例

  • プラグインの非互換: Redmine本体の機能とプラグインが競合している場合がある (Overwriting existing method 警告など)。
  • gemのバージョン競合: Ruby本体に付属のgemと、プラグインが要求するgemのバージョンが異なると起動に失敗することがある (base64の競合など)。この場合は、Gemfileでバージョンを明示的に指定するなどの対策が必要。

DBのデータ容量を確認するSQL文

概要

MySQLの運用時、「このDBはどのぐらいのディスク容量を消費しているのか?」は日々のメンテナンスのみならずバックアップや移行などにも気になるところ。

そんな確認方法についてのTIPSです。

環境

以下のサーバで動作を確認しました。

  • Ubuntu 22.04 / Ubuntu 24.04
  • MySQL 8.0.x

前提

  • MySQLターミナルで操作します。
  • そのDBへのSELECT権限を持っていなければ操作できません。

操作

  • MySQLログイン
mysql -u user -p

自分の環境に合わせます。

  • DB確認
SHOW DATABASES;

ここで、参照したいDB名を確認します。

  • SQL実行
SELECT
    table_schema AS 'データベース名',
    SUM(data_length + index_length) AS '合計サイズ(バイト)',
    SUM(data_length) AS 'データサイズ(バイト)',
    SUM(index_length) AS 'インデックスサイズ(バイト)',
    -- 人が読みやすいようにメガバイト(MB)やギガバイト(GB)でも表示
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS '合計サイズ(MB)',
    ROUND(SUM(data_length) / 1024 / 1024 / 1024, 2) AS '合計サイズ(GB)'
FROM
    information_schema.TABLES
WHERE
    table_schema = '調べたいデータベース名' -- ここにサイズを知りたいデータベース名を入力してください
GROUP BY
    table_schema;
  • 表示例
+-----------------------+----------------------------+-------------------------------+----------------------------------------+---------------------+---------------------+
| データベース名        | 合計サイズ(バイト)         | データサイズ(バイト)          | インデックスサイズ(バイト)             | 合計サイズ(MB)      | 合計サイズ(GB)      |
+-----------------------+----------------------------+-------------------------------+----------------------------------------+---------------------+---------------------+
| nextcloud             |                  432685056 |                     163741696 |                              268943360 |              412.64 |                0.15 |
+-----------------------+----------------------------+-------------------------------+----------------------------------------+---------------------+---------------------+
1 row in set (0.01 sec)

この例では、DB「nextcloud」に対して412MBのデータを消費していることが明らかになりました。

snipe-itでのDBマイグレーションエラー(プロフィール画像の更新時にエラー)に対処。

Ubuntu 20.04→Ubuntu24.04にデータ移行を行った資産管理ツールsnipe-it。

その後、バージョンアップを行いましたが、それに伴うDBの不整合が問題でエラーが発生しました。

こちら、メモとして残します。

環境

  • Ubuntu 24.04
  • php 8.3
  • MySQL 8.0.40
  • Apache 2.4
  • Snipe-IT v7.0.12

発生したエラー

自分のアカウントの画像を変更しようとしたところ、500 internal server errorが発生しました。

エラーの特定

  • snipe-itのログディレクトリに移動
cd /home/www-data/snipe-it/storage/logs
  • ログ確認
cat laravel.log |grep ERROR
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'enable_sounds' in 'field list'

プロファイルの編集にこのような機能があったことから、DBのusersテーブルにenable_soundsやenable_confetti列が存在しないことが原因で、画像変更時にSQLエラーが発生したと考えられます。

調査

このエラーが原因と考え、まずはsnipe-itのルートディレクトリに移動。

cd /home/www-data/snipe-it

artisan migrateを実行。

sudo -u www-data php artisan migrate

以下のエラーが見つかりました。

SQLSTATE[42S01]: Base table or view already exists: 1050 Table 'accessories_checkout' already exists

対処を行います。

対処

MySQLでの対処

  • MySQLログイン
mysql -u snipeit -p snipeit
  • DB切り替え
USE SNIPEIT;
  • テーブル確認
SELECT * FROM migrations WHERE migration = '2024_07_26_143301_add_checkout_for_all_types_to_accessories';

→ 結果: Empty Set このため、これが記録されていないことが分かりました。

  • 該当テーブルの構造確認
DESCRIBE accessories_checkout;

→ テーブルが既に存在しています。

このことで、マイグレーションをスキップして対応することにしました。

  • マイグレーションスキップ
INSERT INTO migrations (migration, batch) VALUES ('2024_07_26_143301_add_checkout_for_all_types_to_accessories', 1);
  • MySQLログアウト
exit

phpでの対応

  • snipe-itのルートディレクトリ確認
cd /home/www-data/snipe-it && pwd

/home/www-data/snipe-itを確認

  • 改めてのDBマイグレーション
sudo -u www-data php artisan migrate
  • マイグレーション結果
2024_08_06_175114_add_shortcuts_enabled_to_settings_table ......................................................... DONE
2024_08_07_204014_add_play_sounds_to_profile ..................................................................... DONE
2024_08_15_111816_add_confetti_to_users .......................................................................... DONE
2024_08_16_104137_add_due_checkin_days_to_settings ............................................................... DONE

今度はマイグレーションが通ったことを確認です。

  • 結果反映
sudo -u www-data php artisan config:clear
sudo -u www-data php artisan cache:clear
sudo -u www-data php artisan view:clear
  • Webサービス再起動
sudo systemctl restart apache2.service && echo $?

0と表示されれば正常に再起動しています。

対処完了確認

ブラウザでsnipe-itにアクセスし、画像がアップロードされることが確認できたので、対処完了です。

MySQLのデータベースを暗号化してバックアップするスクリプト。

概要

以前も作成していた、MySQLのデータベースのバックアップを自動的に取得するスクリプトを少々リファインさせました。

変数指定により、複数のDBを任意にバックアップできます。

スクリプトの動き

  • サーバ内にあるDBのバックアップを取得し、暗号化して指定ディレクトリに保存します。
  • 複合化のパスワードはスクリプトが自動生成し、暗号化と同時に別ディレクトリに保存します。
  • cronの自動実行を前提としているため、古い暗号化ファイルと複合化のパスワードは一定期間後に削除を行います。

動作を確認したサーバ

  • Ubuntu 24.04
  • MySQL 8.0.39

前準備

アカウントファイル

任意のディレクトリに、db_account.txtといった、DBにユーザー名とパスワードを記したファイルを作成しておきます。

[client]
user = db_user
password = "password"
  • パーミッションは400にします。(chmod 400 db_account.txt)
  • 取り扱いは慎重に行ってください。

バックアップDBの格納先

  1. 冗長性があり
  2. 機密性が保たれる

場所を指定してください。筆者はクラウドストレージ(wasabi)をマウントしています。

パスワードの格納先

/home/hoge/dbrestore_password のように、複合化のパスワードを格納するディレクトリを作っておきます。
こちらも運用に合わせ、適切に保管ができる場所を指定します。

それぞれ、スクリプト実行アカウントがアクセス/実行できるものにします。

スクリプト

スクリプト内容

  • スクリプトファイル名(例)
    • mysql_db_backup.sh

変数などは間違いの無いように指定ください。

#!/bin/bash

## 変数ここから ##
# $HOMEの変数を指定します。
HOME_DIR="/home/hoge"
# SQLをバックアップするディレクトリ(保管先)を指定します。運用に合わせて指定ください。
backup_dir="/path/to/backup/directory"
# 保持するバックアップの世代を日数で指定します。
keep_days=7
# ファイルに付与する日付/作業ディレクトリ名/バックアップファイル名を指定します。
current_date=$(date +%Y%m%d)
backup_name="backup_mysql_${current_date}"
zip_file="backup_mysql.${current_date}.zip"
# アカウントファイルを指定します。運用に合わせて指定ください。
credentials_file="${HOME_DIR}/script/config/db_account/db_account.txt"
# パスワードを記録するファイル名を指定します。運用に併せてして指定ください。
password_dir="${HOME_DIR}/dbrestore_password"
password_file="${password_dir}/db-restore.${current_date}.txt"
# redmineのデータベース名を指定します。
database_name=database
# バックアップ時に指定するオプションを指定します。
options="--defaults-extra-file=$credentials_file --no-tablespaces --single-transaction"
# バックアップファイルのパターンを指定します。
backup_file_pattern="backup_mysql.*.zip"
# パスワードファイルのパターンを指定します。
password_file_pattern="*restore*.txt"
## 変数ここまで ##

## 処理ここから ##

# 1.アカウントファイルのパーミッションが400かどうかチェックします。
# 400以外は処理そのものを終了します。
permissions=$(stat -c "%a" "$credentials_file")
if [ "$permissions" != "400" ]; then
echo "アカウントファイルのパーミッションは400である必要があります。"
exit 1
fi

# 2.一時的なバックアップディレクトリを作成します。
mkdir "${backup_dir}/${backup_name}"

# 3. mysqldumpを実行してデータベースのバックアップを取ります。
mysqldump $options -h localhost $database_name > "${backup_dir}/${backup_name}/${backup_name}.sql"

# 4. パスワードによる暗号化を実施します。
password=$(openssl rand -base64 12)
cd "${backup_dir}/${backup_name}"
zip -r "${backup_dir}/${zip_file}" -P "$password" .
cd -

# 5. 一時的なバックアップディレクトリを削除します。
rm -rf "${backup_dir}/${backup_name}"

# 6. 解凍パスワードを指定ディレクトリに保存します。
echo $password > $password_file

# 7.パスワードの読み取り権限を600に変更します。
chmod 600 $password_file

# 8. 保持期間より古いバックアップファイルを削除します。
find "$backup_dir" -name "$backup_file_pattern" ! -type f -newermt "${keep_days} days ago" -delete
find "$password_dir" -name "$password_file_pattern" ! -type f -newermt "${keep_days} days ago" -delete

## 処理ここまで ##

作成後、

chmod +x mysql_db_backup.sh

で実行権を付与します。

スクリプトの動かし方

スクリプトの動き

./mysql_db_backup.sh

として実行すると、

  1. 変数で指定したアカウントファイルを読み込み、mysqldumpでバックアップを取ります。
  2. バックアップ作成後、パスワード付きzipファイルに圧縮します。
  3. 圧縮されたバックアップと複合化のためのテキストファイルを変数で指定したディレクトリに格納します。
  4. 変数で指定した期日が過ぎたバックアップファイルと複合化のためのテキストファイルは自動的に削除されます。

バックアップDBの解凍

unzip backup_mysql.yyyymmdd.zip

とすると、パスワードを尋ねられます。

db-restore.yyyymmdd.txtに表示された文字列を入力します。

または、

unzip -P $(cat /path/to/password_file.txt) /path/to/zip_file.zip -d /path/to/output_directory

でファイルを直接引数にして解凍することもできます。

cronの指定

動作を確認したら、

crontab -e -u hoge

でcron編集画面を出し、

0 2 * * * /home/hoge/script/directory/mysql_db_backup.sh

などとして指定すれば、日次のDBバックアップを取得可能です。

NextcloudのDB、照合順序を変更。

NextcloudのインストールでDBを作成す際に

CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

としていました。

運用中、より正確な比較やソートが必要という判断をしたのでDBの照合順序をci(Case Insentive)ではなく、bin(Binary)に変更します。

DBを操作するため、作業前後にメンテナンスモードに入るとともに、ユーザーへの周知は徹底して行ってください。

メンテナンスモードを実行

  • Nextcloudのルートディレクトリ移動
cd /var/www/html/nextcloud && pwd

自分の環境に合わせます。(筆者環境/home/www-data/nextcloud)

  • メンテナンスモード有効化
sudo -u www-data php occ maintenance:mode --on
  • メンテナンスモード確認

運用中のNextcloudのURLにアクセスし、メンテナンスモードであることを確認します。

mysqldumpでバックアップを取得する

  • 作業ディレクトリに移動
cd /hoge && pwd

任意のディレクトリを指定します。

  • DBバックアップ作成
mysqldump -h localhost -u nextcloud -p --no-tablespaces --single-transaction nextcloud > nextcloud_backup.$(date +%Y%m%d).sql

DB名やユーザーは自分の環境に合わせます。

  • DBバックアップ作成確認
ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあることを確認します。

DB設定変更

  • 管理者権限でMySQLにログインする
mysql -u root -p
  • 対象のDBを確認する
SHOW DATABASES;

nextcloudが動いているDBであることを再確認してください。

  • データベース全体の照合順序を変更する
ALTER DATABASE nextcloud COLLATE utf8mb4_bin;
  • 既存のデーテーブルの照合順序を変更する
USE nextcloud;
SET @DATABASE_NAME = 'nextcloud';

DB名は自分の環境に合わせます。

SET @COLLATE = 'utf8mb4_bin';
SELECT CONCAT('ALTER TABLE ', TABLE_NAME, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE ', @COLLATE, ';')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = @DATABASE_NAME
AND TABLE_TYPE = 'BASE TABLE';
  • MySQLから抜ける
EXIT

メンテナンスモードの解除を実行

  • Nextcloudのルートディレクトリ移動
cd /var/www/html/nextcloud && pwd

自分の環境に合わせます。(筆者環境/home/www-data/nextcloud)

  • メンテナンスモード無効化
sudo -u www-data php occ maintenance:mode --off
  • メンテナンスモード確認

運用中のNextcloudのURLにアクセスし、普通にアクセスできることを確認します。

切り戻し

何か不具合があった場合の切り戻し手順です。上記、メンテナンスモードを有効化してから行ってください。

  • バックアップしたDBがあることを再確認する
ls -l /hoge/nextcloud_backup.$(date +%Y%m%d).sql

バックアップを行ったディレクトリを指定します。

head -100 /hoge/nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあること、平文で読めることを確認します。

  • 管理者権限でMySQLにログインする
mysql -u root -p
  • 対象のDBを確認する
SHOW DATABASES;

nextcloudが動いているDBであることを再確認してください。

  • 不具合が発生したDBを削除する

二回ほど深呼吸して、落ち着いて作業しましょう。

DROP DATABASE nextcloud;
  • DBを再作成する
CREATE DATABASE IF NOT EXISTS nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
  • MySQLから抜ける
EXIT
  • DB復元

mysql -h localhost -u nextcloud -p nextcloud < /hoge/nextcloud_backup.$(date +%Y%m%d).sql

この後、メンテナンスモードを解除して、以前と同じ状態か確認します。

作業後:バックアップDBの削除

平文でSQLがサーバ上にあるのは危険な状態なので、以下の措置を執ります。

  • 作業ディレクトリに移動
cd /hoge && pwd

バックアップを行ったディレクトリを指定します。

  • DBバックアップ確認
ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルがあることを確認します。

  • バックアップしたDBの削除
rm nextcloud_backup.$(date +%Y%m%d).sql
  • DBバックアップ削除確認
ls -la nextcloud_backup.$(date +%Y%m%d).sql

ファイルが無いことを確認します。

アカウントファイルを用いたDBログインとバックアップ。

概要

バックアップスクリプトなどでMySQLにログインして処理を行う場合のTIPSです。

何かと使うのでメモに残します。

さっくりとした手順

  1. アカウントファイルを作ります。
  2. ログインできることを確認します。
  3. アカウントファイルを用いたコマンドでバックアップできることを確認します。

アカウントファイル作成

  • ディレクトリ作成
sudo mkdir -p /home/hoge/db_password

運用に合わせて指定ください。

cd /home/hoge/db_password && pwd

指定したディレクトリに移動します

  • アカウントファイル作成

以下の内容を教義・信仰に沿ったエディタで作成します。(【】内は取り除き、自分の設定に合わせます)

  • アカウントファイル内容
  • ファイル例:account.txt
[client]
user = 【RedmineのDBユーザ】
password = "【RedmineのDBユーザ用パスワード】"

password は""で囲みます。

  • アカウントファイルのパーミッション変更
chmod 400 account.txt
ls -l account.txt

パーミッションが400であることを確認します。

ファイルを用いてのログインを確認

mysql --defaults-extra-file=/path/to/directory/account.txt

--defaults-extra-file=は、アカウントファイルの絶対パスです。

ログインできることを確認します。

SHOW DATABASES;

アカウントの権限で指定されたDBの表示を確認します。

EXIT

MySQLから抜けます。

SQL Dumpの取得

  • SQL Dump
mysqldump --defaults-extra-file=/path/to/directory/account.txt --no-tablespaces -h [DBサーバ] [DB名] > backup.sql
  • --no-tablespacesはPROCESS特権がないユーザでもダンプできるようにするためです。
  • バックアップ先も必要に応じて絶対パスで指定できます。
  • ファイル確認
ls -l backup.sql

ファイルの内容にDBがあれば成功です。取り扱いには慎重を期してください。

Page 1 of 2

次

Powered by WordPress & Theme by Anders Norén