なんだかんだ苦労した。スーパーユーザー権限ないしね。
バックアップ
.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 ==="
fiwadax_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 をみて確認すること。