承前文:【自動備份 @ Linux -- Part I】
四、執行 ssh-agent 讓機器自動存取
ssh-agent 程式扮演的是守門員的角色,在需要的時侯,以安全的方式提供存取所需的安全金鑰。ssh-agent 啟動後將於背景執行,供其它 OpenSSH 應用程式 - 像是 ssh 與 scp 程式使用。這樣的作法可令 ssh 程式要求一個已經加密後的金鑰,而無須每次皆向使用者要求提供私密金鑰的安全 passphrase。
ssh-agent 執行時將產生以下輸出:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Listing 7. ssh-agent in action
[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;
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
我們可以利用 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 變數將 export 出來為可用狀態,你可以執行下面指令查看它們的值:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[offsite]$ echo $SSH_AUTH_SOCK
/tmp/ssh-XX7bhIwq/agent.14197
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(註:反引號字元 ` 指的是與鍵盤上的「 ~ 」同屬一個鍵的那個符號。)
$SSH_AUTH_SOCK ( SSH Authentication Socket 的縮寫 ) 指的是本地端 socket 的位置,這是應用程式用來與 ssh-agent 交談所用。為確保 SSH_AUTH_SOCK 與 SSH_AGENT_PID 變數要使用時皆已註冊過,請將 eval `ssh-agent` 這段語法加在你的 ~/.bash_profile 裡。
ssh-agent 於背景執行後,欲查看請使用 top 與 ps 命令。
到此,我們已經準備好透過 ssh-agent 分享 passphrase 了。接下來就是使用 ssh-add 這個程式,將我們的 passphrase 加入 (傳送) 給執行中的 ssh-agent 程式。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Listing 8. ssh-add for hassle-free login
[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,不會再被提示要求 passphrase 了:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[offsite]$ ssh accountname@server1.com
[server1]$ exit
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
若你有所懷疑,可以試試砍掉 ssh-agent 的程序,再連接一次 server1,這麼一來你就會發現 server1 會向你要私密金鑰的 passphrase 了:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[offsite]$ kill -9 $SSH_AGENT_PID
[offsite]$ ssh accountname@server1.com
Enter passphrase for key '/home/accountname/.ssh/id_dsa':
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
五、keychain 可以簡化金鑰的存取
至此我們已經學到數個 OpenSSH 程式 ( ssh, scp, ssh-agent 以及 ssh-add ),並新建/安裝完私密與公開金鑰,啟動安全、自動的登入程序了。你會發現在這有很多的步驟都只需要作過一次就可以,像是建立金鑰安裝它們、讓 ssh-agent 能透過 .bash_profile 裡的設定執行。
較不完美的就是 ssh-add 必須在我們每次簽入 offsite 的機器就執行一次,且 ssh-agent 無法立即與我們自動化備份所要用到的 cron 排程程序相容。 cron 程序無法與 ssh-agent 溝通的原因在於 cron job 乃以 cron 的子程序執行,但它不繼承 $SSH_AUTH_SOCK 這個 shell 變數。
幸好還有一個解決方案可以解決這裡 ssh-agent 與 ssh-add 的關連性問題,還能讓我們得以透過 cron 將所有必須的安全性備份的程序全部自動化。在 2001 年所推出的 OpenSSH key management,Daniel Robbins 將此 shell script 稱之為 keychain,此乃 ssh-add 與 ssh-agent 的前端程式,能簡化整個無須密碼介入的程序。keychain 經過時間的淬練,現由 Aron Griffis 進行維護,截至 2004 年 6 月 17 日,已釋出至 2.3.2-1 版。
keychain 看起來是一套有點大型的 shell script,不過一個好的 script 本來就應該含括很多的錯誤檢查、豐富的說明文件,以及完整的跨平台程式碼。
(註:你可以到【keychain】這個網站下載它。)
當你下載並安裝完 keychain 後,你會發現它非常容易上手。只要輕鬆登入每台機器,將下列兩行加進它們的 .bash_profile 裡:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
keychain id_dsa
. ~/.keychain/$HOSTNAME-sh
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
第一次登入回每一台機器時,keychain 都會向你要求 passphrase,不過它不會在接下來的每一次登入都跟你要 passphrase - 除非那台機器重新開機。更棒的是:cron 現在已經能夠使用 OpenSSH 的指令,讓你在不需要使用 passphrase 與機器互動的情況下,進行安全的遠端存取了。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Listing 9. Initializing keychain on each machine
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)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
六、將備份程序寫成 script
接下來的工作就是建立一些 shell script 了,用 script 來為你完成必要的備份作業。我們的目標是要完成 Server1 與 2 完整的資料庫備份。在本範例中,每台伺服器皆執行 MySQL 資料庫伺服器,而我們也將使用 mysqldump 命令列工具,將一些資料庫表單匯至 SQL 輸入檔。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Listing 10. The dbbackup.sh shell script for server 1
#!/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
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
在 server2 我們也置入類似的 script 備份站台資料庫裡的那些表單。每一個 script 皆須設定為可執行:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[server1]:$ chmod +x dbbackup.sh
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
完成後 server1 與 2 上的 dbbackup.sh 檔後,回到 offsite date server,我們將在那裡建立呼叫遠端 dbbackup.sh script 的 shell script,以便開始進行壓縮檔資料檔 (.tgz) 的傳輸。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Listing 11. backup_remote_servers.sh shell script for use on the offsite data server
#!/bin/sh
# use ssh to remotely execute the dbbackup.sh script on server 1
/usr/bin/ssh backup_agent@server1.com "/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 backup_agent@server1.com:/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 backup_agent@server2.com "/home/backup_agent/dbbackup.sh"
# use scp to transfer transdb.tgz to offsite server.
/usr/bin/scp backup_agent@server2.com:/home/backup_agent/transdb.tgz
/home/backups/transdb-$(date +%Y%m%d-%H%M%S).tgz
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
backup_remote_servers.sh 使用 ssh 命令執行遠端伺服器裡的 script。由於我們建立了無須密碼的存取方式,ssh 便能夠從 offsite server 上,要求 server1 與 2 執行命令。整個身份認可的程序現已完全自動化,感謝有 keychain !
七、排程
最後的工作就是呼叫排程工作執行 offsite 資料儲存伺服器上的 backup_remote_servers.sh shell script 了。我們會加兩項到 cron 排程伺服器,要求它在每天 3:34 am 以及 8:34 pm 的時侯執行備份 script。於 offsite 伺服器上呼叫 crontab 程式編輯選項:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
[offsite]:$ crontab -e
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
crontab 會呼叫預設的編輯程式 - 這在 VISUAL 或 EDITOR 的環境變數裡已指定。接下來加入這兩行後即可關閉檔案。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Listing 12. Crontab entries on the offsite server
34 3 * * * /home/backups/remote_db_backup.sh
34 20 * * * /home/backups/remote_db_backup.sh
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
crontab 的設定行列可分為兩個段落:時間區段,接著是命令區段。時間區段的各個欄位皆有其意義,用以指定何時執行命令區段裡的指令:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Listing 13. Crontab format
+---- 分鐘
| +----- 時
| | +------ 日
| | | +------ 月
| | | | +---- 週
| | | | | +-- 執行之命令
| | | | | |
34 3 * * * /home/backups/remote_db_backup.sh
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
八、確認備份的動作
你應該養成定期檢查備份的習慣,以確保程序確切運作。自動化的程序可省去日常單調沉悶的一些工作,但也別因此偷懶 !
也可以考慮加一條 cron job 提醒你自已至少一個月檢查一次備份的資料。除此之外,也建議你每隔一段時間就變更你的安全性金鑰,同樣地,你也可以設定 cron job 提醒你作這件事。
九、其它的安全性注意事項
為了更安全,建議你在每台機器上安裝入侵偵測系統 Intrusion Detection System (IDS),例如 Snort。它可以提醒你是否機器發生被入侵的情況。
原文參考:【Automate backups on】
如有版權問題,請來信 (nicaliu at gmail dot com) 告知,謝謝。