ssh hangs if interrupted in the middle - linux

The following code suppose to print "connected" repeatedly if ssh is able to connect to the remote machine, else "not-connected" will be printed.
#!/bin/bash
while [ "1" ]
do
ifconfig usb0 &>/dev/null
if [ "$(echo $?)" == "0" ]
then
sshpass -p passwd ssh -o ConnectTimeout=5 duser#10.1.1.3 sudo echo "connected"
else
echo "not-connected"
fi
sleep 0.2
done
The remote machine is connected via the usb0 interface. I am testing this script by frequently unplugging and plugging the usb interface. The problem is sometimes when i unplug the usb interfaces, the code stuck at ssh and it is not printing repeatedly. I suppose if ssh is interrupted in the middle of executing it is getting stuck. How can i overcome this ? Can someone help?

Most apparently its not hanging at all.
But the way you are printing connected seems like wrong.
This looks pretty much suspicious
sshpass -p passwd ssh -o ConnectTimeout=5 duser#10.1.1.3 sudo grep "connected"
What are you trying to grep ?
Normally if you need to grep the output of some app you need to do it via pipe e.g.
ls | grep "connected"

Since you are using bash, this is a much better way to do your test:
2>/dev/null >/dev/tcp/<ip_addr>/<port> && echo pass || echo fail
For more details, see the Bash documentation on redirections.

Related

is it possible to run bash commands over shell running on telnet?

So we have Embedded Linux board running Linux.
We can connect to that board using telnet and that spawns shell and gives access to it.
Now I am writing a bash script where I want to run commands on that shell and get its output.
e.g. My commands are something like below command over telnet and see if that was successful or not.
test -c /dev/null
When I run it like below I always get 1 as exit status
{ test -c /dev/null; sleep 1;} | telnet <board ip addr>
If possible I don't want to use expect,
Any suggestion/pointers ?
With SSH could trivially and robustly have done:
ssh yourhost 'test -c /dev/null'
With a simple shell on a TCP port, you could somewhat robustly but annoyingly have used:
echo 'test -c /dev/null; echo $?' | nc -q 1 yourhost 1234
telnet is instead notoriously timing sensitive and tricky to script, so since you don't want to do it robustly with expect, you can try to kludge it:
{ sleep 1; echo 'test -c /dev/null; echo $?'; sleep 1; } | telnet somehost

Iterate through a list using 'while read' using bash

I have a list of IP addresses, and my end goal is to ssh into each one, and reset them one-at-a-time. I was asked to use Linux / Bash, which I am not extremely familiar. My code right now will take the first IP from the list, and connect to it, but it never moves on past that point. I believe the issue is somewhere between the while read oneip3 and do code. Any help is greatly appreciated.
The way I run this script is as follows: (I have a list of IP addresses in a separate text file):
./runscript.txt ip_list.txt
while read oneip3
do
(sleep 5
echo "yes\r"
sleep 3
echo -e "password\r"
sleep 3
echo -e "reset\r"
sleep 3
echo -e "yes\r"
sleep 20
echo -e "\r"
) | ssh -t -t -oHostKeyAlgorithms=+ssh-dss admin#$oneip3
done < $1
You didn't provide SSH argument. So it opens an interactive shell.
It is a good reason to be stuck on the first machine (maybe there is other reason...)
Try this to debug
... | ssh -t -t -oHostKeyAlgorithms=+ssh-dss "admin#$oneip3" pwd
Other remarks in comment about StrictHostKeyChecking seams good too (if you are really concern by security, you can deploy all needed keys by hand firstly)

How to be notified when IP is up?

I would like to ping a IP-Adress an want to be notified.
System: Linux Fedora.
Has anybody a idea or a Software?
Use this shell script. Found on http://jeromejaglale.com/doc/unix/shell_scripts/ping
#! /bin/sh
# -q quiet
# -c nb of pings to perform
ping -q -c5 google.com > /dev/null
if [ $? -eq 0 ]; then
echo "ok"
fi
Put the ping in a loop or run the script with cron.
Instead of echoing you can send a notification.

Linux shell script not setting variables with bash -c "$com"

So, I wrote a shell script to kick people off of my wifi, but I'm having trouble getting it to work correctly. The main problem is that when I do bash -c "$com" it does not set the variable like it should. Any help would be appreciated.
echo "You must be connected to the network that you wish to kick the devices off"
gw=`route -n|grep ^0.0.0.0|cut -d' ' -f 10`
sudo nmap -sP $gw-254
long='read -p Enter_the_DEVICE_Bssid'
a=1
end=';'
oend='&'
outside='"'
thesudo='sudo'
num=1
deff='aireplay-ng -0 $number -a $bssid mon0 --ignore-negative-one -c'
read -p "How many devices do you want to kick: " ammount
counter=0
while [ $counter -lt $ammount ];
do
b=device
d1=$b$a
if [ $counter2 -gt $ammount ]
then
com="$com $long $outside$d1$outside"
counter=$(($counter +1))
else
com="$com $long $outside$d1$outside $end"
fi
comfin="$comfin $thesudo $deff $d1 $oend"
a=$(($a +1))
counter=$(($counter +1))
counter2=$(($counter +2))
done
vev="echo done"
comfin="$comfin $vev"
echo $com
bash -c "$com"
#Why does it not set the variables like it should?
echo $device1
echo $device2
echo $device3
#see it dosent say the variables when it is run.
sudo ifconfig wlan0 down
sudo macchanger -m 00:11:22:33:44:55 wlan0
sudo ifconfig wlan0 up
sudo airmon-ng start wlan0
sudo ifconfig mon0 down
sudo macchanger -m 00:11:22:33:44:55 mon0
sudo ifconfig mon0 up
#make sure you dont run it from the file, but from terminal so you can press ctrl z to stop the airodump
echo "make sure you dont run it from the file, but from terminal so you can press ctrl z to stop the airodump"
sleep 2
sudo airodump-ng mon0
read -p "Enter the NETWORK Bssid:" bssid
echo "Ok, its $bssid"
read -p "Do you want to single kick(1) or continuously kick(0)" number
echo "Ok, its $number"
sudo $comfin
sudo ipconfig stop mon0
bash -c "command" runs the command in a new bash process. Variable settings in that process won't have any effect on the original process. If you want to execute a command in the original process's environment, use eval:
eval "$com"
You probably should reconsider your whole approach, though. Dynamically assigning variables is usually a sign of an incorrect design. Instead of having separate variables device1, device2, device3, you should use an array.
read -p 'Enter the device' dev
device[$counter]=$dev

How to set up an automatic (re)start of a background ssh tunnel

I am a beginner user of linux, and also quite newbie at ssh and tunnels.
Anyway, my goal is to maintain a ssh tunnel open in background.
In order to do that, I wrote the following batch that I then added into crontab (the batch is automatically processed every 5 minutes during workdays and from 8am to 9pm).
I read in some other thread in stackoverflow that one should use autossh that will ensure the ssh will always be ok through a recurrent check. So did I....
#!/bin/bash
LOGFILE="/root/Tunnel/logBatchRestart.log"
NOW="$(date +%d/%m/%Y' - '%H:%M)" # date & time of log
if ! ps ax | grep ssh | grep tunnelToto &> /dev/null
then
echo "[$NOW] ssh tunnel not running : restarting it" >> $LOGFILE
autossh -f -N -L pppp:tunnelToto:nnnnn nom-prenom#193.xxx.yyy.zzz -p qqqq
if ! ps ax | grep ssh | grep toto &> /dev/null
then
echo "[$NOW] failed starting tunnel" >> $LOGFILE
else
echo "[$NOW] restart successfull" >> $LOGFILE
fi
fi
My problem is that sometimes the tunnel stops working, although every thing looks ok (ps ax | grep ssh > the result shows the two expected tasks : autossh main task and the ssh tunnel itself). I actually know about the problem cause the tunnel is used by a third party software that triggers an error as soon as the tunnel is no more responding.
SO I am wondering how I should improve my batch in order It will be able to check the tunnel and restart it if it happens to be dead. I saw some ideas in there, but it was concluded by the "autossh" hint... which I already use. Thus, I am out of ideas... If any of you have, I'd gladly have a look at them!
Thanks for taking interest in my question, and for your (maybe) suggestions!
Instead of checking the ssh process with ps you can do the following trick
create script, that does the following and add it to your crontab via crontab -e
#!/bin/sh
REMOTEUSER=username
REMOTEHOST=remotehost
SSH_REMOTEPORT=22
SSH_LOCALPORT=10022
TUNNEL_REMOTEPORT=8080
TUNNEL_LOCALPORT=8080
createTunnel() {
/usr/bin/ssh -f -N -L$SSH_LOCALPORT:$REMOTEHOST:SSH_REMOTEPORT -L$TUNNEL_LOCALPORT:$REMOTEHOST:TUNNEL_REMOTEPORT $REMOTEUSER#$REMOTEHOST
if [[ $? -eq 0 ]]; then
echo Tunnel to $REMOTEHOST created successfully
else
echo An error occurred creating a tunnel to $REMOTEHOST RC was $?
fi
}
## Run the 'ls' command remotely. If it returns non-zero, then create a new connection
/usr/bin/ssh -p $SSH_LOCALPORT $REMOTEUSER#localhost ls >/dev/null 2>&1
if [[ $? -ne 0 ]]; then
echo Creating new tunnel connection
createTunnel
fi
In fact, this script will open two ports
port 22 which will be used to check if the tunnel is still alive
port 8080 which is the port you might want to use
Please check and send me further questions via comments
(I add this as an answer since there is not enough room for it un a comment)
Ok, I managed to make the batch run to launch the ssh tunnel (I had to specify my hostname instead of localhost in order it could be triggered) :
#!/bin/bash
LOGFILE="/root/Tunnel/logBatchRedemarrage.log"
NOW="$(date +%d/%m/%Y' - '%H:%M)" # date et heure du log
REMOTEUSER=username
REMOTEHOST=remoteHost
SSH_REMOTEPORT=22
SSH_LOCALPORT=10022
TUNNEL_REMOTEPORT=12081
TUNNEL_SPECIFIC_REMOTE_PORT=22223
TUNNEL_LOCALPORT=8082
createTunnel() {
/usr/bin/ssh -f -N -L$SSH_LOCALPORT:$REMOTEHOST:$SSH_REMOTEPORT -L$TUNNEL_LOCALPORT:$REMOTEHOST:$TUNNEL_REMOTEPORT $REMOTEUSER#193.abc.def.ghi -p $TUNNEL_SPECIFIC_REMOTE_PORT
if [[ $? -eq 0 ]]; then
echo [$NOW] Tunnel to $REMOTEHOST created successfully >> $LOGFILE
else
echo [$NOW] An error occurred creating a tunnel to $REMOTEHOST RC was $? >> $LOGFILE
fi
}
## Run the 'ls' command remotely. If it returns non-zero, then create a new connection
/usr/bin/ssh -p $SSH_LOCALPORT $REMOTEUSER#193.abc.def.ghi ls >/dev/null 2>&1
if [[ $? -ne 0 ]]; then
echo [$NOW] Creating new tunnel connection >> $LOGFILE
createTunnel
fi
However, I got some immediate message (below) when the tunnel is running and when cron tries to lauch the batch again... sounds like it cannot listen to it. Also since I need some time to get a proof , I can't say yet it will successfully restart if the tunnel is out.
Here's the response to the second start of the batch.
bind: Address already in use channel_setup_fwd_listener: cannot listen
to port: 10022 bind: Address already in use
channel_setup_fwd_listener: cannot listen to port: 8082 Could not
request local forwarding.

Resources