遠程程序運行狀態的容易監控
發表時間:2023-07-22 來源:明輝站整理相關軟件相關文章人氣:
[摘要]民航中南空管局氣象中心數據庫室 歐壯杰 我們知道,在unix操作系統中,遠程主機命令行程序的運行和進程的關閉可通過telnet來實現,當客戶機裝有x-windows時,可以運行遠程主機圖形界面的程序...
民航中南空管局氣象中心數據庫室 歐壯杰
我們知道,在unix操作系統中,遠程主機命令行程序的運行和進程的關閉可通過telnet來實現,當客戶機裝有x-windows時,可以運行遠程主機圖形界面的程序且界面顯示在客戶機上,相當于延長了遠程主機顯示屏的距離。但windows產品在windows2000以前只有一個叫“八爪魚”的不成熟第三方產品可實現該功能。隨著windows2000的發布,終端服務功能成為windows2000的一個亮點,只要在服務器端和客戶端安裝上相應的程序,就可以實現遠程桌面的功能。但是對于要實時監控通過慢速的DDN專線連接的遠程主機上的程序,則終端服務占用了太多的帶寬。因此,我們采用自己編程序的方法,用較少的傳輸量就可以實時監控遠程主機的程序。
我們的設計方法是:在服務器端運行一個實時進程監控程序,定時讀取服務器進程的運行情況;在客戶端運行一個終端程序,通過服務器端的進程監控程序把服務器的進程運行情況在終端顯示出來,并可在終端發送指令指示服務器啟動和停止特定的進程,甚至重啟遠程主機。
1、服務器端進程監控程序
在windows2000 和windows 95以上的版本中,Microsoft 提供了一套工具幫助函數(Tool Help),該套函數用于獲得當前系統中運行的進程、堆、模塊及進程使用的線程的快照集。在windows nt 4.0中是沒有提供。但我們現在的遠程主機都是安裝了windows 2000,因此可在上面運行該套函數,下面是例子(采用delphi 語言):
procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
ContinueLoop:BOOL;
FSnapshotHandle:THandle;
FProcessEntry32:TProcessEntry32;
begin
FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
FProcessEntry32.dwSize:=Sizeof(FProcessEntry32); file://指定結構的大小
ContinueLoop:=Process32First(FSnapshotHandle,FProcessEntry32);
while integer(ContinueLoop)<>0 do
begin
Demo1.Lines.Add(inttostr(FProcessEntry32.th32ProcessID)+
':'+FProcessEntry32.szExeFile);
ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);
end;
CloseHandle (FSnapshotHandle);
end;
程序中首先調用CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0)函數來獲得當前進程快照集的打開句柄。
TProcessEntry32是一個進程入口結構,它用于存儲所掃描到的進程信息,如進程號、進程可執行文件名字等。第二步就是調用Process32First(FSnapshotHandle,FProcessEntry32)函數來尋找第一個進程,當返回值ContinueLoop為True時說明已找到進程;而Process32Next(FSnapshotHandle,FProcessEntry32)用于取得記錄在系統快照集里的下一個進程信息。當返回值為False為說明列舉已完成。TProcessEntry32結構的th32ProcessID屬性記錄了當前進程的進程號;szExeFile屬性記錄了當前進程的可執行文件名字;獲得每一進程的這兩個信息,就可以知當前系統的進程運行情況。
當客戶端軟件提出瀏覽遠端進程要求時,服務器端可運行該段程序并把獲得的信息發給客戶端。
再有,在windows2000下,可執行GetProcessTimes函數來獲得該進程以內核模式已經執行的時間和以用戶模式已經執行的時間,這樣我們就可大概了解該進程對CPU的占用情況。以便及時采取相應的措施。
當獲得服務器端進程后,我們在客戶端可發出指令,讓服務器端程序終止某一進程或啟動某一程序,用TerminateProcess函數可結束指定的進程及其所擁有的線程,該函數使得一個進程中的所有線程都終止,且引起該進程退出,但進程終止的消息不通知給附加的動態連接庫DLL,因此使用該函數不能太頻繁。
我們還可以在服務器端截取屏幕,并把屏幕存為jpg格式圖像后以數據流的方式發送給客戶端。
另外,為了監控服務器上的進程所占用的內存資源,我們可利用 GetProcessMemoryInfo函數來獲得當前進程所占用內存的大小,例子如下:
procedure TForm1.Button1Click(Sender: TObject);
var hd:HWND;
dw:Dword;
PMC: PPROCESS_MEMORY_COUNTERS;
begin
dw:=4294548877;//假設該數值為某一進程的進程號
hd:=OpenProcess(PROCESS_TERMINATE,FALSE,dw); file://獲得進程的句柄
PMC.cb:=sizeof(PMC);
if GetProcessMemoryInfo(hd, PMC, PMC.cb) then
begin
file://調用PMC.WorkingSetSize來獲得所占用內存的大小
end;
CloseHandle(hd);
end;
需要注意的是GetProcessMemoryInfo函數只在windows nt/2000 下可用,在windows98中沒有函數可獲得進程內存的大小,另外要在uses部分引用PsAPI單元,里面有GetProcessMemoryInfo函數引用說明。
2、客戶端程序
客戶端的程序比較簡單,主要功能是要實現指令的發送和信息的接收。
3、程序間的通信
我們采用socket套接字來實現程序間的通信,在服務器端運行一Socket服務器序,監聽來自客戶端的連接和接受指令。在delphi中,復雜的Socket函數被封裝成一控件TserverSocket,該控件繼承自TCustomSocket 對象,封裝了對監聽端口綁定和監聽。只要調用TserverSocket控件的Open方法,就可使服務器端的Sockct處于監聽狀態,當客戶端有連接請求時將自動接受連接,然后在ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket)事件中讀取來自客戶端的請求。為了安全起見,我們可自定義較高層的協議,在客端所發送的信息中加上內容標識,如"user:abcdef",表示收到用戶的驗證,然后和客戶端之間進行安全的認證。在讀到數據時,我們可根據內容做出相應的動作,如取得進程的信息并發送給客戶。
在客戶端,我們采用TclientSocket控件來同服務器端進行通信,在指定了服務器端的IP地址和端口后,調用Open方法來和服務端的Socket取得聯系并發送用戶名和密碼到服務端進行驗證,之后就可以發送指令和接收數據了。需要說明的是,客戶發送的指令要和服務器端進行商議好。
以上只是一個初步的應用,利用該思路還可做得更多,我們在實際應用取得了較好的效果。