Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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:


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

    sleep 3

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
up vote 9 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

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
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

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

while true; do 
    if ! pgrep nmapplet &>/dev/null; then
       echo "Bugger died, resurrecting..."
       nm-applet &>/dev/null
       disown $!
    sleep 3
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

Your Answer


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.