Bash script that check connection with host:port using telnet and netcar - linux

I have task to create quite complicated bash script, which at first part is checking the connection to host:port with telnet and- if telnet would fail or would not be installed, try the connection using netcat.
I have problem with loop, where it will skip netcat if telnet would connect to the host and also, if both- telnet and netcat would fail- script would finish with error message.
The script:
#!/bin/bash
echo Type host IP address
read REMOTEHOST
echo Type port number
read REMOTEPORT
TIMEOUT=5
echo quit | timeout --signal=9 5 telnet $REMOTEHOST $REMOTEPORT
if nc -w $TIMEOUT -z $REMOTEHOST $REMOTEPORT; then
echo "I was able to connect to ${REMOTEHOST}:${REMOTEPORT}"
else
echo "Connection to ${REMOTEHOST}:${REMOTEPORT} failed. Exit code from Netcat was ($?)."
fi

You can use the $? variable to get the exit code from the last command.
I found that your original telnet command exits with error code 1 on my system because the escape character is ^]. When I telnet manually I need to hit ctrl-] to enter the telnet prompt, then I can enter 'quit'.
The trick here is you cannot just type ^], you have to type ctrl-v ctrl-]
ctrl-v tells the system to capture the next ctrl character.
The following gives me an exit code of 0, and you can verify by running it manually with echo $? at the command line
-- remember to use ctrl-v ctr-]
$ (echo ^]; echo quit) | timeout --signal=9 5 telnet <REMOTEHOST> <REMOTEPORT>
$ echo $?
Then you can use this in your script:
#!/bin/bash
echo Type host IP address
read REMOTEHOST
echo Type port number
read REMOTEPORT
TIMEOUT=5
(echo ^]; echo quit) | timeout --signal=9 5 telnet $REMOTEHOST $REMOTEPORT > /dev/null 2>&1
TELNET_EXIT_CODE=$?
if [[ $TELNET_EXIT_CODE -ne 0 ]]; then
nc -w $TIMEOUT -z $REMOTEHOST $REMOTEPORT > /dev/null 2>&1
NC_EXIT_CODE=$?
fi
if [[ $TELNET_EXIT_CODE -eq 0 ]] || [[ $NC_EXIT_CODE -eq 0 ]]; then
echo "success"
else
echo "fail"
fi
Tested on Ubuntu 20.04.04, GNU bash version 5.0.17, Telnet version 0.17-41

Related

SSH Remote command exit code

I know there are lots of discussions about it but i need you help with ssh remote command exit codes. I have that code:
(scan is a script which scans for viruses in the given file)
for i in $FILES
do
RET_CODE=$(ssh $SSH_OPT $HOST "scan $i; echo $?")
if [ $? -eq 0 ]; then
SOME_CODE
The scan works and it returns either 0 or (1 for errors) or 2 if a virus is found. But somehow my return code is always 0. Even, if i scan a virus.
Here is set -x output:
++ ssh -i /home/USER/.ssh/id host 'scan Downloads/eicar.com; echo 0'
+ RET_CODE='File Downloads/eicar.com: VIRUS: Virus found.
code of the Eicar-Test-Signature virus
0'
Here is the Output if i run those commands on the "remote" machine without ssh:
[user#ws ~]$ scan eicar.com; echo $?
File eicar.com: VIRUS: Virus found.
code of the Eicar-Test-Signature virus
2
I just want to have the return Code, i dont need all the other output of scan.
!UPDATE!
It seems like, echo is the problem.
The reason your ssh is always returning 0 is because the final echo command is always succeeding! If you want to get the return code from scan, either remove the echo or assign it to a variable and use exit. On my system:
$ ssh host 'false'
$ echo $?
1
$ ssh host 'false; echo $?'
1
$ echo $?
0
$ ssh host 'false; ret=$?; echo $ret; exit $ret'
1
$ echo $?
1
ssh returns the exit status of the entire pipeline that it runs - in this case, that's the exit status of echo $?.
What you want to do is simply use the ssh result directly (since you say that you don't want any of the output):
for i in $FILES
do
if ssh $SSH_OPT $HOST "scan $i >/dev/lull 2>&1"
then
SOME_CODE
If you really feel you must print the return code, that you can do that without affecting the overall result by using an EXIT trap:
for i in $FILES
do
if ssh $SSH_OPT $HOST "trap 'echo \$?' EXIT; scan $i >/dev/lull 2>&1"
then
SOME_CODE
Demo:
$ ssh $host "trap 'echo \$?' EXIT; true"; echo $?
0
0
$ ssh $host "trap 'echo \$?' EXIT; false"; echo $?
1
1
BTW, I recommend you avoid uppercase variable names in your scripts - those are normally used for environment variables that change the behaviour of programs.

Detecting when Mongod's port is open inside a script

I'm trying to write a bash script that starts a mongod process, waits for it to start (i.e. have it's default port open) and then pipe some commands into it through the mongo shell. I'd like some way to wait for the mongod process to be completely up that's more deterministic than just sleep 5.
This is the script so far:
set_up_authorization() {
echo "Setting up access control"
/path/to/mongo < configure_access_controls.js
}
wait_for_mongod_to_start() {
RETRIES=1000
CONNECTED="false"
echo "Waiting for mongod to start"
while [[ $RETRIES -ge 0 && $CONNECTED == "false" ]] ; do
RESPONSE=$(exec 6<>/dev/tcp/127.0.0.1/27017 || echo "1")
if [[ $RESPONSE == "" ]] # which should happen if the exec is successful
CONNECTED="true"
fi
RETRIES=$((RETRIES - 1))
done
if [[ $RETRIES -eq 0 ]] ; then
echo "Max retries reached waiting for mongod to start. Exiting."
exit 1
fi
echo "Mongod started"
}
./start_mongod_instance.sh
wait_for_mongod_to_start
set_up_authorization
While this script works, it produces a ton of output on the terminal while the exec is failing:
./initialize_cluster.sh: connect: Connection refused
./initialize_cluster.sh: line xx: /dev/tcp/127.0.0.1/27017: Connection refused
...which repeats for all ~900 failed attempts.
Neither of the following seems to get rid of the terminal logging either:
exec 6<>/dev/tcp/127.0.0.1/27017 >/dev/null
OR
exec 6<>/dev/tcp/127.0.0.1/27017 2>/dev/null
I've also tried using the following:
ps -aux | grep "mongod" | wc -l
but the process having a pid that ps lists isn't equivalent to it's port being open or it accepting connections.
Any ideas on either front would be appreciated - a more elegant way to wait for the process to start completely or a way to get rid of the excessive logging to the terminal.
Note: I don't have access to nmap or nc to check the port (this is on a client's machine).
exec is a bit special. It affects the output of the current shell. Meaning you need to redirect stderr of the current shell before running the port check:
host="localhost"
port="9000"
exec 2>/dev/null # redirect error here
while ! exec 3<>"/dev/tcp/${host}/${port}" ; do
echo "Waiting ..."
sleep 1
done
Furthermore you might have noticed that I check the exit status of exec rather than some output to decide whether the port is open or not.
If you want to reset it afterwards:
host="localhost"
port="9000"
# Copy fd 2 into fd 3 and redirect fd 2 to /dev/null
exec 3<&2 2>/dev/null
while ! exec 3<>"/dev/tcp/${host}/${port}" ; do
echo "Waiting ..."
sleep 1
done
# Copy back fd 3 into fd 2
exec 2<&3
echo "EE oops!" >&2

bash: checking host availability over tcp [duplicate]

I'm looking for a quick and simple method for properly testing if a given TCP port is open on a remote server, from inside a Shell script.
I've managed to do it with the telnet command, and it works fine when the port is opened, but it doesn't seem to timeout when it's not and just hangs there...
Here's a sample:
l_TELNET=`echo "quit" | telnet $SERVER $PORT | grep "Escape character is"`
if [ "$?" -ne 0 ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
I either need a better way, or a way to force telnet to timeout if it doesn't connect in under 8 seconds for example, and return something I can catch in Shell (return code, or string in stdout).
I know of the Perl method, which uses the IO::Socket::INET module and wrote a successful script that tests a port, but would rather like to avoid using Perl if possible.
Note: This is what my server is running (where I need to run this from)
SunOS 5.10 Generic_139556-08 i86pc i386 i86pc
As pointed by B. Rhodes, nc (netcat) will do the job. A more compact way to use it:
nc -z <host> <port>
That way nc will only check if the port is open, exiting with 0 on success, 1 on failure.
For a quick interactive check (with a 5 seconds timeout):
nc -z -v -w5 <host> <port>
It's easy enough to do with the -z and -w TIMEOUT options to nc, but not all systems have nc installed. If you have a recent enough version of bash, this will work:
# Connection successful:
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/80'
$ echo $?
0
# Connection failure prior to the timeout
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/sfsfdfdff.com/80'
bash: sfsfdfdff.com: Name or service not known
bash: /dev/tcp/sfsfdfdff.com/80: Invalid argument
$ echo $?
1
# Connection not established by the timeout
$ timeout 1 bash -c 'cat < /dev/null > /dev/tcp/google.com/81'
$ echo $?
124
What's happening here is that timeout will run the subcommand and kill it if it doesn't exit within the specified timeout (1 second in the above example). In this case bash is the subcommand and uses its special /dev/tcp handling to try and open a connection to the server and port specified. If bash can open the connection within the timeout, cat will just close it immediately (since it's reading from /dev/null) and exit with a status code of 0 which will propagate through bash and then timeout. If bash gets a connection failure prior to the specified timeout, then bash will exit with an exit code of 1 which timeout will also return. And if bash isn't able to establish a connection and the specified timeout expires, then timeout will kill bash and exit with a status of 124.
TOC:
Using bash and timeout
Command
Examples
Using nc
Command
RHEL 6 (nc-1.84)
Installation
Examples
RHEL 7 (nmap-ncat-6.40)
Installation
Examples
Remarks
Using bash and timeout:
Note that timeout should be present with RHEL 6+, or is alternatively found in GNU coreutils 8.22. On MacOS, install it using brew install coreutils and use it as gtimeout.
Command:
$ timeout $TIMEOUT_SECONDS bash -c "</dev/tcp/${HOST}/${PORT}"; echo $?
If parametrizing the host and port, be sure to specify them as ${HOST} and ${PORT} as is above. Do not specify them merely as $HOST and $PORT, i.e. without the braces; it won't work in this case.
Example:
Success:
$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/80"; echo $?
0
Failure:
$ timeout 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
124
If you must preserve the exit status of bash,
$ timeout --preserve-status 2 bash -c "</dev/tcp/canyouseeme.org/81"; echo $?
143
Using nc:
Note that a backward incompatible version of nc gets installed on RHEL 7.
Command:
Note that the command below is unique in that it is identical for both RHEL 6 and 7. It's just the installation and output that are different.
$ nc -w $TIMEOUT_SECONDS -v $HOST $PORT </dev/null; echo $?
RHEL 6 (nc-1.84):
Installation:
$ sudo yum install nc
Examples:
Success:
$ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $?
Connection to canyouseeme.org 80 port [tcp/http] succeeded!
0
Failure:
$ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $?
nc: connect to canyouseeme.org port 81 (tcp) timed out: Operation now in progress
1
If the hostname maps to multiple IPs, the above failing command will cycle through many or all of them. For example:
$ nc -w 2 -v microsoft.com 81 </dev/null; echo $?
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
nc: connect to microsoft.com port 81 (tcp) timed out: Operation now in progress
1
RHEL 7 (nmap-ncat-6.40):
Installation:
$ sudo yum install nmap-ncat
Examples:
Success:
$ nc -w 2 -v canyouseeme.org 80 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connected to 52.202.215.126:80.
Ncat: 0 bytes sent, 0 bytes received in 0.22 seconds.
0
Failure:
$ nc -w 2 -v canyouseeme.org 81 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connection timed out.
1
If the hostname maps to multiple IPs, the above failing command will cycle through many or all of them. For example:
$ nc -w 2 -v microsoft.com 81 </dev/null; echo $?
Ncat: Version 6.40 ( http://nmap.org/ncat )
Ncat: Connection to 104.43.195.251 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 23.100.122.175 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 23.96.52.53 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection to 191.239.213.197 failed: Connection timed out.
Ncat: Trying next address...
Ncat: Connection timed out.
1
Remarks:
The -v (--verbose) argument and the echo $? command are of course for illustration only.
With netcat you can check whether a port is open like this:
nc my.example.com 80 < /dev/null
The return value of nc will be success if the TCP port was opened, and failure (typically the return code 1) if it could not make the TCP connection.
Some versions of nc will hang when you try this, because they do not close the sending half of their socket even after receiving the end-of-file from /dev/null. On my own Ubuntu laptop (18.04), the netcat-openbsd version of netcat that I have installed offers a workaround: the -N option is necessary to get an immediate result:
nc -N my.example.com 80 < /dev/null
In Bash using pseudo-device files for TCP/UDP connections is straight forward. Here is the script:
#!/usr/bin/env bash
SERVER=example.com
PORT=80
</dev/tcp/$SERVER/$PORT
if [ "$?" -ne 0 ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
Testing:
$ ./test.sh
Connection to example.com on port 80 succeeded
Here is one-liner (Bash syntax):
</dev/tcp/localhost/11211 && echo Port open. || echo Port closed.
Note that some servers can be firewall protected from SYN flood attacks, so you may experience a TCP connection timeout (~75secs). To workaround the timeout issue, try:
timeout 1 bash -c "</dev/tcp/stackoverflow.com/81" && echo Port open. || echo Port closed.
See: How to decrease TCP connect() system call timeout?
I needed a more flexible solution for working on multiple git repositories so I wrote the following sh code based on 1 and 2. You can use your server address instead of gitlab.com and your port in replace of 22.
SERVER=gitlab.com
PORT=22
nc -z -v -w5 $SERVER $PORT
result1=$?
#Do whatever you want
if [ "$result1" != 0 ]; then
echo 'port 22 is closed'
else
echo 'port 22 is open'
fi
check ports using bash
Example
$ ./test_port_bash.sh 192.168.7.7 22
the port 22 is open
Code
HOST=$1
PORT=$2
exec 3> /dev/tcp/${HOST}/${PORT}
if [ $? -eq 0 ];then echo "the port $2 is open";else echo "the port $2 is closed";fi
If you're using ksh or bash they both support IO redirection to/from a socket using the /dev/tcp/IP/PORT construct. In this Korn shell example I am redirecting no-op's (:) std-in from a socket:
W$ python -m SimpleHTTPServer &
[1] 16833
Serving HTTP on 0.0.0.0 port 8000 ...
W$ : </dev/tcp/127.0.0.1/8000
The shell prints an error if the socket is not open:
W$ : </dev/tcp/127.0.0.1/8001
ksh: /dev/tcp/127.0.0.1/8001: cannot open [Connection refused]
You can therefore use this as the test in an if condition:
SERVER=127.0.0.1 PORT=8000
if (: < /dev/tcp/$SERVER/$PORT) 2>/dev/null
then
print succeeded
else
print failed
fi
The no-op is in a subshell so I can throw std-err away if the std-in redirection fails.
I often use /dev/tcp for checking the availability of a resource over HTTP:
W$ print arghhh > grr.html
W$ python -m SimpleHTTPServer &
[1] 16863
Serving HTTP on 0.0.0.0 port 8000 ...
W$ (print -u9 'GET /grr.html HTTP/1.0\n';cat <&9) 9<>/dev/tcp/127.0.0.1/8000
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.6.1
Date: Thu, 14 Feb 2013 12:56:29 GMT
Content-type: text/html
Content-Length: 7
Last-Modified: Thu, 14 Feb 2013 12:55:44 GMT
arghhh
W$
This one-liner opens file descriptor 9 for reading from and writing to the socket, prints the HTTP GET to the socket and uses cat to read from the socket.
While an old question, I've just dealt with a variant of it, but none of the solutions here were applicable, so I found another, and am adding it for posterity. Yes, I know the OP said they were aware of this option and it didn't suit them, but for anyone following afterwards it might prove useful.
In my case, I want to test for the availability of a local apt-cacher-ng service from a docker build. That means absolutely nothing can be installed prior to the test. No nc, nmap, expect, telnet or python. perl however is present, along with the core libraries, so I used this:
perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("172.17.42.1:3142")))'
In some cases where tools like curl, telnet, nc o nmap are unavailable you still have a chance with wget
if [[ $(wget -q -t 1 --spider --dns-timeout 3 --connect-timeout 10 host:port; echo $?) -eq 0 ]]; then echo "OK"; else echo "FAIL"; fi
If you want to use nc but don't have a version that support -z, try using --send-only:
nc --send-only <IP> <PORT> </dev/null
and with timeout:
nc -w 1 --send-only <IP> <PORT> </dev/null
and without DNS lookup if it's an IP:
nc -n -w 1 --send-only <IP> <PORT> </dev/null
It returns the codes as the -z based on if it can connect or not.
Building on the most highly voted answer, here is a function to wait for two ports to be open, with a timeout as well. Note the two ports that mus be open, 8890 and 1111, as well as the max_attempts (1 per second).
function wait_for_server_to_boot()
{
echo "Waiting for server to boot up..."
attempts=0
max_attempts=30
while ( nc 127.0.0.1 8890 < /dev/null || nc 127.0.0.1 1111 < /dev/null ) && [[ $attempts < $max_attempts ]] ; do
attempts=$((attempts+1))
sleep 1;
echo "waiting... (${attempts}/${max_attempts})"
done
}
I needed short script which was run in cron and hasn't output. I solve my trouble using nmap
open=`nmap -p $PORT $SERVER | grep "$PORT" | grep open`
if [ -z "$open" ]; then
echo "Connection to $SERVER on port $PORT failed"
exit 1
else
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
fi
To run it You should install nmap because it is not default installed package.
I'm guessing that it's too late for an answer, and this might not be a good one, but here you go...
What about putting it inside of a while loop with a timer on it of some sort. I'm more of a Perl guy than Solaris, but depending on the shell you're using, you should be able to do something like:
TIME = 'date +%s' + 15
while TIME != `date +%s'
do whatever
And then just add a flag in the while loop, so that if it times out before completing, you can cite the timeout as reason for failure.
I suspect that the telnet has a timeout switch as well, but just off the top of my head, I think the above will work.
This uses telnet behind the scenes, and seems to work fine on mac/linux. It doesn't use netcat because of the differences between the versions on linux/mac, and this works with a default mac install.
Example:
$ is_port_open.sh 80 google.com
OPEN
$ is_port_open.sh 8080 google.com
CLOSED
is_port_open.sh
PORT=$1
HOST=$2
TIMEOUT_IN_SEC=${3:-1}
VALUE_IF_OPEN=${4:-"OPEN"}
VALUE_IF_CLOSED=${5:-"CLOSED"}
function eztern()
{
if [ "$1" == "$2" ]
then
echo $3
else
echo $4
fi
}
# cross platform timeout util to support mac mostly
# https://gist.github.com/jaytaylor/6527607
function eztimeout() { perl -e 'alarm shift; exec #ARGV' "$#"; }
function testPort()
{
OPTS=""
# find out if port is open using telnet
# by saving telnet output to temporary file
# and looking for "Escape character" response
# from telnet
FILENAME="/tmp/__port_check_$(uuidgen)"
RESULT=$(eztimeout $TIMEOUT_IN_SEC telnet $HOST $PORT &> $FILENAME; cat $FILENAME | tail -n1)
rm -f $FILENAME;
SUCCESS=$(eztern "$RESULT" "Escape character is '^]'." "$VALUE_IF_OPEN" "$VALUE_IF_CLOSED")
echo "$SUCCESS"
}
testPort
My machine does not support nc or /dev/tcp/$hostname/$port but timeout, so I came back to telnet as follows:
if echo "quit" | timeout 2 telnet $SERVER $PORT 2>&1 | grep -q 'Connected to'; then
echo "Connection to $SERVER on port $PORT succeeded"
exit 0
else
echo "Connection to $SERVER on port $PORT failed"
exit 1
fi
nmap-ncat to test for local port that is not already in use
availabletobindon() {
port="$1"
nc -w 2 -i 1 localhost "$port" 2>&1 | grep -v -q 'Idle timeout expired'
return "$?"
}

Bash: Loop until command exit status equals 0

I have a netcat installed on my local machine and a service running on port 25565. Using the command:
nc 127.0.0.1 25565 < /dev/null; echo $?
Netcat checks if the port is open and returns a 0 if it open, and a 1 if it closed.
I am trying to write a bash script to loop endlessly and execute the above command every second until the output from the command equals 0 (the port opens).
My current script just keeps endlessly looping "...", even after the port opens (the 1 becomes a 0).
until [ "nc 127.0.0.1 25565 < /dev/null; echo $?" = "0" ]; do
echo "..."
sleep 1
done
echo "The command output changed!"
What am I doing wrong here?
Keep it Simple
until nc -z 127.0.0.1 25565
do
echo ...
sleep 1
done
Just let the shell deal with the exit status implicitly
The shell can deal with the exit status (recorded in $?) in two ways, explicit, and implicit.
Explicit: status=$?, which allows for further processing.
Implicit:
For every statement, in your mind, add the word "succeeds" to the command, and then add
if, until or while constructs around them, until the phrase makes sense.
until nc succeeds; do ...; done
The -z option will stop nc from reading stdin, so there's no need for the < /dev/null redirect.
You could try something like
while true; do
nc 127.0.0.1 25565 < /dev/null
if [ $? -eq 0 ]; then
break
fi
sleep 1
done
echo "The command output changed!"

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