Score:-1

Reliably prevent apt-get from asking for confirmation when run from cron

cn flag

On my Ubuntu 20.04LTS servers I have a cron job for deleting old kernel versions to prevent their /boot partitions from running out of space. It works by querying with dpkg-query for the list of installed linux-image packages and then feeding all but the last three of those to apt-get purge -y. This works well most of the time.

Every once in a while, for various reasons, this process will select the currently running kernel for removal. This shouldn't be a problem, since according to its manpage, apt-get with the -y option should just abort in that case. In reality however this causes the cron job to hang indefinitely. The standard output from the job, which is captured in a file, shows:

Removing linux-image-5.4.0-100-generic (5.4.0-100.113) ...
debconf: unable to initialize frontend: Dialog
debconf: (TERM is not set, so the dialog frontend is not usable.)
debconf: falling back to frontend: Readline
Removing linux-image-5.4.0-100-generic
--------------------------------------

You are running a kernel (version 5.4.0-100-generic) and attempting to remove
the same version.

This can make the system unbootable as it will remove
/boot/vmlinuz-5.4.0-100-generic and all modules under the directory
/lib/modules/5.4.0-100-generic. This can only be fixed with a copy of the kernel
image and the corresponding modules.

It is highly recommended to abort the kernel removal unless you are prepared to
fix the system after removal.

Abort kernel removal? [yes/no]

The process tree (snipped from ps -axf) looks like this:

    828 ?        Ss     0:00 /usr/sbin/cron -f
  92591 ?        S      0:00  \_ /usr/sbin/CRON -f
  92592 ?        Ss     0:00      \_ /bin/sh -c /usr/local/sbin/remove_old_kernels.sh >> /var/log/remove_old_kernels.log 2>&1
  92593 ?        S      0:00          \_ /bin/bash /usr/local/sbin/remove_old_kernels.sh
  92598 ?        S      0:14              \_ apt-get purge -y linux-image-5.4.0-100-generic
  92785 pts/0    Ss+    0:00                  \_ /usr/bin/dpkg --status-fd 26 --no-triggers --force-depends --abort-after=1 --remove linux-generic:amd64 linux-image-generic:amd64 linux-modules-extra-5.4.0-100-generic:amd64 linux-image-5.4.0-100-generic:amd64
  92798 pts/0    S+     0:00                      \_ /bin/sh /var/lib/dpkg/info/linux-image-5.4.0-100-generic.prerm remove
  92799 pts/0    S+     0:00                          \_ /usr/bin/perl -w /usr/share/debconf/frontend /usr/bin/linux-check-removal 5.4.0-100-generic
  92809 pts/0    S+     0:00                              \_ /usr/bin/perl /usr/bin/linux-check-removal 5.4.0-100-generic

So apt-get emitted a request for confirmation in spite of the -y option. Worse, it even noticed it didn't have a means for actually reaching anyone for an answer, but instead of wisely giving up it created a pseudoterminal out of thin air and now senselessly waits for an answer to appear there.

How can I avoid that behaviour and reliably prevent apt-get from asking any questions when run without a terminal?

Artur Meinild avatar
vn flag
It seems you're choosing an unnecessary solution for this ([XY problem](https://xyproblem.info/)). Ubuntu 20.04 by default will remove old kernels, leaving only the current and the former. So I think you should find out why the default functionality is not working, and restore this.
nobody avatar
gh flag
Is `sudo apt autoremove --purge` not working?
N0rbert avatar
zw flag
Put `purge-old-kernels` from `byobu` package to cron job instead of writing dangerous things which may make system unbootable.
user535733 avatar
cn flag
Seems like your cronjob's logic is the problem. Your job is asking apt to break your system, and apt is quite correctly recognizing the catastrophic implications and so demanding confirmation from a human . That's not a bug to be worked around...it's a well-implemented safety feature of apt. You can avoid the hang by simply not asking apt to break your system.
Tilman avatar
cn flag
I tried for months, in vain to get either the purported standard behaviour, or `apt autoremove`, or `purge-old-kernels` to work, before resorting to build my own. But I will gladly accept an answer providing any solution that works. That said, my job does *not* ask apt-get to break my systems, just to behave as documented on its man page.
nobody avatar
gh flag
Have you a desktop-enviroment installed?
user535733 avatar
cn flag
It-does-not-behave-as-documented seems a clear bug: Please file a bug report, and thanks for discovering and reporting the bug. Beyond that, until the bug is resolved, your job should not depend upon the buggy behavior. I suggest testing first to avoid trying to remove the currently-running kernel.
Tilman avatar
cn flag
@nobody: No desktop environment.
PonJar avatar
in flag
Why not introduce a test to end the job if the selected kernel is the running kernel?
Tilman avatar
cn flag
That would work around that specific scenario. But how can I be sure that this is the only scenario where `apt-get` can block waiting for interactive input when run non-interactively?
PonJar avatar
in flag
It probably isn’t the only scenario where an interactive input is required. However if it hasn’t occurred yet it’s likely to be infrequent. Any process can encounter something that was not anticipated. You just need to ensure you know when it occurs and have a rethink. You shouldn’t need this script at all. A better question is how do you prevent this problem in the first place.
Tilman avatar
cn flag
Yes, and if the (still outstanding) answer to my original question is "you can't" (as I begin to suspect) then that means "do not use `apt` in cronjobs".
PonJar avatar
in flag
If you set up unattended upgrades you can specify the removal of unused kernels
Tilman avatar
cn flag
I won't. Upgrades need to be approved through a staged release process here.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.