Nagios中文顯示問題的解決方案
Nagios的Status Map功能鏈接能夠顯示被監控的網絡拓撲圖,并在節點圖片上面顯示節點設備名。遺憾的是,默認的Nagios不支持中文。為此我研究了兩天Nagios以及GD的源代碼,終于找到了解決方案,詳述如下:
解壓縮Nagios中文源代碼包(以nagios-3.0.3為例),實現繪制網絡拓撲圖的源代碼文件是nagios-3.0.3/cgi/statusmap.c,編譯安裝后,這個文件對應nagios/sbin/statusmap.cgi,當你在Nagios中文運行界面點擊左側的“Status Map”鏈接時,服務器(apache、tomcat等支持CGI的服務器軟件)調用可執行文件statusmap.cgi,實現在瀏覽器客戶區中繪制網絡拓撲圖。
statusmap.c中負責繪制節點設備名的函數是void draw_text(char *buffer,int x,int y,int text_color),就在本文件中定義,它調用GD的一個庫函數——
gdImageString(map_image,gdFontSmall,x-(string_width/2),y-(2*string_height),(unsigned char *)buffer,text_color);來繪制節點設備名。
這里先簡單介紹一下GD以及其他一些軟件與Nagios的關系。Nagios處理圖片(包括繪制文字)需要借助于GD,有些版本的Linux已經集成了GD,所以可以直接安裝使用Nagios。安裝GD以及相關的軟件包的順序如下(版本僅為舉例):
gd:一個處理圖片(包括繪制文字)的軟件包;
freetype:gd解析字庫用到的軟件包;
libpng:gd解析png圖片用到的軟件包;
jpeg:gd解析jpeg圖片用到的軟件包。
安裝方法舉例:
安裝方法
安裝freetype
#cd /data/software
#tar xzvf freetype-2.1.5.tar.gz
#cd freetype-2.1.5
#./configure --prefix=/usr/local/modules/freetype
#make
#make install
安裝libpng
#cd /data/software
#tar xzvf libpng-1.2.5.tar.gz
#cd libpng-1.2.5
#cp scripts/makefile.std makefile \\不要用--prefix自定義安裝目錄,影響gd的安裝
#make
#make install
安裝jpeg
#mkdir /usr/local/modules/jpeg6
#mkdir /usr/local/modules/jpeg6/bin
#mkdir /usr/local/modules/jpeg6/lib
#mkdir /usr/local/modules/jpeg6/include
#mkdir /usr/local/modules/jpeg6/man
#mkdir /usr/local/modules/jpeg6/man/man1
#cd /data/software
#tar xzvf jpegsrc.v6b.tar.gz
#./configure --prefix=/usr/local/modules/jpeg6 --enable-shared --enable-static
#make
#make install
安裝gd
#cd /data/software
#tar xzvf gd-2.0.33.tar.gz
#./configure --prefix=/usr/local/modules/gd --with- jpeg=/usr/local/modules/jpeg6 --with-png --with-zlib --with-freetype=/usr/local/modules/freetype
#make
#make install
最后,在安裝nagios時#./configure步驟加一組參數:--with-gd-lib=/usr/local/modules/gd/lib
原始的Nagios中文版不能繪制中文字符串,與GD的字庫處理方式有關。GD有自己的字庫文件(點陣形式、ASC碼編碼)。gdImageString的第二個參數即GD自己的字庫的索引,第五個參數則是一個ASC編碼的字符串。而GD自己的字庫是不支持中文的。顯然,大名鼎鼎的GD不可能只支持自己的字庫,他用函數gdImageStringFT來支持用外部字庫繪制utf-8編碼的字符串,這里面包含了中文的支持。
gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist,double ptsize, double angle, int x, int y, char *string),函數名中的“FT”就是freetype的意思,這個函數通過調用freetype包,支持解析.ttf格式(ttf是TrueType Font的縮寫)的字庫文件,只要找到Linux下的中文字庫的位置,作為第四個參數傳給該函數,并且保證char *string是utf-8編碼,就能順利繪制中文字符串。在我的調試環境下,修改如下:
原函數:
gdImageString(map_image,gdFontSmall,x-(string_width/2),y-(2*string_height),(unsigned char *)buffer,text_color);
修改后:
gdImageStringFT(map_image,&brect[0],text_color,"/usr/share/fonts/zh_CN/TrueType/gbsn00lp.ttf",10,0.0,x-(string_width/2),y-(2*string_height),buffer);
(gdImageString和gdImageStringFT詳細的功能和參數說明見GD安裝包下的說明文檔index.html)
由于Nagios是從配置文件中讀取設備名字符串然后繪制到屏幕上,所以如果配置文件本身是utf-8編碼,如上修改后,重裝Nagios就可以順利顯示了。如果配置文件不是utf-8,那么可以通過兩種方法解決:
第一種:將配置文件轉成utf-8編碼。這樣不用再度修改源碼,但個人不贊成這種方法,理由是:由于Nagios的CGI是用C寫的,而C是基于ASC編碼的,Nagios又沒有借助第三方數據庫,而是依賴于讀寫自己創建的大量配置文件和日志文件,其中用到很多基于ASC編碼的字符串處理函數,雖然都是英文的,而英文的ASC編碼和utf-8完全相同,但是如果將Nagios的相關文件都轉成utf-8編碼,可能會導致一些潛在的問題。
第二種:在gdImageStringFT之前加一個字符串編碼轉換函數,將讀入的非utf-8編碼字符串buffer轉換成utf-8編碼,再傳給gdImageStringFT處理。這樣的字符串編碼轉換函數網上有很多資源,在此限于篇幅不詳述。
【編輯推薦】