LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-27-2011, 08:53 AM   #1
newbie01.linux
LQ Newbie
 
Registered: Oct 2009
Posts: 15

Rep: Reputation: 0
Problem running a program/script in the background from a script


Hi all,

I have a script that calls another program/script, xxx, to run in the background. Supposedly this program at most should finish within five (5) minutes so after five (5) minutes, I run some other steps to run the script into completion.

My problem is sometimes the program takes longer than five (5) minutes and this is causing problems when running the rest of the steps in the scripts. Can anyone suggest how to re-program my script.

At the moment, the KSH script, i.e. test.ksh, is doing as below:

test.ksh:

....
....
xxx/xxx.ksh <--- program/script called by the script
sleep 300
..... run the rest of the script ......
...... problem is sometimes xxx/xxx.ksh takes longer than 300 seconds ......
...... any way that I can monitor that xxx/xxx.ksh finishes before I run ......
...... the rest of the scripts ......

Any advise will be much appreciated. Thanks in advance.
 
Old 03-27-2011, 09:40 AM   #2
druuna
LQ Veteran
 
Registered: Sep 2003
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
Hi,

Using a fixed time frame is, as you noticed, not the way to go. Using the child's PID and checking its existence might be what you are looking for.

Rough example:
Code:
# the child script:
$ cat foo
#/bin/bash

echo "foo: i'm alive..... I'll sleep for 15 seconds and exit"

sleep 15

echo "foo: Done. exiting now."

# the main script:
$ cat bar
#!/bin/bash

echo "bar: starting foo in background"

./foo &

fooPID="$!"

echo "child pid: $fooPID"

while [[ true ]]
do
  if [[ "$(ps -ef | grep $fooPID | grep -v grep)" == "" ]]
  then
    echo "bar: foo has stopped"
    break
  else
    echo "bar: foo is still running"
  fi
  sleep 2
done

echo "bar: do more stuff here that depends on stopped foo"
Code:
# example run:
$ ./bar
bar: starting foo in background
child pid: 17157
foo: i'm alive..... I'll sleep for 15 seconds and exit
bar: foo is still running
.
.
.
bar: foo is still running
foo: Done. exiting now.
bar: foo has stopped
bar: do more stuff here that depends on stopped foo
There are other ways as well: let foo create a temporary file, which foo removes as last step. bar checks if the file exists, if it does: foo is still running.

Hope this helps.

Last edited by druuna; 03-27-2011 at 09:44 AM. Reason: Spelling/grammar
 
1 members found this post helpful.
Old 03-27-2011, 09:45 AM   #3
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,780

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Wouldn't it make more sense to just run xxx in the foreground?
 
1 members found this post helpful.
Old 03-28-2011, 05:16 AM   #4
newbie01.linux
LQ Newbie
 
Registered: Oct 2009
Posts: 15

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by ntubski View Post
Wouldn't it make more sense to just run xxx in the foreground?
Hi,

It does make sense to just run xxx in the foreground but I also have cases where it just stalled/hanged which causes the rest of the script not to run.

Ideally, the best scenario would be to run xxx in the background but give it for example a maximum of 10 minutes for example and if it does not run to completion, I want to kill -9 it, but how to know what PID to kill if I let it run in the background. Should I Be doing as below:

... xxx &
while loop to check the PID of xxx (???) if it disappears, then xxx is finished, otherwise it is still running? But how to get the PID of xxx &
...
...
 
Old 03-28-2011, 05:18 AM   #5
newbie01.linux
LQ Newbie
 
Registered: Oct 2009
Posts: 15

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by druuna View Post
Hi,

Using a fixed time frame is, as you noticed, not the way to go. Using the child's PID and checking its existence might be what you are looking for.

Rough example:
Code:
# the child script:
$ cat foo
#/bin/bash

echo "foo: i'm alive..... I'll sleep for 15 seconds and exit"

sleep 15

echo "foo: Done. exiting now."

# the main script:
$ cat bar
#!/bin/bash

echo "bar: starting foo in background"

./foo &

fooPID="$!"

echo "child pid: $fooPID"

while [[ true ]]
do
  if [[ "$(ps -ef | grep $fooPID | grep -v grep)" == "" ]]
  then
    echo "bar: foo has stopped"
    break
  else
    echo "bar: foo is still running"
  fi
  sleep 2
done

echo "bar: do more stuff here that depends on stopped foo"
Code:
# example run:
$ ./bar
bar: starting foo in background
child pid: 17157
foo: i'm alive..... I'll sleep for 15 seconds and exit
bar: foo is still running
.
.
.
bar: foo is still running
foo: Done. exiting now.
bar: foo has stopped
bar: do more stuff here that depends on stopped foo
There are other ways as well: let foo create a temporary file, which foo removes as last step. bar checks if the file exists, if it does: foo is still running.

Hope this helps.
Hi druuna,

I think this is what I wanted. I will test it out.

Thanks
 
Old 03-28-2011, 07:28 AM   #6
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
Here is timeout, a bash shell script which runs the given command with a timeout. I did note you use ksh, but I'm too rusty with it, sorry. You could of course run this as-is in your own ksh scripts; just put it somewhere along your PATH.

The script uses a subshell and Bash job control features to do the work, no temporary files or pipes are used. The main shell will sleep in one second intervals, until the command completes or the timeout expires. If the timeout expires, it will first try to terminate the command gracefully with a TERM signal, but if it does not terminate within five seconds, the command will be sent a KILL signal.

The timeout in seconds must be an integer, but you can use a Bash algebraic expression, e.g. '2*5-8'. Remember to quote the expression like I did if it has characters that are special to the shell.
Code:
#!/bin/bash
if [ $# -lt 2 ] || [ "$1" == "-h" ] || [ "$1" == "--help" ]; then
    echo "" >&2
    echo "Usage: $0 [ -h | --help ]" >&2
    echo "       $0 <seconds> command .." >&2
    echo "" >&2
    echo "This will run command in a Bash subshell." >&2
    echo "If the timeout (integer <seconds>) expires before the command completes," >&2
    echo "the command will be forcibly terminated (and exit status will be 127)." >&2
    echo "Note that termination may take up to five seconds." >&2
    echo "" >&2
fi

# Parse <seconds> without bash error messages.
exec 3>&1 4>&2 1>/dev/null 2>/dev/null
timeout=$[ $1 -0 ]
if [ $? -ne 0 ] || [ $timeout -lt 1 ]; then
    echo "$1: Invalid timeout." >&4
    exit 126
fi
exec 1>&3- 2>&4-
shift 1

# Run command in a subshell
(   SECONDS=0
    "$@" &

    # Hide any possible "Terminated" output.
    exec >/dev/null 2>/dev/null

    while [ -n "`jobs -pr`" ] && [ $SECONDS -lt $timeout ]; do
        sleep 1.0
    done

    pids=`jobs -pr`
    if [ -n "$pids" ]; then

        # Send the TERM signal. Give up to five seconds to respond.
        kill -TERM $pids
        SECONDS=0
        while [ -n "`jobs -p`" ] && [ $SECONDS -lt 5 ]; do
            sleep 0.25
        done

        # If that didn't terminate it, send the KILL signal.
        pids=`jobs -p`
        if [ -n "$pids" ]; then
            kill -KILL $pids
        fi

        exit 127
    else
        wait `jobs -p`
        exit $?
    fi
)

exit $?
Usage is very simple. For example (in Bash or ksh):
Code:
./timeout 300 some-command-or-shell-script arguments...
or if you want to know what happened,
Code:
./timeout 300 some-command-or-shell-script arguments...
result=$?
if [ $result -eq 127 ]; then
    echo "Took more than five minutes, therefore killed."
elif [ $result -eq 0 ]; then
    echo "No errors."
else
    echo "Error $result"
fi
Hope you find this useful.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Running script in background? bobbyright Linux - Newbie 4 03-02-2010 02:17 AM
Running script in background bob81 Linux - Newbie 1 03-04-2009 12:11 AM
logging script, running background how lhrt Linux - General 2 06-09-2006 10:06 AM
Running script in background skguha Linux - Newbie 7 04-02-2004 08:32 AM
Running a script in background on a remote machine TheCoffeeMug Linux - Networking 3 11-06-2003 10:08 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:41 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration