LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   AIX (http://www.linuxquestions.org/questions/aix-43/)
-   -   [AIX/HP-UX] ksh timedout hanged command (http://www.linuxquestions.org/questions/aix-43/%5Baix-hp-ux%5D-ksh-timedout-hanged-command-4175422467/)

fritz001 08-16-2012 02:37 PM

[AIX/HP-UX] ksh timedout hanged command
 
I have a ksh script who is calling an external script myscript1.

myscript1 -a -b -c 1>/dev/null
RESULT=$?
if [ $RESULT != "0" ] ; then
# If 'command hanged'/failed
send HPOV alert
fi

Sometimes, this script gets hung. I would like to be able to have a time out, lets say about 50 seconds and if the script didn't finish, I would like to kill it.

Any ideas what should I do ?

kakaka 08-16-2012 06:10 PM

If in the particular version of AIX or HP-UX you have a fully implemented ksh, then could you run the external script in the background, have a sleep of 50 seconds in the main script, then just kill off the external script, if it's still running?

cliffordw 08-17-2012 01:13 AM

Hi there,

kakaka's suggestion puts you on the right track. The only down side of sleeping for 50 seconds in the main script is that you will waste time if myscript1 finishes sooner (say in 10 seconds). Here's a sample script elaborating on this idea, which may help.

Quote:

#!/usr/bin/ksh
# Sample script to run a child process and time out if it takes too long
# Tested on AIX 6.1
# 'echo "Debug:..."' statements can be removed after testing

### VARIABLES ###
basename=$(basename $0)
resultfile=/tmp/$basename.$$

### FUNCTIONS ###

# Used to time out the child script if it runs too long
timeout()
{
tmout=$1
childpid=$2
if [ ! -z "$childpid" ]
then
echo "Debug: timeout: Waiting for pid $childpid for $tmout seconds"
sleep $tmout
ps -fp $childpid > /dev/null
if [ $? -eq 0 ]
then
echo "Debug: timeout: Child timeout exceeded - killing"
kill -TERM $childpid
else
echo "Debug: timeout: Child no longer running"
fi
else
echo "Debug: timeout: No child PID specified"
fi
}

# Wrapper to call child script and save exit code to temp file
wrapper()
{
if [ -f $resultfile ]
then
rm $resultfile
fi
myscript1 $*
rc=$?
umask 077
echo $rc > $resultfile
}

# Fake child script - can be deleted in favour of real script.
# Just sleeps for 60 seconds to test timeout handler; change to less than
# timeout to test successfull completion.
myscript1()
{
echo "myscript1: start: $*"
sleep 60
echo "myscript1: done"
}


### MAIN SCRIPT ###

# Call myscript1 (with args) via wrapper() & save PID
# wrapper -a -b -c 1>/dev/null &
wrapper -a -b -c &
childpid=$!

# Start timer for timeout handler. Arg1 is seconds to wait.
timeout 50 $childpid &
timepid=$!
echo "Debug: main: child pid $childpid timeout pid $timepid"

# Clean up if we're interrupted
trap "kill $childpid $timepid" 1 2 3 15

# Wait for child script to finish
cnt=0
ps -fp $childpid > /dev/null
rc=$?
while [ $rc -eq 0 ]
do
(( cnt = cnt + 1 ))
echo "Debug: main: waiting $cnt"
sleep 1
ps -fp $childpid > /dev/null
rc=$?
done

# Get return code from child process as saved by wrapper()
if [ -f $resultfile ]
then
RESULT=$(cat $resultfile)
rm $resultfile
else
RESULT=1
fi

# If child finished before timeout, kill timeout process
ps -fp $timepid > /dev/null
if [ $? -eq 0 ]
then
echo "Debug: timeout: cleaning up"
kill $timepid
fi

# Handle return code from child script
if [ $RESULT -ne 0 ] ; then
# If 'command hanged'/failed
echo "send HPOV alert"
fi
echo "Debug: main: done: rc $RESULT"
exit $RESULT
Good luck!

fritz001 08-17-2012 09:28 AM

meantime

....

script1 -a -b -c >/dev/null 2>&1 &
PID=$!
sleep 60 && kill -15 $PID 2>/dev/null
wait $PID >/dev/null 2>&1
RC=$?

thanks cliffordw, i'll take a beeter look at your example:

oki now 2nd issue::

f=0
set -A BKS dir1 dir2 dir3 dir4 ...dirN while

[ $f -lt ${#BKS[*]} ]
do
echo "files to be tar-ed ${BKS[$f]}"
tar xfv ${BKS[$f]}
call_function_to_check_disk_space
fi DS <5Gb ==>raise alert
#echo backup failed for dirA dirB....dirN
# Let's say i have an unknown number of folders to archive....
#after each iteration check disk space if less then defined (5gb) show
backup failed for dirA dirB....dirN
((f+=1))
done

again, any ideas ?

kakaka 08-17-2012 03:59 PM

fritz001, what's the question, are you saying that you get the warning every time, even when there is enough disk space?

fritz001 08-20-2012 04:40 AM

back online,
nope : here what i want to do ::

I have a script which generate some tar archives and I have 20 big folders to archive.

So

set -A folders dir1 dir2 dir3 ..... dir20

f=0

[ $f -lt ${#folders[*]} ]
do
echo "files to be tar-ed ${folders[$f]}"
tar xfv ${folders[$f]}
call_function_to_check_disk_space
if diskspace < 4g
#Here is what i want to do:
#Let's say after finishing to compress dir1 dir2 dir3 dir4 the remaining disks space is less then 4G
#i want to create a second array with the failed archives (dir5 dir6 dir7 .... dir20)
and to generate an echo like this :=> echo "backup failed for dir5 dir6 dir7 .... dir20.


done

Well, hope this time I wasn;'t to confusing...

kakaka 08-20-2012 05:06 PM

Hi fritz001, now that we know you're willing to try stuff ( like the trap directive ), I feel that I can say that I'd approach the backup procedure itself, a little differently.

I'd check for disk space, first, before running the tar command.

Unless you're going to actually list the files in the directory you're going to back up, as in ls ${folders[$f]} then I'd call a directory, a directory, in the output messages. I wouldn't output something like "files to be tar-ed" and then show a directory name.

So with the failure notification, that might look something like this:

Code:

function get_disk_space_in_gb
{
    # Code to check disk space goes here...
}


# Main program code.

set -A folders dir1 dir2 dir3 ..... dir20

f=0

while [  $f  -lt  ${#folders[*]}  ]
    do

        echo "directory to be tar-ed ${folders[$f]}"

        get_disk_space_in_gb  ${folders[$f]}
        disk_space_in_gb=$?

        if [  $disk_space_in_gb  -lt  4  ]
            then
                break ;
        fi

        tar xfv ${folders[$f]}

        ((  f += 1  ))

    done


if [  $f  -lt  ${#folders[*]}  ]
    then

        failed_count=0

        while [  $f  -lt  ${#folders[*]}  ]
            do
                failed_folders[ $failed_count ]=${folders[ $f ]}

                ((  failed_count += 1  ))
                ((  f += 1  ))

            done

    echo "backup failed for ${failed_folders[*]}"

fi

Or if you prefer code of higher density, you could do away with the last code section, have one main loop, put a flag in the main loop to:
1) stop executing the tar command, and instead
2) start to put together the failure list after you reach your disk space limit.


All times are GMT -5. The time now is 05:40 AM.