Bug#562506: init scripts should not use set -e
Russ Allbery <rra@debian.org> writes:
> Currently, Debian Policy makes a general statement that all Bourne shell
> scripts should start with set -e and does not (so far as I can see) make
> an exception for init scripts. I've seen several init scripts use set
> -e, which is usually a bad idea. It assumes that the shell function
> libraries used for status reporting are "set -e"-clean, which they may
> not be, and it causes the init scripts to exit in non-obvious ways and
> produce lots of debugging headache.
> I think there's already a consensus that set -e is the wrong approach
> for init scripts and instead the exit status of key commands should be
> checked instead. I think Policy should reflect that consensus somewhere
> in the section on init scripts.
Here is proposed wording, which hopefully reflects the subsequent
discussion. I'm looking for seconds.
diff --git a/policy.sgml b/policy.sgml
index d16df70..1871d4c 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -6011,7 +6011,7 @@ rmdir /usr/local/share/emacs 2>/dev/null || true
</p>
</sect1>
- <sect1>
+ <sect1 id="writing-init">
<heading>Writing the scripts</heading>
<p>
@@ -6062,6 +6062,23 @@ rmdir /usr/local/share/emacs 2>/dev/null || true
</p>
<p>
+ Be careful of using <tt>set -e</tt> in <file>init.d</file>
+ scripts. Writing correct <file>init.d</file> scripts requires
+ accepting various error exit statuses when daemons are already
+ running or already stopped without aborting
+ the <file>init.d</file> script, and common <file>init.d</file>
+ function libraries are not safe to call with <tt>set -e</tt>
+ in effect<footnote>
+ <tt>/lib/lsb/init-functions</tt>, which assists in writing
+ LSB-compliant init scripts, may fail if <tt>set -e</tt> is
+ in effect and echoing status messages to the console fails,
+ for example.
+ </footnote>. For <tt>init.d</tt> scripts, it's often easier
+ to not use <tt>set -e</tt> and instead check the result of
+ each command separately.
+ </p>
+
+ <p>
If a service reloads its configuration automatically (as
in the case of <prgn>cron</prgn>, for example), the
<tt>reload</tt> option of the <file>init.d</file> script
@@ -7158,13 +7175,19 @@ strip --strip-unneeded <var>your-lib</var>
language currently used to implement it.
</p>
<p>
- Shell scripts (<prgn>sh</prgn> and <prgn>bash</prgn>)
- should almost certainly start with <tt>set -e</tt> so that
- errors are detected. Every script should use
- <tt>set -e</tt> or check the exit status of <em>every</em>
- command.
+ Shell scripts (<prgn>sh</prgn> and <prgn>bash</prgn>) other than
+ <file>init.d</file> scripts should almost certainly start
+ with <tt>set -e</tt> so that errors are detected.
+ <file>init.d</file> 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 <ref id="writing-init"> for more
+ information about writing <file>init.d</file> scripts.
+ </p>
+ <p>
+ Every script should use <tt>set -e</tt> or check the exit status
+ of <em>every</em> command.
</p>
-
<p>
Scripts may assume that <file>/bin/sh</file> implements the
SUSv3 Shell Command Language<footnote>
--
Russ Allbery (rra@debian.org) <http://www.eyrie.org/~eagle/>
Reply to: