ntpd -qg: Use with timeout - bash

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.

Related

Shell Script command timeout [duplicate]

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.

Elasticsearch Docker stop seems to ignore SIGKILL

I'm trying to use Elasticsearch in Docker for local dev. While I can find containers that work, when docker stop is sent, the containers hang for the default 10s, then docker forcibly kills the container. My assumption here is that ES is either not on PID 1 or other services prevent it from shutting down immediately.
I'm curious if anyone can expand on this, or explain why this is happening more accurately. I'm running numerous tests and 10s+ to shutdown is just annoying when other containers shutdown after 1-2s.
If you don't want to wait the 10 seconds, you can run a docker kill instead of a docker stop. You can also adjust the timeout on docker stop with the -t option, e.g. docker stop -t 2 $container_id to only wait 2 seconds instead of the default 10.
As for why it's ignoring the sigkill, that may depend on what image you are running (there's more than one for elasticsearch). However, if pid 1 is a shell like /bin/sh or /bin/bash, it will not pass signals through. If pid 1 is the elasticsearch process, it may ignore the signal, or 10 seconds may not be long enough for it to fully cleanup and shutdown.

Bash - create multiple virtual guests in one loop

I'm working on a bash script (I just started learning bash) that involves creating virtual guests on a remote server. I do this by SSH'ing from server A to B and execute 2 different commands:
# create the images
$(ssh -n john#serverB.net "fallocate -l ${imgsize} /home/john/images/${imgname}")
and
# create the virtual machine
$(ssh -n john#serverB.net virt-install --bunch of options)
It is possible that these sets of commands have to be executed twice (if there need to be 2 virtual guests created) in a loop. When the second command is being run for the second time I sometimes get this error:
Domain installation still in progress.
This means I have to wait until the previous virtual guest is completed. How would I be able to do these operations in one loop? Can I run them asynchronously? Can I use threads? Or is there another way?
I have heard about the 'wait' command, but is that safe to use?
Check the man page for virt-install. You can use --wait=0 or --noautoconsole.
--wait=WAIT Amount of time to wait (in minutes) for a VM to complete its install. Without this option, virt-install will wait for the
console to close (not necessarily indicating the guest has shutdown),
or in the case of --noautoconsole, simply kick off the install and
exit. Any negative value will make virt-install wait indefinitely, a
value of 0 triggers the same results as noautoconsole. If the time
limit is exceeded, virt-install simply exits, leaving the virtual
machine in its current state.

What is the best way to run ntpdate at reboot, only after network is ready

I'm using a BeagleBone, and since it has no built in RTC and battery back up, it loses the date on every reboot. I can easily set the date with the command:
/usr/bin/ntpdate -b -s -u pool.ntp.org
But if the power goes out and back on for the house for example, then the time is lost. The solution that comes with the latest beaglebone Angstrom linux distribution is to put a crontab line in that updates the time every half hour. But I would prefer to just run the command once on powerup.
I tried putting this command listed above in crontab with the #reboot line, but that I believe ran before network was configured, or something else failed since it didn't get me the right time when I pulled the power for 5 minutes and put it back to the beaglebone.
Is there some way to use ifconfig or something like that to run a script from init.d only after network is available?
opkg install ntp-systemd
systemctl enable ntpdate.service
systemctl enable ntpd.service
Edit /etc/ntp.conf and comment the following lines (no fallback on an hardware clock that doesn't exist and because the ntpdate service use the "ntpd -q" command)
#server 127.127.1.0
#fudge 127.127.1.0 stratum 14
Two services are installed:
/lib/systemd/system/ntpd.service:
[Unit]
Description=Network Time Service
After=network.target
[Service]
Type=forking
PIDFile=/run/ntpd.pid
ExecStart=/usr/bin/ntpd -p /run/ntpd.pid
/lib/systemd/system/ntpdate.service:
[Unit]
Description=Network Time Service (one-shot ntpdate mode)
Before=ntpd.service
[Service]
Type=oneshot
ExecStart=/usr/bin/ntpd -q -g -x
RemainAfterExit=yes
ntpd is started after the network is up (After=network.target) so the date should be continuously synchronized. BUT has explained in the ntpd man page:
Most operating systems and hardware of today incorporate a
time-of-year (TOY) chip to maintain the time during periods when the
power is off. When the machine is booted, the chip is used to
initialize the operating system time. After the machine has
synchronized to a NTP server, the operating system corrects the chip
from time to time. In case there is no TOY chip or for some reason its
time is more than 1000s from the server time, ntpd assumes something
must be terribly wrong and the only reliable action is for the
operator to intervene and set the clock by hand. This causes ntpd to
exit with a panic message to the system log. The -g option overrides
this check and the clock will be set to the server time regardless of
the chip time. However, and to protect against broken hardware, such
as when the CMOS battery fails or the clock counter becomes defective,
once the clock has been set, an error greater than 1000s will cause
ntpd to exit anyway.
So we need to set the date before starting ntpd and this is done by the ntpdate service by executing "ntpd -q -g -x" before starting ntpd.service.
From ntpd man page:
-q Exit the ntpd just after the first time the clock is set. This behavior mimics that of the ntpdate program, which is to be retired.
The -g and -x options can be used with this option. Note: The kernel
time discipline is disabled with this option.
Another service installed on the Beaglebone interact with the date/time
timestamp.service
[Unit]
Description=Timestamping service
ConditionPathExists=/etc/timestamp
After=remount-rootfs.service
[Service]
RemainAfterExit=yes
ExecStart=/usr/bin/load-timestamp.sh
ExecStop=/usr/bin/load-timestamp.sh --save
This service store the current timestamp in /etc/timestamp when it's stopped and set the date from that timestamp when it's started. So if ntpd isn't installed, the date set manually and the beaglebone rebooted, the date is only behind by the boot duration.
Do you have the /etc/network/if-post-up.d/ directory on your target system? If so, scripts in that directory should be run when the network comes up. If not, are you using DHCP? Your DHCP client may support running scripts.

Can a standalone ruby script (windows and mac) reload and restart itself?

I have a master-workers architecture where the number of workers is growing on a weekly basis. I can no longer be expected to ssh or remote console into each machine to kill the worker, do a source control sync, and restart. I would like to be able to have the master place a message out on the network that tells each machine to sync and restart.
That's where I hit a roadblock. If I were using any sane platform, I could just do:
exec('ruby', __FILE__)
...and be done. However, I did the following test:
p Process.pid
sleep 1
exec('ruby', __FILE__)
...and on Windows, I get one ruby instance for each call to exec. None of them die until I hit ^C on the window in question. On every platform I tried this on, it is executing the new version of the file each time, which I have verified this by making simple edits to the test script while the test marched along.
The reason I'm printing the pid is to double-check the behavior I'm seeing. On windows, I am getting a different pid with each execution - which I would expect, considering that I am seeing a new process in the task manager for each run. The mac is behaving correctly: the pid is the same for every system call and I have verified with dtrace that each run is trigging a call to the execve syscall.
So, in short, is there a way to get a windows ruby script to restart its execution so it will be running any code - including itself - that has changed during its execution? Please note that this is not a rails application, though it does use activerecord.
After trying a number of solutions (including the one submitted by Byron Whitlock, which ultimately put me onto the path to a satisfactory end) I settled upon:
IO.popen("start cmd /C ruby.exe #{$0} #{ARGV.join(' ')}")
sleep 5
I found that if I didn't sleep at all after the popen, and just exited, the spawn would frequently (>50% of the time) fail. This is not cross-platform obviously, so in order to have the same behavior on the mac:
IO.popen("xterm -e \"ruby blah blah blah\"&")
The classic way to restart a program is to write another one that does it for you. so you spawn a process to restart.exe <args>, then die or exit; restart.exe waits until the calling script is no longer running, then starts the script again.

Resources