Search code examples
linuxbashshellsshiptables

Syntax error in expression (error token is "INPUT (policy ACCEPT) | cut -d ' ' -f1)


Hi I'am recently started learning bash scripts, since I'm quite "green" so to speak I hope I can get some help. I have this problem that I just can't seem to figure out on my own. I want this program to read through every line to check if there are any iptables rules for a given IP address. If there is: Take the number of the line, and then change or delete it with the iptables -R INPUT $lineNumberHere -s $IP_ADDRESS -j $newPolicy.

However the program starts reading the first lines and registers the line number as a "Chain" and "num" which causes the error. Is there a method of bypassing these two lines?

Just to clarify. I am running the program as 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



Solution

  • There are several syntax problems in this script. In the lines:

     LINE_NUMBER=$(($line | cut -d " " -f1))
     BANNED_IP=$(($line | cut -d " " -f4 | cut -d "/" -f1))
    

    ...there are two problems: $(( )) evaluates its contents as an arithmetic expression, not as a command (that's why you're getting a "syntax error in expression" error). To run a command and capture its output, you want a single level of parentheses: $( ) instead of $(( )).

    The other problem is with the command pipeline inside that rhe elements of a pipeline must be commands, and $line isn't one, it's just data. You want something like $(echo "$line" | cut ...).

    The other problem I see immediately is in this line:

    if [ "$IP_ADDRESS"="$BANNED_IP" ]; then
    

    you need spaces around the = operator; without them, it's not recognized as an operator at all, just part of a single long string. So use this instead:

    if [ "$IP_ADDRESS" = "$BANNED_IP" ]; then
    

    There may be other problems, these are just the ones that I spotted on inspection. BTW, I recommend shellcheck.net as an easy tool to point out common mistakes in bash scripts.