1

I have following bash script to stop Apache server. I am not getting error but an unexpected result.

#!/bin/bash

/etc/init.d/httpd stop
if [[ $? -ne 0 ]]
then
    exit 1
fi
RTN=10
while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do
    sleep 5
    RTN=`ps -C httpd | wc -l`
    RTN=$(( RTN - 1 ))
echo "After" $RTN
done 

exit 0

I got the following answer which I do not expect to be, with an infinite printing:

Before 10
After 0

Before 0
After 0

Before 0
After 0

I expect to print:

Before 10
After -1 
#and exit here

Could anybody please tell me what is happening?

5
  • 2
    pmverma, it's considered bad form to change the very nature of a question after it has been answered since it renders the answers irrelevant. If the very nature changes, it should be posted as a new question, however even that's not necessary here. As shown in my answer, it was the misplacement that caused the infinite loop. If you're getting 0 as a return value, it will terminate because the condition is gt 0. As I also stated, check the output of your ps, that will tell you why you're getting strange values. Commented May 25, 2015 at 10:26
  • @paxdiablo, I though the edited post was the original... Commented May 25, 2015 at 10:30
  • 1
    @Jahid, no, OP moved the echo inside the loop body which basically made it totally different. I gather what you were trying to do on the subsequent edit was fix the starting value of RET to match the actual output (10 rather than 5), and that's sensible, so I've incorporated that in the latest edit. Commented May 25, 2015 at 10:32
  • Thanks all guys, finally I have figured out everybody is correct. But my problem was concern to file naming of script file, which may be in someway conflicting with the (may be) ps command. Commented May 25, 2015 at 10:55
  • I will post another interesting question, I will also share link here. Commented May 25, 2015 at 10:56

2 Answers 2

2

This doesn't work the way you seem to think it does:

while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do

You want the echo to come after the do. With it before the do, it's part of the list-1 condition rather than the list-2 body. And, as per the bash docs (my bold):

The while command continuously executes the list list-2 as long as the last command in the list list-1 returns an exit status of zero.

You can see the difference between the following script, similar to yours:

#!/usr/bin/bash
RTN=2
while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do
    sleep 1
    RTN=$(( RTN - 1 ))
echo "After" $RTN
done

which outputs (ad infinitum):

Before 2
After 1
Before 1
After 0
Before 0
After -1
Before -1
After -2
Before -2

When you move the echo to inside the body:

#!/usr/bin/bash
RTN=2
while [[ $RTN -gt 0 ]]
do
    echo "Before" $RTN
    sleep 1
    RTN=$(( RTN - 1 ))
    echo "After" $RTN
done

it then terminates properly:

Before 2
After 1
Before 1
After 0
<returns to prompt>

Once that change is made, the loop terminates correctly, given the values being generated by your ps command.


Additionally, if you want to find out what's in the process list (and probably causing an result of zero rather than negative one), output the process list before checking the count:

:
ps -C httpd                 # Add this line temporarily.
RTN=`ps -C httpd | wc -l`
:
Sign up to request clarification or add additional context in comments.

2 Comments

actually my problem is when I run ./stop_server.sh it is not terminating and I have to Ctrl+t. Thus, I tried to echo and see what values are before and after. It was my fault, I put echo in wrong place.
I have updated my script according to your second one from the difference, but still not terminating. Please look at script question.
1

Your ps -C httpd command always returns a line: PID TTY TIME CMD (basically the heading of the ps output) which is counted by wc -l as 1 when there is no process running. If httpd was running the line count would be greater than 1.

Thus $((RTN -1)) becomes 0.

Edit:

I notice, you have an error in your while loop:

while [[ $RTN -gt 0 ]]
echo "Before" $RTN
do

Change it to:

while [[ $RTN -gt 0 ]]
do
echo "Before" $RTN

3 Comments

I think at next point in lopping RTN=$(( RTN - 1 )) , $RTN value will be -1 and loop will end. Am I wrong?
@pmverma In line RTN=ps -C httpd | wc -l it becomes 1 again and then becomes 0 by the next line
It doesnt actually matter whether it's 0 or -1 because the continuation condition is gt 0 which is false for both those values.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.