Omit error from shell script output - bash

I'd like to omit the error from this IF statement if ICMP echo fails.
Example code:
if ping -q -c 1 -W 1 1.2.3.4 >/dev/null; then
echo -e "PING OK"
else
echo -e "PING NOK"
fi
It works perfectly if the ping is successful or you run the command outside of a script, but gives the below output if there is no response.
PING 1.2.3.4 (1.2.3.4): 56 data bytes
--- 1.2.3.4 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
PING NOK
I've seen answers for this out there quoting 2>/dev/null, but this then displays the entire ping query in the output, whether successful or not! Example with 2>/dev/null as below.
PING 1.2.3.4 (1.2.3.4): 56 data bytes
--- 1.2.3.4 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 26.134/26.134/26.134/0.000 ms
PING OK
This is a bit of a n00b question, but I'm a networking chap, not a developer :)
Thanks in advance!!

The «classic» solution:
if ping -q -c 1 -W 1 1.2.3.4 >/dev/null 2>&1; then
echo -e "PING OK"
else
echo -e "PING NOK"
fi
A somewhat more modern (and not POSIX-compliant!) approach, available since BASH 4:
if ping -q -c 1 -W 1 1.2.3.4 &>/dev/null; then
echo -e "PING OK"
else
echo -e "PING NOK"
fi
Both of these mean «redirect both STDOUT and STDERR to /dev/null», but the first one does it sequentially, first redirecting STDOUT and then redirecting STDERR to STDOUT.

You can use the exit status [ Check this ] too..
ping -q -c 1 -W 1 1.2.3.4 >/dev/null 2>&1
[ $? -eq 0 ] && echo "Ping OK" || echo "Ping NOK"

Related

How can i exit, stop, kill autossh if connection timed out, ip, port not exists or response without using ssh and sshd config files?

I run autossh in a script for remote port forwarding and i need to exit, kill, stop the script if connection timed out, ip, port not exists or response, without the using of the ssh, sshd config files, is this possible?
No answer, found on stacksites or the manpage of autossh.
Example 1:
myautossh script
#!/bin/bash
/usr/bin/autossh -NT -o "ExitOnForwardFailure=yes" -R 5555:localhost:443 -l user 1.1.1.1
if [ $? -eq 0 ]; then
echo "SUCCESS" >> errorlog
else
echo "FAIL" >> errorlog
fi
Example 2:
myautossh script
#!/bin/bash
/usr/bin/autossh -f -NT -M 0 -o "ServerAliveInterval=5" -o "ServerAliveCountMax=1" -o "ExitOnForwardFailure=yes" -R 5555:localhost:443 -l user 1.1.1.1 2>> errorlog
if [ $? -eq 0 ]; then
echo "SUCCESS" >> errorlog
else
echo "FAIL" >> errorlog
kill $(ps aux | grep [m]yautossh | awk '{print $2}')
fi
IP 1.1.1.1 not exists in my network so it get a connection timeout, but the script and autossh is still running, checked with:
ps aux | grep [m]yautossh
or
ps x | grep [a]utossh
Can only terminate the script with ctrl+c
I want to run autossh in a script, try to connect to a not existing ip or port and terminate, exit, kill the process of autossh to continue my script, without config ssh & sshd config files, only with the options/commands of autossh and the using of -f for background, is this possible?
the use of timeout with --preserve-status is what you need
timeout allows you to run a cmmand with a time limit
Preserving the Exit Status, timeout with --preserve-status returns 124 when the time limit is reached. Otherwise, it returns the exit status of the managed command
this will terminate the command after 2 seconds and returns the exit status of your command if not equal 0, command not success, you could not establish a successful conection
#!/bin/bash
timeout --preserve-status 2 /usr/bin/autossh -NT -o "ExitOnForwardFailure=yes" -R 33333:localhost:443 -l user 1.1.1.1
if [ $? -eq 0 ]; then
echo "Connection success"
else
echo "Connection fail"
fi
https://linuxize.com/post/timeout-command-in-linux/

ping script - host down vs host not on network

I have the following script where I am trying to differentiate between a server that is down and a server that is no longer on the network.
If I use the ping command on the command line on a server that is just down and echo the $? I get a 1 as expected.
If I use the ping command on the command line on a server that is no longer on the network and echo the $? I get a 2 as expected. I can't seem to capture this behavior in my script. On the script below, the server that is no longer on the network does not appear at all in the badhosts output file. I am using the dev null on the ping line as I don't want to get the host unknown lines on the output which will skew the results.
Thanks in advance for any assistance.
#!/bin/ksh
# Take a list of hostnames and ping them; write any failures
#set -x
for x in `cat hosts`
do
ping -q -c 1 $x > /dev/null 2> /dev/null
if [ "$?" -eq 1 ];then
echo $x is on network but down >> badhosts
elif [ "$?" -eq 2 ];then
echo $x is not on the network >> badhosts
fi
done
I modified my script at the suggestion of Raman as follows and this works.
Thanks Raman !!
#!/bin/ksh
# Take a list of hostnames and ping them; write any failures
set -x
for x in `cat hosts`
do
ping -c 1 $x > /dev/null 2> /dev/null
pingerr=$?
if [ $pingerr -eq 1 ]; then
echo $x is on network but down >> badhosts
fi
if [ $pingerr -eq 2 ]; then
echo $x is not on the network >> badhosts
fi
done

Scanning LAN using ping and Gnu Parallel

I am trying to scan my LAN using ping, invoking using Gnu Parallel. The code ideally will simply report those IP addresses which are up and strip out any verbose reporting. The original code (without parallel) which works well is:
for ip in $(seq 1 254) ; do ping -t5 -c 1 192.168.0.$ip > /dev/null ; [ $? -eq 0 ] && echo "192.168.0.$ip UP" & done
However it is annoying with all the job completed messages (set +m is not helpful). Running sequentially takes too long to poll each IP address.
The Parallel code so far which works (take out the --dry-run to execute) is:
seq 1 254 | parallel --dry-run ping -t5 -c 1 192.168.0.{}
but trying to do
seq 1 254 | parallel --dry-run ping -t5 -c 1 192.168.0.{} ';' [ $? -eq 0 ] && echo "192.168.0.{} UP"
or variations of that, fail to achieve the objective. Can anyone help with the test part here?
Cracked it - hope this is helpful to others.
seq 1 254 | parallel ' ping -t5 -c 1 192.168.0.{} >/dev/null && echo 192.168.0.{} UP ' 2>/dev/null
From the Gnu documentation, a parallel timeout rather than ping timeout seems to be more efficient
seq 1 254 | parallel --timeout 2 -j64 -keep-order ' ping -c 1 192.168.0.{} >/dev/null && echo 192.168.0.{} UP ' 2>/dev/null

Checking whether specific website is up in the terminal?

Is there an easy way to check Internet connectivity from console? I am trying to play around in a shell script. One idea I seem is to wget --spider http://www.google.com/ and check the HTTP response code to interpret if the Internet connection is working fine.
This is what I am trying:
#!/bin/bash
# Sending the output of the wget in a variable and not what wget fetches
RESULT=`wget --spider http://google.com 2>&1`
FLAG=0
# Traverse the string considering it as an array of words
for x in $RESULT; do
if [ "$x" = '200' ]; then
FLAG=1 # This means all good
fi
done
Is there any way to accomplish this?
You can do it with ping or curl commands. Check man for more.
I am using this for myself and kinda works for me! It checks the connection from a reliable website like google and if it gets 200 status as the response, you probably have internet.
if curl -s --head --request GET www.google.com | grep "200 OK" > /dev/null ; then
echo "Internet is present"
else
echo "Internet isn't present"
fi
On one line, thanks #PS
if ping -c1 8.8.8.8 &>/dev/null ;then echo Working ;else echo Down ;fi
An option that does not use the internet to see if it is available is to check for a default route in your routing tables. The routing daemon will remove your default route when the internet is not available and add it back when it is.
netstat -nrf inet | grep -q ^default && \
echo internet is up || \
echo internet is down
To check if a website is up, you can use netcat to see if it is listening on port 80. This helps with sites that refuse head requests with '405 Method Not Allowed'.
nc -zw2 www.example.com 80 &>/dev/null && \
echo website is up || \
echo website is down
Please try this code.
#!/bin/bash
wget -q --spider http://google.com
if [ $? -eq 0 ]; then
echo "Internet connection is OK"
else
echo "Internet connection is FAILED"
fi
A bit more compact variant of #carlos-abraham answer. You can have curl to output just the http response code and make a decision with it
# 200 if everything is ok
http_code=$(curl -s --head -m 5 -w %{http_code} --output /dev/null www.google.com)
if [ "$http_code" -eq 200 ]; then
echo "success"
else
# write error to stderr
echo "http request failed: $http_code" >&2
exit 1
fi
-m 5: wait 5 seconds for the whole operation
--output /dev/null: suppress html site response
-w %{http_code}: write to stdout the http response code.
A bit more elaborated script to check connectivity and http response
#url="mmm.elgoog.moc"
url="www.google.com"
max_wait=5
(ping -w $max_wait -q -c 1 "$url" > /dev/null 2>&1 )
response_code=$?
if [ "$response_code" -eq 0 ]; then
# 200 if everything is ok
response_code=$(curl -s --head -m $max_wait -w %{http_code} --output /dev/null "$url")
fi
case "$response_code" in
1)
echo "Connectivity failed. Host down?" >&2
exit $response_code
;;
2)
echo "Unknown host or other problem. DNS problem?" >&2
exit $response_code
;;
200)
echo "success"
exit 0
;;
*)
echo "Failed to get a response: $response_code" >&2
exit 1
esac

Making bash script to check connectivity and change connection if necessary. Help me improve it?

My connection is flaky, however I have a backup one. I made some bash script to check for connectivity and change connection if the present one is dead. Please help me improve them.
The scripts almost works, except for not waiting long enough to receive an IP (it cycles to next step in the until loop too quick). Here goes:
#!/bin/bash
# Invoke this script with paths to your connection specific scripts, for example
# ./gotnet.sh ./connection.sh ./connection2.sh
until [ -z "$1" ] # Try different connections until we are online...
do
if eval "ping -c 1 google.com"
then
echo "we are online!" && break
else
$1 # Runs (next) connection-script.
echo
fi
shift
done
echo # Extra line feed.
exit 0
And here is an example of the slave scripts:
#!/bin/bash
ifconfig wlan0 down
ifconfig wlan0 up
iwconfig wlan0 key 1234567890
iwconfig wlan0 essid example
sleep 1
dhclient -1 -nw wlan0
sleep 3
exit 0
Here's one way to do it:
#!/bin/bash
while true; do
if ! [ "`ping -c 1 google.com; echo $?`" ]; then #if ping exits nonzero...
./connection_script1.sh #run the first script
sleep 10 #give it a few seconds to complete
fi
if ! [ "`ping -c 1 google.com; echo $?`" ]; then #if ping *still* exits nonzero...
./connection_script2.sh #run the second script
sleep 10 #give it a few seconds to complete
fi
sleep 300 #check again in five minutes
done
Adjust the sleep times and ping count to your preference. This script never exits so you would most likely want to run it with the following command:
./connection_daemon.sh 2>&1 > /dev/null & disown
Have you tried omitting the -nw option from the dhclient command?
Also, remove the eval and quotes from your if they aren't necessary. Do it like this:
if ping -c 1 google.com > /dev/null 2>&1
Trying using ConnectTimeout ${timeout} somewhere.

Resources