Understanding “dpkg –status-fd n”

dpkgfile-descriptors

From man dpkg (1.16.16 (i386) on a Debian (7) based Linux Distro):

--status-fd n
Send machine-readable package status and progress information to file descriptor n

I read this as: "forward machine readable code, such as with generated through printf to a file descriptor". I (think) to know the file descriptors stdin (0), stdout (1), and stderr (2).

Trying to look up some examples I found next to nothing but bug reports, with file descriptors partly consisting of two digits (possibly more…). This extended my knowledge about file descriptors, which lead to more questions. Thus:

Question: How is dpkg option --status-fdused?

An actual example and a some notes of what happens would help me a lot in understanding

Best Answer

The option --status-fd tells dpkg to report the progress in a way that other programs can parse, for example to present nice progress reports to the user in a GUI.

The argument to --status-fd is a file descriptor, i.e. number that designates an open file. Simplifying things a bit:

  • When a process opens a file for the first time, that file gets assigned descriptor number 0. The next time, the file is assigned descriptor number 1, and so on. The open system call returns the file descriptor.
  • When the process wants to perform an operation on the file, such as reading or writing from it, it designates the file by its descriptor, e.g. read(0, addr, 10) means “read 10 bytes from descriptor 0 and put them at memory address addr”.
  • Each process has its own file descriptors: file descriptor n in process p bears no relation with file descriptor n in process q.
  • Processes inherit their parent's file descriptors when they are created.
  • By convention, processes are executed with file descriptors 0, 1 and 2 already open. 0 is to be used for input, 1 for normal output and 2 for error messages.

Redirection opens a file on a particular descriptor. For example, in a shell script or on the command line, mycommand <somefile connects file descriptor number 0 (standard input) so somefile (which is opened for reading) instead of whatever it was before (the terminal, if the command is executed in a terminal). You can prepend a descriptor number to the redirection operator: mycommand 3<somefile connects file descriptor number 3 to somefile (most commands won't do anything with that file descriptor).

When dpkg is installing, upgrading or removing packages, it executes various other commands in the packages' pre/post install/removal scripts. Some of these commands may read input or display messages, so dpkg keeps the standard descriptors connected to whatever they were connected to when it was invoked.

Since the standard file descriptors are already taken, dpkg allows the caller to specify a different one for the status reports. You could put the status reports in a file, for example:

dpkg --status-fd 3 -i somefile.deb 3>/tmp/dpkg.status

In another terminal, run tail -n +1 -f /tmp/dpkg.status and watch the status messages coming.

Often the front-end that calls dpkg and wants status reports will open a pipe (a unidirectional communication channel) before it runs dpkg, and pass the file descriptor to write end of the pipe as the argument of --status-fd. The front-end then reads from the read end of the pipe and gets status messages as they are produced, without risking them getting mixed up with anything else.

Related Question