简体   繁体   中英

Bash script to ping host with while condition

First, I would like to say that I know nothing about bash but I am trying to learn through practice.

So, I am trying to make a script which will send a magic packet to a remote host. While the remote host is starting I would like to print dots on the display.

I really don't have a problem with the wakeonlan part and of course I don't really need a script to do that. However, in order to learn something useful I try to make a script.

So my code is:

#!/bin/bash 

! timeout 0.5 ping -c1 8.8.8.8 > /dev/null 2>&1
if [ $? -eq 1 ]
then
    echo "Host is up"
else
    wakeonlan FF:FF:FF:FF:FF:FF
    echo "Host is starting ..." 
    while ! ping -c1 -w1 -n 8.8.8.8 > /dev/null 2&>1
    do
            printf "%c" "."
    done
    echo "Host is up!\n\n"

fi
exit 0

Now when the host is already up the while loop exits without printing. But when the host is down it outputs infinetely dots on the display, even if the host is up. I really don't understand why the while loop does not stop when the condition is met.

I would appreciate your answer, especially if its aligned with my implementation.

Ok, I think I've figured out what's going on here. In the command

while ! ping -c1 -w1 -n 8.8.8.8 > /dev/null 2&>1

the & and > are in the wrong order. This causes a chain reaction of confusion and unexpected interpretations.

Specifically, bash parses 2&>1 as the argument " 2 " followed by the redirect &>1 which sents both stdout and stderr into a file named "1". So it runs this command, with all output to "1":

ping -c1 -w1 -n 8.8.8.8 2

Some versions of ping will give an error/usage message here, because they only accept a single target IP address (and then exit with an error status, making your loop run forever).

Other versions will interpret 8.8.8.8 as a hop to use on the way to the final destination 2 , which is an old shorthand for the IP address 0.0.0.2 . Which doesn't actually exist on the Internet. Which means the ping will fail and exit with an error status, making your loop run forever.

I suspect if you look in the file "1", you'll be able to tell which of these (or possibly something else) is happening.

There are some scripting lessons to be learned here:

  • All those cryptic piles of symbols matter , and if you get them a little bit wrong you can wind up doing something very different from what you intended.
  • Discarding output (especially error output) is a good way to hide what's going wrong. If a script is having trouble, capture & examine any errors its components produce.
  • set -x tells the shell to print what it thinks it's executing as it runs commands, and putting that before problem sections in scripts (and set +x afterward to turn it off) is a good say to find out what's going on. This is how I figured out that bash was treating " 2 " as an argument rather than part of the redirect.
  • shellcheck.net is handy!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM