It depends on whether there should be 2 hours since the start of the last start of the subroutine START or from the end of the last execution.
1) If the last (2 hours between the end of the last subroutine and the start of a new one), the cespinoza solution is quite acceptable (the cycle is endless and call sleep(7200); after the subroutine is executed).
my $timeout = 7200; while (1) { dostuff(); sleep($timeout); };
The only problem is that it cannot handle the case where dostuff() is executed forever, for example. stuck - to discuss why this is an important situation to consider and approaches to a solution, see below.
2) If the first (2 hours between the starting points), you have three options related to processing the execution time of the subroutine, which exceeds 2 hours [0] . Your 3 options, described in detail below, are intended for either:
2a) launches a new routine, while the old one continues to work (in parallel);
2b) to start a new routine AFTER the completion of the old;
2c) to start a new routine, but first stop the previous one.
2a, 2c options require you to set alarm() for 2 hours and differ in what happens when an alarm is triggered.
[0] NOTE. Since any routine is likely to require at least SOME resources from a PC, there is always at least a small chance that it will exceed 2 hours, so you need to choose one of these three options for processing such a scenario.
2a) Turn off every 2 hours, working in parallel with the old version, if not finished.
This parameter essentially implements the cron functionality.
At any time when you hear the word โparallel,โ you are likely to abandon the process.
my $timeout = 7200; while (1) {
2b) Go every 2 hours, if the old one is not finished, let him run until he finishes
This can be reformulated as a "starting task", if it ends faster than 2 hours, sleep for the rest "
my $timeout = 7200; while (1) { my $start = time; dostuff(); my $end = time; my $lasted = $end - $start; if ($lasted < $timeout) { sleep($timeout - $lasted); } };
2c) Go every two hours, if the previous one is not finished, time and kill him
Whenever you see such logic, anxiety is obviously the answer.
while (1) { my $finished = 0; eval { local $SIG{ALRM} = sub { die "alarm\n" }; alarm 7200; dostuff(); $finished = 1; sleep;
PS As cespinoza noted, you need to somehow demonize the script (make sure that it will not be killed when you exit the shell that started it), either using Unix (for example, starting it as nohup), or Perlish means (search daemonize + Perl on Stackoverflow for the mechanics of this).