10.4. Scripts

All command scripts, including the package maintainer scripts inside the package and used by dpkg, should have a #! line naming the shell to be used to interpret them.

In the case of Perl scripts this should be #!/usr/bin/perl.

When scripts are installed into a directory in the system PATH, the script name should not include an extension such as .sh or .pl that denotes the scripting language currently used to implement it.

Shell scripts (sh and bash) other than init.d scripts should almost certainly start with set -e so that errors are detected. init.d scripts are something of a special case, due to how frequently they need to call commands that are allowed to fail, and it may instead be easier to check the exit status of commands directly. See Writing the scripts for more information about writing init.d scripts.

Every script should use set -e or check the exit status of every command.

Scripts may assume that /bin/sh implements the POSIX.1-2017 Shell Command Language 7 plus the following additional features not mandated by POSIX.1-2017.. 8

  • echo -n, if implemented as a shell built-in, must not generate a newline.

  • test, if implemented as a shell built-in, must support -a and -o as binary logical operators.

  • local to create a scoped variable must be supported, including listing multiple variables in a single local command and assigning a value to a variable at the same time as localizing it. local may or may not preserve the variable value from an outer scope if no assignment is present. Uses such as:

    1. fname () {
    2. local a b c=delta d
    3. # ... use a, b, c, d ...
    4. }

    must be supported and must set the value of c to delta.

  • The XSI extension to kill allowing kill -signal, where signal is either the name of a signal or one of the numeric signals listed in the XSI extension (0, 1, 2, 3, 6, 9, 14, and 15), must be supported if kill is implemented as a shell built-in.

  • The XSI extension to trap allowing numeric signals must be supported. In addition to the signal numbers listed in the extension, which are the same as for kill above, 13 (SIGPIPE) must be allowed.

If a shell script requires non-POSIX.1-2017 features from the shell interpreter other than those listed above, the appropriate shell must be specified in the first line of the script (e.g., #!/bin/bash) and the package must depend on the package providing the shell (unless the shell package is marked “Essential”, as in the case of bash).

You may wish to restrict your script to POSIX.1-2017 features plus the above set when possible so that it may use /bin/sh as its interpreter. Checking your script with checkbashisms from the devscripts package or running your script with an alternate shell such as posh may help uncover violations of the above requirements. If in doubt whether a script complies with these requirements, use /bin/bash.

Perl scripts should check for errors when making any system calls, including open, print, close, rename and system.

csh and tcsh should be avoided as scripting languages. See Csh Programming Considered Harmful, one of the comp.unix.* FAQs, which can be found at http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/. If an upstream package comes with csh scripts then you must make sure that they start with #!/bin/csh and make your package depend on the c-shell virtual package.

Any scripts which create files in world-writeable directories (e.g., in /tmp) must use a mechanism which will fail atomically if a file with the same name already exists.

The Debian base system provides the tempfile and mktemp utilities for use by scripts for this purpose.