I'm writing a file transfer script and it gets pretty complex. So in the beginning when I generate my IP address to transfer from, I want to validate that I can indeed connect to it. The code in the area looks like this:
USER_ID=$1
if [[ $GROUP == "A" ]]; then
ADDRESS="${USER_ID}#morgan.company.gov"
elif [[ $GROUP == "B" ]]; then
ADDRESS="${USER_ID}#mendel.company.gov"
else
log_msg fatal "Couldn't resolve group $GROUP. Exiting"
exit 1;
fi
// HERE I want to test that $ADDRESS exists, and I can connect right now I
// have what is below. I just think there is a better way to do it
ssh -q $ADDRESS exit
if [ $? != 0 ]; then
log_msg fatal "Couldn't resolve host, do you have login privileges with $ADDRESS"
fi
... // lots of other things happen
scp $ADDRESS:$INCOMING_FILE $NEW_FILE
What I have works, but it doesn't seem like its an elegant solution. I'd prefer not to actually ssh and exit the server, just test the connection.
You can use this shell function that tests wether the host has the ssh port open or not:
#!/bin/bash
function isUp(){
local ip=$1
local sshport=22
if [[ $ip =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
if [[ $(nmap -P0 $ip -p$sshport | grep ^$sshport | cut -d' ' -f2) == "open" ]]; then
return 0
else
return 1
fi
fi
}
if isUp $1; then
ssh $1 uptime
else
echo "Host $1 is not available"
fi
or make use of this (new to me) bash functionality:
#!/bin/bash
function isUp(){
local ip=$1
if echo > /dev/tcp/$ip/22 >/dev/null 2>&1; then
return 0
else
return 1
fi
}
If you want to thoroughly check for the connection then you are better off analyzing the return codes from an scp connection. This will allow you to understand the reason why your connection failed and act in consequence (there may be various reasons at different levels, from a general lack of connectivity to issues with the keys for instance).
If you are just interested in a binary answer ("is my connection OK as it is?") then your code is fine, though I would directly use scp.
There is nothing wrong with your line:
ssh -q $ADDRESS exit
This is the best/fastest way to test a connection.
Related
Code works fine until the last for loop.
It tries to login database. Either, it establish a successful connection with database or not, script gives output OK/NOT OK depending to the connection and then exit the shell script. What should I do to solve this?
#!/bin/bash
read -p 'Username: ' var_username
read -sp 'Password: ' var_password
filename="$1"
while read -r line; do
name=$(sed 's/#.*$//g; s/(.*$//g; s/=.*$//g; s/).*$//g')
done < "$filename"
#retval=$? | tail -n1|grep OK
for tns in $name
do
tnsping $tns
if [ $? -eq 1 ]; then
echo $tns 'tnsping i calismiyor' >>tnslatest.log
else
echo $tns 'tnsping i calisiyor' >>tnslatest.log
working_tns+=($tns)
fi
done
#The following lines do not work properly.#
for working in $working_tns
do
echo "exit" | sqlplus -L $var_username/$var_password#$working | grep
Connected > /dev/null
if [ $? -eq 0 ]
then
echo "OK"
else
echo "NOT OK"
fi
done
For example; my tnsnames.ora file contains 4 tns.
So, I want to have for output like OK or NOT OK in total.
Thanks in advance.
I am trying real hard to figure out how to fix my for loop in my bash profile.
So here is my problem, I have an alias command called "command" it works.
For the sake of brevity we will say alias command='teamviewer'
So I am trying to make the bash profile go through a for-loop to detect internet connectivity. I was able to awk my way to success to determine when the state is up and when the state is down. Not I am stuck on my for-loop and am having issues making it work. The for-loop is as follows
#For-loop begins below
# Variable Assignment and Alias Command for Network Connectivity
# ==============================================================
alias command='teamviewer'
alias inet_state="ip addr show | awk '{print $8,$9}' | awk 'NR >= 7 && NR <=7'"
inetstate-good='$(state UP)'
inetstate-bad='$(state DOWN)'
# Loop for Internet Connection & Start Broadsign
# ==============================================
echo "$(inet_state);
for inet_state in "$(inet_state);
do {
if inet_state="$(inetstate-bad)";
then 'sleep 9999999999';
elif inet_state="$(inetstate-good)";
command;
fi}
done
# ==============================================
Anyhelp would be greatly appreciated :D
You can try this. Network test taken from Jesse here
# Test for network connection. Taken from Jesse in
# https://stackoverflow.com/questions/929368/how-to-test-an-internet-connection-with-bash
for interface in $(ls /sys/class/net/ | grep -v lo); do
if [[ $(cat /sys/class/net/$interface/carrier) = 1 ]]; then OnLine=1; fi
done
# Then do the job
if [ $OnLine == 1 ]; then
teamwiewer
else
sleep 9999999999
fi
I finally got it working.
Sorry for the delayed response.
A friend of mine suggested to use fping.
while true; do
if [[ "${inet_state}" = "${inet_state_good}" ]];
then sleep 10 && <insert_process_name && break
elif [[ "${inet_state}" = "${inet_state_bad}" ]];
then echo "Your Player has a technical issue, please call XXXXXXXXXXXXX ext. 150" && sleep 999999999 && sudo pkill <insert_process_name>
fi
done
Consider the following code fragment inside a function:
local -r LSBLK_FAILED="Lsblk failed"
for f in $(lsblk -lno MOUNTPOINT "$DEVPATH"); do
sudo umount "$f";
RET=$?
if (( $RET != 0 )); then
echo "Unable to dismount $f - error $UNABLE_DISMOUNT_PARTITION"
return $UNABLE_DISMOUNT_PARTITION
fi
done
if [[ "$f" -eq "$LSBLK_FAILED" ]]; then
echo "Problem running Lsblk"
fi
The problem I have is that I cannot see how to access the return code for the lsblk command. I can detect whether the command failed but I cannot access the actual return code. Can anyone suggest how I might do this?
You can split the call to lsblk into a separate command. Then you can get its exit status from $?.
l=$(lsblk -lno MOUNTPOINT "$DEVPATH")
if (( !$? )); then
for f in $l; do
// etc.
Actually it seems like you can use a conditional with the assignment as well:
if l=$(lsblk...); then
I have following function which checks connection for internet (I know there are better ways to check for internet connection but that's not the topic):
function checkInternet() {
local HOST="http://google.com"
local WGET="/usr/bin/wget"
$WGET -q --tries=10 --timeout=10 --spider $HOST
if [[ $? -eq 0 ]]
then
echo "online"
else
echo "offline"
fi
}
Now I want to request the return value of the function directly in an if-statement:
I tried several scripts similar to e.g. this one (what I found here):
if( $(checkInternet) -eq "online" )
then
echo "Function returned online"
else
echo "Function returned offline"
fi
I don't want to initialisize further variables before the if-statement what I meant with "directly".
You can use this in BASH to check the output of a function:
[[ $(checkInternet) == online ]] && echo "Function returned online" ||
echo "Function returned offline"
To compare conditions use [[...]] (preferable) or [...].
You can simplify above to to just this without evaluating any conditions:
echo "Function returned $(checkInternet)"
A case statement will do this nicely and without non-portable bashisms:
case $(checkInternet) in
(online) echo is online;;
(offline) echo is offline;;
esac
You can also make your checkInternet return a status, which simplifies things in an if:
...
if [ $? -eq 0 ]; then
true
else
false
fi
Along with
if checkInternet; then
# online
else
# offLine
fi
You are not actually returning a value from your checkInternet () function. If you look at the example you posted, you'll see that their function has a return statement at the end.
I have the following code in bash:
check_port()
{
local host=${1}
local port=${2}
echo $host
echo $port
while true; do
if nc -w 5 -z 127.0.0.1 111 && nc -w 5 -z 127.0.0.1 5001 ;
then
echo -e "\a\n => Port at host is open"
break
else
echo -e "\a\n => Port at host is closed"
break
fi
}
For some reason, I get the following error:
syntax error near unexpected token `}'
`}'
I don't understand why: } is closing the scope of the function.
You need a done line to terminate your while loop, between the fi line and the closing brace }.
However, I'm not entirely certain why you even have the while true loop since you break out of it regardless of whether the if evaluates to true or false. Hence it's superfluous, unless you plan on changing the behaviour of one of those blocks at some point.
If you're not planning that, you're better off with the much simpler:
check_port()
{
local host=${1}
local port=${2}
echo $host
echo $port
if nc -w 5 -z 127.0.0.1 111 && nc -w 5 -z 127.0.0.1 5001 ; then
echo -e "\a\n => Port at host is open"
else
echo -e "\a\n => Port at host is closed"
fi
}
I'm also not entirely certain of the sanity of passing in the host and port and then ignoring them (instead using localhost with two hard-coded ports).
However, I'm going to assume that you're still in the development/testing phase rather than the possibility you've gone insane :-)
The done at the end of the while loop is missing
....
break
fi
done;
}