使用Linux控制Windows的機器的SQLServer數據庫自動恢復需要解決三個問題
1、Linux如何遠程訪問Windows服務器並遠程執行腳本
2、檢測主機是否存活
3、當某個數據庫處於使用之中時,如何強制SQLServer進行恢復
環境介紹:
一台 SQLServer服務器,安裝在Windows 2003上面,ip地址 192.168.0.22
一台 Linux服務器,作為控制台,ip 地址 192.168.0.68
1.1 安裝
Linux下的連接工具我們一般使用ssh,windows默認是不帶ssh服務端的。Linux不能直接ssh登錄windows主機,不過我們可以安裝一個openssh 的windows版本在Windows主機提供ssh服務。
OpenSSH的安裝配置比較麻煩,簡單的做法是使用已經打包好的copssh來安裝ssh服務端。copssh在下面的網址下載:http://sourceforge.Net/projects/sereds/files/copSSH/
我這裡使用的版本是Copssh_3.0.2,需要注意的是有的copssh版本可能工作得不是很好,使用ssh建立信任關系有可能失敗,安裝的時候建議多找幾個版本試一下。另外注意一點,
安裝Copssh_3.0.2還需要下載icwbase-2.0.3-patch-100.zip文件,不然退格鍵和方向鍵在終端上面無法顯示。
Copssh 的安裝很傻瓜的,直接next就可以安裝好.安裝完成後進入系統開始菜單,開始->所有程序->Copssh->01.
Activate a user,激活一個登錄用戶,也就是制定一個用戶可以ssh登錄。這裡我們我們激活administrator帳戶。
激活用戶後我們可以在Copssh 的安裝目錄下home目錄裡面找到以激活用戶administrator命名的文件夾。ssh 的公鑰文件就可以放在這個目錄下面
完成登錄後,客戶端看到的系統根目錄 / 在服務器端是Copssh的安裝目錄。可使用 mount 指令砹私Windows系統下目錄在Copssh模擬的Linux環境下的掛載情況:
$ mount
D:/Program Files/ICW/etc/terminfo on /usr/share/terminfo type vfat (binary,noacl)
D:/Program Files/ICW/bin on /usr/bin type vfat (binary,noacl)
D:/Program Files/ICW/lib on /usr/lib type vfat (binary,auto)
D:/Program Files/ICW on / type vfat (binary,noacl)
C: on /cygdrive/c type vfat (binary,posix=0,user,noumount,auto)
D: on /cygdrive/d type vfat (binary,posix=0,user,noumount,auto)
其中最下面的內容要注意,Windows系統下的各個分區掛載在 /cygdrive 下。訪問d盤,就進入/cygdrive/d目錄。
如果安裝過程中出現故障,無法繼續下去的話請進入D:/Program Files/ICW/執行卸載程序重新安裝,卸載完成後注意檢查Windows進程裡面是否有bash進程,如果存在請結束該進程。使用新版本的
Copssh已經支持中文了,在腳本裡面輸入漢字,服務端可以正常識別。
1.2配置
1.2.1 環境變量
在Linux主機上面我們執行 ssh [email protected],輸入administrator帳戶的密碼,應該可以登錄到Windows主機了。執行echo $PATH,執行結果如下圖
可以看到,Windows的環境變量裡面可執行文件路徑並不包括isql所在的目錄。遠程恢復數據庫需要使用isql執行相應的腳本才能操作,所以需要在ssh服務器上加入
isql所在的路徑。切換到 /etc目錄下,修改profile文件,在export PATH處,添加cygdrive/c/Program Files/Microsoft SQL Server/80/Tools/BINN路徑到PATH變量
然後重新使用SecureCRT登錄 ,輸出$PATH變量,看到isql 的路徑。執行isql -Usa -P123456可以得到命令行,
然後執行
>sp_who
>go
可以看到當前登錄的數據庫用戶。
1.2.2 ssh信任關系
為保證執行ssh 連接過程中不用輸入密碼,我們需要在Windows機器和linux機器之間建立信任關系。如Linux 的當前用戶為restoredb,那麼執行ssh-keygen -t dsa,一路回車,
將產生一個公鑰(pub文件)和一個私鑰,我們將/home/restoredb/.ssh/id_dsa.pub拷貝到192.168.0.22的D:/Program Files/ICW/home/Administrator/.ssh目錄下,打開命令行,切換到
.ssh目錄下,然後執行type id_dsa.pub>>authorized_keys,然後在192.168.0.68以restoredb用戶執行ssh [email protected]試試,如果不成功,很有可能是copssh
服務端有問題,需要換用其它版本的copssh服務端.
1.3 sql 字符集轉換
如果你在Linux下面用文本工具如sed等編輯了sql文件然後傳遞到Windows機器上,用isql工具執行,即便看起來語句正確,執行的時候也會莫名其妙地報一些錯。這是由於
Linux下面文字編碼和Windows下面的文件編碼不一致引起的。Linux下面默認的編碼是UTF-8而Windows平台下面默認的字符編碼是Windows-1252。所以Linux下面處理過的sql腳本
傳遞到服務端之前需要先做一下編碼轉換。
直接執行
cat restoredb.sql|iconv -fUTF8 -tWindows-1252 -o w_restoredb.sql
然後將w_restoredb.sql上傳到Windows機器上面就可以用isql正確執行了。
2.1 檢測主機是否存活
在進行文件傳遞或者遠程操作之前都需要檢查主機是否存活。平常檢測主機是否存活一般用ping 命令,
但是ping命令的檢查不涉及端口,所以即便ping是通的,也不能說明遠程主機的22號打開了。使用telnet命令進行檢測,
在主機存活的情況下,telnet命令的檢測時間尚可接受,在主機關閉或者網絡不可達時,使用telnet檢測就要了親命了,
慢得出奇。其實完全可以利用ssh 進行主機檢測,檢測時候注意帶上參數 -oConnectTimeout=2 -oServerAliveCountMax=5 -oServerAliveInterval=1
完整命令如下:
ssh -p22 -oStrictHostKeyChecking=no -oConnectTimeout=2 -oServerAliveCountMax=5 -oServerAliveInterval=1 [email protected] "exit;" 2>&1|grep ".*192.168.0.22.*out"|wc -l
這樣,當ssh連接不上主機192.168.0.22時,標准錯誤設備會打印出一樣字符“xxx192.168.0.22xxxtimeout”,因此,只要查詢命令的輸出結果裡面是否包含有
“xxx192.168.0.22xxxtimeout”字樣就可以斷定,目標主機無法連接。如果能夠連接上,那麼ssh將執行一條exit語句退出當前的ssh連接。
3.數據恢復
數據恢復可以直接使用sql命令完成
如 restore database esunnyjs from disk='D:\Progra~1\ICW\home\Administrator\esunny\esunnyjs' with replace,這條命令在獨占訪問esunnyJS數據庫時運行良好,
一旦還有其它用戶或者進程訪問該數據庫時,執行該語句將失敗,所以在進行數據庫恢復之前,需要kill 掉esunnyJS 數據庫的spid。這個操作可以編個存儲過程存在master庫
中,每次恢復之前先kill掉esunnyJS的相關進程。存儲過程的代碼如下
use master
go
if exists(SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'dbo' AND ROUTINE_NAME = 'killspid')
drop procedure killspid
go
Create procedure killspid (@dbname varchar(20)) as
begin
declare @sql nvarchar(500)
declare @spid int
set @sql='declare getspid cursor for select spid from sysprocesses where dbid=db_id('''+@dbname+''')'
exec (@sql)
open getspid
fetch next from getspid into @spid
while @@fetch_status <> -1
begin
exec('kill '+@spid)
fetch next from getspid into @spid
end
close getspid
deallocate getspid
end ;
go
將上述存儲過程刷入master 庫,然後每次導入數據都執行如下代碼
use master
go
exec killspid 'esunnyjy';
go
restore database esunnyjs from disk='D:\Progra~1\ICW\home\Administrator\esunny\esunnyJS' with replace
go
即可完成數據庫的恢復
根據上面思路,編寫shell控制腳本,然後在crontab中編寫定時策略就可以定時執行數據庫的恢復操作了。