nbdkit-captive - run nbdkit under another process and have it reliably cleaned up
nbdkit PLUGIN [...] [-e|--exportname EXPORTNAME] \
--run 'COMMAND ARGS ...'
nbdkit --exit-with-parent PLUGIN [...]
You can run nbdkit under another process and have nbdkit reliably clean up. There are two techniques depending on whether you want nbdkit to start the other process ("CAPTIVE NBDKIT"), or if you want the other process to start nbdkit ("EXIT WITH PARENT"). Another way is to have nbdkit exit after the last client connection (nbdkit-exitlast-filter(1)) or after an event (nbdkit-exitwhen-filter(1)).
You can run nbdkit as a "captive process", using the --run option. This means that nbdkit runs as long as (for example) qemu(1) or guestfish(1) is running. When those exit, nbdkit is killed.
Some examples should make this clear.
To run nbdkit captive under qemu:
nbdkit file disk.img --run 'qemu -drive file=$nbd,if=virtio'
On the qemu command line, $nbd
is substituted automatically with the right NBD path so it can connect to nbdkit. When qemu exits, nbdkit is killed and cleaned up automatically.
Running nbdkit captive under guestfish:
nbdkit file disk.img --run 'guestfish --format=raw -a $nbd -i'
When guestfish exits, nbdkit is killed.
Running nbdkit captive under nbdsh for unit testing:
nbdkit memory 1 --run 'nbdsh -u "$uri" -c "print(h.pread(1, 0))"'
The following shell variables are available in the --run argument:
$nbd
$uri
-
A URI that refers to the nbdkit port or socket in the preferred form documented by the NBD project.
As this variable may contain a bare
?
for Unix sockets, it is safest to use $uri within double quotes to avoid unintentional globbing. For plugins that support distinct data based on export names, the -e option to nbdkit controls which export name will be set in the URI.In nbdkit ≤ 1.22
$nbd
tried to guess if you were using qemu or guestfish and expanded differently. Since NBD URIs are now widely supported this magic is no longer necessary. In nbdkit ≥ 1.24 both variables expand to the same URI. $tls
-
Corresponds to the --tls option passed to nbdkit. If --tls=off this is not set. If --tls=on this is set to
"1"
. If --tls=require this is set to"2"
. $port
-
If ≠ "", the port number that nbdkit is listening on.
$unixsocket
-
If ≠ "", the Unix domain socket that nbdkit is listening on.
$exportname
-
The export name (which may be "") that the process should use when connecting to nbdkit, as set by the -e (--exportname) command line option of nbdkit. This only matters to plugins that differentiate what they serve based on the export name requested by the client.
--run implies --foreground. It is not possible, and probably not desirable, to have nbdkit fork into the background when using --run.
Captive nbdkit + qemu-img(1) can be used to copy data into and out of nbdkit plugins. For example nbdkit-example1-plugin(1) contains an embedded disk image. To copy it out:
nbdkit example1 --run 'qemu-img convert $nbd disk.img'
If the source suffers from temporary network failures nbdkit-retry-filter(1) or nbdkit-retry-request-filter(1) may help.
To overwrite a file inside an uncompressed tar file (the file being overwritten must be the same size), use nbdkit-tar-filter(1) like this:
nbdkit file data.tar --filter=tar tar-entry=disk.img \
--run 'qemu-img convert -n disk.img $nbd'
The --exit-with-parent option is almost the opposite of "CAPTIVE NBDKIT" described in the previous section.
Running nbdkit with this option, for example from a script:
nbdkit --exit-with-parent plugin ... &
means that nbdkit will exit automatically if the parent program exits for any reason. This can be used to avoid complicated cleanups or orphaned nbdkit processes.
--exit-with-parent is incompatible with forking into the background (because when we fork into the background we lose track of the parent process). Therefore -f / --foreground is implied.
If the parent application is multithreaded, then (in the Linux implementation) if the parent thread exits, that will cause nbdkit to exit. Thus in multithreaded applications you usually want to run nbdkit --exit-with-parent
only from the main thread (unless you actually want nbdkit to exit with the thread, but that may not work reliably on all operating systems).
To exit when an unrelated process exits, use nbdkit-exitwhen-filter(1) exit-when-process-exits
feature.
This is currently implemented using a non-POSIX feature available in Linux ≥ 2.1.57, FreeBSD ≥ 11.2 and macOS. It won't work on other operating systems (patches welcome to make it work).
To test if the current binary supports this feature the most backwards compatible way is:
nbdkit --exit-with-parent --version && echo "supported"
In nbdkit ≥ 1.34, nbdkit --dump-config
prints either exit_with_parent=yes
or exit_with_parent=no
but earlier versions did not have this.
nbdkit(1), nbdkit-exitlast-filter(1), nbdkit-exitwhen-filter(1), prctl(2) (on Linux), procctl(2) (on FreeBSD).
Eric Blake
Richard W.M. Jones
Pino Toscano
Copyright Red Hat
Hey! The above document had some coding errors, which are explained below:
- Around line 150:
-
Non-ASCII character seen before =encoding in '≥'. Assuming UTF-8