最近把cacti从apache搬到了nginx+php-fpm的环境,程序打包部署的,什么都没有变,但是起来后发现图上的中文都是乱码,类似于:
开始搜索,也参考了无数文章,大多说的都是中文字体的设置问题。照着试了,没效果。后来尝试修改rrdtool,重新编译,又发现和freetype2的版本不协调。于是进入cacti的代码去看它是如何使用rrdtool来绘图的,保存命令行直接执行,也是可以正常显示中文的。于是又怀疑是运行nginx和php-fpm的用户locale问题,用运行用户跑命令行也是ok的。于是再用php页面去跑,果然是乱码了又。
其实这个问题就是locale问题,rrdtool源代码已经很清楚了,但是由于不了解nginx和php-fpm对环境变量的加载规则,还是摸不到头绪。终于还是发现了这篇文章,作者的思考过程可以借鉴,也同时告诉我们如何来跟踪这种locale问题导致的语言问题。特此抓贴分享下:
最近一直在折腾把cactiEZ搬到生产平台上已有的rhel4上,没有想到遇到了图表中文乱码的问题。
用的是系统自带的rrdtool,想起网上说要修改源代码才能正常显示,于是下了源代码进行编译。
下载1.2.27修改setlocale,编译~~~~重启httpd。结果打开IE一看,还是乱码。
是不是老版本的问题,下个最新的1.4.3试试。经过漫长的编译过程(有很多依赖库也要编译,郁闷),重新配置,重启httpd,还是乱码。是不是也要修改setlocale?打开rrd_graph.c ,我日,里面大变样,根本找不到原来的函数了。此路不通。
找来找去,乱码出现的原因百思不得其解。
试着直接命令行运行rrdtool,发现生成出来的图像中文是正常的。难道中文出在调用rrdtool上面?
于是写一个脚本检测传递给rrdtool环境变量
- #!/bin/sh
- LOGDIR=/var/log
- date >> $LOGDIR/debug.log
- echo "---------------------------------" >> $LOGDIR/debug.log
- echo "$@" >> $LOGDIR/debug.log
- echo "---------------------------------" >> $LOGDIR/debug.log
- env >> $LOGDIR/debug.log
- echo "---------------------------------" >> $LOGDIR/debug.log
- locale >> $LOGDIR/debug.log
- /usr/bin/rrdtool.local "$@"
- echo "" >> $LOGDIR/debug.log
将系统自带的rrdtool改名成 rrdtool.local,然后这个脚本保存成rrdtool
在cacti一看图,果然出现了猫腻。
- LANG=C
- LC_CTYPE="C"
- LC_NUMERIC="C"
- LC_TIME="C"
- LC_COLLATE="C"
- LC_MONETARY="C"
- LC_MESSAGES="C"
- LC_PAPER="C"
- LC_NAME="C"
- LC_ADDRESS="C"
- LC_TELEPHONE="C"
- LC_MEASUREMENT="C"
- LC_IDENTIFICATION="C"
- LC_ALL=
- LANG=
- LC_CTYPE="POSIX"
- LC_NUMERIC="POSIX"
- LC_TIME="POSIX"
- LC_COLLATE="POSIX"
- LC_MONETARY="POSIX"
- LC_MESSAGES="POSIX"
- LC_PAPER="POSIX"
- LC_NAME="POSIX"
- LC_ADDRESS="POSIX"
- LC_TELEPHONE="POSIX"
- LC_MEASUREMENT="POSIX"
- LC_IDENTIFICATION="POSIX"
- LC_ALL=
调用rrdtool的时候locale都不对,肯定乱码。于是在脚本的前面添加了export LANG=zh_CN.gb18030。再运行一下,郁闷,还是乱码。
这样完全没有办法了。又翻来复去折腾了几遍,还是老样子。莫非大侠命绝于此。
怀着最后一丝希望点了一遍图表,突然原来图表时间轴上的星期现在能正常显示中文了,而备注和图表标题还是乱码,这一些好像都是从命令行传入的,而星期那一些不是传入的,是rrdtool自动生成的。
会不会是传给rrdtool的参数里中文乱码了?
于是马上修改脚本打印 echo "$@" >> /var/log/debug.log
果然,在debug.log里参数都是乱码的,这就说明传给rrdtool的时候中文都已经乱码了,rrdtool也就死活显示不出中文了。
由于cactiEZ 而且使用的gb2312编码,于是将/etc/sysconfig/i18n 里修改成gb18030 ,service httpd restart
重新进入cacti,看图,中文终于出来了!!!眼泪哗哗的。
最终总结:
1.rrdtool的中文显示与上下文locale有关。需要注意php调用rrdtool时的locale
2.cacti调用rrdtool时会丢失原有的locale,所以需要写一个脚本包装一下rrdtool,重新指定locale
3.cacti能否传递正常的参数给rrdtool,有赖于系统的locale,如果系统的默认locale与cacti应用的编码不对,可能不能正确的传递中文。
2、3点可能和apache以及php的机制有关,没有进一步的去研究。
我是基于cactiEZ修改的中文版进行的测试,原版可能修改的方法不一样,但原理肯定相通。另外,我试用的rrdtool是1.2.23、1.2.27和1.4.3。更老的版本是否可行未知,但可以按上面的思路排查问题。
附上:最终的脚本
将原来的/usr/bin/rrdtool 更名为 /usr/bin/rrdtool
将下面的代码保存为/usr/bin/rrdtool
- #!/bin/sh
- export LANG=zh_CN.gb18030
- /usr/bin/rrdtool.local "$@"
转自:http://www.51cacti.cn/thread-250-1-1.html