repeat pipe command until first command succeeds and second command fails - loops

I am trying to figure out how to get my bash script to work. I have a the following command:
curl http://192.168.1.2/api/queue | grep -q test
I need it to repeat until the first command in the pipline succeeds (meaning the server responds) and the second command fails (meaning the pattern is not found or the queue is empty). I've tried a number of combinations but just can't seem to get it. I looked at using $PIPESTATUS but can't get it to function in a loop how I want. I've tried all kind of variations but can't get it to work. This is what I am currently trying:
while [[ "${PIPESTATUS[0]}" -eq 0 && "${PIPESTATUS[1]}" -eq 1 ]]
do curl http://192.168.1.2 | grep -q regular
echo "The exit status of first command ${PIPESTATUS[0]}, and the second command ${PIPESTATUS[1]}"
sleep 5
done

Although it's not really clear what kind of output is returned by the curl call, maybe you are looking for something like this:
curl --silent http://192.168.1.2 |while read line; do
echo $line |grep -q regular || { err="true"; break }
done
if [ -z "$err" ]; then
echo "..All lines OK"
else
echo "..Abend on line: '$line'" >&2
fi

Figured it out. Just had to re-conceptualize it. I couldn't figure it out strictly with a while or until loop but creating an infinite loop and breaking out of it when the condition is met worked.
while true
do curl http://192.168.1.2/api/queue | grep -q test
case ${PIPESTATUS[*]} in
"0 1")
echo "Item is no longer in the queue."
break;;
"0 0")
echo "Item is still in the queue. Trying again in 5 minutes."
sleep 5m;;
"7 1")
echo "Server is unreachable. Trying again in 5 minutes."
sleep 5m;;
esac
done

Related

How can I do a function that outputs the not of another function in bash shell?

I have an existing function is_active_instance, which determines if a database instance is running (true) or not. I am working in a new function called is_inactive_instance which needs to return true if is_active_instance returns false.
How can I call is_active_instance from is_inactive_instance and negate its return to return True to main program?
I already tried to call is_instance_active with ! to change the result of the original function.
is_active_instance(){
dbservice=""
if is_mysql_db
then
dbservice="mysqld"
elif is_mariadb_db
then
dbservice="mysqld"
elif is_postgre_db
then
dbservice='postgresql'
fi
[ $(ps -ef | grep -v grep | grep $dbservice* | wc -l) > 0 ]
}
is_inactive_instance(){
[ [ ! is_active_instance ] ]
}
if is_active_instance
then
echo "Is active instance"
elif is_inactive_instance
then
echo "Is inactive instance"
else
echo "Other result"
fi
In Main body I will need to be able to detect if the instance is running, stopped or other for my purposes.
Don't use any [s:
is_inactive_instance(){
! is_active_instance
}
Also see Comparing numbers in Bash for how to make your is_active_instance work.
Here is an example of how to do this in BASH. Your code is on the right track but needs syntax changes to work in BASH.
Instead of checking for a NOT you would check for "Yes" or "No", and you may change the outputs to zeroes and ones if you wish and test for those.
Copy the code between CODE STARTS and CODE ENDS into ./active_instance.sh.
Type the line below and press RETURN.
chmod 755 ./active_instance.sh
CODE STARTS HERE ==================
#!/usr/bin/env bash
for some_db in mariadb mysqld postgres oracle sybase
do
echo -n "Checking ${some_db}..."
set `ps -ef|grep -v grep|grep ${some_db}|wc`
if test ${1} -gt 0
then
echo "Yes"
else
echo "No"
fi
done
CODE ENDS HERE ==================
To run, type the line below and press RETURN.
./active_instance.sh
Sample execution:
./active_instance.sh
Checking mariadb...Yes
Checking mysqld...Yes
Checking postgres...Yes
Checking oracle...No
Checking sybase...No

Use curl to get http code from webpage, using list file

Im am struggeling with a script, and are newbie to shell scripting.
I am trying to create a script, that will run curl on several websites, from a source file.
arr_values=()
#Getting list of domains/websites to check, into array.
read -ra arr_values <<< $(head -n 999 web.csv)
for s in "${arr_values[#]}"; do
#Running curl on each websites from list.
res=$(curl -s -o /dev/null -w "%{http_code}" $s)
if [ $res == "200" ]; then
echo "OK";
elif
[ $res == "302" ]; then
echo "OK";
else
echo "Error";
fi
done
But i get code 000 when i run without the if statement.
if i run it manually, it all works fine.
And results in a 200 or 302.
Assuming the CSV file is this:
www.yahoo.com
www.google.ca
I.e. one site per line. Also run dos2unix on the file, to ensure it does not have "\r\n" characters at the end of each line.
Then, run this code:
#!/bin/bash
arr_values=()
#Getting list of domains/websites to check, into array.
read -ra arr_values <<< $(head -n 999 web.csv)
for s in "${arr_values[#]}"
do
#Running curl on each websites from list.
res=$(curl -s -o /dev/null -w "%{http_code}" $s)
if [ $res == "200" ]
then
echo "OK $s $res";
elif [ $res == "302" ]
then
echo "OK $s $res";
else
echo "Error $s $res";
fi
done
And got this output:
./t.bash
Error www.yahoo.com 301
OK www.google.ca 200
What was modified:
if conditions are verified using '=='
Modified the echo statements a bit to make it easier to debug
You can use single brackets around the expression for it i.e. [ and ], not [[ and ]]. Also you can remove the asterisk from the value to check i.e. "200", not *"200"*.

Nagios bash script returns no output when executed through check_nrpe

My nagios bash script works fine from the client's command line.
When I execute the same script through check_nrpe from the nagios server it returns the following message "CHECK_NRPE: No output returned from daemon."
Seems like a command in the bash script is not being executed.
arrVars=(`/usr/bin/ipmitool sensor | grep "<System sensor>"`)
#echo "Hello World!!"
myOPString=""
<Process array and determine string to echo along with exit code>
echo $myOPString
if [[ $flag == "False" ]]; then
exit 1
else
exit 0
fi
"Hello World" shows up on the nagios monitoring screen if I uncomment the echo statement.
I am new to linux but seems like the nagios user isn't able to execute ipmitool
arrVars=(`/usr/bin/ipmitool sensor | grep "<System sensor>"`)
Check the output of the above, You can echo it and check for the values. If it still does not work use another script to be called by this to get the output and assign it to a variable
exit 1
This refers to the Severity , So you would have to define different conditions where the severity changes
Add this line to the sudoers
nagios ALL=(root) NOPASSWD: /usr/bin/ipmitool
Then use "sudo /usr/bin/ipmitool" in your script

While loop in ksh

sh bothworkfile.txt >> cleanup_process.log
while [[ `ps -eaf | grep -c "cleanx"` -ge 2 ]]
do
sleep 10
echo "Please be patient, we are still cleaning stuffs ! "
done
echo " Clean up is done."
Hi I am using ksh.
The bothworkfile.txt contains few lines to run the process in the background.
cat bothworkfile.txt
cleanx data01.xsd*.* &
cleanx data01.xsd*.* &
Cleanx is an utility in my local shell. By default there is always a cleanx running in the background. So,
ps -eaf | grep -c "cleanx"
gives 1 always, but when a script calls it the number increases.
But now the issue is it seems i am not able to enter the while loop at all. And after running the script it prints " Clean up is done."
Please help me to understand why it is not entering while loop. Again, its ksh shell.
To make it easier to debug and see that the result is really what you are expecting, assign the result of ps -eaf | grep -c "cleanx" to a variable, then test the variable. I suspect it is evaluating to null or less than 2 right off the bat, which would cause the test to return false, thus skipping the loop. So, print it out before testing it so you know for sure. Something like this:
cleanx_count=$(ps -eaf | grep -c "cleanx")
printf "Cleanx_count: %d/n" ${cleanx_count}
while [[ ${cleanx_count} -ge 2 ]]

Check database connectivity using Shell script

I am trying to write a shell script to check database connectivity. Within my script I am using the command
sqlplus uid/pwd#database-schemaname
to connect to my Oracle database.
Now I want to save the output generated by this command (before it drops to SQL prompt) in a temp file and then grep / find the string "Connected to" from that file to see if the connectivity is fine or not.
Can anyone please help me to catch the output and get out of that prompt and test whether connectivity is fine?
Use a script like this:
#!/bin/sh
echo "exit" | sqlplus -L uid/pwd#dbname | grep Connected > /dev/null
if [ $? -eq 0 ]
then
echo "OK"
else
echo "NOT OK"
fi
echo "exit" assures that your program exits immediately (this gets piped to sqlplus).
-L assures that sqlplus won't ask for password if credentials are not ok (which would make it get stuck as well).
(> /dev/null just hides output from grep, which we don't need because the results are accessed via $? in this case)
You can avoid the SQL prompt by doing:
sqlplus uid/pwd#database-schemaname < /dev/null
SqlPlus exits immediately.
Now just grep the output of the above as:
if sqlplus uid/pwd#database-schemaname < /dev/null | grep 'Connected to'; then
# have connectivity to Oracle
else
# No connectivity
fi
#! /bin/sh
if echo "exit;" | sqlplus UID/PWD#database-schemaname 2>&1 | grep -q "Connected to"
then echo connected OK
else echo connection FAIL
fi
Not knowing whether the "Connected to" message is put to standard output or standard error, this checks both. "qrep -q" instead of "grep... >/dev/null" assumes Linux.
#!/bin/bash
output=`sqlplus -s "user/pass#POLIGON.TEST " <<EOF
set heading off feedback off verify off
select distinct machine from v\\$session;
exit
EOF
`
echo $output
if [[ $output =~ ERROR ]]; then
echo "ERROR"
else
echo "OK"
fi
Here's a good option which does not expose the password on the command line
#!/bin/bash
CONNECT_STRING=<USERNAME>/<PASS>#<SID>
sqlplus -s -L /NOLOG <<EOF
whenever sqlerror exit 1
whenever oserror exit 1
CONNECT $CONNECT_STRING
exit
EOF
SQLPLUS_RC=$?
echo "RC=$SQLPLUS_RC"
[ $SQLPLUS_RC -eq 0 ] && echo "Connected successfully"
[ $SQLPLUS_RC -ne 0 ] && echo "Failed to connect"
exit SQLPLUS_RC
none of the proposed solutions works for me, as my script is executed in machines running several countries, with different locales, I can't simply check for one String simply because this string in the other machine is translated to a different language. As a solution I'm using SQLcl
https://www.oracle.com/database/technologies/appdev/sqlcl.html
which is compatible with all sql*plus scripts and allow you to test the database connectivity like this:
echo "disconnect" | sql -L $DB_CONNECTION_STRING > /dev/null || fail "cannot check connectivity with the database, check your settings"
#!/bin/sh
echo "exit" | sqlplus -S -L uid/pwd#dbname
if [ $? -eq 0 ]
then
echo "OK"
else
echo "NOT OK"
fi
For connection validation -S would be sufficient.
The "silent" mode doesn't prevent terminal output. All it does is:
-S Sets silent mode which suppresses the display of
the SQL*Plus banner, prompts, and echoing of
commands.
If you want to suppress all terminal output, then you'll need to do something like:
sqlplus ... > /dev/null 2>&1
This was my one-liner for docker container to wait until DB is ready:
until sqlplus -s sys/Oracle18#oracledbxe/XE as sysdba <<< "SELECT 13376411 FROM DUAL; exit;" | grep "13376411"; do echo "Could not connect to oracle... sleep for a while"; sleep 3; done
And the same in multiple lines:
until sqlplus -s sys/Oracle18#oracledbxe/XE as sysdba <<< "SELECT 13376411 FROM DUAL; exit;" | grep "13376411";
do
echo "Could not connect to oracle... sleep for a while";
sleep 3;
done
So it basically does select with magic number and checks that correct number was actually returned.

Resources