表达式中的语法错误(错误标记为“INPUT(策略接受)| cut -d ' ' -f1)
Syntax error in expression (error token is "INPUT (policy ACCEPT) | cut -d ' ' -f1)
嗨,我最近开始学习 bash 脚本,因为我很“新手”,所以可以说我希望能得到一些帮助。我有这个问题,我似乎无法自己解决。我希望这个程序通读每一行以检查给定 IP 地址是否有任何 iptables 规则。如果有:取行号,然后用iptables -R INPUT $lineNumberHere -s $IP_ADDRESS -j $newPolicy.
更改或删除
但是程序开始读取第一行并将行号注册为“Chain”和“num”,这导致了错误。有没有绕过这两条线的方法?
澄清一下。我是 运行 程序 root
# The IP address is listen in rules
# Find the line number of the rule
echo ""
echo "The IP allready has a rule in iptables"
iptables -L INPUT --line-numbers | while read line; do
echo ""
echo "Checking line: $line"
LINE_NUMBER=$(($line | cut -d " " -f1))
BANNED_IP=$(($line | cut -d " " -f4 | cut -d "/" -f1))
re='^[0-9]+$'
if [[ "$LINE_NUMBER" =~ $re ]]; then
echo "Line nr. $LINE_NUMBER"
if [ "$IP_ADDRESS"="$BANNED_IP" ]; then
echo "Changing status to BANNED"
iptables -R INPUT "$LINE_NUMBER" -s "$IP_ADDRESS" -j DROP
fi
else
echo "error: Not a number" >&2
continue;
fi
done
此脚本中存在几个语法问题。在行中:
LINE_NUMBER=$(($line | cut -d " " -f1))
BANNED_IP=$(($line | cut -d " " -f4 | cut -d "/" -f1))
...有两个问题:$(( ))
将其内容计算为算术表达式,而不是命令(这就是为什么您会收到“表达式中的语法错误”错误)。要 运行 命令并捕获其输出,您需要单级括号:$( )
而不是 $(( ))
.
另一个问题是命令管道内部的管道元素必须是命令,而 $line
不是命令,它只是数据。你想要像 $(echo "$line" | cut ...)
.
这样的东西
我立即看到的另一个问题是在这一行中:
if [ "$IP_ADDRESS"="$BANNED_IP" ]; then
您需要在 =
运算符周围留出空格;没有它们,它根本不会被识别为运算符,只是单个长字符串的一部分。所以改用这个:
if [ "$IP_ADDRESS" = "$BANNED_IP" ]; then
可能还有其他问题,这些只是我检查时发现的问题。顺便说一句,我推荐 shellcheck.net 作为指出 bash 脚本中常见错误的简单工具。
虽然 Gordon 已经回答了您提出的问题,但我想提出改进建议。您不需要 运行 多个 cut
来解析此数据,shell 可以很好地完成。此外,由于 iptables
输出的两行 header 不包含行号是正常的,因此我不会输出会警告和混淆用户的错误消息,只需忽略(不要使用)那些行:
iptables -L INPUT --line-numbers | while read ln _ _ ip _; do ip=${ip%/*}
if [[ $ln =~ ^[0-9]+$ && $ip = $IP_ADDRESS ]]; then
echo Changing $IP_ADDRESS to banned
iptables -R INPUT "$LINE_NUMBER" -s "$IP_ADDRESS" -j DROP
fi
done
注意 [[ ]]
是一种特殊语法,不需要用 " "
引用的变量,尽管您可以使用它们来保持一致性。但不是在正则表达式上,因为引用正则表达式使其成为文字匹配。
嗨,我最近开始学习 bash 脚本,因为我很“新手”,所以可以说我希望能得到一些帮助。我有这个问题,我似乎无法自己解决。我希望这个程序通读每一行以检查给定 IP 地址是否有任何 iptables 规则。如果有:取行号,然后用iptables -R INPUT $lineNumberHere -s $IP_ADDRESS -j $newPolicy.
更改或删除但是程序开始读取第一行并将行号注册为“Chain”和“num”,这导致了错误。有没有绕过这两条线的方法?
澄清一下。我是 运行 程序 root
# The IP address is listen in rules
# Find the line number of the rule
echo ""
echo "The IP allready has a rule in iptables"
iptables -L INPUT --line-numbers | while read line; do
echo ""
echo "Checking line: $line"
LINE_NUMBER=$(($line | cut -d " " -f1))
BANNED_IP=$(($line | cut -d " " -f4 | cut -d "/" -f1))
re='^[0-9]+$'
if [[ "$LINE_NUMBER" =~ $re ]]; then
echo "Line nr. $LINE_NUMBER"
if [ "$IP_ADDRESS"="$BANNED_IP" ]; then
echo "Changing status to BANNED"
iptables -R INPUT "$LINE_NUMBER" -s "$IP_ADDRESS" -j DROP
fi
else
echo "error: Not a number" >&2
continue;
fi
done
此脚本中存在几个语法问题。在行中:
LINE_NUMBER=$(($line | cut -d " " -f1))
BANNED_IP=$(($line | cut -d " " -f4 | cut -d "/" -f1))
...有两个问题:$(( ))
将其内容计算为算术表达式,而不是命令(这就是为什么您会收到“表达式中的语法错误”错误)。要 运行 命令并捕获其输出,您需要单级括号:$( )
而不是 $(( ))
.
另一个问题是命令管道内部的管道元素必须是命令,而 $line
不是命令,它只是数据。你想要像 $(echo "$line" | cut ...)
.
我立即看到的另一个问题是在这一行中:
if [ "$IP_ADDRESS"="$BANNED_IP" ]; then
您需要在 =
运算符周围留出空格;没有它们,它根本不会被识别为运算符,只是单个长字符串的一部分。所以改用这个:
if [ "$IP_ADDRESS" = "$BANNED_IP" ]; then
可能还有其他问题,这些只是我检查时发现的问题。顺便说一句,我推荐 shellcheck.net 作为指出 bash 脚本中常见错误的简单工具。
虽然 Gordon 已经回答了您提出的问题,但我想提出改进建议。您不需要 运行 多个 cut
来解析此数据,shell 可以很好地完成。此外,由于 iptables
输出的两行 header 不包含行号是正常的,因此我不会输出会警告和混淆用户的错误消息,只需忽略(不要使用)那些行:
iptables -L INPUT --line-numbers | while read ln _ _ ip _; do ip=${ip%/*}
if [[ $ln =~ ^[0-9]+$ && $ip = $IP_ADDRESS ]]; then
echo Changing $IP_ADDRESS to banned
iptables -R INPUT "$LINE_NUMBER" -s "$IP_ADDRESS" -j DROP
fi
done
注意 [[ ]]
是一种特殊语法,不需要用 " "
引用的变量,尽管您可以使用它们来保持一致性。但不是在正则表达式上,因为引用正则表达式使其成为文字匹配。