歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

在Linux上進行自動備份:輕松進行自主、安全、分布式網絡備份

重要數據的丟失可能意味著致命的破壞。盡管如此,還是有無數專業人員忽視了對他們的數據的備份。雖然原因可能各不相同,但是,最常見的一個解釋是,執行例行備份確實煩瑣。由於機器擅長於完成普通而重復的任務,因此,自動化備份的過程是降低工作內在的枯燥性和人們與生俱來的拖延傾向的關鍵所在。

如果您使用 Linux,那麼您就已經可以使用那些創建定制備份解決方案的極其強大的工具。本文中的方案,可以讓您使用幾乎每個 Linux 發行版本都附帶的開放源代碼工具來執行從簡單的到更高級而且安全的網絡備份。

簡單備份

本文按照一步一步的方法來進行講述,只要您遵循那些基本的步驟,此方法會是非常直觀的。

在研究更高級的分布式備份解決方案之前,讓我們首先來看一個簡單而強大的存檔機制。讓我們來分析一個名為 arc 的方便的腳本,它可以讓我們在 Linux shell 提示符中創建備份快照。

清單 1. arc shell 腳本

  #!/bin/sh
  tar czvf $1.$(date +%Y%m%d%-H%M%S).tgz $1
  exit $?

arc 腳本接收一個單獨的文件或目錄名作為參數,創建一個壓縮的存檔文件,同時將當前日期嵌入到生成的存檔文件的名字之中。例如,如果您有一個名為 beoserver 的目錄,您可以調用 arc 腳本,將 beoserver 目錄名傳遞給它以創建一個壓縮的存檔文件,如: beoserver.20040321-014844.tgz

使用 date 命令是為了嵌入一個日期和時間戳以幫助您組織存檔文件。日期的格式是年、月、日、小時、分、秒 —— 雖然秒域的使用有一些多余。查看 data 命令的手冊( man date )來了解其他選項。另外,在清單 1 中,我們向 tar 傳遞了 -v (verbose)選項。這就使得 tar 顯示出它正在存檔的文件。如果您喜歡靜默地進行備份,那麼刪除這個 -v 選項。

清單 2. 存檔 beoserver 目錄

  $ ls
  arc beoserver
  $ ./arc beoserver
  beoserver/
  beoserver/bookl.dat
  beoserver/beoserver_ab_off
  beoserver/beoserver_ab_on
  $ ls
  arc beoserver beoserver.20040321-014844.tgz

高級備份

這個簡單備份是實用的;不過,它仍然包含一個人工備份的過程。行業最佳經驗通常建議將數據備份到多個媒體上,並備份到分開的不同地理位置。中心思想是避免依賴於任何一個單獨的存儲媒體或單獨的位置。

在下一個例子中我們將應對這一挑戰,我們將分析一個如圖 1 所示的假想的分布式網絡,它展示了對兩台遠程服務器和一台離線存儲服務器的系統管理。

圖 1. 分布式網絡

服務器 #1 和 #2 上的備份文件將安全地傳輸到離線存儲服務器上,而且整個分布式備份過程將在沒有人工干涉的情況下定期進行。我們將使用一組標准的工具(開放安全 shell 工具套件(OpenSSH)的一部分),以及磁帶存檔器(tar)和 cron 任務調度服務。我們的全部計劃是,使用 cron 進行調度,使用 shell 程序和 tar 應用程序完成備份過程,使用 OpenSSH 安全 shell(ssh)加密進行遠程訪問、認證、安全 shell 拷貝(scp)以自動完成文件傳輸。要獲得另外的資料請務必查看每個工具的手冊。

使用公鑰/私鑰進行安全的遠程訪問

在數字安全的上下文中,密鑰(key)指的是用來加密或解密其他數據片斷的一個數據片斷。公鑰私鑰模式的有趣之處在於,使用公鑰加密的數據,只有用相應的私鑰才可以解密。您可以自由地發布一個公鑰,這樣別人就可以對發送給您的消息進行加密。公鑰/私鑰模式徹底改變了數字安全的原因之一是,發送者和接收者不必再共享一個通用的密碼。除了其他方面的貢獻,公鑰/私鑰加密使用電子商務和其他安全傳輸成為可能。在本文中,我們將創建並使用公鑰和私鑰來創建一個非常安全的分布式備份解決方案。

要進行備份過程的每台機器都必須運行 OpenSSH 安全 shell 服務(sshd),同時讓 22 端口可以通過任何內部防火牆被訪問。如果您訪問遠程的服務器,那麼很有可能您正在使用安全 shell。

我們的目標將是,不需要人工提供密碼就可以安全地訪問機器。一些人認為最簡單的辦法是設置無密碼的訪問:不要這樣做。這樣做不安全。不用那樣,本文中我們將使用的方法可能會占用您大約一個小時的時間,建立起一個與使用“無密碼”帳號同樣方便的系統 —— 不過它是公認非常安全的。

讓我們首先確保 OpenSSH 已經安裝,接下來查看它的版本號。完成本文時,最新的發行的 OpenSSH 是 2004 年 2 月 24 日發布的版本 3.8。您應該考慮使用一個較新的而且穩定的發布版本,至少所用的版本應該要比版本 2.x 新。訪問 OpenSSH Security 網頁以獲得關於特定舊版本的缺陷的細節(請參閱本文後面的 參考資料 中的鏈接)。到目前為止,OpenSSH 是非常穩定的,而且已經證明不存在其他 SSH 工具所報告的很多缺陷。

在 shell 提示符中,輸入 ssh 並給出重要的 V 選項來檢查版本號:

$ ssh -V

OpenSSH_3.5p1, SSH protocols 1.5/2.0, OpenSSL 0x0090701f

如果 ssh 返回的版本號大於 2.x,則機器處於相對良好的狀態。無論如何,建議您所有的軟件都使用最新的穩定版本,這對於安全相關的軟件來說尤其重要。

我們的第一個步驟是,使用將會有特權訪問服務器 1 和 2 的帳號登錄到離線存儲服務器機器(見圖 1)。

$ ssh [email protected]

登錄到離線存儲服務器以後,使用 ssh-keygen 程序並給出 -t dsa 選項來創建一個公鑰/密鑰對。 -t 選項是必須的,用來指定我們要生成的密鑰類型。我們將使用數字簽名算法(Digital Signature Algorithm,DSA),它讓我們可以使用更新的 SSH2 協議。參閱 ssh-keygen 手冊以獲得更多細節。

在 ssh-keygen 執行的過程中,在詢問您口令(passphrase)之前,將提示您輸入 ssh 密鑰存儲的位置。當詢問在何處存儲密鑰時只需要按下回車鍵,然後 ssh-keygen 程序將創建一個名為 .ssh 的隱藏目錄(如果原來不存在),以及兩個文件,一個公鑰文件和一個私鑰文件。

ssh-keygen 的一個有趣特性是,當提示輸入一個口令時,它讓您可以只是簡單地按下回車鍵。如果您沒有給出口令,那麼 ssh-keygen 將生成沒有加密的密鑰!如您所想,這不是個好主意。當要求輸入口令時,確保輸入一個足夠長的字符消息,最好包含混合字符而不僅僅是一個簡單的密碼字符串。

清單 3. 永遠選擇好的口令

  [offsite]:$ ssh-keygen -t dsa
  Generating public/private dsa key pair.
  Enter file in which to save the key (/home/accountname/.ssh/id_dsa):
  Enter passphrase (empty for no passphrase): (enter passphrase)
  Enter same passphrase again: (enter passphrase)
  Your identification has been saved in /home/accountname/.ssh/id_dsa.
  Your public key has been saved in /home/accountname/.ssh/id_dsa.pub.
  The key fingerprint is:
  7e:5e:b2:f2:d4:54:58:6a:fa:6b:52:9c:da:a8:53:1b accountname@offsite

由於 ssh-keygen 生成的 .ssh 目錄是一個隱藏的“dot”目錄,所以要給 ls 命令傳入一個 -a 選項來查看新創建的目錄:

[offsite]$ ls -a

. .. .bash_logout .bash_profile .bashrc .emacs .gtkrc .ssh

進入隱藏的 .ssh 目錄並列出其內容:

[offsite]$ cd .ssh

[offsite]$ ls -lrt

id_dsa id_dsa.pub

現在,在隱藏的 .ssh 目錄中,我們已經擁有了一個私鑰(id_dsa)和一個公鑰(id_dsa.pub)。您可以使用 vi 或 emacs 等文本編輯工具或者簡單地使用 less 或 cat 命令來分析每個密鑰文件的內容。您將看到由混合字符構成的內容已經經過了 base64 編碼。

然後,我們需要將公鑰拷貝並安裝到服務器 1 和 2 上。不要使用 ftp。更合理的是,使用安全拷貝程序來將公鑰傳送到每一台遠程機器上。

清單 4. 將公鑰安裝到遠程服務器上

  [offsite]$ scp .ssh/id_dsa.pub [email protected]:offsite.pub
  [email protected]'s password: (enter password, not new
  passphrase!)
  id_dsa.pub 100% |*****************************| 614 00:00
  [offsite]$ scp .ssh/id_dsa.pub [email protected]:offsite.pub
  [email protected]'s password: (enter password, not new
  passphrase!)
  id_dsa.pub 100% |*****************************| 614 00:00

在安裝完新的公鑰後,我們就可以使用創建私鑰和公鑰時指定的口令來登錄到每一台機器。現在,登錄到每台機器,並將 offsite.pub 文件的內容附加到一個名為 authorized_keys 的文件中,這個文件存儲在每台遠程機器的 .ssh 目錄下。我們可以使用一個文本編輯器或者簡單地使用 cat 命令來將 offsite.pub 文件的內容附加到 authorized_keys 文件:

清單 5. 將 offsite.pub 添加到已授權密鑰列表

  [offsite]$ ssh [email protected]
  [email protected]'s password: (enter password, not new
  passphrase!)
  [server1]$ cat offsite.pub >> ./ssh/authorized_keys

接下來的步驟是考慮一些額外的安全性。首先,我們修改 .ssh 的訪問權限,以使得只有所有者有讀、寫和執行的權限。然後,我們確保 authorized_keys 文件只能由所有者來訪問。最後,將先前上傳的 offsite.pub 密鑰文件刪除,因為再也不需要它了。確保設置適當的訪問權限很重要,因為 OpenSSH 服務器可能會拒絕使用具有不安全訪問權限的密鑰。

清單 6. 使用 chmod 修改權限

  [server1]$ chmod 700 .ssh
  [server1]$ chmod 600 ./ssh/authorized_keys
  [server1]$ rm offsite.pub
  [server1]$ exit

在服務器 2 上完成同樣的步驟後,我們就可以返回到離線存儲機器上來測試新的口令類型的訪問。在離線服務器上您可以輸入下面的內容:

[offsite]$ ssh -v [email protected]

在檢驗您的帳號現在可以使用新的口令而不是原來的密碼來訪問遠程的服務器時,使用 -v 或 verbose 標記選項來顯示調試信息。調試輸出除了能讓您在一個高的層面上觀察到認證過程是如何工作的之外,還可以顯示出您可以以其他方式無法得到的重要信息。在以後的連接中您可能並不需要指定 -v 標記;但是在測試連接時它相當有用。

使用 ssh-agent 自動化機器訪問

ssh-agent 程序如同一個看門人,它根據需要安全地提供對安全密鑰的訪問。ssh-agent 啟動後,它就會在後台運行,並且可以由 ssh 和 scp 程序等其他 OpenSSH 應用程序所使用。這就使得 ssh 程序可以請求一個已經解密了的密鑰,而不是在每次需要時向您詢問私鑰的安全口令。

讓我們來仔細研究一下 ssh -agent。ssh-agent 運行時它會輸出 shell 命令:

清單 7. ssh-agent 應用

  [offsite]$ ssh-agent
  SSH_AUTH_SOCK=/tmp/ssh-XX1O24LS/agent.14179; export SSH_AUTH_SOCK;
  SSH_AGENT_PID=14180; export SSH_AGENT_PID;
  echo Agent pid 14180;

我們可以使用 shell 的 eval 命令來讓 shell 執行 ssh-agent 顯示的輸出命令:

[offsite]$ eval `ssh-agent`

Agent pid 14198

eval 命令告訴 shell 去評價(執行)ssh-agent 程序生成的命令。確保您指定的是反引號(`)而不是單引號!執行後, eval `ssh-agent` 語句將返回代理的進程標識符。在幕後, SSH_AUTH_SOCK 和 SSH_AGENT_PID shell 變量已經被導出而可以使用。您可以將它們顯示在 shell 控制台中來查看它們的值:

[offsite]$ echo $SSH_AUTH_SOCK

/tmp/ssh-XX7bhIwq/agent.14197

$SSH_AUTH_SOCK (SSH Authentication Socket 的縮寫)是一個本地套接字的位置,應用程序可以通過它來與 ssh-agent 通信。將 eval `ssh-agent` 語句加入到您的 ~/.bash_profile 文件以確保 SSH_AUTH_SOCK 和 SSH_AGENT_PID 始終被注冊。

ssh-agent 現在就已經成為一個後台進程,可以用 top 和 ps 命令查看得到。

現在我們就已經可以使用 ssh-agent 共享我們的口令。為此,我們必須使用一個名為 ssh-add 的程序,這個程序將我們的口令添加(發送)到運行著的 ssh-agent 程序。

清單 8. 用於免口令登錄的 ssh-add

  [offsite]$ ssh-add
  Enter passphrase for /home/accountname/.ssh/id_dsa: (enter passphrase)
  Identity added: /home/accountname/.ssh/id_dsa
  (/home/accountname/.ssh/id_dsa)

現在,當我們訪問 server1 時,不會再被提示輸入口令:

[offsite]$ ssh [email protected]

[server1]$ exit

如果您還不相信,那麼嘗試去掉( kill -9 )ssh-agent 進程,然後重新連接 server1。這一次,您將注意到,server1 將會詢問存儲在 .ssh 目錄下 id_dsa 中的私鑰的口令:

[offsite]$ kill -9 $SSH_AGENT_PID

[offsite]$ ssh [email protected]

Enter passphrase for key '/home/accountname/.ssh/id_dsa':

使用 keychain 簡化密鑰訪問

到現在為止,我們已經了解了幾個 OpenSSH 程序(ssh、scp、ssh-agent 和 ssh-add),而且我們已經創建並安裝了私鑰和公鑰來啟用一個安全而且自動的登錄過程。您可能已經意識到,大部分設置工作只需要進行一次。例如,創建密鑰、安裝密鑰、通過 .bash_profile 執行 ssh-agent 的過程在每台機器只需要進行一次。那真是好消息。

不太理想的消息是,每次登錄離線服務器的時候都必須調用 ssh-add,而且,ssh-agent 與我們將要用來自動化備份工作的 cron 調度進程並不直接兼容。cron 進程不能與 ssh-agent 通信的原因是,cron 作業是作為 cron 的子進程來執行,這樣它們就不會繼承 $SSH_AUTH_SOCK。

幸運的是,有一個解決方案不僅消除了有關 ssh-agent 和 ssh-add 的限制,而且可以讓我們使用 cron 來自動進行各種需要對其他機器進行安全地無密碼訪問的過程。Daniel Robbins 於 2001 年在 developerWorks 發表了一個包含三部分的系列 OpenSSH key management(參閱 參考資料 中的鏈接),其中提供了一個稱為 keychain 的 shell 腳本。它是 ssh-add 和 ssh-agent 的前端,可以簡化整個無密碼過程。從那時起,這個 keychain 腳本經過了多次改進,現在由 Aron Griffis 維護,目前最新版本是 2004 年 6 月 17 日發布的 2.3.2-1 版本。

keychain shell 腳本太大了,本文不方便列出來,因為這個精心編寫的腳本中包括了很多錯誤檢測、豐富的文檔以及非常多的跨平台代碼。不過,keychain 可以從項目的 Web 站點上方便地下載得到(參見 參考資料 中的相關鏈接)。

在下載並安裝之後,keychain 腳本使用起來非常簡便。只需登錄每台機器並向 .bash_profile 文件添加下面兩行代碼:

keychain id_dsa

. ~/.keychain/$HOSTNAME-sh

在您第一次重新登錄到每台機器時,keychain 將要求您輸入密碼短語。不過,除非機器被重新啟動,否則,以後再登錄時,keychain 將不再要求您重新輸入密碼短語。最好的是,cron 任務現在可以使用 OpenSSH 命令來安全地訪問遠程計算機,而不需要交互地使用密碼短語。現在我們能夠同時獲得更好的安全性和易用性。

清單 9. 在每台計算機上初始化 keychain

KeyChain 2.3.2; http://www.gentoo.org/projects/keychain
Copyright 2002-2004 Gentoo Technologies, Inc.; Distributed under the
GPL
* Initializing /home/accountname/.keychain/localhost.localdomain-sh
file...
* Initializing /home/accountname/.keychain/localhost.localdomain-csh
file...
* Starting ssh-agent
* Adding 1 key(s)...
Enter passphrase for /home/accountname/.ssh/id_dsa: (enter passphrase)

腳本化備份過程

本文的下一個任務是創建 shell 腳本來執行必要的備份過程。它的目標是對服務器 #1 和 #2 進行完全的數據庫備份。在本文的示例中,各服務器都運行 MySQL 數據庫服務器,我們將使用 mysqldump 命令行實用工具將一些數據庫表導出到一個 SQL 導入文件中。

清單 10. 服務器 #1 的 dbbackup.sh shell 腳本

 #!/bin/sh
# change into the backup_agent directory where data files are stored.
cd /home/backup_agent
# use mysqldump utility to export the sites database tables
mysqldump -u sitedb -pG0oDP@sswrd --add-drop-table sitedb --tables
tbl_ccode tbl_machine tbl_session tbl_stats > userdb.sql
# compress and archive
tar czf userdb.tgz userdb.sql

在服務器 #2 上,我們將設置一個類似的腳本來備份站點數據庫中給出的獨有表單。每個腳本都通過下面的步驟標記為可執行:

[server1]:$ chmod +x dbbackup.sh

在服務器 #1 和 #2 上都有了 dbbackup.sh 文件之後,我們返回到離線數據服務器。在那裡,我們將創建一個 shell 腳本來調用各個遠程 dbbackup.sh 腳本,然後傳輸壓縮的(.tgz)數據文件。

清單 11. 離線數據服務器上使用的 shell 腳本 backup_remote_servers.s

#!/bin/sh
# use ssh to remotely execute the dbbackup.sh script on server 1
/usr/bin/ssh [email protected] "/home/backup_agent/dbbackup.sh"
# use scp to securely copy the newly archived userdb.tgz file
# from server 1. Note the use of the date command to timestamp
# the file on the offsite data server.
/usr/bin/scp [email protected]:/home/backup_agent/userdb.tgz
/home/backups/userdb-$(date +%Y%m%d-%H%M%S).tgz
# execute dbbackup.sh on server 2
/usr/bin/ssh [email protected] "/home/backup_agent/dbbackup.sh"
# use scp to transfer transdb.tgz to offsite server.
/usr/bin/scp [email protected]:/home/backup_agent/transdb.tgz
/home/backups/transdb-$(date +%Y%m%d-%H%M%S).tgz

shell 腳本 backup_remote_servers.sh 使用 ssh 命令執行遠程服務器上的腳本。因為我們已經設置了無密碼訪問,所以 ssh 命令能夠從離線服務器執行服務器 #1 和 #2 上的命令。現在,整個身份驗證過程都是自動的,這歸功於 keychain。

本文的下一個也是最後一個任務是,調度離線數據存儲服務器上的 shell 腳本 backup_remote_servers.sh 的執行。我們將給 cron 調度服務器添加兩個條目,以要求每天對腳本備份兩次,一次在凌晨 3:34,另一次在晚上 8:34。在離線服務器上使用編輯選項(-e)調用 crontab 程序。

[offsite]:$ crontab -e

crontab 調用默認編輯器。默認編輯器使用 shell 環境變量 VISUAL 或 EDITOR 來指定。下面鍵入兩個條目,保存並關閉該文件。

清單 12. 離線服務器上的 crontab 條目

34 3 * * * /home/backups/remote_db_backup.sh
34 20 * * * /home/backups/remote_db_backup.sh

一個 crontab 行包括兩個主要部分,即時間調度部分及其後接的命令部分。時間調度被劃分為字段,用於說明命令應該在何時執行:

清單 13. Crontab 格式

          +---- minute
| +----- hour
| | +------ day of the month
| | | +------ month
| | | | +---- day of the week
| | | | | +-- command to execute
| | | | | |
34 3 * * * /home/backups/remote_db_backup.sh

檢驗您的備份

應該對備份進行例行檢查,以保證備份過程工作正常。自動備份過程能夠去除不必要的枯燥工作,但是不應因此而變得懶惰。如果數據值得備份,那麼它也值得您時常進行抽樣檢查。

考慮添加 cron 作業來提醒自己每月至少檢查一次備份。此外,每隔一段時間修改一次安全密鑰也是個好主意,也可以調度一個 cron 作業來提醒自己及時更改安全密鑰。

額外的安全措施

為了加強安全,可以考慮在所有機器上安裝和配置入侵檢測系統(IDS),例如 Snort。當入侵正在發生或者最近曾發生過,IDS 將會通知用戶。使用 IDS,還能夠添加其他級別的安全性,例如對備份進行數字簽名和加密。

流行的開源工具(比如 GNU Privacy Guard (GnuPG)、OpenSSL 和 ncrypt)都支持通過 shell 腳本保護歸檔文件,但是本文不建議在沒有 IDS 提供的額外防護級別的情況下這樣做(有關 Snort 的更多信息,請參閱 參考資料)。

結束語

本文展示了如何在遠程服務器上執行腳本,以及如何進行安全和自動化的文件傳輸。我希望您能由此得到靈感而開始考慮保護您自己的重要數據,並使用 OpenSSH 和 Snort 等開放源代碼工具來構建新的解決方案。

Copyright © Linux教程網 All Rights Reserved