0

First I want to apologize for being an absolute noob at programming, writing scripts, etc. I have a question about some code I used to run on my old FreeNAS 11.1 machine. I also created a thread back when I initiated the script. Back then I got the help and my script worked. Now I updated to FreeNAS 11.2 and get some messages and I want to know why they appear and how to fix this.

But first the Background. My script checks if any Client is online (by pinging the IP-address):

#!/bin/bash

HOST1=10.10.0.100 #Client 1
HOST2=10.10.0.101 #Client 2 
HOST3=10.10.0.102 #Client 3 
HOST4=10.10.0.103 #Client 4
HOST5=10.10.0.104 #Client 5

_exit () { 
case $1 in 
1) echo „No Shutdown – At least one PC is online“ ;; 
2) echo „No PC is online – Shutdown“ ;; shutdown -p now }

#Check if IPs are online 
if [ `ping -c 1 -i 1 $HOST1 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST2 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST3 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST4 | grep -wc 100.0%` -eq 0 ] || [ `ping -c 1 -i 1 $HOST5 | grep -wc 100.0%` -eq 0 ] ; then _exit 1;

#All Clients are offline, shutdown else                                                                                                                                                                                           
_exit 2 fi

The script itself works fine. If one client is online the script stops and if all clients are offline the Server shutsdown. But i get the following message when i run it manually via the Shell:

Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
shutdown_check.sh: -wc not found
[: -eq: unexpected operator

When I ran it on my old Server (11.1) i did not get this message so it is interesting for my, why it now occurs.

codeforester
  • 28,846
  • 11
  • 78
  • 104
AlphaInc.
  • 73
  • 7
  • Run `bash -x yourscript`, and the problem will be obvious. – Charles Duffy Nov 20 '19 at 21:34
  • ...well, except for the `grep -wc` error; for *that*, you'll want to compare `man grep` between the two machines. – Charles Duffy Nov 20 '19 at 21:35
  • BTW, consider having a single *array* of hosts, and iterating over the array instead of having a bunch of repeated code. – Charles Duffy Nov 20 '19 at 21:35
  • ...that said, the `grep` error *causes* the "unexpected operator" error, since `-eq` is only valid when it's between a word on the left and a word on the right, and a `grep` that failed with a usage error emits *no* output and thus, when used unquoted, parses into zero words. – Charles Duffy Nov 20 '19 at 21:37
  • 1
    ...anyhow, you'd be in a much better place if you stopped using `grep` altogether and only checked `ping`'s exit status; you wouldn't even need `[` if you did that. – Charles Duffy Nov 20 '19 at 21:37
  • You can simplify `if [ \`cmd\` = 0 ] || [ \`cmd\` = 0 ]` to `if cmd || cmd`. – MAGA Nov 20 '19 at 21:38
  • 2
    http://shellcheck.net – chepner Nov 20 '19 at 21:40
  • 2
    @sergio, that's not a general-purpose simplification -- the former checks *output*; the latter checks *exit status*. Of course, `ping` *does* usefully indicate whether the remote system could be contacted in its exit status (just as `grep` indicates whether any matches were seen in its stdin the same way), so that's not a big change. – Charles Duffy Nov 20 '19 at 21:48
  • @CharlesDuffy thanks for clarifying the difference. – MAGA Nov 20 '19 at 22:01

1 Answers1

1

There are a lot of separate, independent, unrelated bugs in the above code (making the question "too broad" to be within site rules; this community-wiki answer combines answers from the many flagged duplicates). Consider the below rewrite:

#!/bin/bash

hosts=(
  10.10.0.100 #Client 1
  10.10.0.101 #Client 2 
  10.10.0.102 #Client 3 
  10.10.0.103 #Client 4
  10.10.0.104 #Client 5
)

for host in "${hosts[@]}"; do
  if ping -c 1 -i 1 "$host" >/dev/null; then
    echo "No Shutdown - At least one PC ($host) is online"
    exit 0
  fi
done

echo "No PC is online - Shutdown"
shutdown -p now

So, what specifically was wrong with the original code?

  • When you run [ $(...something...) -eq 0 ], you only get a valid test statement if ...something... emits exactly one word as output. When you give grep invalid syntax, it doesn't emit any output at all, so the result is [ -eq 0 ]. Since [ doesn't recognize -eq when not between two separate arguments, you have your error.
  • If you quoted correctly, as in [ "$(...something...)" -eq 0 ], then you'd have a more useful error message (akin to the one given to [ "" -eq 0 ].
  • Your version of grep does not recognize -wc as a valid combination of arguments.
  • The use of grep was itself unnecessary; ping reflects success or failure in exit status, so one can directly run if ping ...; then.
  • The syntax was broken in some other respects as well; running the original code through http://shellcheck.net/ will show them.
Charles Duffy
  • 235,655
  • 34
  • 305
  • 356
  • Hey, First Thank you for your comment, i tried the code and it worked flawless and even faster then the other code. Now i want to add a function which also checks if a scrub or a resilver is still in progress. I found a python-code but it won't bring my anything i guess. Any idea how to implement it in bash ? – AlphaInc. Nov 27 '19 at 19:24
  • Not nearly enough details given in the comment to allow an answer -- I don't even know if you're talking about a btrfs resilver or a ZFS resilver, whether (if it is ZFS) if you're talking about the userspace or kernelspace implementations, etc. – Charles Duffy Nov 27 '19 at 20:50
  • @AlphaInc. If your question is how to programatically get that information from the ZFS tools, you might ask a question about them at [unix.se]; whereas if you *know* how to get that information from the ZFS tools but don't know how to do the language-level operations in bash to interpret the output, consider asking a new question, showing the command you're running, the output you're receiving from it but don't know how to interpret, and your best-effort attempt at interpreting that output. – Charles Duffy Nov 27 '19 at 20:50
  • Well i use FreeNAS 11.2 and I'm talking about ZFS resilver (using RAID-Z2). But I will ask the question in Unix & Linux. – AlphaInc. Nov 27 '19 at 21:03