I have tried a method using timeout to identify and exit server comes to RUNNING state or else exit watching for RUNNING state at the timeout value, unfortunately one of the server has bash version 3 and doesn't support time out.
timeout 300s grep -q 'Server state changed to RUNNING' <(tail -f AdminServer.out)
if [ $? != 0];then
printf "\n===> unable to bring up the server.please check\n"
else
printf "\n===> server came to RUNNING state\n"
fi
I have tried the following but wasn't able to exit when the log is appeared
( cmdpid=$BASHPID; (sleep 60; kill $cmdpid) & exec `grep -q 'Server state changed to RUNNING' <(tail -f AdminServer.out)`)
but it first give command line substitution error for grep -q 'Server state changed to RUNNING' <(tail -f AdminServer.out) and then gives error for kill usage like below(seems the kill is not working) ,
kill: usage: kill [-s sigspec | etc....
I'm not in a position to upgrade the bash version of the server unfortunately, any guidance for this highly appreciated .Thank you!!
*server: suse distribution 2.6.32.12-0.7-default
Consider to try something like this:
data=$(
tail -f AdminServer.out & pid=$!
till=$[SECONDS+300]
while ((SECONDS<till)); do :; done
kill -9 $pid
)
grep -q 'Server state changed to RUNNING' <<< "$data" \
&& printf "\n===> server came to RUNNING state\n" \
|| printf "\n===> unable to bring up the server.please check\n"
When I was young... on OSF1, DEC Alpha, SPARC...
without timeout command, without <(...) or <<< operators...
I'm actively waiting...
File: timeout.sh
#! /bin/bash
PID="$1"
SEC="$2"
FILE="$3"
DATE_REF=$(date +%s)
DATE_MAX=$(( DATE_REF + ${SEC} ))
while ps -p "${PID}" >/dev/null 2>&1 && [[ $(date +%s) -lt ${DATE_MAX} ]] && ! grep OK "${FILE}" >/dev/null 2>&1; do
sleep 1
done
if grep OK "${FILE}" >/dev/null 2>&1; then
RET=0
else
RET=1
fi
if ps -p "${PID}" >/dev/null 2>&1; then
kill -9 "${PID}"
fi
rm -f "${FILE}"
exit $RET
Used like that:
nb_seconds_to_wait=5
tail -f my_log_file | grep -m 1 my_token_to_search && echo "OK" > my_flag_file &
timeout.sh $! nb_seconds_to_wait my_flag_file
if [[ $? -eq 0 ]]; then
echo "Found"
else
echo "Not found"
fi
I have tried again and came up with the following, am I doing anything harmful here?
( cmdpid=$BASHPID; ( sleep 10; if ps -p $cmdpid > /dev/null; then kill $cmdpid > /dev/null;fi ) & while `tail -f -n0 AdminServer.out | grep -q RUNNING`; do exit 0;done )
echo "proceeding with the rest of commands the previous command status is $?"
I'm trying to workout why this doesn't work
$result=`[ pgrep -x "gedit" ] && echo "Running" || echo "Stopped" `
I get:
-bash: [: -x: binary operator expected
If I run pgrep -x "gedit" direct I get process ID's
Can someone advise why this fails ?
Thanks
You don't need the brackets to run and check the exit status of pgrep:
result=$(pgrep -x "gedit" > /dev/null && echo "Running" || echo "Stopped")
You can use the following code to solve your problem:
#!/bin/bash
result=\`pgrep -x gedit && echo running || echo not\`
echo $result
I'm getting into the error for bash shell [: : integer expression expected" while running below script.
#!/bin/bash
sm=$(ps -e | grep sendmail > /dev/null 2>&1)
pm=$(/etc/init.d/postfix status > /dev/null 2>&1)
check_mail(){
if [ "$sm" -eq 0 ]; then
echo "Service Status: Sendmail is Running!"
elif [ "$pm" -eq 0 ]; then
echo "Service Status: Postfix Service is Running!"
else
echo "Service Status: Both Sendmail & Postfix Service is Not Running On $(uname -n)"
fi
}
check_mail
While running the above script it's simply showing the output of else
condition.
Service Status: Both Sendmail & Postfix Service is Not Running On host
Though, i have tested "==" rather "-eq" for comparison and [[]] but did not worked.
I assume you are trying to assess presence of sendmail in the process list. You should change your code to this :
#!/bin/bash
check_mail(){
if
ps -e | grep sendmail > /dev/null 2>&1
then
echo "Service Status: Sendmail is Running!"
elif
/etc/init.d/postfix status > /dev/null 2>&1
then
echo "Service Status: Postfix Service is Running!"
else
echo "Service Status: Both Sendmail & Postfix Service is Not Running On $(uname -n)"
fi
}
check_mail
The reason your original code fails is that you capture the output of commands using command substitution $(). The standard output, that is, not the exit code. Then, when using the [ -eq ] test, which expects an integer argument (which your variable does not contain), it fails with the message you get. Since both tests always fail, the else clause is entered.
By putting the actual commands inside the conditions of the if statement, you are using the actual numerical return code (0 for true, non-zero for false), which is what you want here.
It seems to me that you are confusing the exit-status of a program with the output.var=$(command) will put the output of command in var. As said in 123's comment, because you redirect everything to /dev/null, there is no output, and therefore, sm and pm are empty.
If you want to see the exit status, use $?:
#!/bin/bash
typeset -i pm
typeset -i sm
ps -e | grep sendmail > /dev/null 2>&1
sm=$?
/etc/init.d/postfix status > /dev/null 2>&1
pm=$?
check_mail(){
if [ $sm -eq 0 ]; then
echo "Service Status: Sendmail is Running!"
elif [ $pm -eq 0 ]; then
echo "Service Status: Postfix Service is Running!"
else
echo "Service Status: Both Sendmail & Postfix Service is Not Running On $(uname -n)"
fi
}
check_mail
I have a shell script that's being executed via Crontab. The shell script is properly creating the Sqlplus jobs and they run to completion. What's not working is the while loop at the end where I want the script to wait for all of the Sqlplus jobs to complete.
If I execute this shell script manually, the while loop at the end works properly and the shell script won't exit until all the Sqlplus jobs have finished.
How do I get the while loop at the end to see the Sqlplus jobs while running via Crontab?
#!/bin/bash
cd /some/path/to/folder
source ~/.profile
echo 'Run started'
echo $(date)
i=0
while [ $i -lt 12 ]
do
echo 'Starting process ' $i
sqlplus username/password#'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=server)(PORT=1521))(CONNECT_DATA=(SID=SERVERSID)))' #import.sql $i > import_batch$i.log &
let i=$i+1
done
while [ $(ps -a | grep -w -c 'sqlplus') -ne 0 ] //This is not working in Crontab
until [[ -z $(pgrep -flx 'sqlplus') ]] //I've also tried this (instead of the while in my script) without success in Crontab
do
sleep 60
done
echo 'Run completed'
echo $(date)
As per my comment above, use "wait" to wait for all processes owned by this process to comlete. e.g.:
#!/bin/bash
cd /some/path/to/folder
source ~/.profile
echo 'Run started'
echo $(date)
i=0
while [ $i -lt 12 ]
do
echo 'Starting process ' $i
sqlplus username/password#'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=server)(PORT=1521))(CONNECT_DATA=(SID=SERVERSID)))' #import.sql $i > import_batch$i.log &
let i=$i+1
done
wait
echo 'Run completed'
echo $(date)
Try using
ps -axww | grep -w 'sqlplus' | grep -v grep | wc -l
because ps -axww | grep -w -c 'sqlplus' will always include 1 line for grep -w -c 'sqlplus' command
Alternatively, try using following to match sqlplus pattern exactly or as regex
pgrep -fl 'sqlplus'
pgrep -flx '.*sqlplus.*'
Maybe you need to use ps -ax in the crontab case ?
while [ $(ps -ax | grep -w -c 'sqlplus') -ne 0 ]
EDIT 2013-04-27 : scratch that, that's dumb. As linuts suggested, just use wait.
#!/bin/bash
cd /some/path/to/folder
source ~/.profile
echo 'Run started'
echo $(date)
i=0
while [ $i -lt 12 ]
do
echo 'Starting process ' $i
sqlplus username/password#'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=server)(PORT=1521))(CONNECT_DATA=(SID=SERVERSID)))' #import.sql $i > import_batch$i.log &
let i=$i+1
done
wait
echo 'Run completed'
echo $(date)
This question already has answers here:
Linux Script to check if process is running and act on the result
(8 answers)
Closed 5 years ago.
I wrote a bash-script to check if a process is running. It doesn't work since the ps command always returns exit code 1. When I run the ps command from the command-line, the $? is correctly set, but within the script it is always 1. Any idea?
#!/bin/bash
SERVICE=$1
ps -a | grep -v grep | grep $1 > /dev/null
result=$?
echo "exit code: ${result}"
if [ "${result}" -eq "0" ] ; then
echo "`date`: $SERVICE service running, everything is fine"
else
echo "`date`: $SERVICE is not running"
fi
Bash version: GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
There are a few really simple methods:
pgrep procname && echo Running
pgrep procname || echo Not running
killall -q -0 procname && echo Running
pidof procname && echo Running
This trick works for me. Hope this could help you. Let's save the followings as checkRunningProcess.sh
#!/bin/bash
ps_out=`ps -ef | grep $1 | grep -v 'grep' | grep -v $0`
result=$(echo $ps_out | grep "$1")
if [[ "$result" != "" ]];then
echo "Running"
else
echo "Not Running"
fi
Make the checkRunningProcess.sh executable.And then use it.
Example to use.
20:10 $ checkRunningProcess.sh proxy.py
Running
20:12 $ checkRunningProcess.sh abcdef
Not Running
I tried your version on BASH version 3.2.29, worked fine. However, you could do something like the above suggested, an example here:
#!/bin/sh
SERVICE="$1"
RESULT=`ps -ef | grep $1 | grep -v 'grep' | grep -v $0`
result=$(echo $ps_out | grep "$1")
if [[ "$result" != "" ]];then
echo "Running"
else
echo "Not Running"
fi
I use this one to check every 10 seconds process is running and start if not and allows multiple arguments:
#!/bin/sh
PROCESS="$1"
PROCANDARGS=$*
while :
do
RESULT=`pgrep ${PROCESS}`
if [ "${RESULT:-null}" = null ]; then
echo "${PROCESS} not running, starting "$PROCANDARGS
$PROCANDARGS &
else
echo "running"
fi
sleep 10
done
Check if your scripts name doesn't contain $SERVICE. If it does, it will be shown in ps results, causing script to always think that service is running. You can grep it against current filename like this:
#!/bin/sh
SERVICE=$1
if ps ax | grep -v grep | grep -v $0 | grep $SERVICE > /dev/null
then
echo "$SERVICE service running, everything is fine"
else
echo "$SERVICE is not running"
fi
Working one.
!/bin/bash
CHECK=$0
SERVICE=$1
DATE=`date`
OUTPUT=$(ps aux | grep -v grep | grep -v $CHECK |grep $1)
echo $OUTPUT
if [ "${#OUTPUT}" -gt 0 ] ;
then echo "$DATE: $SERVICE service running, everything is fine"
else echo "$DATE: $SERVICE is not running"
fi
Despite some success with the /dev/null approach in bash. When I pushed the solution to cron it failed. Checking the size of a returned command worked perfectly though. The ampersrand allows bash to exit.
#!/bin/bash
SERVICE=/path/to/my/service
result=$(ps ax|grep -v grep|grep $SERVICE)
echo ${#result}
if ${#result}> 0
then
echo " Working!"
else
echo "Not Working.....Restarting"
/usr/bin/xvfb-run -a /opt/python27/bin/python2.7 SERVICE &
fi
#!/bin/bash
ps axho comm| grep $1 > /dev/null
result=$?
echo "exit code: ${result}"
if [ "${result}" -eq "0" ] ; then
echo "`date`: $SERVICE service running, everything is fine"
else
echo "`date`: $SERVICE is not running"
/etc/init.d/$1 restart
fi
Something like this
Those are helpful hints. I just needed to know if a service was running when I started the script, so I could leave the service in the same state when I left. I ended up using this:
HTTPDSERVICE=$(ps -A | grep httpd | head -1)
[ -z "$HTTPDSERVICE" ] && echo "No apache service running."
I found the problem. ps -ae instead ps -a works.
I guess it has to do with my rights in the shared hosting environment. There's apparently a difference between executing "ps -a" from the command line and executing it from within a bash-script.
A simple script version of one of Andor's above suggestions:
!/bin/bash
pgrep $1 && echo Running
If the above script is called test.sh then, in order to test, type:
test.sh NameOfProcessToCheck
e.g.
test.sh php
I was wondering if it would be a good idea to have progressive attempts at a process, so you pass this func a process name func_terminate_process "firefox" and it tires things more nicely first, then moves on to kill.
# -- NICE: try to use killall to stop process(s)
killall ${1} > /dev/null 2>&1 ;sleep 10
# -- if we do not see the process, just end the function
pgrep ${1} > /dev/null 2>&1 || return
# -- UGLY: Step trough every pid and use kill -9 on them individually
for PID in $(pidof ${1}) ;do
echo "Terminating Process: [${1}], PID [${PID}]"
kill -9 ${PID} ;sleep 10
# -- NASTY: If kill -9 fails, try SIGTERM on PID
if ps -p ${PID} > /dev/null ;then
echo "${PID} is still running, forcefully terminating with SIGTERM"
kill -SIGTERM ${PID} ;sleep 10
fi
done
# -- If after all that, we still see the process, report that to the screen.
pgrep ${1} > /dev/null 2>&1 && echo "Error, unable to terminate all or any of [${1}]" || echo "Terminate process [${1}] : SUCCESSFUL"
I need to do this from time to time and end up hacking the command line until it works.
For example, here I want to see if I have any SSH connections, (the 8th column returned by "ps" is the running "path-to-procname" and is filtered by "awk":
ps | awk -e '{ print $8 }' | grep ssh | sed -e 's/.*\///g'
Then I put it in a shell-script, ("eval"-ing the command line inside of backticks), like this:
#!/bin/bash
VNC_STRING=`ps | awk -e '{ print $8 }' | grep vnc | sed -e 's/.*\///g'`
if [ ! -z "$VNC_STRING" ]; then
echo "The VNC STRING is not empty, therefore your process is running."
fi
The "sed" part trims the path to the exact token and might not be necessary for your needs.
Here's my example I used to get your answer. I wrote it to automatically create 2 SSH tunnels and launch a VNC client for each.
I run it from my Cygwin shell to do admin to my backend from my windows workstation, so I can jump to UNIX/LINUX-land with one command, (this also assumes the client rsa keys have already been "ssh-copy-id"-ed and are known to the remote host).
It's idempotent in that each proc/command only fires when their $VAR eval's to an empty string.
It appends " | wc -l" to store the number of running procs that match, (i.e., number of lines found), instead of proc-name for each $VAR to suit my needs. I keep the "echo" statements so I can re-run and diagnose the state of both connections.
#!/bin/bash
SSH_COUNT=`eval ps | awk -e '{ print $8 }' | grep ssh | sed -e 's/.*\///g' | wc -l`
VNC_COUNT=`eval ps | awk -e '{ print $8 }' | grep vnc | sed -e 's/.*\///g' | wc -l`
if [ $SSH_COUNT = "2" ]; then
echo "There are already 2 SSH tunnels."
elif [ $SSH_COUNT = "1" ]; then
echo "There is only 1 SSH tunnel."
elif [ $SSH_COUNT = "0" ]; then
echo "connecting 2 SSH tunnels."
ssh -L 5901:localhost:5901 -f -l USER1 HOST1 sleep 10;
ssh -L 5904:localhost:5904 -f -l USER2 HOST2 sleep 10;
fi
if [ $VNC_COUNT = "2" ]; then
echo "There are already 2 VNC sessions."
elif [ $VNC_COUNT = "1" ]; then
echo "There is only 1 VNC session."
elif [ $VNC_COUNT = "0" ]; then
echo "launching 2 vnc sessions."
vncviewer.exe localhost:1 &
vncviewer.exe localhost:4 &
fi
This is very perl-like to me and possibly more unix utils than true shell scripting. I know there are lots of "MAGIC" numbers and cheezy hard-coded values but it works, (I think I'm also in poor taste for using so much UPPERCASE too). Flexibility can be added with some cmd-line args to make this more versatile but I wanted to share what worked for me. Please improve and share. Cheers.
A solution with service and awk that takes in a comma-delimited list of service names.
First it's probably a good bet you'll need root privileges to do what you want. If you don't need to check then you can remove that part.
#!/usr/bin/env bash
# First parameter is a comma-delimited string of service names i.e. service1,service2,service3
SERVICES=$1
ALL_SERVICES_STARTED=true
if [ $EUID -ne 0 ]; then
if [ "$(id -u)" != "0" ]; then
echo "root privileges are required" 1>&2
exit 1
fi
exit 1
fi
for service in ${SERVICES//,/ }
do
STATUS=$(service ${service} status | awk '{print $2}')
if [ "${STATUS}" != "started" ]; then
echo "${service} not started"
ALL_SERVICES_STARTED=false
fi
done
if ${ALL_SERVICES_STARTED} ; then
echo "All services started"
exit 0
else
echo "Check Failed"
exit 1
fi
The most simple check by process name :
bash -c 'checkproc ssh.exe ; while [ $? -eq 0 ] ; do echo "proc running";sleep 10; checkproc ssh.exe; done'