Script สำหรับ Backup ข้อมูล ย้อนหลัง 7 วัน

อันนี้เป็น Script สำหรับ Backup ข้อมูลผ่าน rsync โดย Backup ย้อนหลัง 7 วัน (สามารถปรับได้)

สิ่งที่ต้องเตรียมก่อนใช้

  1. Linux/Unix Only
  2. ติดตั้ง rsync
  3. เครื่อง Backup ต้องสามารถ SSH Without Password เข้าเครื่องเป้าหมายได้ (ลองอ่านอันนี้ หรืออันนี้ดูครับ)
  4. เครื่อง Backup ต้องติดตั้ง PHP (ไม่จำเป็นต้องมี Apache)
  5. เครื่องเป้าหมายควรมี MySQL Tools (พวก mysqldump เป็นต้น) ในกรณ๊ต้องการสำรองข้อมูลจาก MySQL

Script ที่ใช้

<?php
chdir(__DIR__);

$SOURCE_HOST = '[email protected]';
$SOURCE_PATH = '/home/user/';

$MYSQL_USERNAME = "DATABASE_USERNAME";
$MYSQL_PASSWORD = "DATABASE_PASSWORD";

$dateFormat = 'Ymd';

$before = date($dateFormat,strtotime('yesterday'));
$dateKey = date($dateFormat);
$delDate = date($dateFormat,strtotime('-7 days'));

$excludeDirs = [
	'cache1/*',
	'cache2/*',
];

system("ssh {$SOURCE_HOST} \"mysqlcheck --all-databases -u{$MYSQL_USERNAME} -p{$MYSQL_PASSWORD} -r\"");
system("ssh {$SOURCE_HOST} \"mysqldump -u {$MYSQL_USERNAME} -p{$MYSQL_PASSWORD} --lock-tables=false --all-databases  | gzip --rsyncable -f -c - > {$SOURCE_PATH}/backupdb/backup.sql.gz\"");

system("cp -al {$before} {$dateKey}");

$excludeStr = '';
foreach($excludeDirs as $dir){
        $excludeStr .= " --exclude '{$dir}'";
}

system("rsync -a --delete {$excludeStr} {$SOURCE_HOST}:{$SOURCE_PATH} {$dateKey}/");

if(!empty($delDate)){
system("rm -rf ./{$delDate}");
}

echo "COMPLETE";

อธิบายคำสั่ง

บรรทัดที่ 1 – 14 เป็นการตั้งค่าเครื่องเป้าหมาย ว่าจะ backup จาก host ใดและ path ใด ข้อมูลการเข้าถึง Database และจำนวนวันที่ backup ย้อนหลัง โดยสามารถตั้งวันที่ backup สูงสุดได้ในบรรทัดที่ 14

บรรทัดที่ 16-19 เป็นการตั้งค่าว่าจะไม่ backup file ใด้บ้าง เช่นพวก cache เราอาจจะไม่ backup เป็นต้น

บรรทัดที่ 21-22 เป็นการสั่ง backup ฐานข้อมูล ให้ออกมาเป็น file.sql

บรรทัดที่ 24 เป็นการสั่งคัดลอก folder เมื่อวาน แบบ Hardlink มาเป็นโฟลเดอร์วันที่ปัจจุบัน โดยการทำ Hardlink จะช่วยประหยักเนื้อที่ได้มากในกรณีที่ไม่เปลี่ยนแปลง เช่นถ้าเราสั่งคัดลอก a.zip ขนาด 1GB ไปเป็น b.zip แบบ Hardlink ขนาดที่จะถูกใช้บน Harddisk จะถูกใช้แค่ 1GB เท่านั้น ไม่ใช่ 2GB แบบปกติ เพราะไฟล์เก็บที่เดียวกัน (อ่านเพิ่มเติมได้ที่นี่)

บรรทัดที่ 26-29 เป็นการสร้าง exclude parameter หรือก็คือเอา บรรทัด 16-19 มาแปลงให้ rsync เข้าใจได้

บรรทัดที่ 31 เป็นการสั่ง rsync จากต้นฉบับมาโฟลเดอร์ปัจจุบัน โดยจะดึงเฉพาะไฟล์ที่มีการเปลี่ยนแปลงหลังจากเมื่อวานเท่านั้น ทำให้ Backup ได้อย่างรวดเร็ว

บรรทัดที่ 33-35 คือสั่งให้ลบโฟลเดอร์ backup ที่เกิน 7 วันทิ้ง

คำแนะนำอื่นๆ

อย่าใช้ script นี้ผ่าน http เพราะมันจะ timeout ให้ตั้ง cronjob เป็นประมาณ php backup.php

ในกรณที่ MySQL เราใช้แต่ InnoDB และไม่มี MyISAM สามารถเอาบรรทัดที่ 21 ออกได้ (บรรทัด mysqlcheck) เพราะ check ไปก็ทำไรไม่ได้ InnoDB ไม่ Support

ในบรรทัดที่ 22 เราจะเห็นว่ามี –lock-tables=false ซึ่งหมายถึงเราจะไม่ lock table ในการเขียน ซึ่งทำให้เว็บสามารถทำงานได้ปกติตอน dump ข้อมูลออก แต่ข้อมูลที่ได้อาจจะไม่ตรงกัน เช่น table a ถึก dump เสร็จแล้ว ในระหว่างที่ dump table b ออกมา มีการเขียนที่ table a และ c ซึ่ง table c ต้องใช้ข้อมูลจาก table a แบบนี้จตะเกิดปัญหาได้ เพราะ table c ที่ถูก dump มีข้อมูลบางอย่างที่ต้องพึ่ง table a แต่ตอน dump table a ตัว table a ยังไม่มีข้อมูลนั้น ทางแก้มี 2 แบบ

  1. ตั้ง –lock-tables=true
  2. ในกรณีที่มีแต่ InnoDB ให้ใช้ –single-transaction แทน