1

I have a string and a command result so I want to compare them:

A="Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination"

B=$(iptables -L)

if [ "$A" == "$B"]; then
    echo "True"
else
    echo "False"
fi

But it returns False.

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
MLSC
  • 5,872
  • 8
  • 55
  • 89
  • No.. This is not working really.. – MLSC Apr 11 '16 at 06:45
  • 1
    You need a space before the closing bracket like this:`if [ "$A" == "$B" ]; then`. Also it is better to use single equal for compatibility reasons. like `if [ "$A" = "$B" ]; then`. – user000001 Apr 11 '16 at 06:54
  • 1
    Does anyone know of a good canonical duplicate for this? It is a quite common problem. – Jonathan Leffler Apr 11 '16 at 06:57
  • @JonathanLeffler We have tried to compile a list of common Bash questions in the [`bash` tag wiki](http://stackoverflow.com/tags/bash/info). It still needs improvement but the canonical dupe I think you are looking for is http://stackoverflow.com/questions/9581064/why-should-be-there-a-space-after-and-before-in-the-bash-script – tripleee Apr 11 '16 at 10:47
  • @tripleee: It seems the syntax error was only part of the trouble so I won't be closing his as a dupe. But thanks for the info about the list of common Bash questions. – Jonathan Leffler Apr 11 '16 at 12:40

3 Answers3

3

It's due to the different amount of whitespace used. You can find that out using the following command:

diff -u <(iptables -L) - <<EOF | cat -A
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
EOF

Output:

--- /dev/fd/63^I2016-04-11 08:59:52.663962140 +0200$
+++ -^I2016-04-11 08:59:52.666667769 +0200$
@@ -1,8 +1,8 @@$
 Chain INPUT (policy ACCEPT)$
-target     prot opt source               destination         $
+target     prot opt source               destination$
 $
 Chain FORWARD (policy ACCEPT)$
-target     prot opt source               destination         $
+target     prot opt source               destination$
 $
 Chain OUTPUT (policy ACCEPT)$
-target     prot opt source               destination         $
+target     prot opt source               destination$

You see, the iptables -L command appends whitespace after destination.

To remove that whitespace, you can use sed:

iptables -L | sed 's/[[:space:]]*$//'

If you also fix the syntax error discovered by Jonathan Leffler, your code should work.

Let me add, that the way you are checking if "the firewall is not active" might be to weak. (a) you see, the iptables -L command is not really meant to be used for text processing. (b) somebody might have added a custom chain but no rules in it. This would let your check fail.

I don't have really an idea how to do it better. Probably changing firewall rules is meant to be a task executed by the administrator himself rather than by programs. :)

Community
  • 1
  • 1
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
2

Spacing!

Wrong:

if [ "$A" == "$B"]; then

Right:

if [ "$A" == "$B" ]; then

[ is a command; it requires spaces around its separate arguments (and around its name, [), and its last argument must be ]. There are grounds to argue that = rather than == is more portable (but == works OK in Bash).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • This is wrong.. because in all states it returns false – MLSC Apr 11 '16 at 07:04
  • 1
    The syntax error is correctly identified and fixed. If you also have problems with the spacing in your string, that is a separate bag'o'worms which is hard for anyone not on your machine to resolve. So, you would get a syntax error from the `test` (aka `[`) command when you ran what you showed. The test might also fail after the syntax is fixed because of spacing problems. – Jonathan Leffler Apr 11 '16 at 07:21
1

It doesnt match because of whitespaces at end in iptables -L

A=$(cat <<EOF
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
EOF
)
B="$(iptables -L)"

diff -Z <(echo "$A") <(iptables -L) && echo "True" || echo "False"

check this:

meld differences

btw invoked the meld command like this: meld <(echo "$A") <(iptables -L) (meld is a visual diff tool)

riteshtch
  • 8,629
  • 4
  • 25
  • 38
  • When It returns `false` it shows some junc data related to diff command. how can I discard them and just print `false`? – MLSC Apr 11 '16 at 07:08
  • 1
    @MLSC use this: `diff -q -Z <(echo "$A") <(iptables -L) && echo "True" || echo "False"`, here the `-q` option mean s `quiet` i.e `-q, --brief report only when files differ ` – riteshtch Apr 11 '16 at 07:10