mongodb正则表达式应用

mongodb中完全支持正则表达式,一般查询中可以使用操作符$regex

1
2
db.hillmatrix.find({ 'name': /*.hillmatrix.com/i } );
db.hillmatrix.find( { 'name': { $regex: '*.hillmatrix.com', $options: 'i' } } );

以上两种完全等价,可以直接对域(field)即上例中的’name’键,使用正则表达式或者使用操作符,可选项目是i,即忽略大小写。
关于正则可选项,mongodb和其他语言标准正则稍有不同,有自己的标准。
$options的可选值
i 忽略大小写;
m 多行查找,如果内容里面不存在换行符号(例如 \n)或者构造上没有(start/end),该选项没有任何效果;
x 空白字符除了被转义的或在字符类中的以外完全被忽略,在未转义的字符类之外的 # 以及下一个换行符之间的所有字符,包括两头,也都被忽略;
s 圆点元字符(.)匹配所有的字符,包括换行符

假设我们有一个数据库名为mongoDemo

1
use mongoDemo

数据库中有个集合名为hillmatrix

1
db.hillmatrix.find()

有如下数据:

1
2
3
{ "_id" : ObjectId("502dd63d16a25b1ff6000000"), "name" : "www.hillmatrix.com", "site" : "website", "tag" : "l,n,m,o,p,y"}
{ "_id" : ObjectId("502dd63d16a25b1ff6000000"), "name" : "demo.hillmatrix.com", "site" : "unknown", "tag" : "d,e,m,o"}
{ "_id" : ObjectId("502dd63d16a25b1ff6000000"), "name" : "welcome.hillmatrix.com", "site" : "website", "tag" : "w,e,l,c,o,m,e"}

mongodb的正则表达式仅支持i和m的javascript原生写法(如/*.hillmatrix.com/i)。如果要是用x和s选项就必须使用“$regex”操作符并在“$options”中指定选项。
使用正则表达式的更新操作:

1
db.hillmatrix.update( { 'name': /*.hillmatrix.com/i }, { $set: { 'site':'www.hillmatrix.com' } } );

意思是,查找当前数据库中名为“hillmatrix”的集合中“name”字段符合“/*.hillmatrix.com/i”正则的条目,并只将“site”字段更新为“www.hillmatrix.com”,该条更新语句仅更新一条数据,如果不是用$set,那么这条记录就会只剩下你更新的部分和默认的ObjectId,可以说是替换了。如果想替换所有,可以加入参数:

1
db.hillmatrix.update( { 'name': /*.hillmatrix.com/i }, { $set: { 'site':'www.hillmatrix.com' } } , false, true);

参数有顺序,false是upsert,如果没有就插入新的。true就是multi多条记录更新,所有匹配到的结果。或者直接指定{ multi: true }:

1
db.hillmatrix.update( { 'name': /*.hillmatrix.com/i }, { $set: { 'site':'www.hillmatrix.com' } } , { multi: true });

这样就把所有的“site”字段全都更新为“www.hillmatrix.com”了。

我设计的字段“tag”有个缺陷,就是本来是一个单词,现在每个字母都被“,“分隔开了。实际工作中也存在类似问题,由于批量转换数据,或者其他程序操作不当,或者业务需求更改等等原因需要对某些字段进行正则批量处理,mongodb的一般更新方法是不能实现的,这时就需要使用javascript语句。

正则表达式替换查询结果中’,’为”

1
db.hillmatrix.find().forEach( function(u) { u.tag = u.tag.replace(/\,/, ""); db.hillmatrix.save(u); } );

最后执行

1
db.hillmatrix.find()

显示如下数据:

1
2
3
{ "_id" : ObjectId("502dd63d16a25b1ff6000000"), "name" : "www.hillmatrix.com", "site" : "www.hillmatrix.com", "tag" : "hillmatrix"}
{ "_id" : ObjectId("502dd63d16a25b1ff6000000"), "name" : "demo.hillmatrix.com", "site" : "www.hillmatrix.com", "tag" : "demo"}
{ "_id" : ObjectId("502dd63d16a25b1ff6000000"), "name" : "welcome.hillmatrix.com", "site" : "www.hillmatrix.com", "tag" : "welcome"}

后记:javascript是mongodb的一大特色,也是优势,很多复杂的查询和处理都可以用javascript实现,要注意的是,javascript的工作效率较低,原则上应该尽量避免在主要业务逻辑中大量使用。类比的讲,javascript就相当于oracle的存储过程,介于10gen(mongodb的开发团队)是由oracle出来的这点,就一点也不奇怪了。关于如何使用更复杂的javascript,以后会写到。

服务器被黑了,处理SSH-SCAN

为一个甲方做工程的时候,一天发现测试服务器打开网页很慢,ssh登录到测试服务器

1
ps -e

一看全是ssh-scan进程,才知道是被黑了,ssh-scan运行消耗了大量的系统资源,导致程序变慢,先处理掉它。

1
cd /

发现系统根目录下最前面多出来个没有名字的文件夹,这个如果心粗点就发现不了,因为终端命令行里面前面就是空的,只不过占用了一个文件夹的位置,介于有些时候攻破你服务器linux内核的人个人喜好问题,他可能会将ssh-scan源程序放在不同的地方,通用的做法如下:

1
ps -ef|grep ssh-scan

找到ssh-scan对应的进程号PID,如有一个是19087。
进入到/proc/PID对应的目录

1
cd /proc/19087
1
ls -al

查看cwd和exe对应的选项,找到应用ssh-scan程序所在目录,我的情况是在”/”系统根目录下。
首先,将其进程全部杀死

1
killall -9 scanssh

然后,删除对应目录

1
rm \  -fr

注意\后面是个空格,一般你按Tab键能够提示并补全,也许有的名字不是空格,而是别的字符类型或者特殊符号,这样需要ls出来,然后复制其名字,必要时将名字用引号括起来。
最后,将ssh用户密码全部修改。

1
netstat -an|grep 22

查看输出,仍然有很多连接,reboot服务器,系统运行正常。

后记:虽然处理完了,但毕竟liunx内核被攻破了,这样最好是紧急处理完之后,备份全部数据,然后重装操作系统。预防方法就是定期修改密码,密码不要简单,越复杂越好,这样对于猜密码或者穷举的攻击方式可以有效预防。另外也可使用现成的软件或者脚本来预防暴力破解,原理是拒绝ssh验证访问失败的ip,阈值自己设置,比如5次,就是5次访问失败以后不接受该ip访问ssh的22号端口请求。还有种方式就是更改ssh默认端口,一般ssh-scan的目标都是22号端口,如果你改变ssh请求端口,就意味着很少会成为攻击目标了。