views:

383

answers:

4

Is there any reason this script always give me running ? In both cases, when my process is started and when my process is stopped.

if ps ax | grep -v grep | grep "processName" > /dev/null
then
   echo $"running"
else
   echo $"not running"
fi

Thank you very much

UPDATE : I add a full exemple of my script, maybe smothing wrong somewhere else.

case "$1" in
  start)
    # Start daemons.

    echo -n $"Starting daemon: "
    ;;

  stop)
    # Stop daemons.
    echo -n $"Shutting down: "
    echo
    ;;
  status)
    pgrep -f "ProcessName" > /dev/null
    if [ $? -eq 0 ]; then
        echo $"ProcessName is running"
    else
        echo $"ProcessName is not running"
    fi
    ;;
  restart)
    $0 stop
    $0 start
    ;;

  *)
    echo $"Usage: $0 {start|stop|status|restart}"
    exit 1
esac

UPDATE 2 :

[user@dev init.d]# pgrep -f "MyProcess" > /dev/null
[user@dev init.d]# echo $?
0
[user@dev init.d]# service MyProcess stop
Shutting down MyProcess: Terminated
[user@dev init.d]# pgrep -f "MyProcess" > /dev/null
[user@dev init.d]# echo $?
1

But if [ $? -eq 0 ]; then seems to always be true

A: 

your not doing a test. put brackets around the test condition like so:

if [ condition your testing ]

ennuikiller
Without [], the if tests the exit status of the command given, so his script is (in the correct spirit) trying to test the exit of grep.
Emil
@Emil yes effectively not testing the condition he wants!! In fact if anyAccessibleCommand without brackets returns true
ennuikiller
Try `if /bin/false ; then echo ennuikiller is correct ; fi`
mobrule
The OP's problem is that grep returned true when it found itself, not the use of if.
Emil
@Emil I didn't say he shouldn't use the if just that using [] syntactically does what his semantics require!!
ennuikiller
+9  A: 

Try this instead:

ps aux | grep -q "[p]rocessName"
if [ $? -eq 0 ]; then
    echo "running"
else
    echo "not running"
fi

The brackets around the first letter of processName means do don't need the "grep -v grep", while the -q means we don't need the pipe to /dev/null

$? gives you the return code of the previous command executed. Hence, testing if it were 0 would indicate if "grep" found what it was looking for.

Update

If your process name is really short (say "cup"), you might get a false positive as it may match other processes too (say "cupsd"). You can overcome this by having grep match whole words - add the "-w" flag.

Not that this technique is not perfect. You may end up matching entries in the username/date fields. If that happens, look up "man ps" and be more selective of what you print out before doing a grep. Alternatively, prefilter the output with awk to extract only the column showing process/cmd name . E.g:

ps aux | awk '{print $11}' | grep -q -w "[p]rocessName"
if [ $? -eq 0 ]; then
    echo "running"
else
    echo "not running"
fi

Update 2

you can also use pgrep as suggested in answer below.

For really short process names, you might want to specify word boundaries (\b) before and after your process name to prevent overmatching (as described above)

pgrep "\bprocname\b" > /dev/null
if [ $? -eq 0 ]; then
    echo "running"
else
    echo "not running"
fi

Update 3

From the updated question, I see that you're running it from an init script. There's always a danger of pgrep matching the script itself. Try:

pgrep Processname | grep -q -v $$
if [ $? -eq 0 ]; then
    echo "running"
else
    echo "not running"
fi

That excludes the PID of the script from pgrep matches.

Update 4

(final update? fingers crossed)

If the init script is run via the "service" command, then we need to filter out the parent PID as well. How about:

pgrep Processname | grep -v $$ | grep -q -v $PPID
if [ $? -eq 0 ]; then
    echo "running"
else
    echo "not running"
fi
lsc
Hey, that's actually a nifty trick with the [p]rocessname - +1 for proving old dogs can learn new tricks.
paxdiablo
It returned running all the time when I tried.
Mike
He should simply be able to 'if ps aux | grep -q "[p]rocessName"; then echo running; else echo not running; fi' The extra test using [ is unnecessary.
Emil
@Mike: What process name are you grepping for. If it returned running all the time you tried, then it must be matching some other process name too (or usernames, or data, or any other output of 'ps aux').
lsc
@lsc: No when I run the command itself, nothing is returned when the process is stopped.
Mike
@Mike: answer updated with more info. Sorry, but I don't get what you mean by "nothing is returned when the process is stopped".
lsc
ok I think all your answers are good. but there's something wrong with my script. If I open a command line and I type pgrep -f "MyProcessName" there's is no result when the process is stopped. When I put this line in a if statement, it always returns running. It's very strange.
Mike
@Mike: answer update for case where your script has the same name as the process in question.
lsc
Yeah I think you're right about the problem, but the solution doesn't seem to work.
Mike
Quick experiment. Does it work if you call your script using "/etc/init.d/Processname status" instead of "service Processname status"??
lsc
Yes it works in this case
Mike
Answer updated to include case where script is run via another comamnd/script.
lsc
Isc, you're my hero.
MattC
You're the man. Thank you very much for your time.
Mike
+2  A: 

Probably becasue grep "processName" finds itself. I found this self same problem yesterday, except I was xarging the results to kill...

As an alternative you might like to try the pgrep command instead of your string of ps and various greps:

sd@camel:~$ pgrep bash
415
3477
sd@camel:~$ echo $?
0
sd@camel:~$ pgrep arf
sd@camel:~$ echo $?
1
Stephen Darlington
+1 for reminding me of pgrep :)
lsc
@Stephen, no, the OP excludes ps lines containing "grep" in the middle of his original pipeline.
pilcrow
Yes, pgrep is very flexible.
Adam Goode
+1  A: 

G'day,

As an aside, instead of

ps ax | grep -v grep | grep "processName"

Try doing

ps ax | grep "[p]rocessName"

The ps is listing the grep function because it is seeing the string "grep processName" in the process list which is being passed by your grep for the string "processName".

Grepping for "[p]rocessName" will match just "processName" on its own, but not the string "grep [p]rocessName".

Rob Wells
Good observation. pgrep, or ``ps ax -o comm | grep -q -w commandName'', or any number of shellisms will do. But these are comments on the OP's issue, not answers...
pilcrow