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
This prints the number of processes whose basename is "chromium-browser":
ps -e -o args= | awk 'BEGIN{c=0}{
if(!match($1,/^\[.*\]$/)){sub(".*/","",$1)} # Do not strip process names enclosed by square brackets.
if($1==cmd){c++}
}END{print c}' cmd="chromium-browser"
If this prints "0", the process is not running. The command assumes process path does not contain breaking space. I have not tested this with suspended processes or zombie processes.
Tested using gwak
as the awk
alternative in Linux.
Here is a more versatile solution with some example usage:
#!/bin/sh
isProcessRunning() {
if [ "${1-}" = "-q" ]; then
local quiet=1;
shift
else
local quiet=0;
fi
ps -e -o pid,args= | awk 'BEGIN{status=1}{
name=$2
if(name !~ /^\[.*\]$/){sub(".*/","",name)} # strip dirname, if process name is not enclosed by square brackets.
if(name==cmd){status=0; if(q){exit}else{print $0}}
}END{exit status}' cmd="$1" q=$quiet
}
process='chromium-browser'
printf "Process \"${process}\" is "
if isProcessRunning -q "$process"
then printf "running.\n"
else printf "not running.\n"; fi
printf "Listing of matching processes (PID and process name with command line arguments):\n"
isProcessRunning "$process"
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.
None of the answers worked for me, so heres mine:
process="$(pidof YOURPROCESSHERE|tr -d '\n')"
if [[ -z "${process// }" ]]; then
echo "Process is not running."
else
echo "Process is running."
fi
Explanation:
|tr -d '\n'
This removes the carriage return created by the terminal. The rest can be explained by this post.
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
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.
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.
This should work on most flavours of Unix, BSD and Linux:
PATH=/usr/ucb:${PATH} ps aux | grep httpd | grep -v grep
Tested on:
PATH=...
]