On Sun, Jun 15, 2025 at 7:45 AM Nicholas Geovanis
<nickgeovanis@gmail.com> wrote:
On Sat, Jun 14, 2025, 9:15 PM Boyan Penkov <boyan.penkov@gmail.com> wrote:
Hello folks,
I'm wiring to ask how to get apt to run a script after a particular
package is installed or updated. Am I looking for dpkg-triggers or
some apt conf?
Specifically, I have GRUB installed to *every* drive, with the
expectation that all but one drives can fail and the machine will
still boot (to something...). To this end, after I see apt has
updated grub, I manually run something like:
```
sudo update-grub
sudo grub-install /dev/sda
sudo grub-install /dev/sdb
sudo update-grub
```
I'd like to automate this; if grub is changed, run this script automatically.
You could easily do this with ansible. In perhaps 30 lines of YAML you could install those fixes, and do the grub work in the same ansible source file. Repeatable the next time you have fixes to install, just run that playbook again with 1 command.
First of all, 30 lines to automate 2-4 lines is absurd. You have a
hammer, don't recommend it to people who need a screwdriver!
On Sun, Jun 15, 2025 at 09:31:45AM +0200, Anders Andersson wrote:
On Sun, Jun 15, 2025 at 7:45 AM Nicholas Geovanis
<nickgeovanis@gmail.com> wrote:
You could easily do this with ansible. In perhaps 30 lines of
YAML you could install those fixes, and do the grub work in the
same ansible source file. Repeatable the next time you have fixes
to install, just run that playbook again with 1 command.
First of all, 30 lines to automate 2-4 lines is absurd. You have a
hammer, don't recommend it to people who need a screwdriver!
OK, here is the screwdriver (from man apt.conf(5)):
Pre-Invoke, Post-Invoke
This is a list of shell commands to run before/after
invoking dpkg(1). Like options this must be specified
in list notation. The commands are invoked in order
using /bin/sh; should any fail APT will abort.
(Those are in the DPkg section, so probably their full name is DPkg::Post-Invoke, etc).
On 2025-06-15 at 04:01, tomas@tuxteam.de wrote:
OK, here is the screwdriver (from man apt.conf(5)):
Pre-Invoke, Post-Invoke
This is a list of shell commands to run before/after
invoking dpkg(1). Like options this must be specified
in list notation. The commands are invoked in order
using /bin/sh; should any fail APT will abort.
(Those are in the DPkg section, so probably their full name is DPkg::Post-Invoke, etc).
That's for running (before/)after *every* dpkg invocation (within apt), though, isn't it? By my read, the OP was looking for something which
would run *only when grub has been updated as part of the invocation*.
Unless there's some way for the command being run to receive information about the dpkg session involved (in which case this would boil down to
"write a shell script and use that as the command"), or a way for a
command running independent of apt to *detect* whether such an update
has happened, that doesn't look like it would satisfy the need.
On Sun, Jun 15, 2025 at 11:07:41 -0400, Boyan Penkov wrote:
So ultimately, my problem is addressed; however, the larger question
is still open: is there in fact a straightforward way for a user, not
the package maintainer, to tell the package management system: "If and
only if your operation touched package x, also do this one thing
locally."? I can think of about a million use cases for this: "if you touched maildir-utils, run mu index." "if you touched offlineimap,
run offlineimap" "if you touched etckeeper, re-commit the /etc files"
and so on ...
Since the apt documentation is such complete rubbish, the only ways
to actually figure out how anything *works* are source diving and experimenting. I do not feel like trying to source-dive through apt
and its libraries, so I tried an experiment.
According to the apt.conf(5) man page:
Pre-Invoke, Post-Invoke
This is a list of shell commands to run before/after invoking
dpkg(1). Like options this must be specified in list notation. The
commands are invoked in order using /bin/sh; should any fail APT
will abort.
That's clear as mud. What is "list notation"? Again, I had to experiment.
I tried looking for examples, learned that the /usr/share/doc/apt/examples/configure-index.gz file documented at the end
of the man page does not exist, discovered that the file /usr/share/doc/apt/examples/configure-index exists instead, read that, and found nothing helpful in deciphering what an apt.conf.d/* file should
look like.
I looked at other files in /etc/apt/apt.conf.d/ for inspiration, and
tried searching for the word "list" in the man page, but ultimately it
came down to experimenting until I got it right.
Here's what I did:
1) I created the file /etc/apt/apt.conf.d/99localexperiment with the following contents:
==================================================================== DPkg::Post-Invoke { /usr/local/sbin/dpkg-experiment; }; ====================================================================
2) I created the script /usr/local/sbin/dpkg-experiment with the following contents:
==================================================================== #!/bin/sh
exec > /var/tmp/dpkg-experiment
printf '%s args' "$#"
if test "$#" != 0; then
printf :
printf ' <%s>' "$@"
fi
echo; echo
ps -fp "$$,$PPID"
echo
env
====================================================================
and gave it 755 permissions.
3) I installed a package by running "sudo apt-get install sl".
Here's the /var/tmp/dpkg-experiment file that was created as a result:
Conclusion: there is nothing at all in the environment or arguments
passed to the Post-Invoke script(s) that indicate what has been done.
Any such scripts created by the local sysadmin will have to take their
own investigative steps to try to figure out what happened, and what
they should do about it.
Unless of course there's some *other* hook that we don't know about
because the documentation is so poor.
So ultimately, my problem is addressed; however, the larger question
is still open: is there in fact a straightforward way for a user, not
the package maintainer, to tell the package management system: "If and
only if your operation touched package x, also do this one thing
locally."? I can think of about a million use cases for this: "if you touched maildir-utils, run mu index." "if you touched offlineimap,
run offlineimap" "if you touched etckeeper, re-commit the /etc files"
and so on ...
Aaah. I guess they mean Perl-y lists, like ["foo", "bar", "baz"].
Well, I just plagiarised /etc/apt/apt.conf.d/99needrestart:
$ cat /etc/apt/apt.conf.d/99redogrub
DPkg::Post-Invoke {"test -x /var/local/bin/redo && /var/local/bin/redo || true"; };
$
and wrote /var/local/bin/redo:
$ cat /var/local/bin/redo
#!/bin/sh
if [ "/boot/grub/grub.cfg" -nt "/var/local/bin/redo" ]; then
grub-mkconfig -o /boot/grub/grub.cfg
fi
touch "/var/local/bin/redo"
#
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 546 |
Nodes: | 16 (2 / 14) |
Uptime: | 153:24:02 |
Calls: | 10,383 |
Files: | 14,054 |
Messages: | 6,417,839 |