Provided by: nbdkit_1.36.3-1ubuntu10_amd64 bug

NAME

       nbdkit-sh-plugin - nbdkit shell, script or executable plugin

SYNOPSIS

        nbdkit sh /path/to/script [arguments...]

        nbdkit sh - <<'EOF'
        ... shell script ...
        EOF

DESCRIPTION

       "nbdkit-sh-plugin" allows you to write plugins for nbdkit(1) using arbitrary scripting languages,
       including shells like bash(1), dash(1), csh(1), zsh(1) etc., other scripting environments, or any
       executable.

       Note if you want to use an established scripting language like Perl or Python, then nbdkit has specific
       plugins to handle those languages and those will be more efficient (see nbdkit(1) for a complete list).

       To use shell script fragments from the nbdkit command line (rather than a separate script) see
       nbdkit-eval-plugin(1).

   If you have been given an nbdkit sh plugin
       Assuming you have a shell script which is an nbdkit plugin, you run it like this:

        nbdkit sh /path/to/script

       You may have to add further "key=value" arguments to the command line.  The script must be executable
       ("chmod +x").

   Inline shell scripts
       It is also possible to write a shell script plugin "inline" using "-" as the name of the script, like
       this:

        nbdkit sh - <<'EOF'
          case "$1" in
            get_size) echo 1M ;;
            pread) dd if=/dev/zero count=$3 iflag=count_bytes ;;
            *) exit 2 ;;
          esac
        EOF

       By default the inline script runs under /bin/sh.  You can add a shebang ("#!") to use other scripting
       languages.  Of course, reading an inline script from stdin is incompatible with the -s (--single) mode of
       nbdkit that connects a client on stdin.

WRITING AN NBDKIT SH PLUGIN

       For an example plugin written in Bash, see:
       https://gitlab.com/nbdkit/nbdkit/blob/master/plugins/sh/example.sh

       Broadly speaking, nbdkit shell plugins work like C ones, so you should read nbdkit-plugin(3) first.

   Programming model
       This plugin has a simple programming model: For every plugin method that needs to be called, the external
       script is invoked with parameters describing the method and its arguments.  The first parameter is always
       the method name.  For example:

        /path/to/script config file disk.img
                          │      │   │
                          │      │   └─ value ($3)
                          │      └── key ($2)
                      method ($1)

        /path/to/script pread <handle> <count> <offset>
                          │       │       │       │
                          │       │       │       └─ offset in bytes ($4)
                          │       │       └── request size in bytes ($3)
                      method ($1) └── handle ($2) ─ see "Handles" below

       Scripts should ignore extra parameters that they don't understand since we may add new parameters in
       future.

   Exit codes
       The script should exit with specific exit codes:

       0   The method was executed successfully.

       1 and 16-255
           There  was an error.  The script may print on stderr an errno name, optionally followed by whitespace
           and a message, for example:

            echo 'ENOSPC Out of space' >&2
            exit 1

           or if you don't need the log message:

            echo ENOSPC >&2
            exit 1

           If the script doesn't print anything or the output cannot be parsed then nbdkit assumes error  "EIO".
           Note  that  output  to  stderr  is  ignored  if the command succeeds, so it is acceptable to output a
           potential error message prefix prior to attempting a command which will  add  further  details  if  a
           failure occurs.

       2   The requested method is not supported by the script.

       3   For methods which return booleans, this code indicates false.

       4 and 5
           Triggers  a  call  to  the  C  function "nbdkit_shutdown", which requests an asynchronous exit of the
           nbdkit server (disconnecting all clients).  The client will usually get a response before shutdown is
           complete (although this is racy); so once the shutdown is requested, code 4 then behaves like code  0
           (stderr  is  ignored,  and  the  server tries to return success), and code 5 behaves like code 1 (the
           server tries to return an error to the client parsed from stderr, although a missing  error  defaults
           to "ESHUTDOWN" instead of "EIO").

       6   Triggers  a  call  to  the C function "nbdkit_disconnect" with "force" set to true, which requests an
           abrupt disconnect of the current client.  The contents of stderr are  irrelevant  with  this  status,
           since the client will not get a response.

       7 and 8
           Triggers  a  call  to  the C function "nbdkit_disconnect" with "force" set to false, which requests a
           soft disconnect of the current client (future client requests are rejected with  "ESHUTDOWN"  without
           calling  into  the  plugin, but current requests may complete).  Since the client will likely get the
           response to this command, code 7 then behaves like code 0 (stderr is ignored, and the server tries to
           return success), and code 8 behaves like code 1 (the server tries to return an error  to  the  client
           parsed from stderr, although a missing error defaults to "ESHUTDOWN" instead of "EIO").

       9-15
           These  exit  codes  are reserved for future use.  Note that versions of nbdkit < 1.34 documented that
           codes 8 through 15 behaved like code 1; although it is unlikely that  many  scripts  relied  on  this
           similarity in practice.

       In  nbdkit  >  1.34, it is possible to probe whether additional exit codes have been assigned meaning, by
       looking for the line max_known_status= in the output of nbdkit --dump-plugin sh.  If  this  line  is  not
       present, exit codes 4 and above behave like status 1.

   Temporary directory
       A  fresh  script  is  invoked for each method call (ie. scripts are stateless), so if the script needs to
       store state it has to store it somewhere in the filesystem in a format and location which is left  up  to
       the author of the script.

       However  nbdkit  helps  by  creating  a  randomly  named, empty directory for the script.  This directory
       persists for the lifetime of nbdkit and is deleted when nbdkit exits.   The  name  of  the  directory  is
       passed to each script invocation in the $tmpdir environment variable.

   Handles
       Handles are arbitrary strings, but it is best to limit them to short alphanumeric strings.

       Per-connection state

       The  temporary  directory  described  above can be used for state for the lifetime of the nbdkit instance
       (across multiple connections).  If you want to store state per connection then one way to  do  it  is  to
       create a randomly named subdirectory under the temporary directory:

        case "$1" in
          ...
          open)
            mktemp -d $tmpdir/handle-XXXXXX ;;

       The  handle  will  be  the  subdirectory  name,  returned to the script as $2 in all connected calls (eg.
       "pread", "get_size").  You can delete the subdirectory explicitly in "close":

        case "$1" in
          ...
          close)
            rm -rf "$2" ;;

       or rely on nbdkit deleting the whole temporary directory including all per-handle subdirectories when  it
       exits.

   Performance
       This  plugin  has  to  fork  on every request, so performance will never be great.  For best performance,
       consider using the nbdkit-plugin(3) API directly.  Having said that, if you have a sh plugin and want  to
       improve performance then the following tips may help:

       Relax the thread model.
           The  default  "thread_model" is "serialize_all_requests" meaning that two instances of the script can
           never be running at the same time.  This is safe but slow.  If your script is safe to  be  called  in
           parallel, set this to "parallel".

       Implement the "zero" method.
           If  the  "zero"  method  is  not  implemented  then  nbdkit will fall back to using "pwrite" which is
           considerably slower because nbdkit has to send blocks of zeroes to the script.

       You don't have to write shell scripts.
           This plugin can run any external binary, not only shell scripts.  You should get more performance  by
           rewriting the shell script as a program in a compiled language.

   Methods
       This  just  documents  the  arguments to the script corresponding to each plugin method, and any way that
       they differ from the C callbacks.  In all other respects they work the same way as the  C  callbacks,  so
       you should go and read nbdkit-plugin(3).

       "load"
            /path/to/script load

       "unload"
            /path/to/script unload

           This is called just before nbdkit exits.  Errors from this method are ignored.

       "dump_plugin"
            /path/to/script dump_plugin

       "config"
            /path/to/script config <key> <value>

       "config_complete"
            /path/to/script config_complete

       "magic_config_key"
            /path/to/script magic_config_key

           If a magic config key is needed, this should echo it to stdout.  See "Magic parameters" in nbdkit(1).

       "thread_model"
            /path/to/script thread_model

           On  success this should print the desired thread model of the script, one of "serialize_connections",
           "serialize_all_requests", "serialize_requests", or "parallel".

           This method is  not  required;  if  omitted,  then  the  plugin  will  be  executed  under  the  safe
           "serialize_all_requests" model.  However, this means that this method must be provided if you want to
           use the "parallel" or "serialize_requests" model.  Even then your request may be restricted for other
           reasons;  look  for  "thread_model"  in  the  output  of "nbdkit --dump-plugin sh script" to see what
           actually gets selected.

           If an error occurs, the script should output an error message and exit with  status  1;  unrecognized
           output is ignored.

       "get_ready"
            /path/to/script get_ready

       "after_fork"
            /path/to/script after_fork

       "preconnect"
            /path/to/script preconnect <readonly>

       "list_exports"
            /path/to/script list_exports <readonly> <tls>

           The "readonly" and "tls" parameters will be "true" or "false".

           The first line of output informs nbdkit how to parse the rest of the output, the remaining lines then
           supply the inputs of the C "nbdkit_add_export" function (see nbdkit-plugin(3)), as follows:

           NAMES
               The  remaining  output  provides  one  export  name  per  line,  and  no  export  will be given a
               description.  For convenience, this form is also assumed if the first output line does not  match
               one of the recognized parse modes.

           INTERLEAVED
               The remaining output provides pairs of lines, the first line being an export name, and the second
               the corresponding description.

           NAMES+DESCRIPTIONS
               The number of remaining lines is counted, with the first half being used as export names, and the
               second half providing descriptions to pair with names from the first half.

               An  example  of  using  this form to list files in the current directory, followed by their ls(1)
               long description, would be:

                echo NAMES+DESCRIPTIONS
                ls
                ls -l

           Note that other output modes might be introduced in the future; in particular, none of  the  existing
           modes allow a literal newline in an export name or description, although this could be possible under
           a new mode supporting escape sequences.

           This  method  is  not required; if it is absent, the list of exports advertised by nbdkit will be the
           single name result of "default_export" and no description.

       "default_export"
            /path/to/script default_export <readonly> <tls>

           The "readonly" and "tls" parameters will be "true" or "false".

           On success this should print a name on stdout to use in place of the default  export  "",  then  exit
           with  code 0.  For convenience, the output can be any of the list forms recognized by "list_exports",
           in which case the first listed export name is used, and where an  empty  list  uses  "".   Given  the
           current  set  of  recognized  export  lists,  it  is not possible for the resulting name to include a
           newline.

           This method is not required; if it is absent, the default export name will be the empty string, "".

       "open"
            /path/to/script open <readonly> <exportname> <tls>

           The "readonly" parameter will be "true" or "false".  The "exportname" parameter, if present,  is  the
           export name passed to the server from the client.  The "tls" parameter, if present, will be "true" or
           "false" depending on whether the client is using TLS.

           On  success  this should print the handle (any string) on stdout and exit with code 0.  If the handle
           ends with a newline character then the newline is removed.

           Unlike C plugins, this method is not required.  If omitted then the handle will be "" (empty string).

       "close"
            /path/to/script close <handle>

       "export_description"
            /path/to/script export_description <handle>

           The script should print a human-readable description of the disk image on stdout.  If the description
           ends with a newline character then the newline is removed.

           This method is not required; if it is absent, no export description will be provided to the client.

       "get_size"
            /path/to/script get_size <handle>

           The script should print the size of the disk image on stdout.  You can print the size  in  bytes,  or
           use  any  format  understood  by  "nbdkit_parse_size"  such as "1M" (see "PARSING SIZE PARAMETERS" in
           nbdkit-plugin(3)).

           This method is required.

       "block_size"
            /path/to/script block_size <handle>

           This script should print three numbers on stdout, separated by whitespace.  These are (in order)  the
           minimum block size, the preferred block size, and the maximum block size.  You can print the sizes in
           bytes or use any format understood by "nbdkit_parse_size" such as "1M" (see "PARSING SIZE PARAMETERS"
           in nbdkit-plugin(3)).

       "can_write"
       "can_flush"
       "can_trim"
       "can_zero"
       "can_extents"
           Unlike  in  other  languages,  you must provide the "can_*" methods otherwise they are assumed to all
           return false and your "pwrite", "flush", "trim", "zero" and "extents" methods will never  be  called.
           The reason for this is obscure: In other languages we can detect if (eg) a "pwrite" method is defined
           and synthesize an appropriate response if no actual "can_write" method is defined.  However detecting
           if methods are present without running them is not possible with this plugin.

            /path/to/script can_write <handle>
            /path/to/script can_flush <handle>
            /path/to/script can_trim <handle>
            /path/to/script can_zero <handle>
            /path/to/script can_extents <handle>

           The script should exit with code 0 for true or code 3 for false.

       "is_rotational"
       "can_fast_zero"
            /path/to/script is_rotational <handle>
            /path/to/script can_fast_zero <handle>

           The script should exit with code 0 for true or code 3 for false.

       "can_fua"
       "can_cache"
            /path/to/script can_fua <handle>
            /path/to/script can_cache <handle>

           These control Forced Unit Access (FUA) and caching behaviour of the core server.

           Unlike  the  other  "can_*"  callbacks,  these two are not a boolean.  They must print either "none",
           "emulate"  or  "native"  to  stdout.   The  meaning  of  these  is  described  in   nbdkit-plugin(3).
           Furthermore, you must provide a "can_cache" method if you desire the "cache" callback to be utilized,
           similar to the reasoning behind requiring "can_write" to utilize "pwrite".

       "can_multi_conn"
            /path/to/script can_multi_conn <handle>

           The script should exit with code 0 for true or code 3 for false.

       "pread"
            /path/to/script pread <handle> <count> <offset>

           The script should print the requested binary data on stdout.  Exactly "count" bytes must be printed.

           This method is required.

       "pwrite"
            /path/to/script pwrite <handle> <count> <offset> <flags>

           The script should read the binary data to be written from stdin.

           The  "flags"  parameter  can  be  an empty string or "fua".  In the future, a comma-separated list of
           flags may be present.

           Unlike in other languages, if you provide a "pwrite" method  you  must  also  provide  a  "can_write"
           method which exits with code 0 (true).

       "flush"
            /path/to/script flush <handle>

           Unlike in other languages, if you provide a "flush" method you must also provide a "can_flush" method
           which exits with code 0 (true).

       "trim"
            /path/to/script trim <handle> <count> <offset> <flags>

           The  "flags"  parameter  can  be  an empty string or "fua".  In the future, a comma-separated list of
           flags may be present.

           Unlike in other languages, if you provide a "trim" method you must also provide a  "can_trim"  method
           which exits with code 0 (true).

       "zero"
            /path/to/script zero <handle> <count> <offset> <flags>

           The  "flags"  parameter  can  be  an  empty  string  or  a  comma-separated list of the flags: "fua",
           "may_trim", and "fast" (eg. "", "fua", "fua,may_trim,fast" are some of the 8 possible values).

           Unlike in other languages, if you provide a "zero" method you must also provide a  "can_zero"  method
           which exits with code 0 (true).

           To  trigger a fallback to "pwrite" on a normal zero request, or to respond quickly to the "fast" flag
           that a specific zero request is no  faster  than  a  corresponding  write,  the  script  must  output
           "ENOTSUP"  or  "EOPNOTSUPP"  to  stderr  (possibly  followed  by a description of the problem) before
           exiting with code 1 (failure).

       "extents"
            /path/to/script extents <handle> <count> <offset> <flags>

           The "flags" parameter can be an empty string or "req_one".

           This must print, one per line on stdout, a list of one or more extents in the format:

            offset length type

           which correspond to the inputs of the C "nbdkit_add_extent"  function  (see  nbdkit-plugin(3)).   The
           "offset"  and  "length"  fields  may  use any format understood by "nbdkit_parse_size".  The optional
           "type" field may be an integer, missing (same as 0), or a comma-separated list of  the  words  "hole"
           and "zero".  An example of a valid set of extents covering a "10M" disk where the first megabyte only
           is allocated data:

            0  1M
            1M 9M  hole,zero

           Unlike  in  other languages, if you provide an "extents" method you must also provide a "can_extents"
           method which exits with code 0 (true).

       "cache"
            /path/to/script cache <handle> <count> <offset>

           Unlike in other languages, if you provide a "cache" method you must also provide a "can_cache" method
           which prints "native" and exits with code 0 (true).

   Missing callbacks
       Missing: "name", "version", "longname", "description", "config_help"
           These are not yet supported.

FILES

       $plugindir/nbdkit-sh-plugin.so
           The plugin.

           Use "nbdkit --dump-config" to find the location of $plugindir.

VERSION

       "nbdkit-sh-plugin" first appeared in nbdkit 1.8.

SEE ALSO

       nbdkit(1), nbdkit-plugin(3), nbdkit-eval-plugin(1), nbdkit-cc-plugin(1).

AUTHORS

       Richard W.M. Jones

COPYRIGHT

       Copyright Red Hat

LICENSE

       Redistribution and use in source and binary forms, with or without modification, are  permitted  provided
       that the following conditions are met:

       •   Redistributions  of  source  code must retain the above copyright notice, this list of conditions and
           the following disclaimer.

       •   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
           the following disclaimer in the documentation and/or other materials provided with the distribution.

       •   Neither the name of Red Hat nor the names of its contributors may  be  used  to  endorse  or  promote
           products derived from this software without specific prior written permission.

       THIS  SOFTWARE  IS  PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
       INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS  FOR  A  PARTICULAR
       PURPOSE  ARE  DISCLAIMED.  IN  NO EVENT SHALL RED HAT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
       INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  PROCUREMENT  OF
       SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
       DAMAGE.

nbdkit-1.36.3                                      2024-03-31                                nbdkit-sh-plugin(3)