許麗光 翁花群 曾福山
摘要:設(shè)計(jì)一個(gè)基于Delphi編譯環(huán)境的定時(shí)重啟特定服務(wù)的程序,并經(jīng)實(shí)際應(yīng)用環(huán)境反復(fù)實(shí)驗(yàn)測(cè)試,證實(shí)能夠很好地解決由于Tomcat運(yùn)行環(huán)境異常錯(cuò)誤大量累積后,造成內(nèi)存致命錯(cuò)誤,無(wú)法提供正常訪問(wèn)服務(wù)等諸如此類問(wèn)題。
關(guān)鍵詞:Delphi編譯;Apache服務(wù);Tomcat;內(nèi)存溢出錯(cuò)誤;批處理命令
中圖分類號(hào):TP319 文獻(xiàn)標(biāo)識(shí)碼:A
文章編號(hào):1009-3044(2019)12-0284-03
開放科學(xué)(資源服務(wù))標(biāo)識(shí)碼(OSID):
Delphi-based Design and Implementation of Scheduled Service-Restarting Program
XU Li-guang, WENG Hua-qun, ZENG Fu-shan
(Informatization Construction and Management Center, Putian University, Putian 351100, China)
Abstract: A Delphi-based scheduled service-restarting program has been designed and repeatedly tested in the actual application environment, which proves that it can solve such problems as failure to get access to services due to fatal memory error resulting from large accumulation of abnormal errors in the Tomcat runtime environment.
Key words: Delphi compilation; Apache service; Tomcat; Out-Of-Memory Error; batch command
1 背景
在日常信息化運(yùn)維工作中經(jīng)常遇到某個(gè)程序在運(yùn)行一段時(shí)間后出現(xiàn)異常,需要重啟服務(wù)。例如Tomcat運(yùn)行環(huán)境在運(yùn)行一段時(shí)間后,由于大量用戶同時(shí)訪問(wèn)Apache服務(wù)器而對(duì)服務(wù)器內(nèi)存的影響,異常錯(cuò)誤大量累積后,造成內(nèi)存致命錯(cuò)誤,出現(xiàn)“OutOfMemoryError”提示,導(dǎo)致Apache服務(wù)異常,無(wú)法提供正常訪問(wèn)服務(wù)。此時(shí),往往需要重啟Apache服務(wù),重新初始化Tomcat運(yùn)行環(huán)境,以使Apache服務(wù)恢復(fù)正常。在這種情況下,如果手動(dòng)進(jìn)行相關(guān)服務(wù)重啟操作,對(duì)于信息化運(yùn)維工作人員而言,常常不勝其煩,很大程度上增加了信息化日常運(yùn)維工作量;而且由于異常情況的出現(xiàn)無(wú)法提前預(yù)知,錯(cuò)誤總是不定期出現(xiàn),運(yùn)維人員很難都做到及時(shí)處理,影響了工作效率和成效,如此反復(fù),給所服務(wù)的對(duì)象用戶帶來(lái)極差的服務(wù)體驗(yàn)。為了有效解決上述問(wèn)題,本文設(shè)計(jì)了一個(gè)基于Delphi編譯環(huán)境的定時(shí)重啟該特定服務(wù)的程序,經(jīng)實(shí)際應(yīng)用環(huán)境多次實(shí)驗(yàn)測(cè)試,該程序能夠很好地解決此類問(wèn)題。
2 重啟Tomcat運(yùn)行環(huán)境的初始化批處理代碼解析
實(shí)現(xiàn)初始化Tomcat運(yùn)行環(huán)境過(guò)程的批處理(startup.bat)部分內(nèi)容解析如下:
@echo off
if "%OS%" == "Windows_NT" setlocal //檢測(cè)操作系統(tǒng)環(huán)境變量。
……
:okExec
set CMD_LINE_ARGS= //清除CMD_LINE_ARGS環(huán)境變量原值。
:setArgs
if ""%1""=="""" goto doneSetArgs //若參數(shù)%1為空則執(zhí)行doneSetArgs段,表示已接傳入的參數(shù)。
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1 //給 CMD_LINE_ARGS 添加參數(shù)%1,以空格分隔。
Shift //截除原參數(shù),使參數(shù)%1成為原參數(shù)。
// 上述代碼是將所有參數(shù)用空格分隔開,并給CMD_LINE_ARGS賦值。
goto setArgs
:doneSetArgs
call "%EXECUTABLE%" start %CMD_LINE_ARGS%
//運(yùn)行新窗口,重啟執(zhí)行 EXECUTABLE 環(huán)境變量所示的catalina.bat 程序及 CMD_LINE_ARGS 所含的參數(shù)。
:end //初始化結(jié)束。[1]
3 程序設(shè)計(jì)思路
利用可視化編程開發(fā)工具Delphi 2010的Timer時(shí)間組件每隔1秒通過(guò)API函數(shù)獲取系統(tǒng)時(shí)間,并把時(shí)間字符串與所設(shè)定的定時(shí)啟動(dòng)時(shí)間比對(duì),滿足條件即調(diào)用API函數(shù)ShellExecute執(zhí)行特定服務(wù)或程序,本文實(shí)際應(yīng)用于重啟上述初始化Tomcat運(yùn)行環(huán)境的批處理程序(startup.bat)。
關(guān)鍵函數(shù)ShellExecute原型如下[2](須引用ShellAPI .pas單元,即uses ShellAPI;):
function ShellExecute(hWnd: HWND; Operation, FileName, Parameters,Directory: PChar; ShowCmd: Integer): HINST;
若ShellExecute函數(shù)執(zhí)行成功,則返回被執(zhí)行程序的實(shí)例句柄。若返回值低于32,則表示執(zhí)行存在錯(cuò)誤。
4 程序流程圖(如圖1)
程序流程:?jiǎn)?dòng)運(yùn)行程序后,待用戶在時(shí)間輸入框中按照提示的時(shí)間格式設(shè)定好定時(shí)啟動(dòng)運(yùn)行的時(shí)間規(guī)則內(nèi)容,以及在程序輸入框中瀏覽或指定需執(zhí)行的程序的完整路徑和文件名,然后點(diǎn)擊啟動(dòng)按鈕,啟動(dòng)按鈕切換為停止按鈕,定時(shí)器開始持續(xù)獲取系統(tǒng)時(shí)間,每秒比對(duì)系統(tǒng)時(shí)鐘是否滿足設(shè)定好的啟動(dòng)時(shí)間,滿足條件則立即執(zhí)行指定程序,否則定時(shí)器繼續(xù)獲取系統(tǒng)時(shí)間,進(jìn)行下一秒比對(duì),當(dāng)用戶點(diǎn)擊停止按鈕,則程序停止運(yùn)行,關(guān)閉后結(jié)束運(yùn)行。
5 程序?qū)崿F(xiàn)(主要模塊代碼)
5.1 初始化運(yùn)行界面模塊
本模塊代碼用于實(shí)現(xiàn)程序運(yùn)行界面窗體內(nèi)容初始化顯示,提示定時(shí)時(shí)間設(shè)定的格式規(guī)則,并提取時(shí)間輸入范例,方便用戶直接進(jìn)行修改。
procedure TForm_Exe.FormShow(Sender: TObject);
begin
Label_Time.Caption:='執(zhí)行時(shí)刻設(shè)定(格式:'+DateTimeToStr(Now)+')'; [3]
Edit_SetTime.Text:=Copy(DateTimeToStr(Now),Length(DateTimeToStr(Now))-7);
Edit_SetTime.SetFocus;
end;
5.2 “啟動(dòng)”按鈕和“停止”按鈕切換模塊
本模塊代碼用于實(shí)現(xiàn)程序 “啟動(dòng)”功能按鈕和“停止”功能按鈕交替切換,達(dá)到程序交互界面簡(jiǎn)潔友好的目的。
procedure TForm_Exe.Button_ExecuteClick(Sender: TObject);
begin
if Button_Execute.Caption='啟動(dòng)' then
begin
Timer_Now.Enabled:=True;
Edit_SetTime.ReadOnly:=True;
Button_Execute.Caption:='停止';
end
else
begin
Timer_Now.Enabled:=False;
Edit_SetTime.ReadOnly:=False;
Button_Execute.Caption:='啟動(dòng)';
Label_Time.Caption:='執(zhí)行時(shí)刻設(shè)定(格式:'+DateTimeToStr(Now)+')';
end
end;
5.3 瀏覽并提取指定程序的完整路徑和文件名模塊
本模塊代碼用于實(shí)現(xiàn)“瀏覽”按鈕功能,獲得所指定執(zhí)行程序完整的路徑和文件名。
procedure TForm_Exe.Button_LoadClick(Sender: TObject);
begin
if OpenDialog_ExeFile.Execute then Edit_ExeFileName.Text:=(OpenDialog_ExeFile.FileName); [4]
end;
5.4 Timer組件主程序模塊
本模塊代碼用于實(shí)現(xiàn)由Timer定時(shí)器每秒獲取系統(tǒng)時(shí)鐘,判斷系統(tǒng)時(shí)鐘是否包含設(shè)定好的啟動(dòng)時(shí)間,滿足條件則繼續(xù)執(zhí)行并打開指定程序,若所指定的執(zhí)行文件不存在,則給出確認(rèn)文件是否存在的提示信息。
procedure TForm_Exe.Timer_NowTimer(Sender: TObject);
begin
Label_Time.Caption:='現(xiàn)在時(shí)刻:'+DateTimeToStr(Now);
if Pos(Edit_SetTime.Text,Label_Time.Caption)<=0 then Exit;
ExeFile:=Edit_ExeFileName.Text;
if (FileExists(ExeFile)) then
ShellExecute(Handle,nil,PWideChar(ExeFile),nil,nil,SW_NORMAL)
else
messagebox(0,PWideChar(' 請(qǐng)確認(rèn)文件 ('+ExeFile+') 是否存在! '),'請(qǐng)確認(rèn)...',MB_OK);
end;
6 程序運(yùn)行界面設(shè)計(jì)[5](如圖2)
程序運(yùn)行界面設(shè)計(jì)遵循了界面友好的重要原則,兼顧簡(jiǎn)潔和美觀,窗口標(biāo)題欄和界面標(biāo)題體現(xiàn)程序所實(shí)現(xiàn)的功能,交互輸入框內(nèi)容格式提示和功能按鈕含義清晰明了,能夠直觀地引導(dǎo)用戶上手使用。
7 程序運(yùn)行效果
如上例圖2所示,假設(shè)程序重啟時(shí)間設(shè)定為3:59:59,當(dāng)系統(tǒng)時(shí)鐘滿足所設(shè)定的時(shí)間字符串,則立即執(zhí)行所指定的Tomcat運(yùn)行環(huán)境的初始化批處理程序startup.bat。由于系統(tǒng)時(shí)鐘為24小時(shí)格式,故每天滿足所設(shè)定的時(shí)間共有三次,分別為03:59:59、13:59:59、23:59:59,如此可以自動(dòng)在Tomcat運(yùn)行環(huán)境出現(xiàn)異常前定時(shí)恢復(fù)初始化環(huán)境狀態(tài),保持Apache服務(wù)處于良好運(yùn)行狀態(tài)。
8 結(jié)束語(yǔ)
定時(shí)重啟特定服務(wù)的程序不僅可以使需重啟的服務(wù)每天有多個(gè)時(shí)段進(jìn)行重新執(zhí)行,還可以指定某天某個(gè)時(shí)刻執(zhí)行特定程序或服務(wù),能夠有效滿足程序自動(dòng)運(yùn)行的需求,使各類服務(wù)保持良好運(yùn)行狀態(tài)。
定時(shí)重啟特定服務(wù)的程序后續(xù)有待從多個(gè)方面對(duì)程序代碼進(jìn)一步改良和完善,以滿足不同的需求。如根據(jù)需要對(duì)設(shè)定的時(shí)間按日期設(shè)定遞增值,并可設(shè)定日期遞增的間隔長(zhǎng)度;此外,考慮在程序?qū)崿F(xiàn)中調(diào)用進(jìn)程結(jié)束命令,以便使得特定服務(wù)重啟前先結(jié)束內(nèi)存中的進(jìn)程運(yùn)行,釋放內(nèi)存空間,避免程序重復(fù)運(yùn)行,占用多余的內(nèi)存,使用taskkill結(jié)束進(jìn)程的命令是一個(gè)可行的方法之一。taskkill /f /im explorer.exe范例釋義:taskkill是批處理中常用的結(jié)束進(jìn)程的命令,/f和/im都是參數(shù),前者表示強(qiáng)制結(jié)束,后者表示結(jié)束進(jìn)程用程序名顯示,如explorer.exe。[6]
參考文獻(xiàn):
[1] 解讀tomcat 的startup.bat內(nèi)容[EB/OL]. [2013-07-24]. https://zhidao.baidu.com/question/573218387.html.
[2] Delphi中ShellExecute使用詳解[EB/OL]. [2017-04-19]. https://www.cnblogs.com/bestlove/p/6734973.html.
[3] 陳燦煌. Delphi 6徹底研究[M]. 北京: 中國(guó)鐵道出版社, 2002.
[4] 明日科技. Delphi開發(fā)技術(shù)大全[M]. 北京: 人民郵電出版社, 2007.
[5] 求實(shí)科技. Delphi 7程序設(shè)計(jì)與開發(fā)技術(shù)大全[M]. 北京: 人民郵電出版社, 2004.
[6] 自動(dòng)結(jié)束某個(gè)指定進(jìn)程[EB/OL]. [2017-06-22]. https://zhidao.baidu.com/question/2271658977384051068.html.
【通聯(lián)編輯:謝媛媛】