Linux/Unix command to determine if process is running?
Solution 1
While pidof
and pgrep
are great tools for determining what's running, they are both, unfortunately, unavailable on some operating systems. A definite fail safe would be to use the following: ps cax | grep command
The output on Gentoo Linux:
14484 ? S 0:00 apache2 14667 ? S 0:00 apache2 19620 ? Sl 0:00 apache2 21132 ? Ss 0:04 apache2
The output on OS X:
42582 ?? Z 0:00.00 (smbclient) 46529 ?? Z 0:00.00 (smbclient) 46539 ?? Z 0:00.00 (smbclient) 46547 ?? Z 0:00.00 (smbclient) 46586 ?? Z 0:00.00 (smbclient) 46594 ?? Z 0:00.00 (smbclient)
On both Linux and OS X, grep returns an exit code so it's easy to check if the process was found or not:
#!/bin/bash
ps cax | grep httpd > /dev/null
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
Furthermore, if you would like the list of PIDs, you could easily grep for those as well:
ps cax | grep httpd | grep -o '^[ ]*[0-9]*'
Whose output is the same on Linux and OS X:
3519 3521 3523 3524
The output of the following is an empty string, making this approach safe for processes that are not running:
echo ps cax | grep aasdfasdf | grep -o '^[ ]*[0-9]*'
This approach is suitable for writing a simple empty string test, then even iterating through the discovered PIDs.
#!/bin/bash
PROCESS=$1
PIDS=`ps cax | grep $PROCESS | grep -o '^[ ]*[0-9]*'`
if [ -z "$PIDS" ]; then
echo "Process not running." 1>&2
exit 1
else
for PID in $PIDS; do
echo $PID
done
fi
You can test it by saving it to a file (named "running") with execute permissions (chmod +x running) and executing it with a parameter: ./running "httpd"
#!/bin/bash
ps cax | grep httpd
if [ $? -eq 0 ]; then
echo "Process is running."
else
echo "Process is not running."
fi
WARNING!!!
Please keep in mind that you're simply parsing the output of ps ax
which means that, as seen in the Linux output, it is not simply matching on processes, but also the arguments passed to that program. I highly recommend being as specific as possible when using this method (e.g. ./running "mysql"
will also match 'mysqld' processes). I highly recommend using which
to check against a full path where possible.
References:
http://linux.about.com/od/commands/l/blcmdl1_ps.htm
http://linux.about.com/od/commands/l/blcmdl1_grep.htm
Solution 2
You SHOULD know the PID !
Finding a process by trying to do some kind of pattern recognition on the process arguments (like pgrep "mysqld"
) is a strategy that is doomed to fail sooner or later. What if you have two mysqld running? Forget that approach. You MAY get it right temporarily and it MAY work for a year or two but then something happens that you haven't thought about.
Only the process id (pid) is truly unique.
Always store the pid when you launch something in the background. In Bash this can be done with the $!
Bash variable. You will save yourself SO much trouble by doing so.
How to determine if process is running (by pid)
So now the question becomes how to know if a pid is running.
Simply do:
ps -o pid= -p <pid>
This is POSIX and hence portable. It will return the pid itself if the process is running or return nothing if the process is not running. Strictly speaking the command will return a single column, the pid
, but since we've given that an empty title header (the stuff immediately preceding the equals sign) and this is the only column requested then the ps command will not use header at all. Which is what we want because it makes parsing easier.
This will work on Linux, BSD, Solaris, etc.
Another strategy would be to test on the exit value from the above ps
command. It should be zero if the process is running and non-zero if it isn't. The POSIX spec says that ps
must exit >0 if an error has occurred but it is unclear to me what constitutes 'an error'. Therefore I'm not personally using that strategy although I'm pretty sure it will work as well on all Unix/Linux platforms.
Solution 3
On most Linux distributions, you can use pidof
(8).
It will print the process ids of all running instances of specified processes, or nothing if there are no instances running.
For instance, on my system (I have four instances of bash
and one instance of remmina
running):
$ pidof bash remmina
6148 6147 6144 5603 21598
On other Unices, pgrep
or a combination of ps
and grep
will achieve the same thing, as others have rightfully pointed out.
Solution 4
This should work on most flavours of Unix, BSD and Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Tested on:
- SunOS 5.10 [Hence the
PATH=...
] - Linux 2.6.32 (CentOS)
- Linux 3.0.0 (Ubuntu)
- Darwin 11.2.0
- FreeBSD 9.0-STABLE
- Red Hat Enterprise Linux ES release 4
- Red Hat Enterprise Linux Server release 5
Solution 5
The simpliest way is to use ps and grep:
command="httpd"
running=`ps ax | grep -v grep | grep $command | wc -l`
if [ running -gt 0 ]; then
echo "Command is running"
else
echo "Command is not running"
fi
If your command has some command arguments, then you can also put more 'grep cmd_arg1' after 'grep $command' to filter out other possible processes that you are not interested in.
Example: show me if any java process with supplied argument:
-Djava.util.logging.config.file=logging.properties
is running
ps ax | grep -v grep | grep java | grep java.util.logging.config.file=logging.properties | wc -l
Related videos on Youtube
Highway of Life
David has worked in Software Development for over 20 years, from every phase of development, build, deployment, systems engineering, operations, and Site Reliability Engineering (DevOps). David is currently the Lead Site Reliability Engineer for the SRE Product team at Starbucks Technology where the focus is on developing applications and shared platforms to enable rapid development by engineering teams across Starbucks.
Updated on July 08, 2022Comments
-
Highway of Life almost 2 years
I need a platform independent (Linux/Unix|OSX) shell/bash command that will determine if a specific process is running. e.g.
mysqld
,httpd
... What is the simplest way/command to do this? -
oHo about 12 years+1
pidof httpd
works fine on Red Hat 5. But on my Red Hat 4,pidof
is not present :-( -
Frédéric Hamidi about 12 yearsIndeed, this command is less widespread than I thought, I edited my answer to make this clearer.
-
oHo about 12 yearsThanks @Johnsyweb. Can you also check
pidof
please? OK you did. Thank you. So we should find something else working on OSX... Your basicps|grep
may be the single solution ;-) -
oHo about 12 years+1 Yes simply
ps
. To avoid the secondgrep
I suggest:ps aux | grep [h]ttpd
-
johnsyweb about 12 yearsI didn't use the square bracket trick here to make it easier to put a variable into the main
grep
. -
oHo about 12 yearsAll right ;) I have just tested on Red Hat AS 4 and Red Hat AP 5. Of course I works! So you can add in your list: Red Hat Enterprise Linux ES release 4 and Red Hat Enterprise Linux Server release 5. Cheers
-
johnsyweb about 12 years@Downvoter: Why? What did I miss? As far as I can tell, the accepted answer is doing the same lookup!
-
Highway of Life over 11 yearsActually, using
ps cax
eliminates the need to usegrep -v
. So for example, you can use:ps cax | grep java > /dev/null || echo "Java not running"
. -
oluc almost 11 yearsThe process can be running, but stopped. So if the goal is to test if mysqld or httpd are "up and running" (responding), you should also check if it is stopped or not.
-
peterh over 10 yearsSorry, but while the answer is certainly right from a semantic point of view I'm fully against trying to find a process by pattern matching on the process arg vector. Any such approach is doomed to fail sooner or later (you actually admit to that yourself, by saying that more checks are needed). I've added my own recommendation in a separate answer.
-
peterh over 10 yearsHow is this answer portable? (You say that different forms of the ps command should be used on different platforms)
-
Tatjana Heuser over 10 yearsps unfortunately is one of those tools with a different set of options for the same result depending on their ancestry. So, unless you write your own (again incompatible to anything else) wrapper around this, the way to go would be to know the main lines of heritage and adapt accordingly. It is different when you're scripting - there you would use these differences to determine which branch you're on and adapt the behaviour of your script. Bottom line: you'll need to know both. Famous example: Larry Wall's "configure" script. Famous quote: Congratulations, you aren't running Eunice.
-
Kyle G. over 10 years
grep
will also find itself running (e.g.ps cax | grep randomname
will always return 0 becausegrep
findsgrep randomname
(hope this is clear...). One fix is to add square brackets around the first letter of the process name, e.g.ps cax | grep [r]andomname
. -
Highway of Life over 10 yearsExcept this doesn't answer the question, which is to determine if a service is running. The PID won't be known in such cases, therefore this answer is only valid if you do know the PID.
-
peterh over 10 yearsWrong. My whole point of the comment is to take a step back and say that if you first find yourself in the situation where you have to do some form of
grep <sometext>
to find a given process then you have done something wrong when you started the process, IMHO. I take it from the OP's question that indeed he has control over how the process is started. -
Highway of Life over 10 yearsThe more correct "term" for the OP question should have been "cross-platform command to determine if a service is running", it's not the same system running the check, but an outside system, so the PID is just not going to be known at all.
-
peterh over 10 yearsWhether or not the PID will be known depends on if you control the startup process or not. It doesn't depend on from where you do the check. You can implement your own 'is-service-running?' (which uses a stored PID) on a given host which can then be called from a remote host. But again: if you do not control the startup process of the service then I understand your point.
-
Highway of Life over 10 yearsI do, but the scripts are independent of each-other. That is why
ps cax | grep <service>
ended up being a very reliable and simple solution. -
Tyzoid almost 9 years
ps cax | rev | cut -f1 -d' ' | rev
will show only the name column, for easier parsing. -
jarno almost 9 years
ps cax
may not output command name wholly. E.g it prints "chromium-browse" instead of "chromium-browser". -
jarno almost 9 years@KyleG.
ps cax | grep randomname
grep will not return 0 always, butps ax | grep randomname
will. -
jarno almost 9 years
$ isPidRunning 0]
prints e.g. "0] is running 3 [ksoftirqd/0] 8 [rcuop/0] 17 [rcuos/0] 26 [rcuob/0] 34 [migration/0] 35 [watchdog/0] " here. -
Kyle G. almost 9 years@jarno, you're absolutely right, my bad. I should've tested my suggestion first ;)
-
jarno almost 9 yearsWhat do you need that PATH thing for?
-
jarno almost 9 yearsI developed the solution further here.
-
jlliagre almost 9 years@jarno The PATH setting is a requirement for the script to be portable. Otherwise, it would fail at least on Solaris 10 and older and possibly other Unix implementations.
-
jlliagre almost 9 years@jarno Using
args
was indeed a mistake. I updated my solution to usecomm
which avoid the issue you pointed. Thanks! -
jarno almost 9 yearsUsing
comm
is problematic in Linux, at least: column is cut in 15 characters. Thus the script will not find e.g.chromium-browser
. Using--cols 200
option or defining-o comm:200=
does not help. I useps
of procps package, version 3.3.9. -
jarno almost 9 yearsIn Ubuntu Linux
getconf PATH
outputs "/bin:/usr/bin". I wonder, if it has any effect there. -
jlliagre almost 9 years@jarno The 15 characters truncation was the reason why I originally used
args
instead ofcomm
. I revert toargs
then, ignoring the0]
case which while being technically valid is probably out of the OP scope. I can't usecmd
, the OP is asking for a portable solution (Linux, Unix, OS X) butcmd
is not specified by POSIX. About/bin:/usr/bin
, there shouldn't be any issue with Ubuntu, this setting is limited to theps
andawk
commands which will be undoubtedly found there. Funny to see the accepted and most voted solution provided doesn't match the OP requirements ... -
jarno almost 9 yearsIn linux,
args
,cmd
andcommand
are aliases. Evencomm
may contain blanks, so$2
may not equal to wholecomm
in the script. I wonder, if you can easily say where command ends and arguments start, if you use one of the former aliases. -
jarno almost 9 yearsI wonder, if you could use form
PATH=$(getconf PATH) ps ...
instead of exporting PATH? -
jlliagre almost 9 years@jarno I might do it but will need to repeat this PATH setting for awk too. Note that I reverted to the old backtick syntax to be portable with pre-POSIX syntax bourne shells.
-
ShadSterling over 8 yearsHow to determine if process is running (by pid) is exactly what I was looking for. I was surprised that all of the questions in my search results were about how to find the pid.
-
claymation about 8 yearsThis isn't foolproof. The process you're interested in may have died after the system has been up long enough for PIDs to wrap around, and another process may then have been allocated the same PID you're checking for. stackoverflow.com/questions/11323410/linux-pid-recycling
-
peterh about 8 years@claymation. Fair point. However PID method is still better than pattern matching on process args as PID clash is far more unlikely than say accidentally starting two instances of the same service. Just my two cents. :-)
-
Programmer over 7 yearsThere is a mistake in 3rd line. please change "running" to "$running".
-
Mtl Dev about 7 yearsNice clean answer indeed. (on supported systems). Thankyou.