なんだかんだ苦労した。スーパーユーザー権限ないしね。
バックアップ
.pgpass
localhost:5432:DB名:ユーザー名:パスワード
wadax_backup.sh
/usr/bin/pg_dump -h localhost -p 5432 -U <ユーザー名> <DB名> > /var/www/vhosts/ドメイン/backup.dump
wadax_backup.php (これを呼び出してwadax_backup.shを動かす)
<?php $output = shell_exec("/usr/bin/sh /var/www/vhosts/ドメイン/wadax_backup.sh"); ?>
リストア
テーブルを根こそぎ削除してから復元する
事前準備
backup.dumpを古いサーバーからコピーしておくこと
.pgpass
localhost:5432:DB名:ユーザー名:パスワード
cleanup.sql
-- cleanup.sql (最初に読み込む) DO $$ DECLARE r RECORD; BEGIN -- Drop all foreign key constraints FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public') LOOP EXECUTE 'ALTER TABLE IF EXISTS ' || quote_ident(r.tablename) || ' DROP CONSTRAINT IF EXISTS ' || quote_ident(r.tablename) || '_pkey CASCADE'; END LOOP; -- Drop all tables FOR r IN (SELECT tablename FROM pg_tables WHERE schemaname = 'public') LOOP EXECUTE 'DROP TABLE IF EXISTS ' || quote_ident(r.tablename) || ' CASCADE'; END LOOP; -- Drop all sequences FOR r IN (SELECT relname FROM pg_class WHERE relkind = 'S') LOOP EXECUTE 'DROP SEQUENCE IF EXISTS ' || quote_ident(r.relname) || ' CASCADE'; END LOOP; -- Drop all functions FOR r IN ( SELECT routine_name, routine_schema FROM information_schema.routines WHERE routine_schema = 'public' ) LOOP EXECUTE 'DROP FUNCTION IF EXISTS ' || quote_ident(r.routine_name) || ' CASCADE'; END LOOP; END $$;
wadax_restore.sh
#!/bin/bash PG_HOST="localhost" PG_PORT="5432" PG_USER="ユーザー名" PG_DB="DB名" DUMP_FILE="/var/www/vhosts/ドメイン/backup.dump" CLEAN_FILE="/var/www/vhosts/ドメイン/cleanup.sql" LOG_FILE="/var/www/vhosts/ドメイン/pg_restore_logfile.log" echo "=== CLEANING EXISTING DB OBJECTS ===" psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" -f "$CLEAN_FILE" > /dev/null 2>&1 echo "=== RESTORING FROM DUMP FILE ===" psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d "$PG_DB" -f "$DUMP_FILE" > "$LOG_FILE" 2>&1 if [ $? -eq 0 ]; then echo "=== RESTORE COMPLETED SUCCESSFULLY ===" else echo "=== RESTORE FAILED. CHECK LOG: $LOG_FILE ===" fi
wadax_restore.php (wadax_restore.shを実行するもの。タイムアウト対策してる)
<?php $cmd = "/usr/bin/sh /var/www/vhosts/ドメイン/wadax_restore.sh"; $timeout = 600; // タイムアウト秒数 $descriptorspec = [ 0 => ["pipe", "r"], // stdin 1 => ["pipe", "w"], // stdout 2 => ["pipe", "w"], // stderr ]; // プロセス開始 $process = proc_open($cmd, $descriptorspec, $pipes); if (is_resource($process)) { // ノンブロッキング設定 stream_set_blocking($pipes[1], false); stream_set_blocking($pipes[2], false); $start = time(); $stdout = ''; $stderr = ''; while (true) { $status = proc_get_status($process); if (!$status['running']) { break; } // 出力を随時回収 $stdout .= stream_get_contents($pipes[1]); $stderr .= stream_get_contents($pipes[2]); if (time() - $start > $timeout) { proc_terminate($process); // ソフト終了 sleep(1); $status = proc_get_status($process); if ($status['running']) { proc_terminate($process, 9); // 強制終了 (SIGKILL) } $stderr .= "\n[Timeout after {$timeout} seconds]"; break; } usleep(100000); // 0.1秒待つ } // 終了後の残り出力を回収 $stdout .= stream_get_contents($pipes[1]); $stderr .= stream_get_contents($pipes[2]); fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); proc_close($process); // 出力をまとめる $output = "=== STDOUT ===\n" . $stdout . "\n=== STDERR ===\n" . $stderr; echo nl2br(htmlspecialchars($output)); // HTML用表示(必要な場合) } else { echo "Failed to start process.\n"; } ?>
なにかあったら pg_restore_logfile.log をみて確認すること。