• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1218
  • Last Modified:

if conditions in bash script executed in different order at times

I have a script that checks if any of two scripts are running:

# Check if there is another instance of gprswatchdog running or S99viper
if [ `ps | grep -c gprswatchdog` -gt 3 ] || [ `ps | grep -c viper` -gt 1 ]; then
   #do something
fi

However even when i manually do ps and check that the viper script is indeed listed sometimes the second condition that tests for this fails, which is very strange.

Looking at the output of the script i see that when it fails the grep seems to be executed before the ps
++ ps
++ grep -c gprswatchdog
+ '[' 3 -gt 3 ']'
++ grep -c viper
++ ps
+ '[' 1 -gt 1 ']'

however when the test is succesful the grep is executed after the ps as expected
++ ps
++ grep -c gprswatchdog
+ '[' 3 -gt 3 ']'
++ ps
++ grep -c viper
+ '[' 2 -gt 1 ']'

Any ideas of what is happening?


0
ealdaz
Asked:
ealdaz
  • 13
  • 6
  • 4
  • +2
3 Solutions
 
xDamoxCommented:
Hi,

1 is not greater than 1 also 3 is not greater than 3.

If I have got this correctly you want the following:

if [ `ps | grep -c gprswatchdog` -ge 3 ] || [ `ps | grep -c viper` -ge 1 ]; then

Notice the grater than OR equal to :)
0
 
ealdazAuthor Commented:
Hi thanks for the reply.
The problem is not really that, what i'm seeing is that in exactly the same conditions (or so it seems) the test gives one result or another, because it seems to not execute the test in the same order, i'll try to explain it a bit better.
there is a script running called viper, so the test
   ps | grep -c viper
should give  2  as a result as there are two processes with the name viper running, viper itself, and grep -c viper

However sometimes in the same conditions (or so it seems) the test is not succesful as it seems to be running the test out of order, or so it seems judging by the ouput of the script (obtained with set -x)

++ grep -c viper
++ ps
+ '[' 1 -gt 1 ']'

THe result this time is 1 when it should be 2....
0
 
xDamoxCommented:
Hi,

Have you tried:

`ps aux | grep -c gprswatchdog`

The aux should show all instances of it other than that your script should work fine
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
ravenplCommented:
if [ `ps | grep -c gprswatchdog` -gt 3 -o `ps | grep -c viper` -gt 1 ]; then
   #do something
fi

|| will not workfor You in that case, but You concatenate more conditions wit -o (means OR) or with -a (means AND).
Possibly You have to switch from -gt(greater than) to -ge(greater or equal)

Also - not problem here, but You may find it usefull: `ps --no-headers -C viper | wc -l` (consider another process called viperator ;)
0
 
enyamadaCommented:

Hi,

I guess I know what's happening:

Try, for instance, to type "ps -ef|grep -c init". Sometimes you'll get 2, others you'll get 1, because, for a reason
I can't explain in details, grep sometimes grabs the init argument, sometimes dont.

I suggest to use the []s technique: if you type "ps -ef|grep -c ini[t]", you'll allways get 1.

Hope this helps.
0
 
ealdazAuthor Commented:
Hi enyamada
What's the []s technique, what does it do?
0
 
ealdazAuthor Commented:
Hi ravenpl

From what i've tested the or || between the test conditions works fine, the problem seems to be with grep -c viper that sometimes gives 1 others 2, on the lines of what enyamada is suggesting.
0
 
ealdazAuthor Commented:
I meant to write: ps | grep -c viper
0
 
ravenplCommented:
Read my also suggestion
ps --no-headers -C viper
0
 
ealdazAuthor Commented:
Hi ravenpl, thanks, i hadn't realized it addressed the same issue

what does ps --no-headers do ?
0
 
ealdazAuthor Commented:
I've tried ps --no-headers and i seem to get the same result as with ps, i'm running busybox (linux 2.6.11 running in XScale), so that could be related
ps --no-headers | grep -c viper | wc -l

Just to review, when i do the following :
ps | grep -c viper
I should get 1 if the viper script is not running (ps will list grep -c viper)
I should get 2 if the viper script is running (ps will list grep -c viper and viper )

Sometimes i get 1 when i should get 2, so i guess the bottom line is: is this possible or am i seeing ghosts?

From what enyamada says it seems possible, although i don't fully understand how putting brackets improves it.

Do you think that this is a possibility too? or do you think rather that is a question of names, that is if i'm counting 2 processes is because there is a script with a similar name to viper and it gets counted? but if that was the case ps would give me a larger number than expected, not a smaller?

Thanks for your patience
0
 
ravenplCommented:
No, unless Your busybox has striped ps down from -C flag
ps --no-headers -C viper | wc -l #no grep involved
--no-headers # strips the header line from ps output.
0
 
ealdazAuthor Commented:
Just tested, unfortunately it seems that they have stripped the -C flag for busybox :-(

I get the impression you don't really think that it is possible that
ps | grep -c viper
gives different results? and that it should work OK? is this right?  

I might bediagnosing the problem then... not sure




0
 
ravenplCommented:
try then:
ps -e | grep -c " viper$"
should be in standard (-e shows all processes, but without arguments - unlike -f)
0
 
ahoffmannCommented:
> .. the problem seems to be with grep -c viper ..
and some other "strange" behavious according your description:

as already explained:
  ps | grep whatever
will give you either nothing, or at least one match, this is due to the fact that grep starts working when ps finished, it depends on the kernel's time splices if ps sees the piped grep process or not, if ps sees the grep then grep prints it's own process: match!
Hence this method is unreliable. Use
  ps | grep [w]hatever

You also should make yourself used to || vs | and what the result (status/exit code) of a piped command is.

Hope this helps to get you on the right track.
0
 
ealdazAuthor Commented:
Hi ahoffmann, thanks for the reply.
What does grep [w]hatever do?

the [] i guess are some regular expression, i really know nothing about them, what is it doing in this case? I guess making sure the grep matches something starting with 'w' ? is that so that it doesn't match "grep whatever" when ps lists it?

> You also should make yourself used to || vs | and what the result (status/exit code) of a piped command is.
Sorry, not fully sure i understand, how can i use these? what are they for? || i thought was OR and | pipe...
0
 
ealdazAuthor Commented:
> ps -e | grep -c " viper$"
> should be in standard (-e shows all processes, but without arguments - unlike -f)


Unfortunately
ps -e, ps , ps aux
all show the same thing in my linux box, i've just done ps --help and seeing that the busybox version accepts no options !!

However for curiosity, what does the last $ do in ? is the space before the viper important?
I don't get any matches when i try it..
0
 
ravenplCommented:
last $ matches end of line, so we would not match "viperator" process
another shoot
grep "(viper)" /proc/*/stat | wc -l #ps does it anyway
0
 
ahoffmannCommented:
> the [] i guess are some regular expression ..
exactly. this regex is evaluated by the shell befor it (the shell) passes the result (whatever  in this case) to grep, but ps gets the parameter ([w]hatever in this case) which does not match what is searched for.

> || i thought was OR and | pipe...
yes (but keep the previous exit code it relies on in mind)

> ps -e, ps , ps aux
stupid ps ;-)

ps, ps aux are the traditional AT&T (BSD) versions, ps -e, ps -ef is the POSIX (SysV) version.
Most modern Linux support both.

> .. what does the last $ do
in regex (if you mean that as in "viper$") it means end of line, but keep in mind that not all grep support regex, most likely you need the -e option for it (or use egrep)
0
 
ealdazAuthor Commented:
OK, from what i see i have two options:
1.- Get grep to match exactly the process i want.
2.- Get grep to match the process i want more loosely and force grep not to count outputs that include the word grep.

The problem i have with option 1 is that the process is called from crontab and it appears as
  /bin/sh /home/mds/watchdog/gprswatchdog
will ps | grep [g]prswatchdog work with it?

0
 
ahoffmannCommented:
> will ps | grep [g]prswatchdog work with it?
yes, no, depends, ...
   ps ax | grep "[g]prswatchdog"
0
 
enyamadaCommented:

Hi, ealdaz

Yeah, ps | grep [g]prswatchdog should work. The trick is that regular expression "[g]prswatchdog" matches the string
"grpswatchdog", but not the string "[g]prswatchdog" itself.

hth
0
 
ravenplCommented:
if it's started as
/bin/sh /home/mds/watchdog/gprswatchdog
then my sollution will not work, but if it's started as
/home/mds/watchdog/gprswatchdog
grep "(gprswatchdog)" /proc/*/stat | wc -l #should do
0
 
ealdazAuthor Commented:
Thank all for your comments
i think i'm almost there,
it seems that both
 ps | grep [g]prswatchdog
 ps | grep gprswatchdo[g]

count all the processes that have the work gprswatchdog
ie:
 2699 root       1156 S   /bin/sh /home/mds/watchdog/gprswatchdog
 2707 root        636 S   /bin/ping -c 20 gprswatchdog-host

but don't count the process grep gprswatchdog
 2719 root        412 S   grep gprswatchdog

This might be more of a regular expression question, but i must admit i don't quite understand why "grep gprswatchdog" is not taken into account when i use the regular expression, as it seems to match both, as it has the word gprswatchdog... what makes it different from /bin/sh /home/mdswatchdog/gprswatchdog ?

0
 
ealdazAuthor Commented:
Sorry, i think i understand it now, what is happening is that the process is no longer going to be listed as
grep gprswatchdog
but as grep gprswatchdo[g]
correct?

0
 
enyamadaCommented:

Yes, ealdaz, you got the point! :-)
0
 
enyamadaCommented:

Notice also that it does´nt matter where the brackets go -- they may appear at the end, beginning of middle of
the regular expression; the main idea is to force the brackets appear at the ps list and dont match the regular
expression.

0
 
ealdazAuthor Commented:
I figured that finally, is all understood now, thank you all very much
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 13
  • 6
  • 4
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now