Shell Script command timeout [duplicate] - bash

This question already has answers here:
How to kill a child process after a given timeout in Bash?
(9 answers)
Closed 4 years ago.
I am trying to run a command but if the command doesnt succeed in an amount of time (Lets say 30s for example), Cancel out the command and fail out. The script is fairly simple and I am just pausing ntpd and then forcing a time synchronization and starting. However if there is an invalid ntp server this hangs.
systemctl stop ntpd
ntpd -gq
systemctl start ntpd
My thoughts would be, I try to run this in the background, check every 10 seconds to see if the command is still attempting to be run. And say after 3 checks if i see "ntpd -gq" I kill the process and return a failure. Is this the correct way to do this or is there any built in time handling?

The shell doesn't have this kind of time handling.
Running the process in the background and checking it periodically as you suggested is the best way to handle this.

Related

Bash - kill a command after a certain time [duplicate]

This question already has answers here:
Timeout a command in bash without unnecessary delay
(24 answers)
Closed 1 year ago.
In my bash script I run a command that activates a script. I repeat this command many times in a for loop and as such want to wait until the script is finished before running it again. My bash script is as follows
for k in $(seq 1 5)
do
sed_param='s/mu = .*/mu = '${mu}';/'
sed -i "$sed_param" brusselator.c
make brusselator.tst &
done
As far as I know the & at the end lets the script know to wait until the command is finished, but this isn't working. Is there some other way?
Furthermore, sometimes the command can take very very long, in this case I would maximally want to wait 5 seconds. But if the command is done earlier I would't want to wait 5 seconds. Is there some way to achieve this?
There is the timeout command. You would use it like
timeout -k 5 make brusselator.tst
Maybe you would like to see also if it exited successfully, failed or was killed because it timed out.
timeout -k 5 make brusselator.tst && echo OK || echo Failed, status $?
If the command times out, and --preserve-status is not set, then command exits with status 124. Different status would mean that make failed for different reason before timing out.

ntpd -qg: Use with timeout

working on Pi3
Situation: only one server in /etc/ntp.conf is given and this given address is invalid (no NTP-Server running on that address).
Problem: running ntpd -qg does never end, since there is no timeout like in ntpdate -t 60.
Question: Can one specify a timeout for ntpd? If not, how can you assure the process ends after time x?
For now on startup the pi executes a bash-script that tries to get actual time from given NTP-Server in /etc/ntp.conf and then hangs in the process since there is no NTP-Server available on that address. So the process is running from start and i can't call another ntpd until the initial ntpd-process is killed.
Any work around?
PS: I would like not to use ntpdate since it is tagged as a retiring package
EDIT:
The RPi3 is located in an isolated network. Online NTP-servers are no option in my case.
There is a timeout command usually shipped with coreutils that allows you to set timeout on any command (even if it does not support it on its own). E.g.
timeout 60 ntpd -qg
To run run ntpd -qg and have it time out after 60s. If the command finished, you should get its return value, if the timeout intervened, you get 124.

How do we avoid Cron jobs interruption?

I am new at using Cron Jobs on Google Cloud: I was wondering if it is possible to launch a job on an instance and have it run continuously without interruption even after I shut down my local (Laptop). Is it possible to have a job running without any ssh connection?
The CronJobs are a possibility, but they are not meant to be used in your scenario, but when you want to run a command with a certain frequency over the time.
A Bash Builtin command that suits better your needs is disown. First, run your process/script in the background (using &, or stopping it with ^Z and then restarting with bg):
$ long_operation_command &
[1] 1156
Note that at this point the process is still linked to the session and in case it is closed it will be killed.
You can the process attached to the session check running jobs in the background:
$ jobs
[1]+ Running long_operation_command
Therefore you can run disown in order to detach the processes from the session:
$ disown
You can confirm this checking the result of your script or command logging in again or checking with top the process still running.
Check also this because it could be interesting, i.e. the difference between nohup foo, foo & and $ foo & disown
P.S.
The direct answer to your question is yes, the cronjobs run even if you shutdown your laptop/shutdown the session.

Need to write a script that runs two scripts, but needs to stop the first one before the 2nd runs [duplicate]

This question already has answers here:
Timeout a command in bash without unnecessary delay
(24 answers)
Closed 6 years ago.
This is a CentOS 6.x box, on it I have two things that I need to run one right after the other - a shell script and a .sql script.
I want to write a shell script that calls the first script, lets it run and then terminates it after a certain number of hours, and then calls the .sql script (they can't run simultaneously).
I'm unsure how to do the middle part, that is terminating the first script after a certain time limit, any suggestions?
script.sh &
sleep 4h && kill $!
script.sql
This will wait 4 hours then kill the first script and run the second. It always waits 4 hours, even if the script exits early.
If you want to move on immediately, that's a little trickier.
script.sh &
pid=$!
sleep 4h && kill "$pid" 2> /dev/null &
wait "$pid"

Is there a way to create a bash script that will only run for X hours?

Is there a way to create a bash script that will only run for X hours? I'm currently setting up a cron job to initiate a script every night. This script essentially runs until a certain condition is met, exporting it's status to a holding variable to keep track of 'where it is' after each iteration. The intention is to start-up the process every night, run for a few hours, and then stop, holding the status until the process starts up the next night.
Short of somehow collecting the start time, and checking it against the current time in each iteration of the loop, is there an easier way to do this? Bash scripting is not my forte (I know enough to get things done and be dangerous) and I have not done something like this before. Any help would be appreciated. Thanks.
Use GNU Coreutils
GNU coreutils contains an actual timeout binary, usually invoked like this:
# timeout after 5 seconds when sleeping for 30
/usr/bin/timeout 5s /bin/sleep 30
In your case, you'd want to specify hours instead of seconds, so to timeout in 2 hours use something like 2h instead of 5s. See timeout(1) or info coreutils 'timeout invocation' for additional options.
Hacks and Workarounds
Native timeouts or the GNU timeout command are really the best options. However, see the following for some ideas if you decide to roll your own:
How do I run a command, and have it abort (timeout) after N seconds?
The TMOUT variable using read and process or command substitution.
Do it as you described - it is the cleanest way.
But if for some strange reason want kill the process after a time, can use the next
./long_runner &
(sleep 5; kill $!; wait; exit 0) &
will kill the long_runner after 5 secs.
By using the SIGALRM facility you can rig a signal to be sent after a certain time, but traditionally, this was not easily accessible from shell scripts (people would write small custom C or Perl programs for this). These days, GNU coreutils ships with a timeout command which does this by wrapping your command:
timeout 4h yourprogram

Resources