• Re: Run script after package install, update?

    From tomas@tuxteam.de@21:1/5 to Anders Andersson on Sun Jun 15 10:10:01 2025
    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:



    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!

    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).

    There seems to be also a Post-Invoke-Success hook, not documented in
    the man page. From skimming the internet it seems to live Apt::Update
    namespace (possibly it's just called once for a whole bunch of updates?).

    Perhaps this would be worth a bug report against the APT doc, what do
    you think?

    Cheers
    --
    t

    -----BEGIN PGP SIGNATURE-----

    iF0EABECAB0WIQRp53liolZD6iXhAoIFyCz1etHaRgUCaE597QAKCRAFyCz1etHa RgxiAJ4kI3YOwiCC/zzvAGmxWc8rcuH/agCfSOxsy2mAbo0oNoYGjP7IXWcOB+g=
    =Hcxb
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From The Wanderer@21:1/5 to tomas@tuxteam.de on Sun Jun 15 12:30:01 2025
    This is an OpenPGP/MIME signed message (RFC 4880 and 3156)
    On 2025-06-15 at 04:01, tomas@tuxteam.de wrote:

    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).

    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.

    I know there are ways for one package to react to the update of another,
    via dpkg triggers. I don't know whether such a trigger has to be defined
    in the package being updated ("I provide a man page, so tell any package interested in man pages to do its thing") or in the package reacting
    ("any time a package referencing a file under this path is updated, tell
    me").

    If it's the former, then unless grub already defines a trigger which
    other packages could react to, I don't hae any ideas offhand. If it's
    the latter, then in principle it seems like it should be possible to
    create a local dummy package which defines a trigger against (some key
    element contained within) grub, and then in response to that trigger
    would run a script which does what the OP currently does manually.

    That would put you in the domain of package creation, however, unless
    equivs has some ability to help dealing with triggers (which I don't see
    in a glance at its man page). I have *some* degree of experience in that context, but not much, and none of it involves how triggers are arranged.

    --
    The Wanderer

    The reasonable man adapts himself to the world; the unreasonable one
    persists in trying to adapt the world to himself. Therefore all
    progress depends on the unreasonable man. -- George Bernard Shaw


    -----BEGIN PGP SIGNATURE-----

    iQIzBAEBCgAdFiEEJCOqsZEc2qVC44pUBKk1jTQoMmsFAmhOnyEACgkQBKk1jTQo MmvbQw//Unzf7diQHOYgNsgOT+yA/iBU96XHJeUmclWEKWpiXan8VCHu82kt46ps /gV69pM3OaPeTkC1Bd5nTkAl5GDuMeGp6vREiq9iHPTRgd7EggrWc7USN4hINw7d t0Mf4AL5MKpyS5dOm0ljdHaiZqnfExB/cCMFvSpqKKWBXHLeKMrq8NCEKZsG0+D9 Os/ixrGTrkWSWUEYzy4p6ir0dv7ARtgNRW7HP3DCfv/hTJ8aRTtS/d3m+6aaBnEu 5nr/iBtfyRCdKFjuYiGneS6gFrMUI+tvMGYdCeEINrXo1FLnPYixtJeQtZhI2nwj pOva+l5I0hcAh6IcbE2Iez0Ufd5FxStQwYBnDDKNvugGio4QdEY7kucnGuphV4iL gnluPyqEC2yJi/A7QZ0rKurhRnZDL2DFQ5WR4GoXRlvNC2qdA90386PxU5FBWw0t 5rZ90fk0zr8K4uqVewF5lPQu1CCufl032yAHfyMnVwqD/QCxiYF4RHaP9EoyafEU YbNWO9LNvD7KrdCloE2Rmiz+hQ+0YSJ1ChYhhjrRtcwmq1BHXIpFeKeZghzuOIQv MgP9trypT8TASxDpQMKrTx9soWf1CHq1+vLBxAyslimYYLU5pq+9bNTeWdRDZX6z xwqQjmtzhAH0cVwCNjSfG2cImlXd
  • From David Wright@21:1/5 to The Wanderer on Sun Jun 15 16:40:01 2025
    On Sun 15 Jun 2025 at 06:23:20 (-0400), The Wanderer wrote:
    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*.

    But the OP only has to call a script from /etc/apt/apt.conf.d/NNfoo
    that tests whether /boot/grub/config is more recent than an arbitrary
    file that the script touches at the end of its execution, returning
    true when it's not. (For minimal footprint, the arbitrary file could
    be the script itself, or even NNfoo.)

    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.

    Cheers,
    David.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From tomas@tuxteam.de@21:1/5 to Greg Wooledge on Sun Jun 15 18:10:01 2025
    On Sun, Jun 15, 2025 at 11:33:09AM -0400, Greg Wooledge wrote:
    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.

    Aaah. I guess they mean Perl-y lists, like ["foo", "bar", "baz"].

    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; }; ====================================================================

    Hm. Seems they are more permissive than I guessed :-)
    But anyway, you found out.

    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.

    Yep, that's the sad state. Thanks for investigating. Perhaps it'd be
    worth talking to the devels.

    Cheers
    --
    t

    -----BEGIN PGP SIGNATURE-----

    iF0EABECAB0WIQRp53liolZD6iXhAoIFyCz1etHaRgUCaE7v4gAKCRAFyCz1etHa Rj0XAKCCHZAabeooNG2Oy9seE7ldv5SgCACfY3eJfG92ft1GUuwmy0kjY116aDA=
    =RT3X
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to Boyan Penkov on Sun Jun 15 17:40:01 2025
    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:

    ====================================================================
    0 args

    UID PID PPID C STIME TTY TIME CMD
    root 487061 487060 0 11:19 pts/27 00:00:00 sh -c /usr/local/sbin/dpkg-experiment
    root 487062 487061 0 11:19 pts/27 00:00:00 /bin/sh /usr/local/sbin/dpkg-experiment

    SUDO_GID=1000
    DPKG_FRONTEND_LOCKED=true
    MAIL=/var/mail/root
    LC_TIME=C
    USER=root
    HOME=/root
    COLORTERM=rxvt-xpm
    SUDO_UID=1000
    LOGNAME=root
    TERM=rxvt-unicode-256color PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    DISPLAY=:0
    LANG=en_US.utf8
    XAUTHORITY=/home/greg/.Xauthority
    LS_COLORS=ln=31:ex=35:cd=44;37:bd=44;37:pi=32
    SUDO_COMMAND=/usr/bin/apt-get install sl
    SHELL=/bin/bash
    SUDO_USER=greg
    PWD=/tmp
    ====================================================================

    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From tomas@tuxteam.de@21:1/5 to tomas@tuxteam.de on Sun Jun 15 18:20:01 2025
    On Sun, Jun 15, 2025 at 06:08:08PM +0200, tomas@tuxteam.de wrote:

    [...]

    Aaah. I guess they mean Perl-y lists, like ["foo", "bar", "baz"].

    Gah, no. That'd make an array ref. I wanted to write ("foo", "bar", "baz").

    Cheers
    --
    t

    -----BEGIN PGP SIGNATURE-----

    iF0EABECAB0WIQRp53liolZD6iXhAoIFyCz1etHaRgUCaE7wagAKCRAFyCz1etHa Rsq2AJ9BXyci/R9jQWQZ/Ih37GVJVjDsuACeJ07lF2hxebuyKfYYiLVuN20EXik=
    =A8wE
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Greg Wooledge@21:1/5 to David Wright on Sun Jun 15 19:40:01 2025
    On Sun, Jun 15, 2025 at 12:14:30 -0500, David Wright wrote:
    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"
    #

    Looks reasonable. The only thing you might want to take note of is the
    -nt operand in /bin/sh's test command. It's in the 2024 edition of POSIX,
    but it's not in the previous edition, so one shouldn't expect it to be
    present in shells that are more than half a year old.

    Dash (in Bookworm) happens to include it, as well as bash, which is why it works here. It's just not as portable as you might have thought.

    I'm not sure why you've got scripts under /var, though. That's weird.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)