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'
Im a new to docker and i am trying to create a container running multiple services,
using this documentation:Run multiple services in a container
I've managed to get Java and Nodejs installed on the containe, eventually leading to running this script at the end of the Dockerfile as an ENTRYPOINT:
#!/bin/bash
# Start the first process
/tmp/cliffer/bin/startup.sh &
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start my_first_process: $status"
exit $status
fi
# Start the second process
npm start &
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start my_second_process: $status"
exit $status
fi
# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container will exit with an error
# if it detects that either of the processes has exited.
# Otherwise it will loop forever, waking up every 60 seconds
while /bin/true; do
PROCESS_1_STATUS=$(ps aux |grep -q my_first_process |grep -v grep)
PROCESS_2_STATUS=$(ps aux |grep -q my_second_process | grep -v grep)
# If the greps above find anything, they will exit with 0 status
# If they are not both 0, then something is wrong
if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
echo "One of the processes has already exited."
exit -1
fi
sleep 60
done
both services are running in the background, and the result is that the npm start, starts a webserver but immediately shuts it down.
This is the output im getting from the npm start &
[--:--:--][CONSOLE] [09:19:11] [Start] Listening at port 3000
[09:19:11] [Stop] Shutting down
when I run the the container with each of the services separately in a container of its own it works perfect.
any ideas why?
Docker needs one process to run in the foreground otherwise it will exit. Your foreground program is your entrypoint that sleeps for 60 seconds and checks if both processes are still in the background.
The check is for the process name "my_first_process". That should be for your instance be something like "java"
so instead of
ps aux |grep -q my_first_process |grep -v grep
ps aux |grep -q my_second_process |grep -v grep
try
ps aux |grep -q java |grep -v grep
ps aux |grep -q npm |grep -v grep
Joel's comment is still valid, it makes more sense to run two different docker containers for your use case.
I want my micro services to open in a new command line and run it from there one after the other. below is my bash script
################ first SERVER #####################
gnome-terminal -x sh -c 'java -jar server/target/first-server.jar; exec bash'
################ second SERVER #####################
export service_port=8771
export host_name=firstdomain
gnome-terminal -x sh -c 'java -Dservice.port="${service_port}" -Dhost.name="${host_name}" -jar eureka/target/second-server.jar; exec bash'
The problem is it that i want to start my "second-server.jar" after successfully started the "first-server.jar". I can detect that by checking if the service is listening to network port. Is there any way to archive this? sleep bash command is not a option for me.
Basically, you need to use sleep command. But you can use it in a loop checking continuously if the port became available. But how to check availability of the port?
One option is to use netstat command as suggested by Jack. The proper usage is:
netstat -tna | grep 'LISTEN\>' | grep ':NNNN\>'
where NNNN is the port. To make that a condition to wait on, you can write following loop:
while ! netstat -tna | grep 'LISTEN\>' | grep -q ':NNNN\>'; do
sleep 10 # time in seconds, tune it as needed
done
Please mind the -q option in the last instance of grep.
The other option is to check, if you can connect to port:
{
while ! echo -n > /dev/tcp/localhost/NNNN; do
sleep 10
done
} 2>/dev/null
Depending on the distribution you are using and the options bash has been compiled with, this method may or may not working.
Another option to check if port is accessible is to use nc:
while ! nc -q0 localhost 2222 < /dev/null > /dev/null 2>&1; do
sleep 10
done
You can replace localhost with your hostname or ip address.
I am trying to create a script that monitors a java runtime process,which makes use of a Virgo service. It should start the process when its not running. As there is no specific service name, i was thinking of grepping the name of the process and use it as an identifier.
Here is the code i thought of:
#!/bin/sh
service=virgo
ps auxw | grep $service | grep -v grep > /dev/null
if [ $? != 0 ]
then
/opt/apromore/ApromoreCode/build.xml start-virgo > /dev/null
else
echo Apromore is running already
fi
and this is the process I try to monitor (value from ps aux)
/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java -classpath usr/share/ant/lib/ant-launcher.jar:/ usr/share/java/xmlParserAPIs.jar:/usr/share/java/xercesImpl.jar -Dant.home=/usr/ share/ant -Dant.library.dir=/usr/share/ant/lib org.apache.tools.ant.launch.Launc her -cp start-virgo
but even when the process is running, i cant identify it with the mentioned script. There is a error called $'\r'. I have no idea how to get rid of it.
I did a script to execute every 10 minutes and when the files open on my Java app is greater than 10000 it will execute a jmap command to give to me a heapdump.
My intention is to discover which class of my app is not closing the files or where there is a memory leak or why I receive the message "Too many files open" after 20 hours executing it.
This is my script. Does anybody have other ways or tools to discover where my app is not closing the files? Thanks a lot!
#!/bin/bash
rm openfiles.log
flag=1
for (( ; ; ))
do
sleep 10m
files=`ps -A x |grep iscsi | awk '{print $1}' | xargs -I '{}' ls /proc/29192/fd | wc -l`
msg="open files: $files - date: `date`"
echo "$msg - infinite loops [ hit CTRL+C to stop]"
echo $msg >> openfiles.log
if [ $files -gt 10000 ] && [ $flag -eq 1 ]
then
jmap -F -dump:file=heapdump.hprof 29192
flag=0;
echo "############################################ heapdump of 29192" >> openfiles.log
fi
echo "" >> openfiles.log
done
Take a look at File Leak Detector written by Kohsuke Kawaguchi of Jenkins fame. It is a java agent that you attach to your java process.
There are also other ways to scan for them via FindBugs/PMD, etc. I'd take a look at SonarQube. There are rules specifically about not closing resources.