LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Other *NIX (https://www.linuxquestions.org/questions/other-%2Anix-55/)
-   -   Bash script to check for dead process (https://www.linuxquestions.org/questions/other-%2Anix-55/bash-script-to-check-for-dead-process-500918/)

MaffooClock 11-12-2006 01:16 PM

Bash script to check for dead process
 
My bash scripting skills are horrible (if non-existant). I've been trying for a couple of hours now to write a simple script which will check for a process, and if it's not running, start it. I can't seem to pull this off.

Code:

  1 #!/bin/bash
  2
  3 TEST=`ps ax | grep motion | grep -v grep | wc -l`
  4
  5 if [ $TEST = 0 ]
  6 then
  7    telinit run motion start
  8 fi

The ps command works: it returns 0 if the process is not running, and 1 if it is. But for some reason, the if statement seems to not be evaluating correctly, and I have no idea what to do.

Here's the test:
Code:

  1 #!/bin/bash
  2
  3 TEST=`ps ax | grep motion | grep -v grep | wc -l`
  4
  5 if [ $TEST = 1 ]
  6 then
  7    echo "Alive!"
  8 else
  9    echo "Dead :("
 10 fi

And even though the ps command correctly returns either 1 or 0, the if statement always evaluates false. Clearly, I don't know what I'm doing.

So to clarify: I run from-source Linux PC which is actually a DVR for security cameras. I use Motion as the v4l recording application. The process is 'motion'. All I want to do is check for the motion process, and if it isn't running, execute 'telinit run motion start'. Once I get this working, it'll be a cron job.

Thank you in advance for your time :).

gilead 11-12-2006 01:59 PM

If you wanted to keep the structure of the script the same, just change from = to -eq. For example:
Code:

if [ $TEST -eq 1 ]
You could just put the original commands in the test. I haven't tested my syntax, but the following should work:
Code:

if [ $(ps ax | grep motion | grep -v grep) ]
Also, once you get to the cron job stage... Cron uses a cut down execution environment, so you'll probably need to modify your script to use the full path to commands. For example, /usr/bin/ps instead of ps, etc.

Lastly, I'd suggest a look at the Advanced Bash-Scripting Guide - it's well worth a read. :)

MaffooClock 11-12-2006 03:02 PM

I appreciate your response and am grateful for the time you took to help me, however, nothing you suggested was useable.

Your first suggestion is pointless, as = and -eq are identical. But I tried it anyway :).

Your second suggestion is (as you may have already guessed) syntactically incorrect. If motion is running, $(ps ax | grep motion | grep -v grep) will return several items which causes bash to belch out a error about "too many arguments". But I got yoru point and tried my original ps command string in place of the variable, but the behavior was identical (no surprise).

As far as the cron job: I'm extremely familiar with cron, but I do appreciate the advice. But for the record: until I can get this stupid script to work, there won't be a cron job.

But, hey, the way I'm goign abotu it may not necessarily be the only way I want to do this. If ANYONE has any ideas on routinely checking for a process and restarting it, please, share :). Google has not turned anything up (yet), but if I find a solution, I'll certainly close off my own thread with the solution I come to...

slakmagik 11-12-2006 04:58 PM

Code:

#!/bin/bash
if pgrep PROCESS &>/dev/null; then
    echo alive
else
    echo dead
fi


gilead 11-12-2006 05:01 PM

The following works on my bash shell (version 3.1.17(2)-release (i486-slackware-linux-gnu)). It prints out Dead :( as is, and doesn't print anything if I change the httpdz to httpd since I have Apache running:
Code:

#!/bin/bash

TEST=`ps ax | grep httpdz | grep -v grep | wc -l`

if [ $TEST -eq 0 ]
then
  echo "Dead :("
fi

Using "=" is not the same as using "-eq". According to man bash on my box, using "=" is the POSIX compliant version of using "==" for comparing strings, not numbers.

The following also works on my box:
Code:

#!/bin/bash

if [ ! "$(ps ax | grep httpdz | grep -v grep)" ]
then
  echo "Dead :("
fi

It returns Dead :( for httpdz and nothing for httpd while Apache is running.

sensovision 11-20-2006 03:46 PM

hi folks! maybe I'm a bit late but maybe you would be interested in this code:
it's shorter and I think less resource consuming than grep:
Code:

#!/bin/bash

if [ ! "$(pidof httpdz)" ]
then
  echo "Dead :("
else
  echo "Alive :)"
fi


vvard 02-10-2007 12:04 AM

pretty nice solution sensovision, works really fine. And for those using "ps type" solution there is a lil issue with that, when u pipe the output and grep for a pattern, sometimes u can get the ps command itself on the output, and sometimes dont, so that is not a good approach.

Oupa 05-16-2007 11:10 AM

bash start process
 
Another solution:

ps ax | grep motion | grep -v grep || telinit run motion start

jiml8 05-16-2007 01:25 PM

Quote:

Here's the test:
Code:

  1 #!/bin/bash
  2
  3 TEST=`ps ax | grep motion | grep -v grep | wc -l`
  4
  5 if [ $TEST = 1 ]
  6 then
  7    echo "Alive!"
  8 else
  9    echo "Dead :("
 10 fi


This script runs fine here, without any modifications.

I do believe proper syntax is this:

TEST=`ps ax | grep motion | grep -v grep | wc -l`;
if [ $TEST = 1 ];

but my bash doesn't seem to care.

edit:

I also constructed this version, which allows you to specify the command on the command line. Also notice that I changed the test; rather than checking for a line count that equals 1 it checks for a line count greater than 1.

Now, this version sometimes returns alive and sometimes returns dead if I specify a process that has only one instance running. I put the echo statement in to see what is happening, and sometimes one line is returned, sometimes two. I have kget running so I tried it with the command "tstscript kget".

I find the result to be peculiar. Anyone here have a comment on why it happens?
Code:

#!/bin/bash
TEST=`ps ax | grep ${1} | grep -v tstscript | wc -l`;
echo $TEST;
if [ $TEST -gt 1 ];
then
    echo "Alive!"
else
    echo "Dead :("
fi


vvard 05-17-2007 08:41 AM

Quote:

Originally Posted by jiml8
Now, this version sometimes returns alive and sometimes returns dead if I specify a process that has only one instance running. I put the echo statement in to see what is happening, and sometimes one line is returned, sometimes two. I have kget running so I tried it with the command "tstscript kget".

I find the result to be peculiar. Anyone here have a comment on why it happens?
Code:

#!/bin/bash
TEST=`ps ax | grep ${1} | grep -v tstscript | wc -l`;
echo $TEST;
if [ $TEST -gt 1 ];
then
    echo "Alive!"
else
    echo "Dead :("
fi


See my post above.
Try this several times on your shell $ ps | grep process where process is only 1 in the process list, do that and see what results u get.

jiml8 05-17-2007 11:03 AM

Quote:

Originally Posted by vvard
See my post above.
Try this several times on your shell $ ps | grep process where process is only 1 in the process list, do that and see what results u get.

Yes, well...

The question is not whether this is happening. Clearly it is. The question is WHY it is happening.

Shouldn't happen. Program should work the same way every time.

slakmagik 05-18-2007 04:36 AM

Quote:

Originally Posted by jiml8
This script runs fine here, without any modifications.

I do believe proper syntax is this:

TEST=`ps ax | grep motion | grep -v grep | wc -l`;
if [ $TEST = 1 ];

but my bash doesn't seem to care.

That's not the proper syntax - the semi-colon is an alternate for a newline. It's completely useless at the end of TEST and, while you will often see
Code:

if foo; then
  bar
fi

the semi-colon is there because bash is expecting either it or a newline before the 'then' - putting both a semi-colon and a newline is redundant.

Quote:

edit:

I also constructed this version, which allows you to specify the command on the command line. Also notice that I changed the test; rather than checking for a line count that equals 1 it checks for a line count greater than 1.

Now, this version sometimes returns alive and sometimes returns dead if I specify a process that has only one instance running. I put the echo statement in to see what is happening, and sometimes one line is returned, sometimes two. I have kget running so I tried it with the command "tstscript kget".

I find the result to be peculiar. Anyone here have a comment on why it happens?
Code:

#!/bin/bash
TEST=`ps ax | grep ${1} | grep -v tstscript | wc -l`;
echo $TEST;
if [ $TEST -gt 1 ];
then
    echo "Alive!"
else
    echo "Dead :("
fi


ps has an annoying habit of sometimes matching itself and sometimes not - I can't recall the precise reason - perhaps simply a sort of race condition - but it does. Hence the 'grep foo | grep -v ps' dance. Another way to avoid this is to use 'pgrep' which never matches itself.

Code:

TEST=`ps ax | grep $1 | grep -v ps | wc -l`
Also, it would more properly be
Code:

TEST=$(ps ax | grep $1 | grep -v ps | wc -l)
I type backticks in most interactive cases because it's quicker, but I type the $(...) notation in scripts - it's POSIX and nests better.

And, while we're on syntactical matters, the brace notation for variables (${1}) while always permissable is only required when there's ambiguity about where the variable leaves off -
Code:

:cat demo
#!/bin/bash
foo=bar
echo $foobar
echo ------
echo ${foo}bar

:./demo

------
barbar

the first references a nonexistent variable 'foobar' because foobar is a 'word'. The braces tell bash 'foo' is the variable and 'bar' is a literal string.

slakmagik 05-18-2007 05:14 AM

I'd have followed up sooner to correct an omission but half the net seems to have disappeared, including this site for a bit - weird DNS issues.

Anyway, obviously you need the braces for things like arrays and parameter expansion and so on. So my 'only required' was a misstatement, because I was speaking in too narrow a focus.

And I turned up this from the bashFAQ - doesn't shed much more light on it, but corroborates. ;)


All times are GMT -5. The time now is 05:08 AM.