长话短说,查看生产环境Elasticsearch (5.6版本) 时,发现一些如下有着非ascii码的索引
1 2 3 4 5 6 red zhangxin-xxx-༠༠༣༡.༠༣.༢༢ red zhangxin-xxx-༠༠༣༡.༠༣.༢༣ red zhangxin-xxx-༠༠༣༡.༠༣.༢༤ red zhangxin-xxx-༠༠༣༡.༠༤.༡༢ red zhangxin-xxx-༠༠༣༡.༠༤.༡༧ red zh날炷gxꆀ鍀ᒶ⒐ጆ䬯ꀳ20₨炠.021
上面是某系统因为历史缘故,使用用户的数据创建索引了,因暂时无法推动其做修改,于是需要考虑用脚本定时删除。
如果你对过程不感兴趣,可以考虑跳到 总结2 直接看方法。题外话:上述看起来是藏文,用了bing/sogou翻译,识别为北欧语言(为:我的天呐),看起来不一样而且不像,不过用google翻译像日期格式(为:0031.03.22)倒是接近。 i>
不过,如果直接用 curl -XDELETE ‘10.135.20.38:9200/zhangxin-xxx-༠༠༣༡.༠༣.༢༢’ 会提示索引不存在,因为需要转义。 而且,ES也不存在POST方式删除索引的方法,索引需要修改为:
1 2 3 4 5 6 7 curl -XDELETE 10.135.20.38:9200/zhangxin-xxx-%e0%bc%a0%e0%bc%a0%e0%bc%a3%e0%bc%a1.%e0%bc%a0%e0%bc%a3.%e0%bc%a2%e0%bc%a2 curl -XDELETE 10.135.20.38:9200/zhangxin-xxx-%e0%bc%a0%e0%bc%a0%e0%bc%a3%e0%bc%a1.%e0%bc%a0%e0%bc%a3.%e0%bc%a2%e0%bc%a3 curl -XDELETE 10.135.20.38:9200/zhangxin-xxx-%e0%bc%a0%e0%bc%a0%e0%bc%a3%e0%bc%a1.%e0%bc%a0%e0%bc%a3.%e0%bc%a2%e0%bc%a4 curl -XDELETE 10.135.20.38:9200/zhangxin-xxx-%e0%bc%a0%e0%bc%a0%e0%bc%a3%e0%bc%a1.%e0%bc%a0%e0%bc%a4.%e0%bc%a1%e0%bc%a2 curl -XDELETE 10.135.20.38:9200/zhangxin-xxx-%e0%bc%a0%e0%bc%a0%e0%bc%a3%e0%bc%a1.%e0%bc%a0%e0%bc%a4.%e0%bc%a1%e0%bc%a7 curl -XDELETE 10.135.20.38:9200/zhangxin-xxx-%e0%bc%a0%e0%bc%a0%e0%bc%a3%e0%bc%a1.%e0%bc%a0%e0%bc%a4.%e0%bc%a1%e0%bc%a8 curl -XDELETE '10.135.20.38:9200/zh%EB%82%A0%E7%82%B7gx%EA%86%80%00%E9%8D%80%E1%92%B6%E2%92%90%E1%8C%86%01%00%E4%AC%AF%EA%80%B3%32%30%E2%82%A8%E7%82%A0%2E%30%1A%00%32%31'
方式删除,这里索引可以使用逗号分隔拼凑起来,不过为了脚本方便就一行一条了。
那么怎么去定位这些非正常字符的索引呢?
curl -s 10.135.20.38:9200/_cat/indices?v|grep -P '[\xB0\xA1-\xF7\xFE]+'
上面索引就是用该行grep出来,不过按上述删完后,发现‘zh날炷gxꆀ鍀ᒶ⒐ጆ䬯ꀳ20₨炠.021’ 这个索引还在。
这让我有点不知所措,直到我把grep出来的结果保存,并用16进制模式查看时,才发现,原来是自己手动从服务器拷贝该索引时把部分不可string化的字符拷贝丢了。
1 2 3 4 5 6 7 8 curl -s 10.135.20.38:9200/_cat/indices?v|grep -P '[\xB0\xA1-\xF7\xFE]+' green open zh날炷gxꆀ鍀ᒶ⒐ጆ䬯ꀳ20₨炠.021 tfpRU2KeRCG6yBWhYq5J2w 5 1 1 0 9.2kb 4.6kb # 将上述结果打开vi十六进制模式,部分如下 7a68 green open zh 0000010: eb82 a0e7 82b7 6778 ea86 8000 e98d 80e1 ......gx........ 0000020: 92b6 e292 90e1 8c86 0100 e4ac afea 80b3 ................ 0000030: 3230 e282 a8e7 82a0 2e30 1a00 3231 20.......0..21
可以看到通过字符串拷贝时丢失,还是老老实实写脚本实现删除吧。
总结1
如下是完整实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 首先是之前通过curl命令进行 urlencode 编码的函数 function urlencode() { local data if [[ $# != 1 ]]; then echo "Usage: $0 str" return 1 fi data="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "$1" "")" # if [[ $? == 0 ]]; then echo "${data##/?}" # fi return 0 } function callDel(){ indx=$(urlencode $1) curl -s -XDELETE 10.135.20.38:9200/$indx }
其次合起来完整的脚本就是
1 2 curl -s 10.135.20.38:9200/_cat/indices?v|grep -P '[\xB0\xA1-\xF7\xFE]+' | \ awk '{print $3}' |xargs -I@ -P4 bash -c "$(declare -f urlencode; declare -f callDel) ; callDel @ ; echo @ "
题外话:起先怀疑这个urlencode有误,后来使用 python -c “import urllib;print urllib.quote(raw_input())” <<< “zhangxin-xxx-༢༥༦༢.༠༤.༠༡” 也是如此。
总结2
上述方法可以完美运行,但是觉得有点麻烦,实现的不是非常的 Elasticsearch。
无意翻看了下 Elasticsearch 的索引匹配支持,显然索引匹配是不支持正则表达式的,但是支持通配符,include,excluse,具体代码可以看 Elasticsearch 的 IndexNameExpressionResolver 实现,在innerResolve 会判断是否支持。有个exclude模式是支持的。 即,也可以用这种方式去删除:
1 curl -XDELETE '10.135.20.38:9200/zhangxin-xxx-*,-zhangxin-xxx-2019.07.*'
这句就表示删除 zhangxin-xxx- 除 zhangxin-xxx-2019.07- 开头的索引。
不过这个方案不如上面的通用,但是非常简单且清晰易懂。