2

I have bash script and I would like to set time limit for it. For example if scripts runs longer than 50s, exit with 0. It should be done inside script, I can not change the command how script is called.

What would be the best way to do it?

Is there something like time trap?

I could put all the code inside loop, but this is not an option in this case.

Rokas.ma
  • 563
  • 2
  • 1
    @dr01 no, that one has very, very specific portability requirements which don't apply here. A better choice would be https://unix.stackexchange.com/q/43340/22222 but that doesn't meet the OP's requirement that the method of launching remain unchanged. – terdon May 18 '17 at 13:49
  • Could you explain your requirements in more detail? Why can't you change the way the script is launched? Why don't you want a loop? When you say "loop" does that also include functions? The obvious approach would be to make your script into a function and call the function with a timeout. – terdon May 18 '17 at 13:50
  • script is launched by other software that reads configuration xml file. So it is not possible to change the way script is called. My script is quite big, contains many functions. I want to avoid having hundreds lines functions. – Rokas.ma May 18 '17 at 13:53

2 Answers2

1

You need a wrapper.

The most obvious one is to rename the original script and in its place to create a wrapper script that would call the original with a timeout. A variation on this is to create a link with a different name to the script itself, and the way the script is called would decide what happens in it. It should be clear in a moment.

If your script is called without parameters, you can add this inner wrapper to your script. It will invoke itself again with timeout and with a switch in the $1 parameter.

#!/usr/bin/env bash

TIMEOUT=10
WRAPPER=FALSE
if [ "$1" != FALSE ]; then
    timeout "$TIMEOUT" "$0" "$WRAPPER"
    exit
fi

#the proper script
echo Here\'s the original script starting.
sleep 11
echo End of the original script.   

So going back to the previous solution, you might use $0 to see how the script was called. Was it the file or the link to it?

If you don't want or can't create a new executable/link, and the original call uses parameters, other switches are available. For example, a temp file might be used. This will involve some corner cases that demand a cleanup of that file in case something goes wrong. You might also use PPID as a switch. If the parent's command is the same as child's, then it executes the script proper, otherwise it executes itself with a timeout.

0

It seems that it has already been answered elsewhere, but here's what you can do.

This is a command that returns for how many seconds this command has been running (the added s in times returns only the seconds).

ps -p "<process-id>" -o times=

You may also need

pgrep <name-of-the-script>

Or, altogether,

ps -p "$(<name-of-the-script>)" -o times=

to get the process id.

Then, you assign the outcome to a variable and check it as often as you want.

nikolas
  • 463