Other *NIXThis forum is for the discussion of any UNIX platform that does not have its own forum. Examples would include HP-UX, IRIX, Darwin, Tru64 and OS X.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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.
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.
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...
Last edited by MaffooClock; 11-12-2006 at 03:08 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.
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.
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
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.
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.
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 -
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.
Last edited by slakmagik; 05-18-2007 at 04:39 AM.
Reason: very tired
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.