はじめに
先日、既存DBを壊さず「別名の一時DB」として複製する pg_dump / pg_restore の実践という記事を投稿しました。
この作業に際して、 pg_dump / pg_restore を実行した際に進捗を把握するためにnohup でバックグラウンド実行しつつ、ログで進捗を追い、完了・失敗を把握する方法が役に立ったので今後の備忘のため記事にしたいと思います。
想定環境: Linux / macOS のシェル(bash)。SSM やSSH経由でリモート端末に入って重い処理を流す場面を想定します。
テーマ・場面設定
大きなDBのダンプ/リストアには、次のような「あるある」があります。
- 実行中に SSHセッションが切れて処理ごとお亡くなりになってしまう
-
--verboseを付けてもあと何分で終わるのか分からない - ログにタイムスタンプがなく、どこで詰まったか後から追えない
これらを、nohup・tee・watch・行単位のタイムスタンプ付与で解決します。
1. nohup でセッション切断に強くする
nohup ... & でバックグラウンド実行し、標準出力・標準エラーをログファイルに落とします。sleep 1 && tail -f で、投入直後からログを追えます。
touch dump.log && nohup bash -c "
pg_dump -h 127.0.0.1 -p 15432 -U \$DB_USER -d \$SRC_DB \
-F c --verbose \
-f ./dump_\$(date +%Y%m%d).dump \
&& echo '=== DUMP完了: '\$(date)' ===' \
|| echo '=== DUMP失敗: '\$(date)' ==='
" > dump.log 2>&1 & sleep 1 && tail -f dump.log
ポイントは3つです。
-
nohup ... &で端末から切り離す。SSHが切れても処理は継続する -
&& echo '完了' || echo '失敗'で、** 処理が正常に終了したかどうかをログ末尾に明示的に記録**する -
> dump.log 2>&1で標準出力・標準エラーの両方を1ファイルに集約する
nohup bash -c "..." の中では、変数やコマンド置換をシェルにその場で展開させたくないものは \$DB_USER \$(date ...) のようにエスケープします。逆に、投入時点の値で固定したいものはエスケープしません。意図に応じて使い分けてください。
2. watch で「ファイルサイズ+ログ末尾」を同時監視する
進捗が本当に進んでいるかは、出力ファイルサイズが変化しているかを見るのが確実です。別ターミナルで watch を回します。
watch -n 5 'ls -lh ./ && echo "---" && tail -5 dump.log'
5秒ごとに、ダンプファイルのサイズとログ末尾5行が更新されます。ファイルサイズが伸びていれば処理は生きています。
余談ですが、VPNや混雑具合によりネットワーク状況が悪い場合は進捗が進まなく見える場合があります。そういう場合は一度ダンプを中断し、再度初めから実行したほうが結果的には早く終わることもありますね。
3. リストアは各行にタイムスタンプを刻む
pg_restore のログは行数が多く、後から「どのオブジェクトで時間を食ったか」を追いたくなります。while read で各行の先頭に時刻を付与し、tee で画面表示とファイル保存を同時に行います。
LOG=restore_$(date +%Y%m%d_%H%M%S).log && \
echo "=== 開始: $(date '+%Y-%m-%d %H:%M:%S') ===" | tee "$LOG" && \
pg_restore \
-h 127.0.0.1 -p 15432 -U "$DB_USER" -d "$TEMP_DB" \
--no-owner --no-acl --verbose \
./dump_$(date +%Y%m%d).dump \
2>&1 | while IFS= read -r line; do echo "$(date '+%H:%M:%S') $line"; done | tee -a "$LOG" && \
echo "=== 終了: $(date '+%Y-%m-%d %H:%M:%S') ===" | tee -a "$LOG"
得られる効果は次のとおりです。
- ログファイル名に実行時刻が入るので、複数回流しても上書きされない
-
=== 開始 ===/=== 終了 ===で全体の所要時間が一目で分かる - 各行の
HH:MM:SSで、どの処理に時間がかかったかを事後分析できる
出力イメージ:
=== 開始: 2026-09-29 19:55:00 ===
19:55:01 pg_restore: connecting to database for restore
19:55:03 pg_restore: creating TABLE "public.foo"
19:58:42 pg_restore: processing data for table "public.big_table"
=== 終了: 2026-09-29 20:10:12 ===
完了・失敗の判定
ログ末尾を見るだけで判定できます。
# 完了していれば末尾に完了行が出る
tail -3 dump.log
=== DUMP完了: Wed Sep 29 19:00:00 JST 2026 ===
まとめ
-
nohup ... &+ ログファイルで、SSH切断に強い長時間処理にする -
&& echo 完了 || echo 失敗で成否をログに明示し、判定を簡単にする - 別ターミナルの
watchでファイルサイズ+ログ末尾を監視し、処理が生きているか確認する -
while readで各行に時刻を刻み、teeで画面とファイルに同時出力する
pg_dump をテーマに記載しましたが、重いバッチや移行スクリプト全般に応用で切ると思います。
※筆者の小言:最近は生成AIがいい感じにスクリプトを作ってくれるので覚える必要性が減っていますが、ぱっとコマンドを見た際に何をやっているかわかるのはなんだかんだ大事だよなと思います
参考
- man nohup / GNU coreutils: https://www.gnu.org/software/coreutils/
- PostgreSQL 公式: pg_dump: https://www.postgresql.org/docs/current/app-pgdump.html