Bash管道中变量赋值失败:无法将登录失败IP赋值给变量
Bash管道中变量赋值失败:无法将登录失败IP赋值给变量
嗨,我来帮你搞定这个问题!你遇到的核心问题是管道中的变量赋值在子shell里执行,导致父shell拿不到变量值,咱们一步步拆解来看:
你的写法为什么不行?
你原来的命令是这样的:
tail -10 /var/log/authlog | grep '403 Forbidden' | ip_addr=$(grep -oE '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | sort | uniq | sort)
这里的ip_addr=$(...)是在管道的第三个环节执行的,而管道的每个环节都是一个独立的子shell进程。子shell里创建的变量,不会传递回父shell,所以当你在后面执行echo "The following IPs have failed login '$ip_addr'"时,父shell里的ip_addr根本没被赋值,自然是空的。
正确的赋值方式
你需要把整个管道命令的输出结果通过命令替换$(...)直接赋值给变量,这样赋值操作是在父shell里完成的,变量就能被正常读取了:
ip_addr=$(tail -10 /var/log/authlog | grep '403 Forbidden' | grep -oE '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' | sort | uniq | sort)
然后再执行echo命令:
echo "The following IPs have failed login: $ip_addr"
如果想让换行显示更清晰,可以用echo -e,或者直接用printf:
printf "The following IPs have failed login:\n%s\n" "$ip_addr"
额外小技巧:遍历每个IP
要是你需要对每个IP做进一步处理(比如加入防火墙黑名单),可以用循环遍历变量里的IP:
for ip in $ip_addr; do echo "正在处理恶意IP: $ip" # 这里可以加你的处理逻辑,比如 iptables -A INPUT -s $ip -j DROP done
关于你后来用文件的方式
其实输出到文件的写法是没问题的,但如果还是想直接用变量操作,上面的方法就能解决你的问题啦!
备注:内容来源于stack exchange,提问作者Apollo
相关产品推荐
相关产品推荐

