บันทึก batch บ้าน ๆ จับวันคู่-คี่ เพื่อ restore จาก external backup 2 ตัว

ปูมหลังของการทดลองนี้ เกิดจากผมมี External Backup อยู่ 2 ที่ ซึ่งมันจะเก็บไฟล์สลับวันกัน ซึ่งในทางทฤษฏีแล้ว ต้องการให้มันเก็บแบบวันคู่ วันคี่ แต่ด้วยการตั้ง task schedule นั้น เราจะ Run ให้มันสลับกันเก็บคนละวัน แปลว่า มันก็ใช้วันคู่/วันคี่ ไม่ได้ เพราะเดือนไหนมี 31 วัน แปลว่า Backup ตัวนั้นต้องเก็บวันที่ 31 และเริ่มต้นอีกที วันที่ 2 ซึ่งข้อมูลตรงนี้ผมเพิ่งมาคิดได้ทีหลังจากการทดลองสร้าง batch แล้ว ซึ่งถ้าใช้งานจริง คงต้องปรับให้มันสลับกันวันเว้นวันแทน โดยใช้เงื่อนไขที่เป็น day of year แทน ซึ่งมาดูวิธีการที่ผมทำไว้ทีและ และสรุปปัญหาและอุปสรรค

Batch เงื่อนไขวันคู่-วันคี่

ตั้งค่าวัน YYYYMMDD เช่นวันนี้ คือ 20180124 จากนั้น %2 เพื่อหาเศษ ถ้ามันมีเศษแสดงว่าหารไม่ลงตัว สรุปได้เลยว่าเป็นวันคี่ SET /a Sets string to a numerical expression that is evaluated. จากนั้นเช็คด้วย IF ถ้าเป็น 0 หมายถึงวันคู่ ถ้าเป็น 1 จะหมายถึงวันคี่

SET YYYYMMDD=%date:~6,9%%date:~3,2%%date:~0,2%
SET /a odd=%YYYYMMDD%%%2

if %odd%==0 echo Today %date% is even
if %odd%==1 echo Today %date% is odd

กำหนด Path ของ Backup

เมื่อทราบเงื่อนไขแล้วว่าเป็นวันคี่หรือวันคู่ ก็มาจับกับ path ที่ backup เอาไว้

SET YYYYMMDD=%date:~6,9%%date:~3,2%%date:~0,2%
SET /a odd=%YYYYMMDD%%%2

IF %odd%==0 SET path=\\personalcloud1\backup
IF %odd%==1 SET path=\\personalcloud2\backup

ตรวจสอบไฟล์ล่าสุดที่ถูก backup ไว้

ด้วยการอ่าน path ที่ได้ด้วย DIR /B /O:D เรียงตามวันที่ และแสดงผลแค่ไฟล์ล่าสุด โดยมี filter *.bak ซึ่งตอนที่ทำลองใส่ findstr ไปแล้ว ไม่ประสบผลสำเร็จ

SET DatabaseBackupPath=\\personalcould1\backup

FOR /F "delims=|" %%I IN ('DIR "%DatabaseBackupPath%\*.bak" /B /O:D') DO SET NewestFile=%%I

ECHO %NewestFile%

จากนั้นเอา %NewestFile% ไปใช้งานได้เลย

batch file ตอนจบ

@ECHO OFF
SET dbname=YOURDATABASENAME

SET YYYYMMDD=%date:~6,9%%date:~3,2%%date:~0,2%
SET /a odd=%YYYYMMDD%%%2

IF %odd%==0 SET path=\\personalcloud1\backup
IF %odd%==1 SET path=\\personalcloud2\backup

rem check file exist before rename pattern dbname_YYYYMMDD.bak

IF EXIST %path%\%dbname%.bak (
    ECHO FILE: %path%\%dbname%.bak
    OSQL -E -Q "RESTORE DATABASE %dbname% FROM DISK = '%path%\%dbname%.bak' WITH REPLACE"
) ELSE (
    FOR /F "delims=|" %%I IN ('
        DIR /B /O:D "%path%\%dbname%_*.bak"
    ') DO SET latest=%%I

    ECHO FILE: %path%\%latest%
     OSQL -E -Q "RESTORE DATABASE %dbname% FROM DISK = '%path%\%latest%' WITH REPLACE"
)

ในที่นี้มี IF EXIST เพื่อเช็คว่าไฟล์ที่ backup นั้น ใช้ชื่อเดิมเดียวกับ database หรือป่าว หรือเปลี่ยนชื่อแล้ว ถ้ายังใช้ชื่อเดิม ก็ run คำสั่งต่อไปได้เลย แต่ถ้าไม่ ก็ไปหาว่าใน external backup มีไฟล์ใหม่หรือป่าว

สรุป

  • สิ่งที่ยังไม่ได้ทำ ก็คือ เช็ควันที่ของไฟล์ มันเป็นของเมื่อวานหรือป่าว เพราะถ้าเกิดว่า ไฟล์ที่ backup มาไม่สำเร็จ มันจะเป็นข้อมูลของเมื่อวานซืนทันที
  • ยังไม่ได้ แจ้งเตือน เมื่อ restore สำเร็จแล้ว
  • ปัญหาที่เจอหลักๆ คือ ตัว Personal Cloud ของ Seagate มันค่อนข้างห่วยแตก เหมือนกล่องโง่ๆ ใบนึงที่เอามาแค่ฝากไฟล์เท่านั้น มันจะติดปัญหาเรื่อง permission ที่ยังหาทางแก้ไม่ได้
  • ลองสอบถามเรื่องการแก้ปัญหา access is denied ทางสมาชิกท่านหนึ่งกลุ่ม thaiadmin.org ให้ลองตั้งค่า workgroup เป็นชื่อเดียวกับ domain ที่ใช้ แต่…. Personal cloud ตัวที่ผมมีอยู่ มันไม่ support ด้าน Network
  • permission นี้จะเกิดขึ้นใน folder ที่เป็น root/user แต่กับ folder public สามารถใช้งานได้ปกติ แต่!! มันไม่ปลอดภัย