Here is a recap of my work and current status : #1) when a system has a separated /var, the unit will hang since it is looking for /var/run to be present and it has been unmounted.
#2) when using Unattended-Upgrade::InstallOnShutdown "true"; the upgrade never completes as the query to the online archive fails since the network is no longer available. #3) it is impossible to enable the unattended-upgrades.service unit. Here is an example : > $ systemctl status unattended-upgrades.service > ● unattended-upgrades.service - Unattended Upgrades Shutdown > Loaded: loaded (/lib/systemd/system/unattended-upgrades.service; enabled; > vendor preset: enabled) > Active: inactive (dead) > Docs: man:unattended-upgrade(8) According to the doc[2], during shutdown, even if Before= or After= is used, the unit being started will only start after the Shutdown of its dependencies. Prior to the recent addition of local-fs.target network.target, the unit ran quickly enough for the /var to be still mounted. But even without these dependencies, InstallOnShutdown would fail with the following : > 2017-03-10 13:40:42,803 INFO Starting unattended upgrades script > 2017-03-10 13:40:42,803 INFO Allowed origins are: ['o=Ubuntu,a=zesty', > 'o=Ubuntu,a=zesty-security'] > 2017-03-10 13:41:40,554 ERROR An error occurred: 'Cannot initiate the > connection to 192.168.200.3:8000 (192.168.200.3). - connect (101: Network is > unreachable)' > 2017-03-10 13:41:40,555 ERROR The URI > 'http://fr.archive.ubuntu.com/ubuntu/pool/main/i/init-system-helpers/init-system-helpers_1.47_all.deb' > failed to download, aborting When trying to switch the unit to an ExecStop=, we find that the Stop never runs. This is caused by the fact that the unit is disabled (#3). Trying to enable the unit leads to : > # systemctl enable unattended-upgrades > Synchronizing state of unattended-upgrades.service with SysV service script > with /lib/systemd/systemd-sysv-install. > Executing: /lib/systemd/systemd-sysv-install enable unattended-upgrades > update-rc.d: error: unattended-upgrades Default-Start contains no runlevels, > aborting. Adding runlevels 2 3 4 5 fixes this then the unit can be enabled. So we get to a unit that looks like this : > [Unit] > Description=Unattended Upgrades Shutdown > DefaultDependencies=no > After=network.target local-fs.target > RequiresMountsFor=/var/run /var/log > Documentation=man:unattended-upgrade(8) > > [Service] > Type=oneshot > RemainAfterExit=yes > ExecStop=/usr/share/unattended-upgrades/unattended-upgrade-shutdown > TimeoutStopSec=900 > > [Install] > WantedBy=multi-user.target Before= is replaced by After= as, during shutdown otherwise the unit does not run. RequiresMountsFor= is added as both /var/log and /var/run are needed in order to run correctly. RemainAfterExit=yes is added so the unit appears as started. There is no longer a requirement to have an ExecStart present. WantedBy is switched to multi-user.target as on the way up, we do nothing and we are no longer depending on anything related to shutdown. Now this only works IF /var is a separate FS. The reason for that is the presence of DefaultDependencies=no. I don't think that it is required but was there in the initial unit. Removing it in the final unit fixes the only remaining issue. The unit is now : > [Unit] > Description=Unattended Upgrades Shutdown > After=network.target local-fs.target > RequiresMountsFor=/var/run /var/log > Documentation=man:unattended-upgrade(8) > > [Service] > Type=oneshot > RemainAfterExit=yes > ExecStop=/usr/share/unattended-upgrades/unattended-upgrade-shutdown > TimeoutStopSec=900 > > [Install] > WantedBy=multi-user.target This works correctly and has been tested on : - Xenial with and without /var as a separate FS - Zesty with and without /var as a separate FS InstallOnShutdown now also works as advertized. I am now getting confirmation on that change since it is a rather sensible modification. -- You received this bug notification because you are a member of Ubuntu Touch seeded packages, which is subscribed to unattended-upgrades in Ubuntu. https://bugs.launchpad.net/bugs/1654600 Title: unattended-upgrade-shutdown hangs when /var is a separate filesystem Status in unattended-upgrades package in Ubuntu: In Progress Status in unattended-upgrades source package in Xenial: Triaged Status in unattended-upgrades source package in Yakkety: Triaged Status in unattended-upgrades package in Debian: New Bug description: [SRU justification] This fix is needed to make sure that the system does not hang on shutdown when /var is a speparate file system [Impact] System can hang up to 10 minutes if not fixed. [Fix] Change the systemd unit's ExecStart to an ExecStop so the unit is correctly sequenced. [Test Case] In a VM with /var separated from the / file system, shutdown the VM. It will hang for 10 minutes [Regression] None to be expected. A ExecStop unit will be sequenced before the Before= units which is earlier than previously. [Original description of the problem] The systemd unit file unattended-upgrades.service is used to stop a running unattended-upgrade process during shutdown. This unit file is running together with all filesystem unmount services. The unattended-upgrades service checks if the lockfile for unattended-upgrade (in /var/run) exists, and if it does, there is an unattended-upgrade in progress and the service will wait until it finishes (and therefore automatically wait at shutdown). However, if /var is a separate filesystem, it will get unmounted even though /var/run is a tmpfs that's still mounted on top of the /var/run directory in the /var filesystem. The unattended-upgrade script will fail to find lockfile, sleeps for 5 seconds, and tries to check the lockfile again. After 10 minutes (the default timeout), it will finally exit and the system will continue shutdown. The problem is the error handling in /usr/share/unattended-upgrades/unattended-upgrade-shutdown where it tries to lock itself: while True: res = apt_pkg.get_lock(options.lock_file) logging.debug("get_lock returned %i" % res) # exit here if there is no lock if res > 0: logging.debug("lock not taken") break lock_was_taken = True The function apt_pkg.get_lock() either returns a file descriptor, or -1 on an error. File descriptors are just C file descriptors, so they are always positive integers. The code should check the result to be negative, not positive. I have attached a patch to reverse the logic. Additional information: 1) Description: Ubuntu 16.04.1 LTS Release: 16.04 2) unattended-upgrades: Installed: 0.90ubuntu0.3 Candidate: 0.90ubuntu0.3 Version table: *** 0.90ubuntu0.3 500 500 http://nl.archive.ubuntu.com/ubuntu xenial-updates/main amd64 Packages 500 http://nl.archive.ubuntu.com/ubuntu xenial-updates/main i386 Packages 100 /var/lib/dpkg/status 0.90 500 500 http://nl.archive.ubuntu.com/ubuntu xenial/main amd64 Packages 500 http://nl.archive.ubuntu.com/ubuntu xenial/main i386 Packages 3) Fast reboot 4) Very slow reboot (after a 10 minutes timeout) To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/unattended-upgrades/+bug/1654600/+subscriptions -- Mailing list: https://launchpad.net/~touch-packages Post to : touch-packages@lists.launchpad.net Unsubscribe : https://launchpad.net/~touch-packages More help : https://help.launchpad.net/ListHelp