我在 Linux 中创建了一个服务 sshield,用于防止通过 ssh 进行的暴力攻击。我的服务已完成,一切运行良好。
但是...我看到了一个细节。这个服务消耗了太多的 CPU!
它消耗了20.6%,太多了
我的服务在一秒钟内运行了一个无限循环。这会导致 CPU 占用如此之高吗?否则会是什么原因?
Github:https://github.com/cleanet/sshield
评论 sshield:https://www.youtube.com/watch?v=0rj4j7VqXXI
修改 | 2020 年 3 月 1 日 13:09
我编辑了脚本,删除了以下内容:
lineas_antiguas=$(wc -l /var/log/auth.log);
IFS=" " read -ra lineas_antiguas <<< $lineas_antiguas;
添加常量:
declare -r SSHIELD_LOG_FILE="/var/log/sshield.log"
declare -r AUTH_LOG_FILE="/var/log/auth.log"
并用它替换路径。另外,我将 while 循环替换为:
tail -F -n 0 "$AUTH_LOG_FILE" | while read line
do
...
done
并删除:
lineas=$(wc -l /var/log/auth.log);
IFS=" " read -ra lineas <<< $lineas;
linea_contenido=$(tail -n 1 /var/log/auth.log);
我的脚本已在我的 GITHUB 中更新
结果是,它不会消耗太多的 CPU 和内存 0.3% CPU 和 0.2% RAM
但是。为什么服务是重复的
答案1
如果我没看错的话,你是不断地/var/log/auth.log
从头开始计算文件中的行数,并执行以下操作:
while [ TRUE ]
do
lineas=$(wc -l /var/log/auth.log);
...
ip_logueada=$(wc -l /var/log/auth.log | grep -E -o "[0-9]{1,9}")
....
done
因此,承受压力的不仅仅是 CPU,还有硬盘。
如果您确实必须从头开始处理日志文件来计算行数或收集统计数据,那么在脚本启动时只执行一次,不要循环重复此操作,这是浪费和不必要的。
你想要的是某种尾巴在你监视的文件上。因此,你可以使用类似下面的命令:
tail -n0 -F /var/log/auth.log | while read line
do
echo "$line"
# do something
done
此代码片段将在新行写入文件时回显它们。因此,您只需“监听”新行流、解析它们并跟踪有问题的 IP 地址。这种方法应该可以解决您的性能问题。
一点建议:对源文件和目标文件使用变量名。例如,/var/log/auth.log
在代码中多次重复出现,也是如此/var/log/sshield.log
。
您可以在脚本开头添加一些变量,甚至将它们声明为常量(只读变量)像这样:
declare -r SOURCE_LOG_FILE="/var/log/auth.log"
然后你就可以简单地写:tail -n0 -F "$SOURCE_LOG_FILE"
。这样就避免了重复。
我也会划分代码在一些功能块中。例如,您可以拥有:
- 一个用于发送邮件的函数
- 另一个函数是跟踪计数器:您传递一个 IP 地址,它会检查当前会话中记录了多少次违规,如果达到阈值,它会阻止该 IP 地址。
这将使代码更清晰,更易于维护。目前流程不太容易理解,代码到处都是。
你还应该有一个函数日志记录提醒到您的文件/var/log/sshield.log
。您有很多重复如下代码:
echo "logged ip: $ip_logueada - $(date)" >> /var/log/sshield.log
创建一个函数,然后只需将要记录的文本作为参数传递,让函数添加时间戳并将文本写入文件,格式如您所愿。您可以通过摆脱以下代码来简化代码冗余。
现在我不得不同意你正在重新发明轮子,有免费工具可以做更多、更高效。不过,这种练习对于教育目的来说很有好处。