The software method would be “sudo shutdown -h now”. If you don’t have serial console or network access, perhaps you could add a GPIO monitor and toggle that command when a key press is detected.
What access do you have? What is the use-case you have for determining when the best time is for on/off? If you just want a timer it may be simplified.
I am unsure about how those different shutdown methods from your URL work. What it comes down to is that when a program is terminated it receives a signal. That signal tends to provide options in how abrupt the program shutdown is. So determining whether your program is allowed to finish its logs or not depends on sending the right signal.
Note that some signals can be caught (see “man -a signal” and “man -a sigaction”…as you quit the next man page section will show up…some are about signals in C, others are just about signals). This is called installing a signal handler…I’ve only installed signal handlers in C/C++, I have not tried in bash or python.
You have the choices of either catching a signal which is too abrupt and changing it to something less abrupt, or else having shutdown actually recognize that it is supposed to wait and “be nice” by sending a less authoritative signal. Some signals cannot be caught, e.g., SIGKILL, so in those cases the only choice you will have is configuring init to send a nicer signal. The trouble is that I don’t know where Ubuntu configures those signals. Typically it would send SIGTERM, and then after a delay, SIGKILL; the wait time for SIGTERM should be configurable, but I don’t know where from. SIGKILL cannot be caught, but SIGTERM could be caught and allow you to run whatever destructor/cleanup/exit code you have. You might investigate seeing if you can catch SIGTERM and successfully clean up then exit. If this doesn’t work, then the system itself will need configuration to avoid immediate SIGKILL (which is an Ubuntu admin topic…it should be the same regardless of hardware, but will differ across various Linux flavors).
In earlier Linux distributions the init scripts for startup and shutdown were entirely bash scripts. As things have become more complicated an XML configuration system (“systemd”) has replaced much of those scripts with targets which have services as dependencies…when systemd tries to read a target the target can be told to start or stop a dependency. If you run your program as part of the system, then I’d think you could turn your program into a service, then use systemd to mark when a target should stop or start your program, along with the delay to use after a SIGTERM before it sends a SIGKILL.
If it works I think a SIGTERM handler would be the easiest thing to do.