我们的首届伟大的命令行挑战赛非常受欢迎,吸引了来自世界各地的 80 多个参赛作品。
注意:由于比赛的条款和条件,一些开源爱好者没有资格赢得 T 恤,因为他们居住在某些国家或提交了多个解决方案(只能考虑参赛者的第一个解决方案)。 但是,请不要担心,我仍然能够在这篇文章中对这些人给予认可。
挑战
伟大的命令行挑战赛的目标是创建一个单一的命令行程序,以计算来自每个尝试使用 SSH 访问我的主机的 IP 地址的电子邮件数量。 请参阅文章,《 迎接伟大的命令行挑战》
我对这个挑战有自己的简单解决方案,但它不是一个获胜方案。 事实上,许多参赛作品提供了比我自己的更好的解决方案
grep -i banned admin.index | grep SSH | awk '{print $4}' | sort -n | uniq -c | sort -n
我的解决方案提供了一个按 IP 地址升序排序的列表,其中 admin.index 文件中的条目最多。 最后一次排序不是赢得比赛的要求,但这是我喜欢做的事情,以查看大多数攻击来自何处。 此解决方案产生 5377 行输出,因此大约是唯一 IP 地址的数量。 但是,我的解决方案没有考虑到一些异常条目,这些条目中没有 IP 地址。 当我思考这项挑战的目标应该是什么时,我决定不指定应该生成的行数,因为我觉得这可能太局限,并且会对条目施加不必要的约束。 我认为这是一个好主意,因为我收到的大多数条目产生的数字都有些不同。 因此,获胜的解决方案不需要产生与我的解决方案相同行数的数据。
我对 Opensource.com 读者能够提出的针对此问题的许多不同解决方案感到惊讶。 在大多数情况下,即使是相似的条目也存在一些差异。
获奖者
事不宜迟,让我们宣布获奖者!
第一个提交解决方案的参赛作品
来自美国新泽西州汉密尔顿的 Michael DiDomenico
Michael 提交了第一个参赛作品,这是一个可行的解决方案。 我特别喜欢 Michael 使用 sort 命令来确保输出按 IP 地址顺序排序。 他的参赛作品产生 5,295 行输出,这与我自己的结果没有太大差异。 这也是许多其他参赛作品产生的输出行数。
grep "SSH: banned" admin.index | sed 's/","/ /g'| cut -f4 -d" " | grep "^[0-9]" | sort -k1,1n -k2,2 -k3,3n -k4,4n -t. | uniq -c
最短解决方案
来自西班牙马德里的 Víctor Ochoa Rodríguez
Victor 提交了一个 65 个字符的解决方案,该解决方案非常优雅,并且很好地使用了 egrep 来仅选择包含 SSH 以及 IP 地址的行,同时仅打印每行中与表达式匹配的部分。 我从这个条目中了解了“o”选项,因此感谢 Víctor 提供了这一新知识。 该解决方案以及下面的荣誉提名都产生 5,295 行输出。
egrep -o '".F.*H.*\.[0-9]+' admin.index|cut -d\ -f4|sort|uniq -c
最短解决方案荣誉提名
Teresa e Junior 提交了一个长度为 58 个字符的条目; 但是,她没有资格赢得 T 恤。
grep SSH admin.index|grep -Po '(\d+\.){3}\d+'|sort|uniq -c
最具创意解决方案
一点背景知识:前两个类别可以完全根据客观标准进行评判,因此此类别的目的是提供一个机会来认可更具创意的参赛作品。 因此,此类别的获奖者是根据我的主观意见确定的。
而且,我们打成了平局! (两者都将获得一件 T 恤。)
来自爱尔兰科克郡的 Przemo Firszt
Przemo 提交了一个有趣且富有创意的参赛作品,因为它使用了 tee 和 xargs 命令。 它也很独特,因为除了使用管道之外,它还使用 tee 命令将中间数据存储在文件中,tee 命令还将数据传递到 STDOUT,并且最终输出被重定向到另一个文件,而不是允许输出到 STDOUT。 它甚至在最后通过删除临时文件来清理。 此解决方案产生 7,403 行输出。 这似乎是因为许多 IP 地址都有多行。 因此,尽管这不是一个完美的解决方案,但只需稍作修改即可为每个 IP 地址生成单行输出。
grep SSH admin.index | awk '{print $4}' | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sed 's/\".*//' | tee ips | xargs -I % sh -c "echo -ne '%\t' ; grep -o % ips | wc -w" | sort | uniq > results ; rm ips
来自美国德克萨斯州弗里斯科的 Tim Chase
Tim 的参赛作品的独特之处在于它使用了 curl 命令从服务器下载文件,然后它使用 awk 命令来选择文件中的所需行,并从每行中仅选择 IP 地址。 此解决方案产生 5,295 行输出。
curl -s http://www.millennium-technology.com/downloads/admin.index|awk -F, '$1~/SSH: banned/{print $1}'|grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+'|sort|uniq -c
加分解决方案
许多参赛作品的目标是比赛的加分选项,即为每个 IP 地址提供国家/地区名称。 此类别没有奖品,只有在 Opensource.com 上获得提及的满足感。
有两个参赛作品特别引起了我的兴趣; 两者都使用 GeoIP 软件包来提供用于获取国家/地区信息的本地数据库。 另外几个参赛作品使用了 whois 命令,但除此之外,whois 使用远程数据库,并且当从单个 IP 地址访问速度过快时,可能会被阻止。 GeoIP 软件包在标准 Fedora 存储库和 CentOS 的 EPEL 存储库中可用。
来自阿根廷的Gustavo Yzaguirre
Gustavo 提交了一个参赛作品,该作品首先给出了带有计数的 IP 地址的简要列表,然后列出了国家/地区。 它产生 16,419 行输出,其中许多是重复的。 Gustavo 说它没有优化,但这不是要求之一。
awk '/SSH: banned/ && $4 ~ /^[0-9]/ {print $4}' admin.index | sed 's/[^0-9.]*//g' | sort | uniq -c | awk '{printf $1 " " $2 " "; system("geoiplookup "$2)};' | sort -gr | sed 's/ GeoIP Country Edition: / /g'
来自塞尔维亚贝尔格莱德的 Dejan Bogdanovic
Dejan 提交了一个有趣的参赛作品,该作品按频率降序列出了 IP 地址以及国家/地区信息。 Dejan 的参赛作品产生 5,764 行输出。
cat admin.index | egrep -o '([0-9]*\.){3}[0-9]*' | sort -n | uniq -c | sort -nr | awk '{ORS=" "} {print $1} {print $2} {system("geoiplookup " $2 "| cut -d: -f 2 | xargs")}'
结论
感谢所有提交伟大的命令行挑战赛参赛作品的人。 祝贺我们的获奖者,以及那些没有获胜但其参赛作品值得一提的人!
看到你们对问题的许多解释和解决方案真的很有趣和愉快。 此外,一些人提到他们非常喜欢这次比赛,并希望 Opensource.com 举办更多此类比赛。 工作人员和我学到了很多关于举办此类比赛的知识,因此我们希望举办更多比赛,并在进行过程中融入“经验教训”。
4 条评论