Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm have a process on my system which is notorious for crashing, and is kind of mission critical, my network manager. In any case, I need to write a loop which tests if it's running and starts it if it isn't. This is what I've come up with thus far:

#!/bin/bash

while [ true ]; do 
    if [ -z $(ps aux | grep "[n]m-applet") ]; then
        echo "Bugger died, resurrecting..."
        nm-applet >/dev/null 2>/dev/null &
        disown $!
    fi

    sleep 3
done 

Unfortunately, this isn't quite doing the trick, as it seems to be starting the process even when not necessary, and after the first run, I get the following error output:

line 4: [: too many arguments

What am I doing wrong here?

share|improve this question
    
while [ true ]; do ... is interpreted as while [ -n "true" ]; do ...; that is, it tests whether the string "true" is non-empty. This gives the same result as while true; do ... or while :; do ... which are probably what you meant to be using. (This isn't meant to answer your question; the answers below do that properly. It's just a side comment.) –  dubiousjim Nov 6 '12 at 23:20

3 Answers 3

up vote 8 down vote accepted

Try wrapping the $(...) in double quotes:

if [ -z "$(ps aux | grep '[n]m-applet')" ]; then

But you might want to try using pgrep or ps axo cmd | grep '[n]m-applet' instead.

share|improve this answer
    
Looks like it's working! –  Naftuli Tzvi Kay Aug 26 '11 at 1:42

I'm unsure about your reasons for while [ true ]; do and I second Arcege's suggestion to use pgrep.

#!/bin/bash
while true; do 
    if ! pgrep nmapplet &>/dev/null; then
       echo "Bugger died, resurrecting..."
       nm-applet &>/dev/null
       disown $!
    fi
    sleep 3
done
share|improve this answer
    
you need to put the pgrep inside the infinite loop –  glenn jackman Aug 26 '11 at 1:54
    
@glenn Do you mind explaining why? The variable is not enough? –  jasonwryan Aug 26 '11 at 1:55
    
You set the variable when you start the script. Even if the process dies, the "-z" test will never fail because the variable never changes. –  glenn jackman Aug 26 '11 at 1:59
    
D'oh! Thanks: sort of painfully obvious... –  jasonwryan Aug 26 '11 at 2:01
    
Simpler to use the exit status. Updated. –  Mikel Nov 6 '12 at 22:38

That error comes from giving multiple arguments to -z. It's a unary operator, and if the $() expands to something with the $IFS in it, it will see multiple arguments. To fix that, you can put quotes around it like so: [ -z "$(ps...)" ].

In this case, you actually don't need the test ([]) because grep will return non-zero if it doesn't find anything. You can do:

if ps aux | grep '[n]m-applet' > /dev/null; then

And you might want to see if the systems you plan on deploying this to have pgrep. It's is made for looking for processes that match a pattern.

Also, you might want the script to not background the nm-applet. This way, the script will block until nm-applet dies.

Finally, you might want to look at Monit, which is made for doing what your script does.

share|improve this answer
2  
Might want to add either -s to the grep or close stdout (>&-) to prevent the output getting to the user. –  Arcege Aug 26 '11 at 2:21
    
Thanks, @Arcege; I edited it included `> /dev/null'. –  Shawn J. Goff Oct 30 '11 at 15:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.