How can I determine if a process is running or not and then have a bash script execute some stuff based on that condition?
For example:
if process
abc
is running, do thisif it is not running, do that.
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It only takes a minute to sign up.
Sign up to join this communityA bash script to do something like that would look something like this:
#!/bin/bash
# Check if gedit is running
# -x flag only match processes whose name (or command line if -f is
# specified) exactly match the pattern.
if pgrep -x "gedit" > /dev/null
then
echo "Running"
else
echo "Stopped"
fi
This script is just checking to see if the program "gedit" is running.
Or you can only check if the program is not running like this:
if ! pgrep -x "gedit" > /dev/null
then
echo "Stopped"
fi
/dev/null
: "/dev/null redirects the command standard output to the null device, which is a special device which discards the information written to it" ... using 0
would redirect the command output to a file called 0
. In this case, I'd advise becoming more comfortable with > /dev/null
-- you'll see it everywhere, as it's the standard / proper way to discard output.
Nov 10, 2015 at 5:33
-x
parameter to pgrep
so that it is looking for the exact application or else it will get a false correct if it finds the same string inside the name of another app. I just spent 1 hour to find that out.
Aug 31, 2016 at 21:24
Any solution that uses something like ps aux | grep abc
or pgrep abc
are flawed.
Because you are not checking if a specific process is running, you are checking if there are any processes running that happens to match abc
. Any user can easily create and run an executable named abc
(or that contains abc
somewhere in its name or arguments), causing a false positive for your test. There are various options you can apply to ps
, grep
and pgrep
to narrow the search, but you still won't get a reliable test.
That depends on what you need the test for.
This is what systemd is for. It can start the service automatically and keep track of it, and it can react when it dies.
See How can I check to see if my game server is still running... for other solutions.
In this case, use a lockfile or a lockdir. E.g.
#!/usr/bin/env bash
if ! mkdir /tmp/abc.lock; then
printf "Failed to acquire lock.\n" >&2
exit 1
fi
trap 'rm -rf /tmp/abc.lock' EXIT # remove the lockdir on exit
# rest of script ...
See Bash FAQ 45 for other ways of locking.
pgrep
or ps
is perfectly adequate and your approach seems like overkill. If you're writing a scrip for public distribution, though, you should write it in the safest way possible.
Jun 30, 2012 at 13:21
rm
command is run. So as long as it ends after the trap has been set, the lock should be gone.
This is what I use:
#!/bin/bash
#check if abc is running
if pgrep abc >/dev/null 2>&1
then
# abc is running
else
# abc is not running
fi
In plain English: if 'pgrep' returns 0, the process is running, otherwise it is not.
Related reading:
Bash Scripting :: String Comparisons
Ubuntu Manuals pgrep
pgrep
has the same 15 character limit "feature" previously mentioned, thus for example pgrep gnome-power-manager
would also fail
-x
option: "Only match processes whose name (or command line if -f is specified) exactly match the pattern."
Jul 21, 2014 at 4:31
pgrep
. Moreover, this assumes pgrep
to be installed in the first place. See also this authoritative answer. </sigh>
Jan 30, 2020 at 2:57
I usually have a pidof -x $(basename $0)
on my scripts to check if it's already running.
Riffing on @rommel-cid's idea, you can use pidof
with the || (||) to run a command if the process does not exist and && to run something if the process does exist, thus creating a quick if/then/else conditional. For example here's one with a running process (my chrome browser, whose process name is "chrome") and one testing for a process that does not exist. I suppressed the standard output using 1>/dev/null so that it doesn't print:
$ (pidof chrome 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run instea\
d"
its running? ok, so am i then
$ (pidof nosuchprocess 1>/dev/null && echo "its running? ok, so am i then" ) || echo "it's not running? ok i'll run\
instead"
it's not running? ok i'll run instead
$
## bash
## function to check if a process is alive and running:
_isRunning() {
ps -o comm= -C "$1" 2>/dev/null | grep -x "$1" >/dev/null 2>&1
}
## example 1: checking if "gedit" is running
if _isRunning gedit; then
echo "gedit is running"
else
echo "gedit is not running"
fi
## example 2: start lxpanel if it is not there
if ! _isRunning lxpanel; then
lxpanel &
fi
## or
_isRunning lxpanel || (lxpanel &)
Note: pgrep -x lxpanel
or pidof lxpanel
still reports that lxpanel
is running even when it is defunct (zombie); so to get alive-and-running process, we need to use ps
and grep
bash
), (B) it's distro-agnostic (because it only leverages ps
and grep
), (C) it's resilient against false positives (because it passes -o
and -C
to ps
and -x
to grep
), and (D) it's resilient against zombie processes (as noted). In short, it's the CLI equivalent of spring-fed glacier water imported at considerable expense from the fjords of Norway.
Jan 30, 2020 at 2:53
By pid:
test -d /proc/[pid]
By name:
pgrep -u [user] -x [name] >/dev/null
"-x" means "exact match".
None of the "simple" solutions worked for me because the binary I need to check is not installed system-wide, so I have to check with path, which in turn requires using ps -ef | grep
approach:
app="$_sdir/Logic 1.2.18 (64-bit)/Logic"
app_pid=`ps -ef | grep "$app" | awk '{print $2}'`
if `ps -p $app_pid > /dev/null`; then
echo "An instance of logic analyzer is appear to be running."
echo "Not starting another instance."
exit 5
else
nohup "$app" &> /dev/null &
fi
First thing that came to my mind for your problem:
ps aux | grep -i abc
will show the details of the process if its running. You may match the number of lines or time for which its running and compare with zero or any other manipulation. When you run the above command it will show you atleast one line of output i.e. detail about the process created by thi grep command.. So take care of that.
That should do as a simple hack. Put it in the bash script and see if its helpful.
Using start-stop-daemon
:
/sbin/start-stop-daemon --background --make-pidfile --pidfile /tmp/foo.pid -S --startas /usr/bin/program -- arg1 arg2
It works as normal user.
I found that the accepted answer posted by @John Vrbanac did not work for me, and that the answer posted by @geirha doesn't answer the original question.
John Vrbanac's solution didn't work to check if a PHP process was running or not for me, I'm running CentOS 7.
@geirha's answer only makes sure an instance isn't already running before starting another. This was not the original question, the original question was to check if a process is running or not.
Here's what worked for me:
Say my process had the string "Jane" in it's process name. This will find if it's running or not. This works for BASH and PHP scripts.
ps -aux | grep "[J]ane" > /dev/null 2>&1
if [[ "$?" == "0" ]]; then
echo "It's running"
else
echo "It's not running"
fi
ps
and grep
. See also this authoritative answer. </sigh>
Jan 30, 2020 at 2:56
#!/bin/bash
while [ true ]; do # Endless loop.
pid=`pgrep -x ${1}` # Get a pid.
if [ -z $pid ]; then # If there is none,
${1} & # Start Param to background.
else
sleep 60 # Else wait.
fi
done
zombie
process' (Not what I would describe as a "running" process). A full list of what theSTAT
column values, in the output ofps
, indicates is here for those inclined to write an answer that accommodates this, or edit their own.