景象
MySQL服务器装置MHA,sed命令批改装置脚本时卡死:
[root@TJ-DB-6CU552YPXS backup]# sed -i "s/.*vip.*ping valid.*/#&/g" mha_install.sh ^C[root@TJ-DB-6CU552YPXS backup]#
top查看,sed过程CPU使用率100%:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 14343 root 20 0 104m 1020 852 R 100.0 0.0 0:13.94 sed
剖析
pstack打印过程堆栈信息:
[root@TJ-DB-6CU552YPXS ~]# pstack 14343#0 0x00007f123d474e46 in gconv () from /usr/lib64/gconv/GBK.so#1 0x0000003f8368c6ab in mbrtowc () from /lib64/libc.so.6#2 0x00000000004052ed in ?? ()#3 0x0000000000405373 in ?? ()#4 0x0000000000406323 in ?? ()#5 0x0000000000407875 in ?? ()#6 0x00000000004026e4 in ?? ()#7 0x0000003f8361f0bd in __libc_start_main () from /lib64/libc.so.6#8 0x0000000000402029 in ?? ()#9 0x00007ffcde547f38 in ?? ()#10 0x000000000000001c in ?? ()#11 0x0000000000000004 in ?? ()#12 0x00007ffcde5498d0 in ?? ()#13 0x00007ffcde5498d4 in ?? ()#14 0x00007ffcde5498d7 in ?? ()#15 0x00007ffcde5498da in ?? ()#16 0x0000000000000000 in ?? ()
sed卡在字符集转换gconv ()函数上,mha_install.sh文件字符集为uft-8,os以后session字符集为gbk:
[root@TJ-DB-6CU552YPXS backup]# file -i mha_install.sh mha_install.sh: text/x-shellscript; charset=utf-8[root@TJ-DB-6CU552YPXS backup]# localeLANG=zh_CN.gbkLC_CTYPE="zh_CN.gbk"LC_NUMERIC="zh_CN.gbk"LC_TIME="zh_CN.gbk"LC_COLLATE="zh_CN.gbk"LC_MONETARY="zh_CN.gbk"LC_MESSAGES="zh_CN.gbk"LC_PAPER="zh_CN.gbk"LC_NAME="zh_CN.gbk"LC_ADDRESS="zh_CN.gbk"LC_TELEPHONE="zh_CN.gbk"LC_MEASUREMENT="zh_CN.gbk"LC_IDENTIFICATION="zh_CN.gbk"LC_ALL=[root@TJ-DB-6CU552YPXS backup]#
即文件中某些内容通过sed命令从uft-8转gbk时卡死,设置环境变量LANG=en_US,不进行字符集转换,再次执行sed命令疾速返回后果:
[root@TJ-DB-6CU552YPXS backup]# export LANG=en_US[root@TJ-DB-6CU552YPXS backup]# sed -i "s/.*vip.*ping valid.*/#&/g" mha_install.sh [root@TJ-DB-6CU552YPXS backup]#
sed命令到底是读到哪一行内容出了问题?应用二分查找,很快便定位了问题所在行为325:
[root@TJ-DB-6CU552YPXS backup]# head -n 324 mha_install.sh|tail -1|sed -n '1p'[root@TJ-DB-6CU552YPXS backup]# head -n 325 mha_install.sh|tail -1|sed -n '1p'^C[root@TJ-DB-6CU552YPXS backup]# head -n 325 mha_install.sh|tail -1 #生成密钥对[root@TJ-DB-6CU552YPXS backup]#
从输入不难猜测,应该是正文符号和中文之间没有空格,导致sed命令卡死,上面咱们论证测试:
[root@TJ-DB-6CU552YPXS backup]# cat fxtest.txt # 生成密钥对#生成密钥对[root@TJ-DB-6CU552YPXS backup]#[root@TJ-DB-6CU552YPXS backup]# head -n 1 fxtest.txt |sed -n '1,$p'# 生成密钥对[root@TJ-DB-6CU552YPXS backup]# head -n 2 fxtest.txt |sed -n '1,$p'# 生成密钥对^C[root@TJ-DB-6CU552YPXS backup]#
这个装置脚本曾经运行屡次了,始终都没问题,为何在这台机器上出了问题?机器操作系统为centos 6,预计是sed版本低导致,查看sed版本:
[root@TJ-DB-6CU552YPXS backup]# sed --versionGNU sed 4.2.1
找一台centos 7机器,查看sed版本:
[root@fxtest01 ~]# sed --versionsed (GNU sed) 4.2.2
将 centos 7上sed拷贝到这台centos 6,再次执行同样操作,很快输入后果:
[root@TJ-DB-6CU552YPXS backup]# head -n 2 fxtest.txt |sed -n '1,$p'# 生成密钥对^C[root@TJ-DB-6CU552YPXS backup]#chmod +x sed && head -n 2 fxtest.txt |./sed -n '1,$p'# 生成密钥对#生成密钥对[root@TJ-DB-6CU552YPXS backup]#
总结
1、正文符号和汉字之间养成应用空格分隔习惯。
2、一些低版本工具在某些非凡状况下可能会触发bug,仔细分析及比对,总会找到问题本源。
本文关键字:#sed# #cpu# #字符集#