So, i've tried dinit on real aarch64 board. Since it has no rtc, i have to sync time via ntp but this brings up two porblems:
1) ntpd must be started after system has internet connection
2) ntpdate must be run before ntpd
In order solve 1) i created service named dhcpc with following contents (maybe different will fir better):
type = internal
waits-for.d = dhcpc.d
Since i use dhclient on this board, i linked that service to dhcpc.d. Now any service which requires network connection can depend on dhcpc
For 2) i created scripted service ntpd-pre as follows:
type = scripted
command = /etc/dinit.d/scripts/ntpd-pre
restart = false
waits-for = setup
depends-on = dhcpc
I put here restart=false since, as i understand (which may be wrong) the script will be also restarted after successful termination. The script for it is:
#!/bin/sh
[ -r /etc/dinit.d/config/ntpd.conf ] && . /etc/dinit.d/config/ntpd.conf
# exit immediately if there are no configured ntpdate servers
[ -z ${NTPDATE_SERVERS} ] && exit 0
while [ /bin/true ]; do
[ ! -z ${NTPDATE_SERVERS} ] && ntpdate ${NTPDATE_SERVERS} && exit 0
sleep 1s
done
So, it should only exit if ntpdate is not needed or it has synced time. I made ntpd-pre a hard dependency for ntpd.
Although this approach works, it looks like boot process is stuck until this script exits. Could there be a better solution?
Thanks
I am facing time problem on Desktop machine.
This is a tricky one to solve in a better way without needing user intervention, I think, due to the many connections manager Artix has (e.g. NetworkManager, plain dhcpcd, and so on).
We already have a network service (https://gitea.artixlinux.org/artix/dinit-rc/src/commit/eb20e93e299a696baa603d4cf308cc7c81beedef/services/network) and network script (https://gitea.artixlinux.org/artix/dinit-rc/src/commit/eb20e93e299a696baa603d4cf308cc7c81beedef/scripts/network) which detects if we already have routes to certain network. But the tricky part here is how do we make them depend on networking-related services (e.g. dhcpcd, NM, connman) without them conflicting?
For example, suppose I create network.d directory (or in your case, dhcpc.d), suppose every single service which relates to connections are installed in that directory, if a service (like ntpd) waits for network.d, the installed services will conflict.
How did i miss them?
But it seems that this script just checks if network exists at some point and exits, probably doing nothing but preventing network-dependent services to start. Or do i understand dinit restrating rules wrong?
Why would they conflict?
Currently yes, they just preventing network-dependent services to start (because dinit has a default limit for restarts and I've yet to test the limit). I just don't know how to handle dependencies because of the current problem.
Just imagine
connman,
NetworkManager,
dhclient,
dhcpcd, and
wicd all running together. Won't they conflict?
(EDIT: Perhaps I can make the dinit service (not the main package) conflict so it's impossible to have all possible
network.d services running at the same time unless user forces it, but man I don't really know how to approach this one because there are some moving parts here (incl. dhcpcd, wpa_supplicant, etc)).
They can be configured to control different interfaces and won't conflict then
I think there is a need in some generic way to determine if we have at least tried to connect to network. I guess internal service depending on directory is more convenient choise than symlinking chosen dhcp client do e.g. /etc/dinit.d/network. If someone doesn't need network connection, the directory can be left empty
Not sure it will solve any problem, but that's what I have done in a VM with artix/dinit :
I have created a pseudo service network-ready :
type = internal
restart = false
waits-for.d = network-ready.d
Then the mentionned directory, in which I have symlinked my network manager (connmand) :
ls -l network-ready.d
connmand -> ../connmand
And finally modified the
ntpd service to wait for network-ready :
waits-for = setup
waits-for = network-ready
I suppose that it should also work with different network topologies (to access different networks from different services) by adding the symlinks to this new dependencies directory.
I have the same issue as phoenix_king_rus and others regarding no rtc. In runit I worked out to create some additional steps in the startup code about setting up so I had this script in /lib/rc/sv.d/timestamp
#!/bin/bash
#check for an RTC
if [ -c /dev/rtc ]; then
echo "+++++ not executing $(basename) because /dev/rtc found"
exit 0
fi
# sourcing our current rc.conf requires this to be a bash script
. /usr/lib/rc/functions
TSD=/var/lib/ntp
[ ! -d "$TSD" ] && mkdir -p "$TSD"
TSF="$TSD/timestamp"
case "$1" in
start)
if [ -f "$TSF" ]; then
if TS="$(/usr/bin/date -u $(/usr/bin/cat ${TSF}))"; then
echo "+++++ timestamp read from ${TSF} as ${TS}"
else
echo "!!!!! failed to read timestamp from ${TSF}"
fi
fi
;;
stop)
if TS="$(date -u +%m%d%H%M%Y.%S)" &&echo "${TS}" > ${TSF}; then
echo "+++++ timestamp ${TS} written to ${TSF}"
else
echo "!!!!! failed to write timestamp ${TS} to ${TSF}"
fi
;;
*)
echo "usage: $0 {start|stop}"
exit 1
;;
esac
this was then linked by /etc/rc/sysinit/09-timestamp and /etc/rc/shutdown/59-timestamp
The effect is to write a timestamp file on shutdown and read on sysinit. The software clock can then be set from that prior to starting ntp. The effect is to mostly avoid the 1970 date issue for systems without an RTC. Before setting this up all my daemons were started @ 1970/01/01.
I wonder if there's a route to doing this sort of hack to dinit..
As an aside I suppose that the network issue needs one or more fake services to act as in between nodes in the startup graph.
You can use the exact same script for dinit (although you may want to remove the old runit-rc references). You can put it into
/etc/dinit.d/scripts/timestamp, and create a new dinit service
/etc/dinit.d/timestamp (type = scripted, command =
/etc/dinit.d/scripts/timestamp start, stop-command =
/etc/dinit.d/scripts/timestamp stop and so on) and make it start at boot.
thanks I'll give it a whirl
Thanks konimex that seems to work; however, I find that it's harder to work out where to put the timestamp service and another issue is the hwclock service.
I think I need to start the timestamp when the files become available ie after root-rw; can I disable hwclock when root-rw depends on it?
A whole bunch of things seem to start when root-rw becomes available; ideally we should set the time as early as possible. Is there a way to make this the first so other services will receive a recent time rather than 1970.
Ideally the stop should be the last thing done before shutting off the file write capability. It seems much harder to control the sequencing for dinit. Runit has a simpler (hence slower) pure linear startup/shutdown controlled by the filenames of the scripts.
Is there a way to create a fake service that comes after root-rw, but delays the reporting of root-rw as available? Obviously I can do a lot of hacks to create such a service, but that is not ideal. Probably I have missed something obvious in the docs.
Since I don't have any RTC-less device for me to test on (not that Artix is officially supporting ARM anyway, but at the very least I want to make it easier when we do support ARM later on), what happens when hwclock is started on these devices? Fails? Since the dependency is
waits-for (i.e. soft) rather than a hard one,
root-rw should start regardless of
hwclock failing or succeeding, I'm just making sure that hwclock is set before root is mounted rw. Theoretically, you can make your timestamp service start wait for hwclock (or root-rw), but as you mentioned the services need to know the more recent time rather than 1970-01-01, which brings us to the second point I'm making:
The bunch of services should start after
setup, but this weekend I'm planning to move them to be started after
loginready rather than
setup (because I found the way to make the services stop spewing garbage, and so they will start at the same time as the TTY instead of before) and so they are running later rather than sooner.
Looks like so (dinitctl list from Odroid N2):
[ {X}] hwclock
Again it's not exactly clear what the start order is here, but presumably I can wait directly for root-rw and hope it gets done before loginready. Does a 'waits-for = hwclock' become a no-op when hwclock is disabled? When I try to disable hwclock it comes back at boot.
As an exercise I managed to create a slim-dinit
type = process
command = /usr/bin/slim -nodaemon
restart = true
depends-on = logind
smooth-recovery = true
it would not start. I used strace and the problem is that there's no /run/lock folder. Slim uses /var/lock/slim.lock, but /var/lock is a link to ../run/lock and there's no /var/run/lock folder. If I just create the folder then slim will start. I suppose there's somewhere else to create these temporary folder/files, but as /var/lock is part of filesystem it ought at least to point somewhere.
Unfortunately,
hwclock can't exactly be disabled (since
hwclock and
misc has a *soft* dependency on it), but
hwclock will fail to start (as RTC doesn't exist), and
root-rw will start regardless.
Perhaps this should be handled by tmpfiles, but you can create a wrapper script in this case.
/etc/dinit.d/scripts/slim (0755)
-------------------------
#!/bin/sh
mkdir -p /run/lock
exec /usr/bin/slim -nodaemon
and have
command = /etc/dinit.d/scripts/slim in the actual dinit service script.
I added this in /etc/tmpfiles.d/ run-lock.conf
D /run/lock 0755 root root - -
and it seems to work.