8

How can I run a command before apt-get starts to download a package?

I know about the dpkg pre-invoke hook ( hook a script to apt-get ), but that seems to be run after the download.

$ apt-get update
Get: 11 http://security.debian.org/ wheezy/updates/main qemu amd64 1.1.2+dfsg-6a+deb7u7 [115 kB]
Fetched 70.9 MB in 10s (6,776 kB/s)
refreshing freenet index
--2015-05-19 15:55:25--  http://127.0.0.1:8888/freenet:USK@oRy7ltZLJM-w-kcOBdiZS1pAA8P-BxZ3BPiiqkmfk0E,6a1KFG6S-Bwp6E-MplW52iH~Y3La6GigQVQDeMjI6rg,AQACAAE/deb.mempo.org/-42/

What we need is to run a command before the download. More exactly: The script must run after calling apt-get but before apt-get accesses any online resource.

Is there something like a Pre-Download hook?

It is important that the installation can be done without having to replace the script apt-get (and without doing anything else which could be undone by an update).

  • 2
    You could declare a function named apt-get which would itself call the real apt-get. Depending on the scope you want it to have, the function could be declared either in /etc/profile or ~/.profile or ~/.bashrc. – user43791 May 19 '15 at 20:23
  • What exactly does "The script must run after calling apt-get but before apt-get accesses any online resource" mean? What part of the producion apt-get needs to be running before your hook can execute properly? – jthill May 20 '15 at 1:27
  • @jthill we need to trigger a download of a given URL before any other URL gets accessed. The reason is that we download from freenet (decentralized anonymous datastore used as deb repository) and we want to trigger one aggressive search for the most recent version before downloading anything. – Arne Babenhauserheide May 23 '15 at 18:54
  • From comments, you're asking how to replace a system command in a way that can't be bypassed and can't be removed even by the system's installer. You're asking how to rootkit the system. – jthill May 23 '15 at 20:29
  • It would be helpful if you could describe your use case. Or in other words, what are you trying to do? – Faheem Mitha May 27 '15 at 11:02
5

What about using apt pre/post-invoke hooks?

Essentially it is similar to dpkg pre/post-invoke hooks but for apt (which I'm assuming is actually the important one in your usage scenario). AFAIK there are others but I've only used like this.

E.g.

$ sudo cat /etc/apt/apt.conf.d/05new-hook
APT::Update::Pre-Invoke {"your-command-here"};
  • Apt doesn't provide a pre-invoke hook for Upgrade or Install though, so this only works for apt-get update. – Andrew Domaszek May 16 '17 at 14:09
  • True, but I was answering the question specifically! :) You can use dpkg hooks (as per the OP) for anything which requires pre/post install tweaks. – Jeremy Davis May 17 '17 at 3:31
  • Kind of; assuming that update is always run before upgrade/install. Hooking all commands before network access occurs appears to be impossible with the currently (2017-05-17) available apt hooks. This is still the best answer for scripting but it doesn't help for things like existing automatic update scripts. – Andrew Domaszek May 17 '17 at 13:37
  • Oh ok, I get you now. Sorry; yes you have a really good point. So you can tweak apt-get update, but apt-get install will still download, before the dpkg hooks will run?! Hmmm, that really sucks! – Jeremy Davis May 19 '17 at 8:03
  • What you are trying to do? If you want auto updates but only install from specific repos (e.g. Debian security), then you can use cronapt with a script like TurnKey's cronapt script[1]. Split your sources.list entries into separate files; the ones that you want auto updates from go in security.sources.list. [1] github.com/turnkeylinux/common/blob/master/conf/turnkey.d/… – Jeremy Davis May 19 '17 at 8:36
2

First determine where is apt-get using whereis apt-get or which apt-get; I will assume it's in /usr/bin/apt-get

Then create a file in /usr/local/bin/apt-get with this content:

#!/bin/bash
# (commands to run before apt-get)
/usr/bin/apt-get "$@"

now chmod +x /usr/local/bin/apt-get.

This should survive all upgrades of the distribution but it should not change the behavior of apt-get (aside from running the command before doing anything else). As bonus, it could parse the command line arguments to only run the command when it is truly needed.

(This answer builds upon the answer from Mohammad Etemaddar, merged with the feedback from muru)

2

You can use an "alias" in the .bashrc file. For example, put that in your root .bashrc file:

alias apt-get='echo blahblah && apt-get'

Command-line arguments will be added automatically to the end of the alias.

Just replace echo blahblah by the command you need.

But in this case, it only works when you're executing commands as root (not sudo).

  • Is it possible to put this alias in normal user profile in order to use it by sudo? – Mohammad Etemaddar May 19 '15 at 22:25
  • 1
    Yes, I thik so. Try: alias apt-get='echo blahblah && sudo apt-get'. Then you only need to type in the terminal for example - apt-get update without sudo, and you'll be asked for a sudo password automatically. – Roman May 19 '15 at 22:33
  • it's true. of course then 'echo blahblah' won't work under su privileges. – Mohammad Etemaddar May 19 '15 at 22:39
  • 1
    It might be better to use a shell function or a script (in /usr/local/bin or ~/bin), because aliases don't handle arguments well. – Scott May 25 '15 at 1:38
1

First determine where is apt-get using whereis apt-get; I will assume it's in /usr/bin/apt-get

as muru says, You can create a script named apt-get in /usr/local/bin/ which is before /usr/bin in Debian and Ubuntu $PATH. Then put the following code to it (/usr/local/bin/apt-get):

#!/bin/bash
commands to run before apt-get
/usr/bin/apt-get "$@"

Thanks muru for offer as comment.

Other way:

Of course there's another way which is not better than previous one.

You can mv /usr/bin/apt-get /usr/bin/apt-get2

Then create a file in /usr/bin/apt-get with this content:

#!/bin/bash
commands to run before apt-get
apt-get2 "$@"

now chmod +x /usr/bin/apt-get

  • does this survive a dist-upgrade? – Arne Babenhauserheide May 23 '15 at 16:31
  • Yes. $@ causes script to work with every arguments. – Mohammad Etemaddar May 24 '15 at 17:05
  • 6
    Eek. If you want to create a replacement, put it in /usr/local/bin, which comes before /usr/bin in the default PATH in Debian and Ubuntu. – muru May 24 '15 at 17:33
  • 3
    This is really bad advice, sorry. (a) The apt-get executable is located in /usr/bin/apt-get, not sbin. (b) Don't mess with system commands. As muru says, you can create a local override in /usr/local/bin, though even that is not a good solution. – Faheem Mitha May 27 '15 at 9:56
  • @muru /usr/local/bin sounds like a possible way to go - I hadn’t thought of that. Thank you! – Arne Babenhauserheide May 29 '15 at 13:41
0

Try an alias in the .bashrc file. It only works when logged in to the account that the file corresponds to. The syntax of an alias is:

alias newcommand='command1; command2; command3' So your line might look a bit like this:

alias apt-get='firstcommand; apt-get'

Or this:

alias apt-get='firstcommand && apt-get'

With the second, apt-get will only execute if firstcommand succeeds.

  • Aside from clarifying the root / normal user issue, this is essentially a reiteration of the first answer. – G-Man May 24 '15 at 18:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.