It is possible to wait for this condition without polling this command on a loop, but unfortunately it's not that straightforward...
systemd will post a StartupFinished signal on D-Bus once the boot is complete, so it is possible to watch for that and get a notification for it.
Here is a simple
dbus-wait tool that can watch for signals on D-Bus.
I managed to wait until startup was completed by using this command:
dbus-wait org.freedesktop.systemd1.Manager StartupFinished
The problem with this approach is that there's a race condition there. If first I check whether the system is running (with
systemctl is-system-running) and see that it's still "starting" and then decide to wait for the signal, it's possible that by the time
dbus-wait will connect to the bus and start waiting for the signal, that systemd just finished startup and already posted this signal in the bus, which will make
dbus-wait wait for an event that won't happen and eventually time out...
On the other hand, it should be possible to implement this in a way that is free from race conditions, by first registering the watch for the event, then checking the property and if it's still not set to "running" then run the event loop to wait for the signal.
I implemented the approach above and proposed it to upstream systemd. My suggestion is to allow running
systemctl is-system-running --wait for this purpose (but it is possible this might end up making it to systemd with a different syntax, possibly a separate command.) The proposal for the new systemd feature can be found at PR #9796 on systemd project. (I'll update this answer once it's accepted and merged.)
UPDATE: PR #9796 was just merged into systemd, so starting with systemd v240, it will be possible to wait until boot is completed with the following command:
systemctl is-system-running --wait