LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Script not running as expected (https://www.linuxquestions.org/questions/programming-9/script-not-running-as-expected-819490/)

fw12 07-12-2010 07:40 PM

Script not running as expected
 
My script is not working as expected.

I have a need to restart a program every hour.

If the program is running when the script runs,
kill it
then
restart it.

If the program is NOT running when script runs,
then
just start it.

Here is the script's behavior currently:

The script kills the program if the program is running,
but
it won't restart it, until the next time the script runs.
I.e., the only time it restarts the program is if it wasn't running.

Why is it doing this?

Here is the script...

#!/bin/sh

APP='ffmpeg2theora'
APPID=`pidof ffmpeg2theora`

if ps ax | grep -v grep | grep $APP > /dev/null
then
kill $APPID
fi

wait

/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout ...

Sergei Steshenko 07-12-2010 07:50 PM

What did you do to debug the issue ? E.g. did you check until what line inclusive your script is executed ?

For example, did you try to put

-xv

after

#/bin/sh

?

fw12 07-12-2010 09:38 PM

Quote:

Originally Posted by Sergei Steshenko (Post 4031348)
What did you do to debug the issue ? E.g. did you check until what line inclusive your script is executed ?

For example, did you try to put

-xv

after

#/bin/sh

?

Even without doing any debugging,
it makes no sense that the line
/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout ...
only runs if the program wasn't previously running.

Isn't a script supposed to run line-by-line?
And that anything outside a conditional statement runs automatically?

Anyway, I debugged the script the following way:

$ watch cat `pidof ffmpeg2theora`

When the script runs from cron,
the pid changes. E.g. from 14449 to 24045

But then 24045 disappears 2 seconds later.

Quite a bizarre behavior.

The following seems to work for now, but I still don't know where the problem lies.

Code:

#!/bin/sh

APP='ffmpeg2theora'
APPID=`pidof ffmpeg2theora`

if ps ax | grep -v grep | grep $APP > /dev/null
then
kill $APPID
fi
wait
/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout ...
wait
/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout ...

By running the line:
/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout ...
twice, I'm getting the expected behavior.

ntubski 07-13-2010 08:14 AM

What is the wait for?

It seems to me that the following much simpler script would work:
Code:

#!/bin/sh
killall /usr/bin/ffmpeg2theora
/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout ...


fw12 07-13-2010 09:04 AM

Quote:

Originally Posted by ntubski (Post 4031797)
What is the wait for?

It seems to me that the following much simpler script would work:
Code:

#!/bin/sh
killall /usr/bin/ffmpeg2theora
/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout ...


The "wait" tells the script to wait for one line to finish before trying to run the next line.

I could use "sleep X" in place of "wait", but there is no guarantee that the line would finish executing in X seconds.

Your suggestion,

killall /usr/bin/ffmpeg2theora
/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout ...

suffers the same problem as I'm having. It kills the running process, but does not restart, until the next time the script runs.

Sergei Steshenko 07-13-2010 09:20 AM

Quote:

Originally Posted by fw12 (Post 4031859)
The "wait" tells the script to wait for one line to finish before trying to run the next line.
...

Justify your statement by excerpts from documentation.

Sergei Steshenko 07-13-2010 09:27 AM

Quote:

Originally Posted by fw12 (Post 4031428)
Even without doing any debugging ...

Enough said - please first make minimum decency effort. Debugging is first of all about checking your assumptions - you haven't shown any proof that in reality your assumptions are correct.

ntubski 07-13-2010 11:02 AM

The killall has a --wait option, perhaps that is what you are looking for. The following appears to work correctly over here:
Code:

#!/bin/sh
killall --wait --quiet /usr/bin/ffmpeg
/usr/bin/ffmpeg -f mpegvideo -i /dev/zero -o /dev/null 2>/dev/null &

Without the --wait option it still works but there is a period of time in which 2 ffmpeg processes are running. I imagine if 2 processes try to read from a real camera (instead of /dev/zero) there could be a problem. Have you tried redirecting stderr to a log file to see if any errors are reported?

I don't have ffmpeg2theora here, is it by any chance a shell script? That could also complicate things.

fw12 07-13-2010 08:13 PM

Quote:

Originally Posted by ntubski (Post 4031961)
The killall has a --wait option, perhaps that is what you are looking for. The following appears to work correctly over here:
Code:

#!/bin/sh
killall --wait --quiet /usr/bin/ffmpeg
/usr/bin/ffmpeg -f mpegvideo -i /dev/zero -o /dev/null 2>/dev/null &

Without the --wait option it still works but there is a period of time in which 2 ffmpeg processes are running. I imagine if 2 processes try to read from a real camera (instead of /dev/zero) there could be a problem. Have you tried redirecting stderr to a log file to see if any errors are reported?

I don't have ffmpeg2theora here, is it by any chance a shell script? That could also complicate things.

Yes, I need to forestall two ffmpeg2theora process running and trying to read from the same /dev/video0.

This is why the kill/killall command has to finish executing, before the script is allowed to proceed.

fw12 07-13-2010 08:30 PM

Quote:

Originally Posted by Sergei Steshenko (Post 4031881)
Enough said - please first make minimum decency effort. Debugging is first of all about checking your assumptions - you haven't shown any proof that in reality your assumptions are correct.

What assumptions are you referring to?

If you read my post carefully, I said I debugged using

$ watch echo `pidof ffmpeg2theora`

Did you just read the one line, and quickly ran to reply? Don't do that. You should read the entire post, and my reasoning.

fw12 07-13-2010 08:32 PM

Quote:

Originally Posted by Sergei Steshenko (Post 4031873)
Justify your statement by excerpts from documentation.

If you're looking for a guide on "wait" command, here it is

http://www.linux.com/archive/feed/43774

ntubski 07-13-2010 09:08 PM

Quote:

Originally Posted by fw12 (Post 4032446)
If you're looking for a guide on "wait" command, here it is

http://www.linux.com/archive/feed/43774

Wow, I guess that explains where your misconceptions come from but that article is completely wrong. Just read a few of the comments on it.

Quote:

Yes, I need to forestall two ffmpeg2theora process running and trying to read from the same /dev/video0.

This is why the kill/killall command has to finish executing, before the script is allowed to proceed.
The problem is not waiting for kill/killall command to finish executing, it is that the kill/killall command may finish executing before the other process receives the signal. Passing the --wait option to killall should solve this problem, have you tried that?

fw12 07-14-2010 08:46 AM

Quote:

Originally Posted by ntubski (Post 4032459)
Wow, I guess that explains where your misconceptions come from but that article is completely wrong. Just read a few of the comments on it.



The problem is not waiting for kill/killall command to finish executing, it is that the kill/killall command may finish executing before the other process receives the signal. Passing the --wait option to killall should solve this problem, have you tried that?

I now have a better feel for what the "wait" command does.

As for using --wait with killall, I'm reluctant to use killall, because a case may arise where I have more than two ffmpeg2theora processes running.

So, I've rewritten my code as follows with grep and kill. Grep lets me find particular ffmpeg2theora processes.


APP='ffmpeg2theora'
APPID=`pidof ffmpeg2theora`

CMD=/usr/bin/ffmpeg2theora /dev/video0 -o /dev/stdout...

if ps ax | grep -v grep | grep $APP > /dev/null
then
kill $APPID & # backgrounding makes it a sub-process, and gives it a pid.
LPID=$! #$! contains the PID of the last called process.
wait $LPID
$CMD

else
$CMD
fi

This seems to do what I want.
Please critique for obvious flaws.

ntubski 07-14-2010 09:30 AM

Quote:

Originally Posted by fw12 (Post 4032865)
I now have a better feel for what the "wait" command does.

Still not correct though,
Code:

kill $APPID & # backgrounding makes it a sub-process, and gives it a pid.
LPID=$! #$! contains the PID of the last called process.
wait $LPID

is completely identical to kill $APPID. Also it doesn't really solve the problem because the kill command may finish before the process receives the signal; perhaps it turns out that doing things this way happens to cause processes to be scheduled in such a way that things work, but there is no more assurance of correctness than using sleep.

Quote:

As for using --wait with killall, I'm reluctant to use killall, because a case may arise where I have more than two ffmpeg2theora processes running.

So, I've rewritten my code as follows with grep and kill. Grep lets me find particular ffmpeg2theora processes.
How will grep know which process you want? You're applying kill to the pidof result, so even if grep did magically know, it wouldn't matter. pidof will return both pids if you have 2 ffmpeg2theora processes, so your method has the same problems as killall. If you want to kill a particular process, you should save its pid when you start it.

By the way, I suggest pgrep instead of the ps | grep foo | grep -v grep thing in general.

Sergei Steshenko 07-14-2010 09:41 AM

Quote:

Originally Posted by ntubski (Post 4032894)
Still not correct though,
Code:

kill $APPID & # backgrounding makes it a sub-process, and gives it a pid.
LPID=$! #$! contains the PID of the last called process.
wait $LPID

is completely identical to kill $APPID. Also it doesn't really solve the problem because the kill command may finish before the process receives the signal; perhaps it turns out that doing things this way happens to cause processes to be scheduled in such a way that things work, but there is no more assurance of correctness than using sleep.



How will grep know which process you want? You're applying kill to the pidof result, so even if grep did magically know, it wouldn't matter. pidof will return both pids if you have 2 ffmpeg2theora processes, so your method has the same problems as killall. If you want to kill a particular process, you should save its pid when you start it.

By the way, I suggest pgrep instead of the ps | grep foo | grep -v grep thing in general.


FWIW, 'man killall' might be useful if one wants to kill processes by name.


All times are GMT -5. The time now is 02:00 AM.