自動備份在每個月的第一個工作日(不包含週六及週日)

舊文章:
定期自動備份伺服器資料(前篇)
伺服器-rsync 異地備援(後篇)
定期自動備份伺服器資料(前篇)

為了備份網頁伺服器的資料(含資料庫),當時在crontab設定每個月的1號早上6點備份到NAS,但執行一段時間後發現了2個問題。
  1. NAS週末關機,如果1號剛好是週六或週日的早上6點,就會備份失敗。
  2. crontab原設定無法辨每個月的1號是不是週六或週日,如以下範例,2013年9月1日剛好就是星期日
  3. 0 6 1 * * /root/mysql-backup.sh

解決方法就是改寫crontab,讓系統在每個月第一個工作日(不包含週六或週日)執行備份。


方法一


以下寫法的意思為第一週(1日~7日)的星期一執行備份看起來好像是對的,但day of month和day of week是OR邏輯概念,也就是1日~7日都會執行之外,每週一還會再執行1次,所以這個方法就沒必要再研究下去。

0 6 1-7 * 1 /root/mysql-backup.sh
# man 5 crontab
Note:
The day of a command’s execution can be specified by two fields —
day of month, and day of week. If both fields are restricted (ie, aren’t *),
the command will be run when either field matches the current time.

For example, "30 4 1,15 * 5" would cause a command to be run at 4:30 am on the 1st and 15th of each month, plus every Friday.


方法二:正解


第一個工作日在排除週六與週日後,會隨機的落在週一至週五,而且不一定是每個月的1號(由前圖可以2013年8月的第一個工作日為8月1日週四,2013年8月的第一個工作日為9月2日週一,2013年10月的第一個工作日為10月1日週二)。

如何取出每個月的第一個工作日,並設定在crontab內?以2013年9月為範例。
  1. 使用cal指令列出當月行事曆,並且使用awk指令抓出行事曆行數(NR)及各行總欄位數(NF),NR及NF會做為判斷式的值。
  2. # cal -m   //參數m:Display Monday as the first day of the week.
    # cal -m | awk '{print $0 "\t NR:" NR "\t NF:" NF}   //可得知目前行事曆有8行(NR),每行最多7個欄位數(NF)。


  3. 取出9月份行事曆中3天以上的週數:取3天的意義為,若有2天為週六及週日,那剩下的必為週五或週一。
  4. # cal -m | awk '{if(NF>=3)print $0}' | grep '[0-9]'

  5. 取出9月份第一個工作日為9月2日。
  6. # cal -m | awk '{if(NF>=3)print $1}' | grep '[0-9]'| head -n 1

  7. 修正crontab後,記得要重啟crond服務。
  8. # crontab -e
      0 6 1,2,3 * * [ `/bin/date +\%d` -eq `cal -m | awk '{if(NF>=3)print $1}' | grep '[0-9]' | head -n 1` ] && /bin/sh /root//mysql-backup.sh  //&&的意思為,若前面的條件成立則執行後面的指令
    # service crond stop
    # service crond start

  9. 從此以後備份的工作都在每個月的第一個工作日,修正了週末備份失敗的問題。

沒有留言:

張貼留言