views:

1429

answers:

5

How do you check if a process on Mac OS X is running using the process's name in a Bash script?

I am trying to write a Bash script that will restart a process if it has stopped but do nothing if it is still running.

+3  A: 

Parsing this:

ps aux | grep [-i] $ProcessName | wc -l

...is probably your best bet. Here's a short script that does what you're after:

#!/bin/bash
PROCESS=myapp
number=$(ps aux | grep $PROCESS | wc -l)

if [ $number -gt 0 ]
    then
        echo Running;
fi

EDIT: I initially included a -i flag to grep to make it case insensitive; I did this because the example program I tried was python, which on Mac OS X runs as Python -- if you know your application's case exactly, the -i is not necessary.

The advantage of this approach is that it scales with you -- in the future, if you need to make sure, say, five instances of your application are running, you're already counting. The only caveat is if another application has your program's name in its command line, it might come up -- regular expressions to grep will resolve that issue, if you're crafty (and run into this).

Research the Darwin man pages for ps, grep, and wc.

Jed Smith
Thanks. This worked with one exception: it has to be `-gt 1` rather than `0`, because the `grep` command from the Bash script itself gets counted as one of the lines in the `ps aux`, at least in my preliminary tests.
Chris Redford
I had it at first and couldn't get it to replicate after that...it depends on the shell running the script, I think. You're quite right, though -- I think even though I shebanged it `/bin/bash` `zsh` might have been executing it, which might make it behave differently...I dunno. But you're quite right.
Jed Smith
I like to add a `grep -v grep` to the pipeline before the `wc`. That way, the grep command gets excluded from the number of matches found.
Jacob
Does it work with really long filenames and paths? Especially if they are similar in the beginning?, eg. my-long-filename-that-is-really-stupid-of-file-1, my-long-filename-that-is-really-stupid-of-file-2... I bet it doesn't, at least not on both Linux and Mac OS X, using the same arguments to ps...
Ludvig A Norin
+3  A: 

Another way is to use (abuse?) the -d option of the killall command. The -d options won't actually kill the process, but instead print what will be done. It will also exit with status 0 if it finds a matching process, or 1 if it does not. Putting this together:

#!/bin/bash
`/usr/bin/killall -d "$1" &> /dev/null`
let "RUNNING = ! $?"     # this simply does a boolean 'not' on the return code
echo $RUNNING

To give credit where its due, I originally pulled this technique from a script in the iTunes installer.

amrox
EWW. I'm not going to -1 because I think that should only be used for incorrect or inappropriate answers, but wow. Why do that when you can use ps and grep? especially since I'm pretty sure that using ps and grep is exactly what killall does...
Brian Postow
Actually killall is a little smarter than 'ps | grep'. If you just grep the output of ps, you can get false positives. Contrived, but say your process is named 'Library'. 'ps waux | grep Library' will match a lot of stuff on a Mac. The killall method, while a bit wacky I admit, will only match an actual process named 'Library'.
amrox
A: 

does Mac have pidof? ...

if pidof $processname >/dev/null ; then echo $processname is running ; fi
matja
No it doesn't unfortunately.
amrox
A: 

It has for sure!

pgrep, pkill and pfind for OpenBSD and Darwin (Mac OS X)

http://proctools.sourceforge.net

(also available via MacPorts: port info proctools )

pidof by nightproductions.net

kusai
Great stuff, but not in standard. Sometimes it is better to solve this problem only using the standard stuff, sometimes not!
Ludvig A Norin
A: 

I lack the reputation to comment on the killall answer above, but there's killall -s for doing it without sending any signals:

killall -s "$PROCESSNAME" &> /dev/null
if [ $? -eq 0 ]; then
    echo "$PROCESSNAME is running"
    # if you also need the PID:
    PID=`killall -s "$PROCESSNAME" | awk '{print $3}'`
    echo "it's PID is $PID"
fi
Ingmar Hupp