699 lines
32 KiB
HTML
699 lines
32 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html>
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||
|
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||
|
<title>Defensive Coding Guide | Defensive Coding Guide | Programming Languages | Shell Programming and bash</title>
|
||
|
|
||
|
<!-- Bootstrap -->
|
||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||
|
|
||
|
<!-- Overpass Font -->
|
||
|
<link rel="stylesheet" href="https://overpass-30e2.kxcdn.com/overpass.css">
|
||
|
|
||
|
<link href="../../../master/_stylesheets/asciibinder.css" rel="stylesheet" />
|
||
|
|
||
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||
|
<!--[if lt IE 9]>
|
||
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||
|
<![endif]-->
|
||
|
|
||
|
<link href="../../../master/_images/favicon32x32.png" rel="shortcut icon" type="text/css">
|
||
|
<!--[if IE]><link rel="shortcut icon" href="../../../master/_images/favicon.ico"><![endif]-->
|
||
|
<meta content="AsciiBinder" name="application-name">
|
||
|
</head>
|
||
|
<body>
|
||
|
<div class="navbar navbar-default" role="navigation">
|
||
|
<div class="container-fluid">
|
||
|
<div class="navbar-header">
|
||
|
<a class="navbar-brand" href="https://docs.fedoraproject.org/"><img alt="Fedora Documentation" src="../../../master/_images/fedora.svg"></a>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="container">
|
||
|
<p class="toggle-nav visible-xs pull-left">
|
||
|
<button class="btn btn-default btn-sm" type="button" data-toggle="offcanvas">Toggle nav</button>
|
||
|
</p>
|
||
|
<ol class="breadcrumb">
|
||
|
<li class="sitename">
|
||
|
<a href="../../../index.html">Home</a>
|
||
|
</li>
|
||
|
<li class="hidden-xs active">
|
||
|
<a href="../../en-US/index.html">Defensive Coding Guide </a>
|
||
|
</li>
|
||
|
<li class="hidden-xs active">
|
||
|
<a href="../../en-US/index.html">Defensive Coding Guide</a>
|
||
|
</li>
|
||
|
<li class="hidden-xs active"><a href="../../en-US/programming-languages/C.html">Programming Languages</a></li>
|
||
|
<li class="hidden-xs active">
|
||
|
Shell Programming and bash
|
||
|
</li>
|
||
|
</ol>
|
||
|
<div class="row row-offcanvas row-offcanvas-left">
|
||
|
<div class="col-xs-8 col-sm-3 col-md-3 sidebar sidebar-offcanvas">
|
||
|
<ul class="nav nav-sidebar">
|
||
|
<li class="nav-header">
|
||
|
<a class="" href="#" data-toggle="collapse" data-target="#topicGroup0">
|
||
|
<span id="tgSpan0" class="fa fa-angle-down"></span>Defensive Coding Guide
|
||
|
</a>
|
||
|
<ul id="topicGroup0" class="collapse in list-unstyled">
|
||
|
<li><a class="" href="../../en-US/index.html">Book Information</a></li>
|
||
|
<li class="nav-header">
|
||
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-1">
|
||
|
<span id="sgSpan-0-1" class="fa fa-caret-down"></span> Programming Languages
|
||
|
</a>
|
||
|
<ul id="topicSubGroup-0-1" class="nav-tertiary list-unstyled collapse in">
|
||
|
<li><a class="" href="../../en-US/programming-languages/C.html">The C Programming Language</a></li>
|
||
|
<li><a class="" href="../../en-US/programming-languages/CXX.html">The C++ Programming Language</a></li>
|
||
|
<li><a class="" href="../../en-US/programming-languages/Java.html">The Java Programming Language</a></li>
|
||
|
<li><a class="" href="../../en-US/programming-languages/Python.html">The Python Programming Language</a></li>
|
||
|
<li><a class=" active" href="../../en-US/programming-languages/Shell.html">Shell Programming and bash</a></li>
|
||
|
<li><a class="" href="../../en-US/programming-languages/Go.html">The Go Programming Language</a></li>
|
||
|
<li><a class="" href="../../en-US/programming-languages/Vala.html">The Vala Programming Language</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
<li class="nav-header">
|
||
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-2">
|
||
|
<span id="sgSpan-0-2" class="fa fa-caret-right"></span> Specific Programming Tasks
|
||
|
</a>
|
||
|
<ul id="topicSubGroup-0-2" class="nav-tertiary list-unstyled collapse">
|
||
|
<li><a class="" href="../../en-US/tasks/Tasks-Library_Design.html">Library Design</a></li>
|
||
|
<li><a class="" href="../../en-US/tasks/Tasks-Descriptors.html">File Descriptor Management</a></li>
|
||
|
<li><a class="" href="../../en-US/tasks/Tasks-File_System.html">File System Manipulation</a></li>
|
||
|
<li><a class="" href="../../en-US/tasks/Tasks-Temporary_Files.html">Temporary Files</a></li>
|
||
|
<li><a class="" href="../../en-US/tasks/Tasks-Processes.html">Processes</a></li>
|
||
|
<li><a class="" href="../../en-US/tasks/Tasks-Serialization.html">Serialization and Deserialization</a></li>
|
||
|
<li><a class="" href="../../en-US/tasks/Tasks-Cryptography.html">Cryptography</a></li>
|
||
|
<li><a class="" href="../../en-US/tasks/Tasks-Packaging.html">RPM Packaging</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
<li class="nav-header">
|
||
|
<a class="" href="#" data-toggle="collapse" data-target="#topicSubGroup-0-3">
|
||
|
<span id="sgSpan-0-3" class="fa fa-caret-right"></span> Implementing Security Features
|
||
|
</a>
|
||
|
<ul id="topicSubGroup-0-3" class="nav-tertiary list-unstyled collapse">
|
||
|
<li><a class="" href="../../en-US/features/Features-Authentication.html">Authentication and Authorization</a></li>
|
||
|
<li><a class="" href="../../en-US/features/Features-TLS.html">Transport Layer Security (TLS)</a></li>
|
||
|
<li><a class="" href="../../en-US/features/Features-HSM.html">Hardware Security Modules and Smart Cards</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
<li><a class="" href="../../en-US/Revision_History.html">Revision History</a></li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div class="col-xs-12 col-sm-9 col-md-9 main">
|
||
|
<div class="page-header">
|
||
|
<h2>Shell Programming and <strong class="application">bash</strong></h2>
|
||
|
</div>
|
||
|
<div id="preamble">
|
||
|
<div class="sectionbody">
|
||
|
<div class="paragraph">
|
||
|
<p>This chapter contains advice about shell programming, specifically
|
||
|
in <strong class="application">bash</strong>. Most of the advice will apply
|
||
|
to scripts written for other shells because extensions such as
|
||
|
integer or array variables have been implemented there as well, with
|
||
|
comparable syntax.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect1">
|
||
|
<h2 id="sect-Defensive_Coding-Shell-Alternatives"><a class="anchor" href="#sect-Defensive_Coding-Shell-Alternatives"></a>Consider Alternatives</h2>
|
||
|
<div class="sectionbody">
|
||
|
<div class="paragraph">
|
||
|
<p>Once a shell script is so complex that advice in this chapter
|
||
|
applies, it is time to step back and consider the question: Is
|
||
|
there a more suitable implementation language available?</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>For example, Python with its <code>subprocess</code> module
|
||
|
can be used to write scripts which are almost as concise as shell
|
||
|
scripts when it comes to invoking external programs, and Python
|
||
|
offers richer data structures, with less arcane syntax and more
|
||
|
consistent behavior.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect1">
|
||
|
<h2 id="sect-Defensive_Coding-Shell-Language"><a class="anchor" href="#sect-Defensive_Coding-Shell-Language"></a>Shell Language Features</h2>
|
||
|
<div class="sectionbody">
|
||
|
<div class="paragraph">
|
||
|
<p>The following sections cover subtleties concerning the shell
|
||
|
programming languages. They have been written with the
|
||
|
<strong class="application">bash</strong> shell in mind, but some of these
|
||
|
features apply to other shells as well.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Some of the features described may seem like implementation defects,
|
||
|
but these features have been replicated across multiple independent
|
||
|
implementations, so they now have to be considered part of the shell
|
||
|
programming language.</p>
|
||
|
</div>
|
||
|
<div class="sect2">
|
||
|
<h3 id="sect-Defensive_Coding-Shell-Parameter_Expansion"><a class="anchor" href="#sect-Defensive_Coding-Shell-Parameter_Expansion"></a>Parameter Expansion</h3>
|
||
|
<div class="paragraph">
|
||
|
<p>The mechanism by which named shell variables and parameters are
|
||
|
expanded is called <strong>parameter expansion</strong>. The
|
||
|
most basic syntax is
|
||
|
“<code>$</code><strong>variable</strong>” or
|
||
|
“<code>${</code><strong>variable</strong><code>}</code>”.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>In almost all cases, a parameter expansion should be enclosed in
|
||
|
double quotation marks <code>“…”</code>.</p>
|
||
|
</div>
|
||
|
<div class="listingblock">
|
||
|
<div class="content">
|
||
|
<pre class="CodeRay highlight"><code data-lang="bash">external-program "$arg1" "$arg2"</code></pre>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>If the double quotation marks are omitted, the value of the
|
||
|
variable will be split according to the current value of the
|
||
|
<code>IFS</code> variable. This may allow the injection of
|
||
|
additional options which are then processed by
|
||
|
<code>external-program</code>.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Parameter expansion can use special syntax for specific features,
|
||
|
such as substituting defaults or performing string or array
|
||
|
operations. These constructs should not be used because they can
|
||
|
trigger arithmetic evaluation, which can result in code execution.
|
||
|
See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect2">
|
||
|
<h3 id="sect-Defensive_Coding-Shell-Double_Expansion"><a class="anchor" href="#sect-Defensive_Coding-Shell-Double_Expansion"></a>Double Expansion</h3>
|
||
|
<div class="paragraph">
|
||
|
<p><strong>Double expansion</strong> occurs when, during the
|
||
|
expansion of a shell variable, not just the variable is expanded,
|
||
|
replacing it by its value, but the <strong>value</strong> of
|
||
|
the variable is itself is expanded as well. This can trigger
|
||
|
arbitrary code execution, unless the value of the variable is
|
||
|
verified against a restrictive pattern.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>The evaluation process is in fact recursive, so a self-referential
|
||
|
expression can cause an out-of-memory condition and a shell crash.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Double expansion may seem like as a defect, but it is implemented
|
||
|
by many shells, and has to be considered an integral part of the
|
||
|
shell programming language. However, it does make writing robust
|
||
|
shell scripts difficult.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Double expansion can be requested explicitly with the
|
||
|
<code>eval</code> built-in command, or by invoking a
|
||
|
subshell with “<code>bash -c</code>”. These constructs
|
||
|
should not be used.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>The following sections give examples of places where implicit
|
||
|
double expansion occurs.</p>
|
||
|
</div>
|
||
|
<div class="sect3">
|
||
|
<h4 id="sect-Defensive_Coding-Shell-Arithmetic"><a class="anchor" href="#sect-Defensive_Coding-Shell-Arithmetic"></a>Arithmetic Evaluation</h4>
|
||
|
<div class="paragraph">
|
||
|
<p><strong>Arithmetic evaluation</strong> is a process by which
|
||
|
the shell computes the integer value of an expression specified
|
||
|
as a string. It is highly problematic for two reasons: It
|
||
|
triggers double expansion (see <a href="#sect-Defensive_Coding-Shell-Double_Expansion">Double Expansion</a>), and the
|
||
|
language of arithmetic expressions is not self-contained. Some
|
||
|
constructs in arithmetic expressions (notably array subscripts)
|
||
|
provide a trapdoor from the restricted language of arithmetic
|
||
|
expressions to the full shell language, thus paving the way
|
||
|
towards arbitrary code execution. Due to double expansion,
|
||
|
input which is (indirectly) referenced from an arithmetic
|
||
|
expression can trigger execution of arbitrary code, which is
|
||
|
potentially harmful.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Arithmetic evaluation is triggered by the follow constructs:</p>
|
||
|
</div>
|
||
|
<div class="ulist">
|
||
|
<ul>
|
||
|
<li>
|
||
|
<p>The <strong>expression</strong> in
|
||
|
“<code>$</code><strong>expression</strong><code></code>”
|
||
|
is evaluated. This construct is called <strong>arithmetic
|
||
|
expansion</strong>.</p>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p></p>
|
||
|
<div class="paragraph">
|
||
|
<p>“<code>$[</code><strong>expression</strong><code>]</code>”
|
||
|
is a deprecated syntax with the same effect.</p>
|
||
|
</div>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p>The arguments to the <code>let</code> shell built-in
|
||
|
are evaluated.</p>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p></p>
|
||
|
<div class="paragraph">
|
||
|
<p>“<code></code><strong>expression</strong><code></code>”
|
||
|
is an alternative syntax for “<code>let</code> <strong>expression</strong>”.</p>
|
||
|
</div>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p>Conditional expressions surrounded by
|
||
|
“<code>[[</code>…<code>]]</code>” can trigger
|
||
|
arithmetic evaluation if certain operators such as
|
||
|
<code>-eq</code> are used. (The
|
||
|
<code>test</code> built-in does not perform arithmetic
|
||
|
evaluation, even with integer operators such as
|
||
|
<code>-eq</code>.)</p>
|
||
|
<div class="paragraph">
|
||
|
<p>The conditional expression
|
||
|
“<code>[[ $</code><strong>variable</strong> <code>=~</code> <strong>regexp</strong> <code>]]</code>”
|
||
|
can be used for input validation, assuming that
|
||
|
<strong>regexp</strong> is a constant regular
|
||
|
expression.
|
||
|
See <a href="#sect-Defensive_Coding-Shell-Input_Validation">Performing Input Validation</a>.</p>
|
||
|
</div>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p>Certain parameter expansions, for example
|
||
|
“<code>${</code><strong>variable</strong><code>[</code><strong>expression</strong><code>]}</code>”
|
||
|
(array indexing) or
|
||
|
“<code>${</code><strong>variable</strong><code>:</code><strong>expression</strong><code>}</code>”
|
||
|
(string slicing), trigger arithmetic evaluation of
|
||
|
<strong>expression</strong>.</p>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p>Assignment to array elements using
|
||
|
“<strong>array_variable</strong><code>[</code><strong>subscript</strong><code>]=</code><strong>expression</strong>”
|
||
|
triggers evaluation of <strong>subscript</strong>, but
|
||
|
not <strong>expression</strong>.</p>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p>The expressions in the arithmetic <code>for</code>
|
||
|
command,
|
||
|
“<code>for </code><strong>expression1</strong><code>;</code> <strong>expression2</strong><code>;</code> <strong>expression3</strong><code>; do</code> <strong>commands</strong><code>; done</code>”
|
||
|
are evaluated. This does not apply to the regular
|
||
|
for command,
|
||
|
“<code>for</code> <strong>variable</strong> <code>in</code> <strong>list</strong><code>; do</code> <strong>commands</strong><code>; done</code>”.</p>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div class="admonitionblock important">
|
||
|
<table>
|
||
|
<tr>
|
||
|
<td class="icon">
|
||
|
<i class="fa icon-important" title="Important"></i>
|
||
|
</td>
|
||
|
<td class="content">
|
||
|
<div class="paragraph">
|
||
|
<p>Depending on the <strong class="application">bash</strong> version, the
|
||
|
above list may be incomplete.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>If faced with a situation where using such shell features
|
||
|
appears necessary, see <a href="#sect-Defensive_Coding-Shell-Alternatives">Consider Alternatives</a>.</p>
|
||
|
</div>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>If it is impossible to avoid shell arithmetic on untrusted
|
||
|
inputs, refer to <a href="#sect-Defensive_Coding-Shell-Input_Validation">Performing Input Validation</a>.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect3">
|
||
|
<h4 id="sect-Defensive_Coding-Shell-Types"><a class="anchor" href="#sect-Defensive_Coding-Shell-Types"></a>Type declarations</h4>
|
||
|
<div class="paragraph">
|
||
|
<p><strong class="application">bash</strong> supports explicit type
|
||
|
declarations for shell variables:</p>
|
||
|
</div>
|
||
|
<div class="listingblock">
|
||
|
<div class="content">
|
||
|
<pre class="CodeRay highlight"><code data-lang="bash"> declare -i integer_variable
|
||
|
declare -a array_variable
|
||
|
declare -A assoc_array_variable
|
||
|
|
||
|
typeset -i integer_variable
|
||
|
typeset -a array_variable
|
||
|
typeset -A assoc_array_variable
|
||
|
|
||
|
local -i integer_variable
|
||
|
local -a array_variable
|
||
|
local -A assoc_array_variable
|
||
|
|
||
|
readonly -i integer_variable
|
||
|
readonly -a array_variable
|
||
|
readonly -A assoc_array_variable</code></pre>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Variables can also be declared as arrays by assigning them an
|
||
|
array expression, as in:</p>
|
||
|
</div>
|
||
|
<div class="listingblock">
|
||
|
<div class="content">
|
||
|
<pre class="CodeRay highlight"><code data-lang="bash">array_variable=(1 2 3 4)</code></pre>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Some built-ins (such as <code>mapfile</code>) can
|
||
|
implicitly create array variables.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Such type declarations should not be used because assignment to
|
||
|
such variables (independent of the concrete syntax used for the
|
||
|
assignment) triggers arithmetic expansion (and thus double
|
||
|
expansion) of the right-hand side of the assignment operation.
|
||
|
See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Shell scripts which use integer or array variables should be
|
||
|
rewritten in another, more suitable language. Se <a href="#sect-Defensive_Coding-Shell-Alternatives">Consider Alternatives</a>.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect2">
|
||
|
<h3 id="sect-Defensive_Coding-Shell-Obscure"><a class="anchor" href="#sect-Defensive_Coding-Shell-Obscure"></a>Other Obscurities</h3>
|
||
|
<div class="paragraph">
|
||
|
<p>Obscure shell language features should not be used. Examples are:</p>
|
||
|
</div>
|
||
|
<div class="ulist">
|
||
|
<ul>
|
||
|
<li>
|
||
|
<p>Exported functions (<code>export -f</code> or
|
||
|
<code>declare -f</code>).</p>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p>Function names which are not valid variable names, such as
|
||
|
“<code>module::function</code>”.</p>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p>The possibility to override built-ins or external commands
|
||
|
with shell functions.</p>
|
||
|
</li>
|
||
|
<li>
|
||
|
<p>Changing the value of the <code>IFS</code> variable to
|
||
|
tokenize strings.</p>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect1">
|
||
|
<h2 id="sect-Defensive_Coding-Shell-Invoke"><a class="anchor" href="#sect-Defensive_Coding-Shell-Invoke"></a>Invoking External Commands</h2>
|
||
|
<div class="sectionbody">
|
||
|
<div class="paragraph">
|
||
|
<p>When passing shell variables as single command line arguments,
|
||
|
they should always be surrounded by double quotes. See
|
||
|
<a href="#sect-Defensive_Coding-Shell-Parameter_Expansion">Parameter Expansion</a>.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Care is required when passing untrusted values as positional
|
||
|
parameters to external commands. If the value starts with a hyphen
|
||
|
“<code>-</code>”, it may be interpreted by the external
|
||
|
command as an option. Depending on the external program, a
|
||
|
“<code>--</code>” argument stops option processing and treats
|
||
|
all following arguments as positional parameters. (Double quotes
|
||
|
are completely invisible to the command being invoked, so they do
|
||
|
not prevent variable values from being interpreted as options.)</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Cleaning the environment before invoking child processes is
|
||
|
difficult to implement in script. <strong class="application">bash</strong>
|
||
|
keeps a hidden list of environment variables which do not correspond
|
||
|
to shell variables, and unsetting them from within a
|
||
|
<strong class="application">bash</strong> script is not possible. To reset
|
||
|
the environment, a script can re-run itself under the “<code>env
|
||
|
-i</code>” command with an additional parameter which indicates
|
||
|
the environment has been cleared and suppresses a further
|
||
|
self-execution. Alternatively, individual commands can be executed
|
||
|
with “<code>env -i</code>”.</p>
|
||
|
</div>
|
||
|
<div class="admonitionblock important">
|
||
|
<table>
|
||
|
<tr>
|
||
|
<td class="icon">
|
||
|
<i class="fa icon-important" title="Important"></i>
|
||
|
</td>
|
||
|
<td class="content">
|
||
|
<div class="paragraph">
|
||
|
<p>Complete isolation from its original execution environment
|
||
|
(which is required when the script is executed after a trust
|
||
|
transition, e.g., triggered by the SUID mechanism) is impossible
|
||
|
to achieve from within the shell script itself. Instead, the
|
||
|
invoking process has to clear the process environment (except for
|
||
|
few trusted variables) before running the shell script.</p>
|
||
|
</div>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Checking for failures in executed external commands is recommended.
|
||
|
If no elaborate error recovery is needed, invoking “<code>set
|
||
|
-e</code>” may be sufficient. This causes the script to stop on
|
||
|
the first failed command. However, failures in pipes
|
||
|
(“<code>command1 | command2</code>”) are only detected for the
|
||
|
last command in the pipe, errors in previous commands are ignored.
|
||
|
This can be changed by invoking “<code>set -o pipefail</code>”.
|
||
|
Due to architectural limitations, only the process that spawned
|
||
|
the entire pipe can check for failures in individual commands;
|
||
|
it is not possible for a process to tell if the process feeding
|
||
|
data (or the process consuming data) exited normally or with
|
||
|
an error.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>See <a href="#sect-Defensive_Coding-Tasks-Processes-Creation">[sect-Defensive_Coding-Tasks-Processes-Creation]</a>
|
||
|
for additional details on creating child processes.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect1">
|
||
|
<h2 id="sect-Defensive_Coding-Shell-Temporary_Files"><a class="anchor" href="#sect-Defensive_Coding-Shell-Temporary_Files"></a>Temporary Files</h2>
|
||
|
<div class="sectionbody">
|
||
|
<div class="paragraph">
|
||
|
<p>Temporary files should be created with the
|
||
|
<code>mktemp</code> command, and temporary directories with
|
||
|
“<code>mktemp -d</code>”.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>To clean up temporary files and directories, write a clean-up
|
||
|
shell function and register it as a trap handler, as shown in
|
||
|
<a href="#ex-Defensive_Coding-Tasks-Temporary_Files">Creating and Cleaning up Temporary Files</a>.
|
||
|
Using a separate function avoids issues with proper quoting of
|
||
|
variables.</p>
|
||
|
</div>
|
||
|
<div id="ex-Defensive_Coding-Tasks-Temporary_Files" class="exampleblock">
|
||
|
<div class="title">Example 1. Creating and Cleaning up Temporary Files</div>
|
||
|
<div class="content">
|
||
|
<div class="listingblock">
|
||
|
<div class="content">
|
||
|
<pre class="CodeRay highlight"><code data-lang="bash">tmpfile="$(mktemp)"
|
||
|
|
||
|
cleanup () {
|
||
|
rm -f -- "$tmpfile"
|
||
|
}
|
||
|
|
||
|
trap cleanup 0</code></pre>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect1">
|
||
|
<h2 id="sect-Defensive_Coding-Shell-Input_Validation"><a class="anchor" href="#sect-Defensive_Coding-Shell-Input_Validation"></a>Performing Input Validation</h2>
|
||
|
<div class="sectionbody">
|
||
|
<div class="paragraph">
|
||
|
<p>In some cases, input validation cannot be avoided. For example,
|
||
|
if arithmetic evaluation is absolutely required, it is imperative
|
||
|
to check that input values are, in fact, integers. See <a href="#sect-Defensive_Coding-Shell-Arithmetic">Arithmetic Evaluation</a>.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p><a href="#ex-Defensive_Coding-Shell-Input_Validation">Input validation in <strong class="application">bash</strong></a>
|
||
|
shows a construct which can be used to check if a string
|
||
|
“<code>$value</code>” is an integer. This construct is
|
||
|
specific to <strong class="application">bash</strong> and not portable to
|
||
|
POSIX shells.</p>
|
||
|
</div>
|
||
|
<div id="ex-Defensive_Coding-Shell-Input_Validation" class="exampleblock">
|
||
|
<div class="title">Example 2. Input validation in <strong class="application">bash</strong></div>
|
||
|
<div class="content">
|
||
|
<div class="listingblock">
|
||
|
<div class="content">
|
||
|
<pre class="CodeRay highlight"><code data-lang="bash">Unresolved directive in <stdin> - include::../snippets/Shell-Input_Validation.adoc[]</code></pre>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Using <code>case</code> statements for input validation is
|
||
|
also possible and supported by other (POSIX) shells, but the
|
||
|
pattern language is more restrictive, and it can be difficult to
|
||
|
write suitable patterns.</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>The <code>expr</code> external command can give misleading
|
||
|
results (e.g., if the value being checked contains operators
|
||
|
itself) and should not be used.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="sect1">
|
||
|
<h2 id="sect-Defensive_Coding-Shell-Edit_Guard"><a class="anchor" href="#sect-Defensive_Coding-Shell-Edit_Guard"></a>Guarding Shell Scripts Against Changes</h2>
|
||
|
<div class="sectionbody">
|
||
|
<div class="paragraph">
|
||
|
<p><strong class="application">bash</strong> only reads a shell script up to
|
||
|
the point it is needed for executed the next command. This means
|
||
|
that if script is overwritten while it is running, execution can
|
||
|
jump to a random part of the script, depending on what is modified
|
||
|
in the script and how the file offsets change as a result. (This
|
||
|
behavior is needed to support self-extracting shell archives whose
|
||
|
script part is followed by a stream of bytes which does not follow
|
||
|
the shell language syntax.)</p>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>Therefore, long-running scripts should be guarded against
|
||
|
concurrent modification by putting as much of the program logic
|
||
|
into a <code>main</code> function, and invoking the
|
||
|
<code>main</code> function at the end of the script, using
|
||
|
this syntax:</p>
|
||
|
</div>
|
||
|
<div class="listingblock">
|
||
|
<div class="content">
|
||
|
<pre class="CodeRay highlight"><code data-lang="bash">main "$@" ; exit $?</code></pre>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="paragraph">
|
||
|
<p>This construct ensures that <strong class="application">bash</strong> will
|
||
|
stop execution after the <code>main</code> function, instead
|
||
|
of opening the script file and trying to read more commands.</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div id="bottom" class="text-muted py-3" >
|
||
|
<div class="foot">
|
||
|
<div class="container">
|
||
|
<div class="row footerlinks">
|
||
|
<div class="col-sm-3 col-xs-6 widget">
|
||
|
<h3 class="widget-title">About</h3>
|
||
|
<div class="widget-body">
|
||
|
<dl>
|
||
|
<dd><a href="https://fedoraproject.org/wiki/Overview">About Fedora</a></dd>
|
||
|
<dd><a href="https://getfedora.org/en/sponsors">Sponsors</a></dd>
|
||
|
<dd><a href="https://fedoramagazine.org">Fedora Magazine</a></dd>
|
||
|
<dd><a href="https://fedoraproject.org/wiki/Legal:Main#Legal">Legal</a></dd>
|
||
|
</dl>
|
||
|
<ul class="list-inline">
|
||
|
<li>
|
||
|
<a href="https://www.facebook.com/TheFedoraProject" class="btn-social btn-outline"><i class="fa fa-fw fa-facebook"></i></a>
|
||
|
</li>
|
||
|
<li>
|
||
|
<a href="https://plus.google.com/112917221531140868607" class="btn-social btn-outline"><i class="fa fa-fw fa-google-plus"></i></a>
|
||
|
</li>
|
||
|
<li>
|
||
|
<a href="https://twitter.com/fedora" class="btn-social btn-outline"><i class="fa fa-fw fa-twitter"></i></a>
|
||
|
</li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="col-sm-3 col-xs-6 widget">
|
||
|
<h3 class="widget-title uppercase">Download</h3>
|
||
|
<div class="widget-body">
|
||
|
<dl>
|
||
|
<dd><a href="https://getfedora.org/en/workstation/download">Get Fedora Workstation</a></dd>
|
||
|
<dd><a href="https://getfedora.org/en/server/download">Get Fedora Server</a></dd>
|
||
|
<dd><a href="https://getfedora.org/en/atomic/download">Get Fedora Atomic</a></dd>
|
||
|
<dd><a href="https://spins.fedoraproject.org">Fedora Spins</a></dd>
|
||
|
<dd><a href="https://labs.fedoraproject.org">Fedora Labs</a></dd>
|
||
|
<dd><a href="https://arm.fedoraproject.org">Fedora ARM<span class="sup">®</span></a></dd>
|
||
|
<dd><a href="https://alt.fedoraproject.org/">Alternative Downloads</a></dd>
|
||
|
|
||
|
</dl>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="col-sm-3 col-xs-6 widget">
|
||
|
<h3 class="widget-title">Support</h3>
|
||
|
<div class="widget-body">
|
||
|
<dl>
|
||
|
<dd><a href="https://fedoraproject.org/wiki/Communicating_and_getting_help">Get Help</a></dd>
|
||
|
<dd><a href="https://ask.fedoraproject.org/">Ask Fedora</a></dd>
|
||
|
<dd><a href="https://fedoraproject.org/wiki/Common_F27_bugs">Common Bugs</a></dd>
|
||
|
<dd><a href="https://developer.fedoraproject.org/">Fedora Developer Portal</a></dd>
|
||
|
<dd><a href="https://docs.fedoraproject.org/f27/install-guide/index.html">Installation Guide</a></dd>
|
||
|
</dl>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="col-sm-3 col-xs-6 widget">
|
||
|
<h3 class="widget-title">Join</h3>
|
||
|
<div class="widget-body">
|
||
|
<dl>
|
||
|
<dd><a href="https://fedoraproject.org/wiki/Join">Join Fedora</a></dd>
|
||
|
<dd><a href="http://fedoraplanet.org">Planet Fedora</a></dd>
|
||
|
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
|
||
|
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
|
||
|
<dd><a href="https://fedoracommunity.org/">Fedora Community</a></dd>
|
||
|
</dl>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div> <!-- /row of widgets -->
|
||
|
|
||
|
<div class="row">
|
||
|
<div class="col-md-2">
|
||
|
<div class="widget-body">
|
||
|
<a href="https://www.redhat.com/"><img class="rh-logo" src="../../../master/_images/redhat-logo.png" alt="Red Hat Logo" /></a>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="col-md-7">
|
||
|
<div class="widget-body">
|
||
|
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
|
||
|
<p class="sponsor"><a href="https://www.redhat.com/en/technologies/linux-platforms/articles/relationship-between-fedora-and-rhel">Learn more about the relationship between Red Hat and Fedora »</a></p>
|
||
|
<p class="copy">© 2017 Red Hat, Inc. and others. Please send any comments or corrections to the <a href="https://pagure.io/fedora-docs/docs-fp-o">documentation team</a></p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div> <!-- /row of widgets -->
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||
|
<!-- Latest compiled and minified JavaScript -->
|
||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||
|
<script src="../../../master/_javascripts/bootstrap-offcanvas.js" type="text/javascript"></script>
|
||
|
<script type="text/javascript">
|
||
|
/*<![CDATA[*/
|
||
|
$(document).ready(function() {
|
||
|
$("[id^='topicGroup']").on('show.bs.collapse', function (event) {
|
||
|
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||
|
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||
|
}
|
||
|
});
|
||
|
$("[id^='topicGroup']").on('hide.bs.collapse', function (event) {
|
||
|
if (!($(event.target).attr('id').match(/^topicSubGroup/))) {
|
||
|
$(this).parent().find("[id^='tgSpan']").toggleClass("fa-angle-right fa-angle-down");
|
||
|
}
|
||
|
});
|
||
|
$("[id^='topicSubGroup']").on('show.bs.collapse', function () {
|
||
|
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||
|
});
|
||
|
$("[id^='topicSubGroup']").on('hide.bs.collapse', function () {
|
||
|
$(this).parent().find("[id^='sgSpan']").toggleClass("fa-caret-right fa-caret-down");
|
||
|
});
|
||
|
});
|
||
|
/*]]>*/
|
||
|
</script>
|
||
|
</body>
|
||
|
</html>
|