Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash script for notification when internet is accessible

I wrote this bash script to have a notification when internet becomes accessible but I don't understand many of things that are happening. Here is the script:

while ! ping 8.8.8.8 -c 1 2&> /dev/null ; do true; done;
  • The -c 1 option tells ping that i want to send only one packet.
  • The 2&> /dev/null is there because i don't want to see output.
  • true is there because bash didn't accept the do; syntax.
  • the terminating condition is ! ping ... because ping returns non zero status code when no packet is received before some timeout.

The intended behavior was for this loop to end when ping succeeds and the terminal emulator will automatically send me a notification.


Problems

  • This command doesn't end even when internet becomes accessible.
  • Trying to kill the command with ctrl + C doesn't work. I think it's killing the sub-command ping instead of the whole command.
  • Only removing 2&> /dev/null makes every thing works except for the minor issue that it writes output to the terminal.

Questions

  1. What's wrong with my command?
  2. How exactly do terminal emulators react to ctrl + C?
  3. Why does removing 2&> /dev/null make it work?

Note that I already have a turnaround. Nevertheless I want to understand bash a little more.

f() { while ! ping 8.8.8.8 -c 1 ; do true; done; }; f 2&> /dev/null
like image 488
nawfel bgh Avatar asked Nov 23 '15 14:11

nawfel bgh


3 Answers

The correct redirection operator is &>, not 2&>. The 2 is parsed as a separate argument to ping, and since pinging 2 never succeeds, the loop never exists.

like image 140
chepner Avatar answered Oct 26 '22 14:10

chepner


Something I usually do in that kind of loops is adding a sleep command instead of true:

while ! ping 8.8.8.8 -c 1 &> /dev/null ; do sleep 1; done;

In that way you can use Ctrl+C while in the sleep and cancel the whole loop.

like image 24
FJRA Avatar answered Oct 26 '22 12:10

FJRA


I think the better way is to setup Timeout in the ping.

while ! ping -c 1 -W 2 8.8.8.8 >/dev/null 2>&1 ; do sleep 1 ; done
like image 30
Mal V Bonner Avatar answered Oct 26 '22 14:10

Mal V Bonner