How to send Internet connectivity alerts using a Bash script? - linux

I have a flaky Internet connection, so I decided to make a bash script that would alert me whenever the internet is back. This is the script:
#!/bin/bash
# set -x
while [ 1 ];do
STATUS_CURRENT=$(ping -q -w 1 -c 1 google.com > /dev/null && echo connected || echo disconnected)
if [[ $STATUS_CURRENT == "connected" && $STATUS_LAST != "connected" ]];then
aplay /home/user/bin/online.wav
notify-send "We've connected"
elif [[ $STATUS_CURRENT == "disconnected" && $STATUS_LAST == "connected" ]];then
aplay /home/user/bin/offline.wav
notify-send "Disconnected now"
fi
STATUS_LAST=$STATUS_CURRENT
sleep 2
done
I have this added in /etc/rc.local to have it executed on startup. The problem with this script is that it sometimes fail. Even when there's Internet connectivity, the script sends notification saying it's disconnected (immediately followed by the "connected" message).
How can I avoid this problem? Does it have something to do with the fact that ping is slow to fail? How can the script be improved?

With "netcat" it works very stable for me
#!/bin/bash
status=0
do_on=("/home/user/bin/online.wav"
"We've connected")
do_off=("/home/user/bin/offline.wav"
"Disconnected now")
while [ 1 ] ;do
nc -zw 2 google.de 80
ret="$?"
if [ "$ret" = 0 -a "$status" = 0 ] ;then
aplay ${do_on[0]}
notify-send ${do_on[1]}
status=1
elif [ "$ret" -ne 0 -a "$status" = 1 ] ;then
aplay ${do_off[0]}
notify-send ${do_off[1]}
status=0 ;fi
sleep 2 ;done
You should test your DNS server in advance
cheers Karim

Related

Terminal Freezing after Bash Script Succeeded

I have a pretty simple bash script that coordinates running a couple python scripts. What I am having trouble figuring out is why after running the bash script (. bash_script.sh), the terminal hangs. I can't ctrl+c, ctrl+z or do anything except restart the SSH session. All I see is just a blinking cursor. Checking all the log files indicates a 0 status exit code with no errors in the scripts themselves. Running ps aux | grep bash_script.sh does not show any anything running either. Is there anyway to debug this?
#!/bin/bash
exec >> <DIR>/logfile.log 2>&1
script_message () {
status_arg=$1
if [[ $status_arg = "pass" ]]; then
printf "Script Done\n"
printf '=%.0s' {1..50}
printf "\n"
elif [[ $status_arg = "fail" ]]; then
printf "Script Failed\n"
printf '=%.0s' {1..50}
printf "\n"
else
:
fi
}
current_date=$(date '+%Y-%m-%d %H:%M:%S')
day=$(date +%u)
hour=$(date +%H)
printf "RUN DATE: $current_date\n"
# activate virtual env
source /<VENV DIR/bin/activate>
python <PYTHON SCRIPT>.py >> <DIR>/logfile2.log 2>&1
retVal=$?
if [[ $retVal -eq 0 && $day -eq 4 ]]; then
python <PYTHON SCRIPT 2>.py >> <DIR>/logfile3.log 2>&1
script_message pass
elif [[ $retVal -eq 0 ]]; then
script_message pass
else
#:
script_message fail
fi
echo $?

Linux shutdown with countdown. (made with while)

Hello I want to create a script that shutdowns Linux after a certain time (e.g 15 seconds) with a countdown displayed in the terminal (Linux is shutting down after 15s.). It has to be with while.
You can use the following :
#!/bin/bash
COUNTER=15
while [ 1 ]
do
if [ ${COUNTER} -eq 0 ]
then
break
fi
echo "Linux is shutting down after ${COUNTER}s."
sleep 1
COUNTER=$( echo "${COUNTER}-1" | bc )
done
sudo poweroff
If you really want to display the counter on the screen, this would work:
#!/bin/bash
seconds=15
echo "Linux is shutting down after ${seconds}s"
date_1=$((`date +%s` + $seconds))
while [ "$date_1" -ge `date +%s` ]; do
echo -ne "$(date -u --date #$(($date_1 - `date +%s` )) +%H:%M:%S)\r"
done
echo -e "Do you really want to shutdown the system? Press [Y/y] to shutdown or [n/N] to cancel/exit:"
read var
if [[ "$var" == "y" ]] || [[ "$var" == "Y" ]]
then
sudo poweroff
elif [[ "$var" == "n" ]] || [[ "$var" == "N" ]]
then
exit 1
fi
Basically, it'll accept [Y/y] from the user to shutdown and [n/N] to exit.

file check 3 times and exit shell script

I want to check for file in directory if there then push it to ssh server checing server connection if file not there then try 3 times with each 1min interval and in between if it comes ( on 2nd attend for example) then try again to connect ssh and push. else check for 3 attempts and exit
Please check my below code it is halting after 1st attempt ( during 2nd attempt I am making file available)
#!/bin/sh
echo "OK, start pushing the Userdetails to COUPA now..."
cd /usr/App/ss/outbound/usrdtl/
n=0
until [ $n -ge 3 ] || [ ! -f /usr/App/ss/outbound/usrdtl/USERS_APPROVERS_*.csv ]
do
if [ -f /usr/App/ss/outbound/usrdtl/USERS_APPROVERS_*.csv ] ;
then
pushFiles()
else
n=$[$n+1]
sleep 60
echo " trying " $n "times "
fi
done
pushFiles()
{
echo "File present Now try SSH connection"
while [ $? -eq 0 ];
do
echo $(date);
scpg3 -v /usr/App/ss/outbound/usrdtl/USERS_APPROVERS_*.csv <sshHost>:/Incoming/Users/
if [ $? -eq 0 ]; then
echo "Successfull"
echo $(date);
echo "Successfull" >> /usr/App/ss/UserApproverDetails.log
exit 1;
else
echo $(date);
echo "Failed" >> /usr/App/ss/UserApproverDetails.log
echo "trying again to push file.."
scpg3 -v /usr/App/sg/outbound/usrdtl/USERS_APPROVERS_*.csv <ssh Host>:/Incoming/Users/
echo $(date);
exit 1;
fi
done
}
I've tried to simplify this code for you. I hope it helps:
#!/bin/bash
outdir="/usr/App/ss/outbound/usrdtl"
logfile="/usr/App/ss/UserApproverDetails.log"
file_prefix="USERS_APPROVERS_"
function push_files() {
echo "File present now try SSH connection"
local attempts=1
local retries=2
date
while [[ ${attempts} -lt ${retries} ]]; do
if scp ${outdir}/${file_prefix}*.csv <sshHost>:/Incoming/Users/ ; then
echo "Successful" | tee -a ${logfile}
date
exit 0
else
echo "Failed" >> ${logfile}
fi
attempts=$((attempts+1))
do
echo "scp failed twice" | tee -a ${logfile}
exit 2
}
echo "OK, start pushing the Userdetails to COUPA now..."
cd ${outdir}
attempts=1
retries=3
while [[ ${attempts} -lt ${retries} ]]; do
echo "looking for files...attempt ${attempts}"
if test -n "$(shopt -s nullglob; echo ${outdir}/${file_prefix}*.csv)"; then
push_files()
fi
attempts=$((attempts+1))
sleep 60
done
echo "Files were never found" | tee -a ${logfile}
exit 1
Look at this code and tell me how it's not doing what you're trying to do. The most complicated part here is the nullglob stuff, which is a handy trick to see if any file in a glob matches
Also, I generally used bashisms.

Bash continue only if ping is down

I'm trying to create a script which will only continue when pinging is unresponsive.
I'm running into 2 main issues. One being that it will require 2 CTL-C commands to end the script, and the other issue being that the script will never end and will need killing.
Here are my attempts;
rc=0
until [ $rc -gt 0 ]
do
ping 69.69.69.69 > /dev/null 2>&1
rc=$?
done
## Here will be the rest of code to be executed
I feel this one above is very close as it requires the 2 CTL-C commands and continues.
Here is something I found on SO but can't get to work at all.
counter=0
while [ true ]
do
ping -c 1 69.69.69.69 > /dev/null 2>&1
if [ $? -ne 0 ] then
let "counter +=1"
else
let "counter = 0"
fi
if [ $counter -eq 10 ] then
echo "Here should be executed once pinging is down"
fi
done
Any assistance is greatly appreciated, Thank you.
Try this:
while ping -c 1 -W 20 "$host" >& /dev/null
do
echo "Host reachable"
sleep 10 # do not ping too often
done
echo "Host unreachable within 20 seconds"
There's a few issues with that:
Firstly the if statements are wrong
Use this format
if [ $? -ne 0 ] then;
or this other format
if [ $? -ne 0 ]
then
Secondly I suspect that your pings are not timing out
ping -c 1 -w 2 69.69.69.69 > /dev/null 2>&1
might be helpfull
Thirdly your loop will continue incrementing counter even after 10. You might want to quit after 10
while [ $counter -le 10 ]
If you would be happy with executing something if ping times out after x seconds without any response it could be all condensed (ten seconds in the example below):
ping -c 1 -w 10 69.69.69.69 >/dev/null 2>&1 || echo "run if ping timedout without any response"

Automatically establish ssh-tunnel, wait until ssh-tunnel is established, then establish normal VPN connection

I got this script:
#!/usr/bin/env bash
if [ ! "$UID" = 0 ]; then
if [ `type -P gksu` ]; then
SUDOAPP="gksu"
elif [ `type -P kdesu` ]; then
SUDOAPP="kdesu"
else
SUDOAPP="sudo"
fi
fi
if [ -n "$1" ]; then
if [ "$1" = "start" ]; then
$SUDOAPP systemctl start openvpn#******
elif [ "$1" = "stop" ]; then
$SUDOAPP systemctl stop openvpn#******
elif [ "$1" = "restart" ]; then
$SUDOAPP systemctl restart openvpn#******
else
echo "Invalid command"
exit 1
fi
else
echo "Run 'start', 'stop' or 'restart' as an argument to start, stop or restart the ******"
exit 1
fi
It works fine. However I also need to establish the ssh tunnel. - Before openvpn connects to my VPN. I've got a script which does precisely that:
#!/bin/bash
# --------------------------------------------------------
# ******* | https://******.org | ****************************************
# SSH Client Configuration, Linux/OSX
# ******_*************
# --------------------------------------------------------
chmod 600 /etc/openvpn/sshtunnel.key
while :
do
echo ""; echo "****** SSH Tunnel"
ssh -i /etc/openvpn/sshtunnel.key -L ****:127.0.0.1:**** sshtunnel#**.**.**.* -p ** -N -T -v
read -t 5 -p "Retry? (or wait 5 sec for Y)" yn
if [[ $yn == "n" || $yn == "N" ]]; then break; fi
done
How do I add this to the first script in a way as to make the openvpn part wait until the ssh client is fired up?
The first script can loop checking the tunnel until it succeeds. You can use nc (netcat) to do that and capture the output in a shell variable:
while [[ -z "$nc_output" ]]; do
read -r nc_output < <(nc -v -d -u localhost openvpn 2>&1)
sleep 2
done
This checks every 2 seconds whether UDP port "openvpn" (substitute what you're actually tunnelling) can be connected to, relying on the -v option to output text if it succeeds.

Resources