杭州校区切换校区

新闻资讯

  • news

    MySQL 查找删除重复行

    发布时间:2018-05-04

    <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:25.6px;font-size:14px;color:#000000;">本文讲述如何</span><span style="line-height:25.6px;font-size:14px;color:#007AAA;">查找数据库里重复的行</span><span style="line-height:25.6px;font-size:14px;color:#000000;">。这是初学者十分普遍遇到的问题。方法也很简单。这个问题还可以有其他演变,例如,如何查找“两字段重复的行”(#mysql IRC 频道问到的问题)</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;line-height:25.6px;color:#4F4F4F;"><br></span></p><span style="color:#007AAA;font-size:18px;"><strong>如何查找重复行</strong></span><br><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">第一步是定义什么样的行才是重复行。多数情况下很简单:它们</span><span style="line-height:24.5px;font-size:14px;color:#007AAA;">某一列</span><span style="line-height:24.5px;font-size:14px;color:#000000;">具有相同的值。本文采用这一定义,或许你对“重复”的定义比这复杂,你需要对sql做些修改。</span><span style="font-size:14px;">本文要用到的数据样本:</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;"></span></p> <pre>create&nbsp;table&nbsp;test(id&nbsp;int&nbsp;not&nbsp;null&nbsp;primary&nbsp;key,&nbsp;day&nbsp;date&nbsp;not&nbsp;null); &nbsp; &nbsp; insert&nbsp;into&nbsp;test(id,&nbsp;day)&nbsp;values(1,&nbsp;'2006-10-08'); &nbsp; insert&nbsp;into&nbsp;test(id,&nbsp;day)&nbsp;values(2,&nbsp;'2006-10-08'); &nbsp; insert&nbsp;into&nbsp;test(id,&nbsp;day)&nbsp;values(3,&nbsp;'2006-10-09'); &nbsp; &nbsp; select&nbsp;*&nbsp;from&nbsp;test; &nbsp; +----+------------+ &nbsp; | id | day &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; +----+------------+ &nbsp; | &nbsp;1 | 2006-10-08 | &nbsp; | &nbsp;2 | 2006-10-08 | &nbsp; | &nbsp;3 | 2006-10-09 | &nbsp; +----+------------+</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;"></span><span style="line-height:24.5px;font-size:14px;color:#000000;">前面两行在</span><span style="line-height:24.5px;font-size:14px;color:#007AAA;">day字段</span><span style="line-height:24.5px;font-size:14px;color:#000000;">具有相同的值,因此如何我将他们当做重复行,这里有一查询语句可以查找。查询语句使用</span><span style="line-height:24.5px;font-size:14px;color:#007AAA;">GROUP BY</span><span style="line-height:24.5px;font-size:14px;color:#000000;">子句把具有相同字段值的行归为一组,然后计算组的大小。</span></p> <pre>select day, count(*) from test GROUP BY day; &nbsp; +------------+----------+ &nbsp; | day &nbsp; &nbsp; &nbsp; &nbsp;|&nbsp;count(*)&nbsp;| &nbsp; +------------+----------+ &nbsp; |&nbsp;2006-10-08&nbsp;| &nbsp; &nbsp; &nbsp; &nbsp;2 |&nbsp;&nbsp; | 2006-10-09 |&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;1&nbsp;| &nbsp; +------------+----------+</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;">重复行的组大小大于1。如何希望只显示重复行,必须使用</span><span style="font-size:14px;line-height:24.5px;color:#007AAA;">HAVING</span><span style="font-size:14px;line-height:24.5px;">子句,比如</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;"></span></p> <pre>select&nbsp;day, count(*)&nbsp;from&nbsp;test&nbsp;group&nbsp;by&nbsp;day HAVING&nbsp;count(*) &gt; 1; &nbsp; +------------+----------+ &nbsp; | day &nbsp; &nbsp; &nbsp; &nbsp;| count(*) | &nbsp; +------------+----------+ &nbsp; |&nbsp;2006-10-08&nbsp;| &nbsp; &nbsp; &nbsp; &nbsp;2&nbsp;| &nbsp; +------------+----------+</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;"></span><span style="line-height:24.5px;font-size:14px;color:#000000;">这是基本的技巧:根据具有相同值的字段分组,然后知显示大小大于1的组。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#007AAA;"><strong>为什么不能使用WHERE子句?</strong></span><span style="line-height:24.5px;font-size:14px;">因为WHERE子句过滤的是分组之前的行,HAVING子句过滤的是分组之后的行。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;"><br></span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;"><br></span></p><span style="color:#007AAA;"><strong><span style="font-size:18px;">如何删除重复行</span></strong></span><br><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">一个相关的问题是如何</span><span style="line-height:24.5px;font-size:14px;color:#007AAA;">删除重复行</span><span style="line-height:24.5px;font-size:14px;color:#000000;">。一个常见的任务是,重复行只保留一行,其他删除,然后你可以创建适当的索引,防止以后再有重复的行写入数据库。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">同样,首先是弄清楚重复行的定义。你要保留的是哪一行呢?第一行,或者某个字段具有最大值的行?</span><span style="line-height:24.5px;font-size:14px;color:#007AAA;">本文中,假设要保留的是第一行</span><span style="line-height:24.5px;font-size:14px;color:#000000;">——id字段具有最小值的行,意味着你要删除其他的行。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">也许最简单的方法是通过临时表。尤其对于MYSQL,有些限制是不能在一个查询语句中select的同时update一个表。简单起见,这里只用到了临时表的方法。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">我们的任务是:删除所有重复行,除了分组中id字段具有最小值的行。因此,需要找出大小大于1的分组,以及希望保留的行。你可以使用</span><span style="line-height:24.5px;font-size:14px;color:#007AAA;">MIN</span><span style="line-height:24.5px;font-size:14px;color:#000000;">()函数。这里的语句是创建临时表,以及查找需要用DELETE删除的行。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;"></span></p> <pre>create&nbsp;temporary&nbsp;table&nbsp;to_delete (day&nbsp;date&nbsp;not&nbsp;null, min_id&nbsp;int&nbsp;not&nbsp;null); &nbsp; &nbsp; insert&nbsp;into&nbsp;to_delete(day, min_id) &nbsp; &nbsp;&nbsp;select&nbsp;day,&nbsp;MIN(id)&nbsp;from&nbsp;test&nbsp;group&nbsp;by&nbsp;day&nbsp;having&nbsp;count(*) &gt;&nbsp;1; &nbsp; &nbsp; select&nbsp;*&nbsp;from&nbsp;to_delete; &nbsp; +------------+--------+ &nbsp; | day &nbsp; &nbsp; &nbsp; &nbsp;| min_id | &nbsp; +------------+--------+ &nbsp; | 2006-10-08 | &nbsp; &nbsp; &nbsp;1 | &nbsp; +------------+--------+</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">有了这些数据,你可以开始删除“脏数据”行了。可以有几种方法,各有优劣(详见我的文章many-to-one problems in SQL),但这里不做详细比较,只是说明在支持查询子句的关系数据库中,使用的标准方法。</span></p> <pre>delete&nbsp;from&nbsp;test&nbsp;&nbsp; &nbsp;&nbsp;where&nbsp;exists( &nbsp; &nbsp; &nbsp; &nbsp;select&nbsp;*&nbsp;from&nbsp;to_delete &nbsp; &nbsp; &nbsp; &nbsp;where&nbsp;to_delete.day = test.day&nbsp;and&nbsp;to_delete.min_id &lt;&gt; test.id &nbsp; &nbsp; )</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:center;background-color:#FFFFFF;"><br></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:center;background-color:#FFFFFF;"><br></p><span style="color:#007AAA;"><strong><span style="font-size:18px;">如何查找多列上的重复行</span></strong></span><br><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">有人最近问到这样的</span><span style="line-height:24.5px;font-size:14px;color:#007AAA;">问题</span><span style="line-height:24.5px;font-size:14px;color:#000000;">:我的一个表上有两个字段b和c,分别关联到其他两个表的b和c字段。我想要找出在b字段或者c字段上具有重复值的行。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">咋看很难明白,通过对话后我理解了:他想要对b和c分别创建unique索引。如上所述,查找在某一字段上具有重复值的行很简单,只要用group分组,然后计算组的大小。并且查找全部字段重复的行也很简单,只要把所有字段放到group子句。但如果是判断b字段重复或者c字段重复,问题困难得多。这里提问者用到的样本数据</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;"></span></p> <pre>create&nbsp;table&nbsp;a_b_c( &nbsp; &nbsp; a&nbsp;int&nbsp;not&nbsp;null&nbsp;primary&nbsp;key&nbsp;auto_increment, &nbsp; &nbsp; b&nbsp;int, &nbsp; &nbsp; c&nbsp;int&nbsp;&nbsp; ); &nbsp; &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(1,&nbsp;1); &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(1,&nbsp;2); &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(1,&nbsp;3); &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(2,&nbsp;1); &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(2,&nbsp;2); &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(2,&nbsp;3); &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(3,&nbsp;1); &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(3,&nbsp;2); &nbsp; insert&nbsp;into&nbsp;a_b_c(b,c)&nbsp;values&nbsp;(3,&nbsp;3);</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;"></span><span style="line-height:24.5px;font-size:14px;color:#000000;">现在,你可以轻易看到表里面有一些重复的行,但找不到两行具有相同的二元组{b, c}。这就是为什么问题会变得困难了。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#007AAA;"><strong>错误的查询语句</strong></span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">如果把两列放在一起分组,你会得到不同的结果,具体看如何分组和计算大小。提问者恰恰是困在了这里。有时候查询语句找到一些重复行却漏了其他的。这是他用到了查询&nbsp;&nbsp;</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;"></span></p> <pre>select&nbsp;b, c,&nbsp;count(*)&nbsp;from&nbsp;a_b_c &nbsp; group&nbsp;by&nbsp;b, c &nbsp; having&nbsp;count(distinct&nbsp;b &gt;&nbsp;1) &nbsp; &nbsp;&nbsp;or&nbsp;count(distinct&nbsp;c &gt;&nbsp;1);</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;">结果返回所有的行,因为CONT(*)总是1.为什么?因为 &gt;1 写在COUNT()里面。这个错误很容易被忽略,事实上等效于</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;"></span></p> <pre>select&nbsp;b, c,&nbsp;count(*)&nbsp;from&nbsp;a_b_c &nbsp; group&nbsp;by&nbsp;b, c &nbsp; having&nbsp;count(1) &nbsp; &nbsp;&nbsp;or&nbsp;count(1);</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;">为什么?因为(b &gt; 1)是一个布尔值,根本不是你想要的结果。你要的是</span></p> <pre>select&nbsp;b, c,&nbsp;count(*)&nbsp;from&nbsp;a_b_c &nbsp; group&nbsp;by&nbsp;b, c &nbsp; having&nbsp;count(distinct&nbsp;b) &gt;&nbsp;1&nbsp;&nbsp; &nbsp;&nbsp;or&nbsp;count(distinct&nbsp;c) &gt;&nbsp;1;</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;">返回空结果。很显然,因为没有重复的{b,c}。这人试了很多其他的</span><span style="font-size:14px;line-height:24.5px;color:#FF2941;">OR</span><span style="font-size:14px;line-height:24.5px;">和</span><span style="font-size:14px;line-height:24.5px;color:#FF2941;">AND</span><span style="font-size:14px;line-height:24.5px;">的组合,用来分组的是一个字段,计算大小的是另一个字段,像这样</span></p> <pre>select b, count(*) from a_b_c group by b having count(distinct c) &gt;&nbsp;1; &nbsp; +------+----------+ &nbsp; | b &nbsp; &nbsp;|&nbsp;count(*)&nbsp;| &nbsp; +------+----------+ &nbsp; |&nbsp;&nbsp; &nbsp;1&nbsp;| &nbsp; &nbsp; &nbsp; &nbsp;3 |&nbsp;&nbsp; | &nbsp; &nbsp;2 |&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;3&nbsp;| &nbsp; |&nbsp;&nbsp; &nbsp;3&nbsp;| &nbsp; &nbsp; &nbsp; &nbsp;3 |&nbsp;&nbsp; +------+----------+</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">没有一个能够找出全部的重复行。而且最令人沮丧的是,对于某些情况,这种语句是有效的,如果错误地以为就是这么写法,然而对于另外的情况,很可能得到错误结果。</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">事实上,单纯用GROUP BY 是不可行的。为什么?因为当你对某一字段使用group by时,就会把另一字段的值分散到不同的分组里。对这些字段排序可以看到这些效果,正如分组做的那样。首先,对b字段排序,看看它是如何分组的</span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;background-color:#FFFFFF;"><img class="img_loading" src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==" data-ke-src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWNgYGBgAAAABQABh6FO1AAAAABJRU5ErkJggg==" style="height:336.127px !important;width:668px !important;"></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;">当你对b字段排序(分组),相同值的c被分到不同的组,因此不能用COUNT(DISTINCT c)来计算大小。COUNT()之类的内部函数只作用于同一个分组,对于不同分组的行就无能为力了。类似,如果排序的是c字段,相同值的b也会分到不同的组,无论如何是不能达到我们的目的的。</span><span style="line-height:24.5px;font-size:14px;color:#000000;"></span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="color:#007AAA;"><strong>几种正确的方法</strong></span></p><p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;color:#000000;">也许最简单的方法是分别对某个字段查找重复行,然后用UNION拼在一起,像这样:</span></p> <pre>select&nbsp;b&nbsp;as&nbsp;value,&nbsp;count(*)&nbsp;as&nbsp;cnt,&nbsp;'b'&nbsp;as&nbsp;what_col &nbsp; from&nbsp;a_b_c&nbsp;group&nbsp;by&nbsp;b&nbsp;having&nbsp;count(*) &gt;&nbsp;1&nbsp;&nbsp; union&nbsp;&nbsp; select&nbsp;c&nbsp;as&nbsp;value,&nbsp;count(*)&nbsp;as&nbsp;cnt,&nbsp;'c'&nbsp;as&nbsp;what_col &nbsp; from&nbsp;a_b_c&nbsp;group&nbsp;by&nbsp;c&nbsp;having&nbsp;count(*) &gt;&nbsp;1; &nbsp; +-------+-----+----------+ &nbsp; | value | cnt | what_col | &nbsp; +-------+-----+----------+ &nbsp; | &nbsp; &nbsp; 1 | &nbsp; 3 | b &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; | &nbsp; &nbsp; 2 | &nbsp; 3 | b &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; | &nbsp; &nbsp; 3 | &nbsp; 3 | b &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; | &nbsp; &nbsp; 1 | &nbsp; 3 | c &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; | &nbsp; &nbsp; 2 | &nbsp; 3 | c &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; | &nbsp; &nbsp; 3 | &nbsp; 3 | c &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; +-------+-----+----------+</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="color:#000000;font-size:14px;line-height:24.5px;"></span><span style="font-size:14px;line-height:24.5px;">输出what_col字段为了提示重复的是哪个字段。</span><span style="font-size:14px;line-height:24.5px;color:#007AAA;">另一个办法</span><span style="font-size:14px;line-height:24.5px;">是使用</span><span style="font-size:14px;line-height:24.5px;color:#007AAA;">嵌套查询</span><span style="font-size:14px;line-height:24.5px;">:</span></p> <pre>select a, b, c from a_b_c &nbsp; where b&nbsp;in&nbsp;(select b from a_b_c group by b having count(*) &gt;&nbsp;1) &nbsp; &nbsp; &nbsp;or&nbsp;c&nbsp;in&nbsp;(select c from a_b_c group by c having count(*) &gt;&nbsp;1); &nbsp; +----+------+------+ &nbsp; | a &nbsp;|&nbsp;b &nbsp; &nbsp;| c &nbsp; &nbsp;|&nbsp;&nbsp; +----+------+------+ &nbsp; | &nbsp;7 |&nbsp;&nbsp; &nbsp;1&nbsp;| &nbsp; &nbsp;1 |&nbsp;&nbsp; | &nbsp;8 |&nbsp;&nbsp; &nbsp;1&nbsp;| &nbsp; &nbsp;2 |&nbsp;&nbsp; | &nbsp;9 |&nbsp;&nbsp; &nbsp;1&nbsp;| &nbsp; &nbsp;3 |&nbsp;&nbsp; | 10 |&nbsp;&nbsp; &nbsp;2&nbsp;| &nbsp; &nbsp;1 |&nbsp;&nbsp; | 11 |&nbsp;&nbsp; &nbsp;2&nbsp;| &nbsp; &nbsp;2 |&nbsp;&nbsp; | 12 |&nbsp;&nbsp; &nbsp;2&nbsp;| &nbsp; &nbsp;3 |&nbsp;&nbsp; | 13 |&nbsp;&nbsp; &nbsp;3&nbsp;| &nbsp; &nbsp;1 |&nbsp;&nbsp; | 14 |&nbsp;&nbsp; &nbsp;3&nbsp;| &nbsp; &nbsp;2 |&nbsp;&nbsp; | 15 |&nbsp;&nbsp; &nbsp;3&nbsp;| &nbsp; &nbsp;3 |&nbsp;&nbsp; +----+------+------+</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="font-size:14px;line-height:24.5px;"></span><span style="line-height:24.5px;font-size:14px;color:#000000;">这种方法的</span><span style="line-height:24.5px;font-size:14px;color:#007AAA;">效率</span><span style="line-height:24.5px;font-size:14px;color:#000000;">要比使用UNION低许多,并且显示每一重复的行,而不是重复的字段值。还有一种方法,将自己跟group的嵌套查询结果联表查询。写法比较复杂,但对于复杂的数据或者对效率有较高要求的情况,是很有必要的。</span></p> <pre>select&nbsp;a, a_b_c.b, a_b_c.c &nbsp; from&nbsp;a_b_c &nbsp; &nbsp;&nbsp;left&nbsp;outer&nbsp;join&nbsp;( &nbsp; &nbsp; &nbsp; &nbsp;select&nbsp;b&nbsp;from&nbsp;a_b_c&nbsp;group&nbsp;by&nbsp;b&nbsp;having&nbsp;count(*) &gt;&nbsp;1&nbsp;&nbsp; &nbsp; )&nbsp;as&nbsp;b&nbsp;on&nbsp;a_b_c.b = b.b &nbsp; &nbsp;&nbsp;left&nbsp;outer&nbsp;join&nbsp;( &nbsp; &nbsp; &nbsp; &nbsp;select&nbsp;c&nbsp;from&nbsp;a_b_c&nbsp;group&nbsp;by&nbsp;c&nbsp;having&nbsp;count(*) &gt;&nbsp;1&nbsp;&nbsp; &nbsp; )&nbsp;as&nbsp;c&nbsp;on&nbsp;a_b_c.c = c.c &nbsp; where&nbsp;b.b&nbsp;is&nbsp;not&nbsp;null&nbsp;or&nbsp;c.c&nbsp;is&nbsp;not&nbsp;null</pre> <p style="color:#3E3E3E;font-family:&quot;font-size:16px;text-align:justify;background-color:#FFFFFF;"><span style="line-height:24.5px;font-size:14px;color:#000000;">以上方法可行,我敢肯定还有其他的方法。如果UNION能用,我想会是最简单不过的了。</span></p><div><br></div>
  • news

    程序员为什么一定要用Linux?

    发布时间:2018-03-20

    <p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">大多数人推荐Linux,基本上都会说Linux让你更高效、更优秀。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><span style="font-family:&quot;color:#0C0C0C;line-height:28px;"><strong>然而工具只是工具。</strong></span></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><span style="font-family:&quot;color:#0C0C0C;line-height:28px;"><strong>然而工具只是工具。</strong></span></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><span style="font-family:&quot;color:#0C0C0C;line-height:28px;"><strong>然而工具只是工具。</strong></span></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">优秀程序员和不优秀程序员的区别首先是态度上的区别。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">他们有自己的理想,思考很多,不管是项目开始之前还是在项目进行中,项目完成之后也会进行总结。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">他们对待问题比较严谨,思考比较全面,在动手写代码之前肯定经过了一定的思考,对可能引入的问题进行预估。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">而不优秀的程序员对待问题比较随意,也就是态度上不是那么认真,代码写的也比较随意:他们不会意识到他们的代码已经污染了整个项目。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">除了态度上的不同,在能力上也有很大的差别。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">遇到比较难缠的问题,优秀的程序员总是能从原理出发,一针见血的看出问题的真正原因,进而解决问题,而不优秀的程序员总是停留在表面——<strong>认为Linux会把你变得优秀就是停留在表面,只有你自己才能把你变优秀。</strong></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><strong><span style="color:#666666;line-height:32px;font-size:16px;">那么Linux的好处到底在哪里呢?</span></strong></p><p style="font-family:&quot;color:#333333;font-size:14px;background-color:#FFFFFF;"><br></p><p class="" style="font-family:&quot;color:#757576;font-size:18px;text-align:center;background:#FFFFFF;">0<span class="" style="color:#666666;line-height:36px;">1</span></p><p class="" style="font-family:&quot;color:#333333;background-color:#FFFFFF;font-size:18px;">开源</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><br></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">这个我想不用解释。</p><p style="font-family:&quot;color:#333333;font-size:14px;background-color:#FFFFFF;"><br></p><p class="" style="font-family:&quot;color:#757576;font-size:18px;text-align:center;background:#FFFFFF;">0<span class="" style="color:#666666;line-height:36px;">2</span></p><p class="" style="font-family:&quot;color:#333333;background-color:#FFFFFF;font-size:18px;">多用户、多任务、多线程</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><br></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">Linux系统同时可以支持多个用户,每个用户对自己的文件设备有特殊的权利,能够保证各用户之间互不干扰,就像手机开了助手一样,同时登陆多个qq账号,当硬件配置非常高时,每个用户还可以同时执行多个任务、多个线程同时工作、提高效率,简直是完美的一塌糊涂,单凭多用户而言就完爆其他操作系统。</p><p style="font-family:&quot;color:#333333;font-size:14px;background-color:#FFFFFF;"><br></p><p class="" style="font-family:&quot;color:#757576;font-size:18px;text-align:center;background:#FFFFFF;">0<span class="" style="color:#666666;line-height:36px;">3</span></p><p class="" style="font-family:&quot;color:#333333;background-color:#FFFFFF;font-size:18px;">稳定性和高效性</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><br></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">你也许会听到Windows服务器长时间运行而突然宕机,但你绝不会听到Linux系统服务器因为长时间不关机会卡死,在Linux上几乎是不会出现这种情况的。Linux服务器可以无休止的运行下去不宕机,因为它继承了Unix卓越的稳定性和高效性。正因为它的稳定才获得了众多用户的青睐,因为它的高效,它的使用范围更加广阔,然而Linux还可以提供一些高可靠性的服务,比如:LNMP、虚拟化、数据库服务等等。</p><p style="font-family:&quot;color:#333333;font-size:14px;background-color:#FFFFFF;"><br></p><p class="" style="font-family:&quot;color:#757576;font-size:18px;text-align:center;background:#FFFFFF;">0<span class="" style="color:#666666;line-height:36px;">4</span></p><p class="" style="font-family:&quot;color:#333333;background-color:#FFFFFF;font-size:18px;">安全性和SELinux</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><br></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">其安全性相比其他系统也要安全很多,由于Linux拥有相当庞大的用户和开源社区支持,因此能很快发现系统漏洞,并迅速发布安全补丁及时更新,同时还具有很强的“免疫力”特点,很少受到病毒攻击,对于一个开放式系统而言,在方便用户的同时,很可能存在安全隐患。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">不过,利用Linux自带防火墙(iptables,firewalld)、入侵检测和安全认证等工具,及时修补系统的漏洞,就能大大提高Linux系统的安全性,让黑客们无机可乘,同时还有安全增强机制SElinux,在linux内核中提供强制访问控制,功能非常全面,能够很好保护系统和服务,不过很多人喜欢把它关闭,这相对安全性就不是很好了。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">还有Tcp_wrappers也能够提供很好的网络服务访问控制,Linux系统对于用户和文件管理权限的管理也是相当出色的,能够很好的控制权限,保证文件的机密性,也是其他系统无法比拟,所以Linux系统在一定程度上是坚不可摧的。</p><p style="font-family:&quot;color:#333333;font-size:14px;background-color:#FFFFFF;"><br></p><p class="" style="font-family:&quot;color:#757576;font-size:18px;text-align:center;background:#FFFFFF;">0<span class="" style="color:#666666;line-height:36px;">5</span></p><p class="" style="font-family:&quot;color:#333333;background-color:#FFFFFF;font-size:18px;">性能优势</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;"><br></p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">由于Linux要保证其稳定性,所以并没有像其它操作系统一样内核如此臃肿庞大、漏洞百出,随着Linux内核的不断更新,不断提升着优势,Linux操作系统能把服务器的硬件优势体现的淋漓尽致,因为Linux系统吸取了Unix系统近1/4世纪发展的经验,最主要的是Linux开放源代码,保证系统稳定性,更好的调用硬件功能,同时还提供了丰富的系统资源工具top,freee,df,vmstat,dmesg,iostat,sar,uptime等,方便查看资源的利用率。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">以上这些足够让你投向Linux的怀抱了。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">当然,除了这些,还有一些说不定道不明的定西,比如:</p><h2 style="font-family:微软雅黑;color:#A1A1A1;font-size:16px;font-weight:normal;text-align:justify;background-color:#FFFFFF;"><span style="font-family:&quot;color:#666666;line-height:36px;font-size:18px;">bigger than bigger</span></h2><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">把你的Linux系统拿出去,开始用命令行做点事情。</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">比如说,输入 sudo rm -rf /*</p><p style="font-family:微软雅黑;color:#A1A1A1;font-size:14px;text-align:justify;background-color:#FFFFFF;">在外行人看来,非常之酷炫!</p>
  • news

    黑客用勒索软件攻击机器人 损失比攻击PC更大

    发布时间:2018-03-13

    <p style="margin-left:16px;font-family:&quot;font-size:14px;background-color:#FFFFFF;color:#3E3E3E;"><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;">安全咨询公司IOActive最近发起了一场测试性质的概念攻击,通过勒索软件来对大公司进行攻击。这次攻击并没有在公司或个人电脑上加密文件获取数据,相反研究人员攻击了另一种新形势的计算机,也就是机器人。机器人现在在汽车制造、医疗等许多领域都有很深层次的运用,破坏这些机器人的工作环境,可以让大公司每一秒都损失一大笔钱。</span><br><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;"></span></p><p style="margin-left:16px;font-family:&quot;font-size:14px;background-color:#FFFFFF;color:#3E3E3E;"><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;">一个攻击矢量依赖于机器人如何处理数据,尽管它们通常包含内部存储组件,但大多数由机器人处理的数据仍大规模传输。这就意味着机器人接收、处理数据,然后将数据发送回存储源中。这些数据可以包含高清视频、音频、客户的支付信息以及如果执行当前任务的说明。</span></p><p style="margin-left:16px;font-family:&quot;font-size:14px;background-color:#FFFFFF;color:#3E3E3E;"><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;">研究人员表示:“在支付赎金之前,攻击者可以将目标锁定在关键机器人的组件上,而不是对数据进行加密处理。”</span></p><p style="margin-left:16px;font-family:&quot;font-size:14px;background-color:#FFFFFF;color:#3E3E3E;"><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;">为了证明自己的理论,研究人员将自己的攻击重点放在了NAO机器人上。这是一种主要在研究和教学领域使用的高度化机器人,在全球范围内的使用量大约有1万部。它的操作系统以及相关漏洞与软银的Pepper机器人有些相似,都是面向商业的机器人。已近累计在2000个企业的2万多个部门中部署。就算是Sprint这样的大型企业也已经开始使用Pepper来帮助服务人员进行销售与指导。</span></p><p style="margin-left:16px;font-family:&quot;font-size:14px;background-color:#FFFFFF;color:#3E3E3E;"><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;">攻击的最开始是利用一个没有记录的功能,允许任何人远程执行命令。在此之后,研究人员禁用管理功能,更改了机器人的默认功能,并将所有视频和音频信息发送到网络远程服务器上。其他步骤包括提高用户权限、破坏工厂重置机制、并感染所有行为文件。换句话说,它们会让机器人觉得很不舒服,甚至是“身体”上的损害。</span></p><p style="margin-left:16px;font-family:&quot;font-size:14px;background-color:#FFFFFF;color:#3E3E3E;"><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;">通过对机器人的劫持,黑客可以完全中断服务,导致企业在每一秒钟都损失金钱。他们甚至可以强迫机器人向顾客展示露骨的色情内容,在一对一的互动中咒骂顾客,或者进行暴力活动。扭转这种行为的唯一方法就是屈服于黑客,因为最终支付赎金的成本可能比修理费用更低。</span></p><p style="margin-left:16px;font-family:&quot;font-size:14px;background-color:#FFFFFF;color:#3E3E3E;"><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;">考虑到隐私和亲密关系的情况,这种局面甚至适用于性爱机器人。用户可能会把钱花在给黑客上支付酬金上,而不是打电话给技术支持直接联系客服,并安排客服来修理。</span></p><p style="margin-left:16px;font-family:&quot;font-size:14px;background-color:#FFFFFF;color:#3E3E3E;"><span style="font-family:Optima-Regular, PingFangTC-light;color:#666666;line-height:28px;">“其实联系客服售后的价格并不便宜,”报告称。“工厂重新设置或修复软件和硬件问题并不容易。通常情况下,当一个机器人出现故障时,你必须把它还给工厂或者雇技术人员来修理它。不管怎样,你可能要等上几周才能恢复正常使用的状态。”</span></p>
  • news

    为初学者介绍 Linux whereis 命令(5个例子)

    发布时间:2018-02-26

    <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">有时,在使用命令行的时候,我们需要快速找到某一个命令的二进制文件所在位置。这种情况下可以选择&nbsp;<span style="font-family:&quot;color:#4D8AD8;line-height:28px;">find</span><span class="" style="font-family:&quot;color:#FFFFFF;line-height:1em;font-size:9px;vertical-align:super;background-color:#666666;">[1]</span>&nbsp;命令,但使用它会耗费时间,可能也会出现意料之外的情况。有一个专门为这种情况设计的命令:whereis。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">在这篇文章里,我们会通过一些便于理解的例子来解释这一命令的基础内容。但在这之前,值得说明的一点是,下面出现的所有例子都在 Ubuntu 16.04 LTS 下测试过。</p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">Linux whereis 命令</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">whereis&nbsp;命令可以帮助用户寻找某一命令的二进制文件,源码以及帮助页面。下面是它的格式:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">whereis</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">[</span><span class="" style="color:#B8FFB8;line-height:28px;">options</span><span class="" style="color:#B8FFB8;line-height:28px;">]</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">[-</span><span class="" style="color:#B8FFB8;line-height:28px;">BMS directory</span><span class="" style="color:#B8FFB8;line-height:28px;">...</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">f</span><span class="" style="color:#B8FFB8;line-height:28px;">]</span><span class="" style="color:#B8FFB8;line-height:28px;"> name</span><span class="" style="color:#B8FFB8;line-height:28px;">...</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">这是这一命令的 man 页面给出的解释:</p><blockquote style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;"><p style="font-family:&quot;color:#333333;">whereis&nbsp;可以查找指定命令的二进制文件、源文件和帮助文件。 被找到的文件在显示时,会去掉主路径名,然后再去掉文件的(单个)尾部扩展名 (如:&nbsp;.c),来源于源代码控制的&nbsp;s.&nbsp;前缀也会被去掉。接下来,whereis&nbsp;会尝试在标准的 Linux 位置里寻找具体程序,也会在由&nbsp;$PATH&nbsp;和&nbsp;$MANPATH&nbsp;指定的路径中寻找。</p></blockquote><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">下面这些以 Q&amp;A 形式出现的例子,可以给你一个关于如何使用 whereis 命令的直观感受。</p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">Q1. 如何用 whereis 命令寻找二进制文件所在位置?</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">假设你想找,比如说,whereis&nbsp;命令自己所在位置。下面是你具体的操作:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">whereis</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#E28964;line-height:28px;">whereis</span></p></li></ol></pre> <p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;text-align:center;"><img src="http://115.29.210.249/tggPic/content/2018-02/1519636813469.jpg" data-ke-src="http://115.29.210.249/tggPic/content/2018-02/1519636813469.jpg" alt=""></p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;text-align:center;"><span style="font-family:&quot;color:#333333;">How to find location of binary file using whereis</span></p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">需要注意的是,输出的第一个路径才是你想要的结果。使用&nbsp;whereis&nbsp;命令,同时也会显示帮助页面和源码所在路径。(如果能找到的情况下会显示,但是在这一例中没有找到)所以你在输出中看见的第二个路径就是帮助页面文件所在位置。</p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">Q2. 怎么在搜索时规定只搜索二进制文件、帮助页面,还是源代码呢?</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">如果你想只搜索,假设说,二进制文件,你可以使用&nbsp;-b&nbsp;&nbsp;这一命令行选项。例如:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">whereis</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">b </span><span class="" style="color:#E28964;line-height:28px;">cp</span></p></li></ol></pre> <p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;text-align:center;"><img src="http://115.29.210.249/tggPic/content/2018-02/1519636827774.jpg" data-ke-src="http://115.29.210.249/tggPic/content/2018-02/1519636827774.jpg" alt=""></p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;text-align:center;"><span style="font-family:&quot;color:#333333;">How to specifically search for binaries, manuals, or source code</span></p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">类似的, &nbsp;-m&nbsp;和&nbsp;-s&nbsp;这两个&nbsp;选项分别对应 帮助页面和源码。</p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">Q3.如何限制 whereis 命令搜索位置?</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">默认情况下,whereis&nbsp;是从由匹配符所定义的硬编码路径来寻找文件的。但如果你想的话,你可以用命令行选项来限制搜索。例如,如果你只想在&nbsp;/usr/bin&nbsp;寻找二进制文件,你可以用&nbsp;-B&nbsp;这一选项来实现。</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">whereis</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">B </span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">usr</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">bin</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">f </span><span class="" style="color:#E28964;line-height:28px;">cp</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">注意:使用这种方式时可以给出多个路径。使用&nbsp;-f&nbsp;这一选项来明确分隔目录列表和要搜索的文件名。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">类似的,如果你想只搜索帮助文件或源码,你可以对应使用 &nbsp;-M&nbsp;和&nbsp;-S&nbsp;&nbsp;这两个选项。</p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">Q4. 如何查看 whereis 的搜索路径?</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">与此相对应的也有一个选项。只要在&nbsp;whereis&nbsp;后加上&nbsp;-l。</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">whereis</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">l</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">这是例子的部分输出结果:</p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;text-align:center;"><img src="http://115.29.210.249/tggPic/content/2018-02/1519636838506.jpg" data-ke-src="http://115.29.210.249/tggPic/content/2018-02/1519636838506.jpg" alt=""></p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;text-align:center;"><span style="font-family:&quot;color:#333333;">How to see paths that whereis uses for search</span></p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">Q5. 如何找到一个有异常条目的命令?</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">对于&nbsp;whereis&nbsp;命令来说,如果一个命令对每个显式的请求类型都不止一项,则该命令被视为异常。例如,没有可用文档的命令,或者对应文档分散在各处的命令都可以算作异常命令。 当使用&nbsp;-u&nbsp;这一选项,whereis&nbsp;就会显示那些有异常条目的命令。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">例如,下面这一例子就显示,在当前目录中,没有对应文档或有多个文档的命令。</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">whereis</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">m </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">u </span><span class="" style="color:#B8FFB8;line-height:28px;">*</span></p></li></ol></pre> <p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">总结</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">我觉得,whereis&nbsp;不是那种你需要经常使用的命令行工具。但在遇到某些特殊情况时,它绝对会让你的生活变得轻松。我们已经涉及了这一工具提供的一些重要命令行选项,所以要注意练习。想了解更多信息,直接去看它的&nbsp;<span style="font-family:&quot;color:#4D8AD8;line-height:28px;">man</span><span class="" style="font-family:&quot;color:#FFFFFF;line-height:1em;font-size:9px;vertical-align:super;background-color:#666666;">[2]</span>&nbsp;页面吧。</p>
  • news

    用 Apache 服务器模块保护您的网站免受应用层 DOS 攻击

    发布时间:2018-02-05

    <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;"><span style="color:#999999;line-height:19.2px;">&nbsp; &nbsp; 通过配置普通的网页服务器,可以保护网页免受应用层攻击,至少是适度的防护。防止这种形式的攻击是非常重要的,因为 Cloudflare 最近 报告称 网络层攻击的数量正在减少,而应用层攻击的数量则在增加。</span></p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">&nbsp; &nbsp; &nbsp;有多种可以导致网站下线的攻击方法,比较复杂的方法要涉及数据库和编程方面的技术知识。一个更简单的方法被称为“拒绝服务Denial Of Service”(DOS)攻击。这个攻击方法的名字来源于它的意图:使普通客户或网站访问者的正常服务请求被拒绝。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">一般来说,有两种形式的 DOS 攻击:</p><span style="color:#666666;font-family:&quot;font-size:14px;background-color:#FFFFFF;">☉&nbsp;OSI 模型的三、四层,即网络层攻击☉&nbsp;OSI 模型的七层,即应用层攻击</span><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">第一种类型的 DOS 攻击——网络层,发生于当大量的垃圾流量流向网页服务器时。当垃圾流量超过网络的处理能力时,网站就会宕机。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">第二种类型的 DOS 攻击是在应用层,是利用合法的服务请求,而不是垃圾流量。当页面请求数量超过网页服务器能承受的容量时,即使是合法访问者也将无法使用该网站。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">本文将着眼于缓解应用层攻击,因为减轻网络层攻击需要大量的可用带宽和上游提供商的合作,这通常不是通过配置网络服务器就可以做到的。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">通过配置普通的网页服务器,可以保护网页免受应用层攻击,至少是适度的防护。防止这种形式的攻击是非常重要的,因为&nbsp;<span style="font-family:&quot;color:#4D8AD8;line-height:28px;">Cloudflare</span><span class="" style="font-family:&quot;color:#FFFFFF;line-height:1em;font-size:9px;vertical-align:super;background-color:#666666;">[1]</span>&nbsp;最近&nbsp;<span style="font-family:&quot;color:#4D8AD8;line-height:28px;">报告称</span><span class="" style="font-family:&quot;color:#FFFFFF;line-height:1em;font-size:9px;vertical-align:super;background-color:#666666;">[2]</span>&nbsp;网络层攻击的数量正在减少,而应用层攻击的数量则在增加。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">本文将介绍如何使用&nbsp;<span style="font-family:&quot;color:#4D8AD8;line-height:28px;">zdziarski</span><span class="" style="font-family:&quot;color:#FFFFFF;line-height:1em;font-size:9px;vertical-align:super;background-color:#666666;">[3]</span>&nbsp;开发的 Apache2 的模块&nbsp;<span style="font-family:&quot;color:#4D8AD8;line-height:28px;">mod_evasive</span><span class="" style="font-family:&quot;color:#FFFFFF;line-height:1em;font-size:9px;vertical-align:super;background-color:#666666;">[4]</span>。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">另外,mod_evasive 会阻止攻击者通过尝试数百个用户名和密码的组合来进行猜测(即暴力攻击)的企图。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">mod_evasive 会记录来自每个 IP 地址的请求的数量。当这个数字超过相应 IP 地址的几个阈值之一时,会出现一个错误页面。错误页面所需的资源要比一个能够响应合法访问的在线网站少得多。</p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">在 Ubuntu 16.04 上安装 mod_evasive</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">Ubuntu 16.04 默认的软件库中包含了 mod_evasive,名称为 “libapache2-mod-evasive”。您可以使用&nbsp;apt-get&nbsp;来完成安装:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">apt-get</span><span class="" style="color:#B8FFB8;line-height:28px;"> update</span></p></li><li><p><span class="" style="color:#E28964;line-height:28px;">apt-get</span><span class="" style="color:#B8FFB8;line-height:28px;"> upgrade</span></p></li><li><p><span class="" style="color:#E28964;line-height:28px;">apt-get</span><span class="" style="color:#B8FFB8;line-height:28px;"> install libapache2</span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">mod</span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">evasive</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">现在我们需要配置 mod_evasive。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">它的配置文件位于&nbsp;/etc/apache2/mods-available/evasive.conf。默认情况下,所有模块的设置在安装后都会被注释掉。因此,在修改配置文件之前,模块不会干扰到网站流量。</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#89BDFF;line-height:28px;">&lt;IfModule</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#BDB76B;line-height:28px;">mod_evasive20</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span><span class="" style="color:#BDB76B;line-height:28px;">c</span><span class="" style="color:#89BDFF;line-height:28px;">&gt;</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSHashTableSize &nbsp; &nbsp;3097</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSPageCount &nbsp; &nbsp; &nbsp; &nbsp;2</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSSiteCount &nbsp; &nbsp; &nbsp; &nbsp;50</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSPageInterval &nbsp; &nbsp; 1</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSSiteInterval &nbsp; &nbsp; 1</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSBlockingPeriod &nbsp; 10</span></p></li><li></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSEmailNotify &nbsp; &nbsp; &nbsp;you@yourdomain.com</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSSystemCommand &nbsp; &nbsp;"su - someuser -c '/sbin/... %s ...'"</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSLogDir &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "/var/log/mod_evasive"</span></p></li><li><p><span class="" style="color:#89BDFF;line-height:28px;">&lt;/IfModule&gt;</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">第一部分的参数的含义如下:</p><span style="color:#666666;font-family:&quot;font-size:14px;background-color:#FFFFFF;">◈&nbsp;DOSHashTableSize&nbsp;- 正在访问网站的 IP 地址列表及其请求数的当前列表。◈&nbsp;DOSPageCount&nbsp;- 在一定的时间间隔内,每个页面的请求次数。时间间隔由 DOSPageInterval 定义。◈&nbsp;DOSPageInterval&nbsp;- mod_evasive 统计页面请求次数的时间间隔。◈&nbsp;DOSSiteCount&nbsp;- 与&nbsp;DOSPageCount&nbsp;相同,但统计的是来自相同 IP 地址对网站内任何页面的请求数量。◈&nbsp;DOSSiteInterval&nbsp;- mod_evasive 统计网站请求次数的时间间隔。◈&nbsp;DOSBlockingPeriod&nbsp;- 某个 IP 地址被加入黑名单的时长(以秒为单位)。</span><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">如果使用上面显示的默认配置,则在如下情况下,一个 IP 地址会被加入黑名单:</p><span style="color:#666666;font-family:&quot;font-size:14px;background-color:#FFFFFF;">◈&nbsp;每秒请求同一页面超过两次。◈&nbsp;每秒请求 50 个以上不同页面。</span><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">如果某个 IP 地址超过了这些阈值,则被加入黑名单 10 秒钟。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">这看起来可能不算久,但是,mod_evasive 将一直监视页面请求,包括在黑名单中的 IP 地址,并重置其加入黑名单的起始时间。只要一个 IP 地址一直尝试使用 DOS 攻击该网站,它将始终在黑名单中。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">其余的参数是:</p><span style="color:#666666;font-family:&quot;font-size:14px;background-color:#FFFFFF;">◈&nbsp;DOSEmailNotify&nbsp;- 用于接收 DOS 攻击信息和 IP 地址黑名单的电子邮件地址。◈&nbsp;DOSSystemCommand&nbsp;- 检测到 DOS 攻击时运行的命令。◈&nbsp;DOSLogDir&nbsp;- 用于存放 mod_evasive 的临时文件的目录。</span><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">配置 mod_evasive</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">默认的配置是一个很好的开始,因为它不会阻塞任何合法的用户。取消配置文件中的所有参数(DOSSystemCommand&nbsp;除外)的注释,如下所示:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#89BDFF;line-height:28px;">&lt;IfModule</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#BDB76B;line-height:28px;">mod_evasive20</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span><span class="" style="color:#BDB76B;line-height:28px;">c</span><span class="" style="color:#89BDFF;line-height:28px;">&gt;</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; DOSHashTableSize &nbsp; 3097</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; DOSPageCount &nbsp; &nbsp; &nbsp; 2</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; DOSSiteCount &nbsp; &nbsp; &nbsp; 50</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; DOSPageInterval &nbsp; &nbsp;1</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; DOSSiteInterval &nbsp; &nbsp;1</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; DOSBlockingPeriod &nbsp;10</span></p></li><li></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; DOSEmailNotify &nbsp; &nbsp; &nbsp; JohnW@example.com</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; #DOSSystemCommand &nbsp; &nbsp;"su - someuser -c '/sbin/... %s ...'"</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; DOSLogDir &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"/var/log/mod_evasive"</span></p></li><li><p><span class="" style="color:#89BDFF;line-height:28px;">&lt;/IfModule&gt;</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">必须要创建日志目录并且要赋予其与 apache 进程相同的所有者。这里创建的目录是&nbsp;/var/log/mod_evasive&nbsp;,并且在 Ubuntu 上将该目录的所有者和组设置为&nbsp;www-data&nbsp;,与 Apache 服务器相同:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">mkdir</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#E28964;line-height:28px;">var</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">log</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">mod_evasive</span></p></li><li><p><span class="" style="color:#E28964;line-height:28px;">chown</span><span class="" style="color:#B8FFB8;line-height:28px;"> www</span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">data</span><span class="" style="color:#B8FFB8;line-height:28px;">:</span><span class="" style="color:#B8FFB8;line-height:28px;">www</span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">data </span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#E28964;line-height:28px;">var</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">log</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">mod_evasive</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">在编辑了 Apache 的配置之后,特别是在正在运行的网站上,在重新启动或重新加载之前,最好检查一下语法,因为语法错误将影响 Apache 的启动从而使网站宕机。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">Apache 包含一个辅助命令,是一个配置语法检查器。只需运行以下命令来检查您的语法:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#B8FFB8;line-height:28px;">apachectl configtest</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">如果您的配置是正确的,会得到如下结果:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#89BDFF;line-height:28px;">Syntax</span><span class="" style="color:#B8FFB8;line-height:28px;"> OK</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">但是,如果出现问题,您会被告知在哪部分发生了什么错误,例如:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#B8FFB8;line-height:28px;">AH00526</span><span class="" style="color:#B8FFB8;line-height:28px;">:</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Syntax</span><span class="" style="color:#B8FFB8;line-height:28px;"> error on line </span><span class="" style="color:#3387CC;line-height:28px;">6</span><span class="" style="color:#B8FFB8;line-height:28px;"> of </span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">etc</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">apache2</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">mods</span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">enabled</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#B8FFB8;line-height:28px;">evasive</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span><span class="" style="color:#B8FFB8;line-height:28px;">conf</span><span class="" style="color:#B8FFB8;line-height:28px;">:</span></p></li><li><p><span class="" style="color:#89BDFF;line-height:28px;">DOSSiteInterval</span><span class="" style="color:#B8FFB8;line-height:28px;"> takes one argument</span><span class="" style="color:#B8FFB8;line-height:28px;">,</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Set</span><span class="" style="color:#B8FFB8;line-height:28px;"> site interval</span></p></li><li><p><span class="" style="color:#89BDFF;line-height:28px;">Action</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#65B042;line-height:28px;">'configtest'</span><span class="" style="color:#B8FFB8;line-height:28px;"> failed</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span></p></li><li><p><span class="" style="color:#89BDFF;line-height:28px;">The</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Apache</span><span class="" style="color:#B8FFB8;line-height:28px;"> error log may have </span><span class="" style="color:#E28964;line-height:28px;">more</span><span class="" style="color:#B8FFB8;line-height:28px;"> information</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">如果您的配置通过了 configtest 的测试,那么这个模块可以安全地被启用并且 Apache 可以重新加载:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#B8FFB8;line-height:28px;">a2enmod evasive</span></p></li><li><p><span class="" style="color:#E28964;line-height:28px;">systemctl</span><span class="" style="color:#B8FFB8;line-height:28px;"> reload apache2</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span><span class="" style="color:#B8FFB8;line-height:28px;">service</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">mod_evasive 现在已配置好并正在运行了。</p><p class="" style="font-family:Optima-Regular, PingFangTC-light;color:#FFFFFF;font-size:1.4em;background-color:#3F51B5;">测试</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">为了测试 mod_evasive,我们只需要向服务器提出足够的网页访问请求,以使其超出阈值,并记录来自 Apache 的响应代码。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">一个正常并成功的页面请求将收到如下响应:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">200</span><span class="" style="color:#B8FFB8;line-height:28px;"> OK</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">但是,被 mod_evasive 拒绝的将返回以下内容:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">403</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Forbidden</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">以下脚本会尽可能迅速地向本地主机(127.0.0.1,localhost)的 80 端口发送 HTTP 请求,并打印出每个请求的响应代码。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">你所要做的就是把下面的 bash 脚本复制到一个文件中,例如&nbsp;mod_evasive_test.sh:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#AEAEAE;line-height:28px;font-style:italic;">#</span><span class="" style="color:#B8FFB8;line-height:28px;">!</span><span class="" style="color:#65B042;line-height:28px;">/bin/</span><span class="" style="color:#E28964;line-height:28px;">bash</span></p></li><li><p><span class="" style="color:#E28964;line-height:28px;">set</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">e</span></p></li><li></li><li><p><span class="" style="color:#E28964;line-height:28px;">for</span><span class="" style="color:#B8FFB8;line-height:28px;"> i </span><span class="" style="color:#E28964;line-height:28px;">in</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">{</span><span class="" style="color:#3387CC;line-height:28px;">1.</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span><span class="" style="color:#3387CC;line-height:28px;">50</span><span class="" style="color:#B8FFB8;line-height:28px;">};</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#E28964;line-height:28px;">do</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;"> &nbsp; &nbsp; &nbsp; &nbsp;curl </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">s </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">I </span><span class="" style="color:#3387CC;line-height:28px;">127.0</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span><span class="" style="color:#3387CC;line-height:28px;">0.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">|</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#E28964;line-height:28px;">head</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#B8FFB8;line-height:28px;">-</span><span class="" style="color:#B8FFB8;line-height:28px;">n </span><span class="" style="color:#3387CC;line-height:28px;">1</span></p></li><li><p><span class="" style="color:#E28964;line-height:28px;">done</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">这个脚本的部分含义如下:</p><span style="color:#666666;font-family:&quot;font-size:14px;background-color:#FFFFFF;">◈&nbsp;curl&nbsp;- 这是一个发出网络请求的命令。◈&nbsp;-s&nbsp;- 隐藏进度表。◈&nbsp;-I&nbsp;- 仅显示响应头部信息。◈&nbsp;head&nbsp;- 打印文件的第一部分。◈&nbsp;-n 1&nbsp;- 只显示第一行。</span><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">然后赋予其执行权限:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#E28964;line-height:28px;">chmod</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">755</span><span class="" style="color:#B8FFB8;line-height:28px;"> mod_evasive_test</span><span class="" style="color:#B8FFB8;line-height:28px;">.</span><span class="" style="color:#B8FFB8;line-height:28px;">sh</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">在启用 mod_evasive&nbsp;<span style="font-family:&quot;color:#C40F0F;line-height:28px;">之前</span>,脚本运行时,将会看到 50 行 “HTTP / 1.1 200 OK” 的返回值。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">但是,启用 mod_evasive 后,您将看到以下内容:</p> <pre class=""><ol class="list-paddingleft-2"><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">200</span><span class="" style="color:#B8FFB8;line-height:28px;"> OK</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">200</span><span class="" style="color:#B8FFB8;line-height:28px;"> OK</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">403</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Forbidden</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">403</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Forbidden</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">403</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Forbidden</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">403</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Forbidden</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;">HTTP</span><span class="" style="color:#B8FFB8;line-height:28px;">/</span><span class="" style="color:#3387CC;line-height:28px;">1.1</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#3387CC;line-height:28px;">403</span><span class="" style="color:#B8FFB8;line-height:28px;"> </span><span class="" style="color:#89BDFF;line-height:28px;">Forbidden</span></p></li><li><p><span class="" style="color:#B8FFB8;line-height:28px;">...</span></p></li></ol></pre> <p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">前两个请求被允许,但是在同一秒内第三个请求发出时,mod_evasive 拒绝了任何进一步的请求。您还将收到一封电子邮件(邮件地址在选项&nbsp;DOSEmailNotify&nbsp;中设置),通知您有 DOS 攻击被检测到。</p><p style="font-family:Optima-Regular, PingFangTC-light;color:#3E3E3E;font-size:14px;background-color:#FFFFFF;">mod_evasive 现在已经在保护您的网站啦!</p>
在线咨询 ×

您好,请问有什么可以帮您?我们将竭诚提供最优质服务!