From 7cf216c97672442bb812e79dfd5d2daae72986db Mon Sep 17 00:00:00 2001
From: "mark@chromium.org"
Date: Fri, 15 Feb 2013 20:56:05 +0000
Subject: [PATCH] Initial public release of Shell Style Guide (1.25).
---
shell.xml | 1087 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1087 insertions(+)
create mode 100644 shell.xml
diff --git a/shell.xml b/shell.xml
new file mode 100644
index 0000000..1735ed7
--- /dev/null
+++ b/shell.xml
@@ -0,0 +1,1087 @@
+
+
+
+
+Revision 1.25
+
+ Executables must start with
+ Restricting all executable shell scripts to bash
+ gives us a consistent shell language that's installed on all our
+ machines.
+
+ The only exception to this is where you're forced to by whatever
+ you're coding for. One example of this is Solaris SVR4 packages which
+ require plain Bourne shell for any scripts.
+
+ While shell scripting isn't a development language, it is used for
+ writing various utility scripts throughout Google. This
+ style guide is more a recognition of its use rather than
+ a suggestion that it be used for widespread deployment.
+
+ Some guidelines:
+
+ Too many more to mention
+
+
+Bash
is the only shell scripting language permitted for
+ executables.
+ #!/bin/bash
and a minimum
+ number of flags. Use set
to set shell options so that
+ calling your script as bash <script_name>
+ does not break its functionality.
+
+
+ ${PIPESTATUS}
, you should use Python.
+
.sh
extension.
+ Libraries must have a .sh
extension and should not be
+ executable.
+ + It is not necessary to know what language a program is written in when + executing it and shell doesn't require an extension so we prefer not to + use one for executables. +
++ However, for libraries it's important to know what language it is and + sometimes there's a need to have similar libraries in different + languages. This allows library files with identical purposes but + different languages to be identically named except for the + language-specific suffix. +
+ ++ There are too many security issues with shell that make it nearly + impossible to secure sufficiently to allow SUID/SGID. While bash does + make it difficult to run SUID, it's still possible on some platforms + which is why we're being explicit about banning it. +
+
+ Use sudo
to provide elevated access if you need it.
+
STDERR
.
+ + This makes it easier + to separate normal status from actual issues. +
+
+ A function to print out error messages along with other status
+ information is recommended.
+
+ Every file must have a top-level comment including a brief overview of + its contents. + A + copyright notice + and author information are optional. +
+
+ Example:
+
+ It should be possible for someone else to learn how to use your + program or to use a function in your library by reading the comments + (and self-help, if provided) without reading the code. +
++ All function comments should contain: +
+ Example:
+
+ This follows general Google coding comment practice. Don't comment + everything. If there's a complex algorithm or you're doing something + out of the ordinary, put a short comment in. +
+ ++ This matches the convention in the C++ + Guide. +
++ TODOs should include the string TODO in all caps, followed by your + username in parentheses. A colon is optional. It's preferable to put a + bug/ticket number next to the TODO item as well. +
+
+ Examples:
+
+
+ While you should follow the style that's already there for files that + you're modifying, the following are required for any new code. +
+ ++ Use blank lines between blocks to improve readability. Indentation is + two spaces. Whatever you do, don't use tabs. For existing files, stay + faithful to the existing indentation. +
+ ++ If you have to write strings that are longer than 80 characters, this + should be done with a here document or an embedded newline if possible. + Literal strings that have to be longer than 80 chars and can't sensibly + be split are ok, but it's strongly preferred to find a way to make it + shorter. +
+
+
+ If a pipeline all fits on one line, it should be on one line. +
+
+ If not, it should be split at one pipe segment per line with the pipe
+ on the newline and a 2 space indent for the next section of the pipe.
+ This applies to a chain of commands combined using '|' as well as to
+ logical compounds using '||' and '&&'.
+
; do
and ; then
on the same line as the
+ while
, for
or if
.
+
+ Loops in shell are a bit different, but we follow the same principles
+ as with braces when declaring functions. That is: ; then
+ and ; do
should be on the same line as the if/for/while.
+ else
should be on its own line and closing statements
+ should be on their own line vertically aligned with the opening
+ statement.
+
+ Example:
+
+ These are meant to be guidelines, as the topic seems too controversial for
+ a mandatory regulation.
+
+ They are listed in order of precedence.
+
+ Don't brace-quote single character shell
+ specials / positional parameters, unless strictly necessary
+ or avoiding deep confusion.
+
+ Prefer brace-quoting all other variables.
+
+
$(command)
instead of backticks.
+
+ Nested backticks require escaping the inner ones with \
.
+ The $(command)
format doesn't change when nested and is
+ easier to read.
+
+ Example:
+
[[ ... ]]
is preferred over [
,
+ test
and /usr/bin/[
.
+
+ [[ ... ]]
reduces errors as no pathname expansion or word
+ splitting takes place between [[
and ]]
and
+ [[ ... ]]
allows for regular expression matching where
+ [ ... ]
does not.
+
+ Bash is smart enough to deal with an empty string in a test. So, given
+ that the code is much easier to read, use tests for empty/non-empty
+ strings or empty strings rather than filler characters.
+
+ To avoid confusion about what you're testing for, explicitly use
+ -z
or -n
.
+
+ As filenames can begin with a -
, it's a lot safer to
+ expand wildcards with ./*
instead of *
.
+
eval
should be avoided.
+
+ Eval munges the input when used for assignment to variables and can set
+ variables without making it possible to check what those variables
+ were.
+
+ The implicit subshell in a pipe to while can make it difficult to track
+ down bugs.
+
+ Use a for loop if you are confident that the input will not contain
+ spaces or special characters (usually, this means not user input).
+
+ Using process substitution allows redirecting output but puts the
+ commands in an explicit subshell rather than the implicit subshell that
+ bash creates for the while loop.
+
+ Use while loops where it is not necessary to pass complex results
+ to the parent shell - this is typically where some more complex
+ "parsing" is required. Beware that simple examples are probably
+ more easily done with a tool such as awk. This may also be useful
+ where you specifically don't want to change the parent scope variables.
+
::
. Parentheses are required after the function name.
+ The keyword function
is optional, but must be used
+ consistently throughout a project.
+
+ If you're writing single functions, use lowercase and separate words
+ with underscore. If you're writing a package, separate package names
+ with ::
. Braces must be on the same line as the function
+ name (as with other languages at Google) and no space between the
+ function name and the parenthesis.
+
+ The function
keyword is extraneous when "()" is present
+ after the function name, but enhances quick identification of
+ functions.
+
+ Variables names for loops should be similarly named for any variable
+ you're looping through.
+
+ Constants and anything exported to the environment should be
+ capitalized.
+
+ Some things become constant at their first setting (for example, via
+ getopts). Thus, it's OK to set a constant in getopts or based on a
+ condition, but it should be made readonly immediately afterwards.
+ Note that declare
doesn't operate on global variables
+ within functions, so readonly
or export
is
+ recommended instead.
+
+ This is for consistency with other code styles in Google:
+ maketemplate
or make_template
but not
+ make-template
.
+
readonly
or declare -r
to ensure they're
+ read only.
+
+ As globals are widely used in shell, it's important to catch errors
+ when working with them. When you declare a variable that is
+ meant to be read-only, make this explicit.
+
local
. Declaration
+ and assignment should be on different lines.
+
+ Ensure that local variables are only seen inside a function and its
+ children by using local
when declaring them. This avoids
+ polluting the global name space and inadvertently setting variables
+ that may have significance outside the function.
+
+ Declaration and assignment must be separate statements when
+ the assignment value is provided by a command substitution; as
+ the 'local' builtin does not propagate the exit code from the
+ command substitution.
+
+ If you've got functions, put them all together near the top of the
+ file. Only includes, set
statements and setting constants
+ may be done before declaring functions.
+
+ Don't hide executable code between functions. Doing so makes the code + difficult to follow and results in nasty surprises when debugging. +
+ +main
is required for scripts long enough
+ to contain at least one other function.
+
+ In order to easily find the start of the program, put the main
+ program in a function called main
as the bottom most
+ function. This provides consistency with the rest of the code base as
+ well as allowing you to define more variables as local
+ (which can't be done if the main code is not a function). The last
+ non-comment line in the file should be a call to main
:
+
+ Obviously, for short scripts where it's just a linear flow,
+ main
is overkill and so is not required.
+
+ For unpiped commands, use $?
or check directly via an
+ if
statement to keep it simple.
+
+ Example:
+
+ Bash also has the PIPESTATUS
variable that allows checking
+ of the return code from all parts of a pipe. If it's only necessary to
+ check success or failure of the whole pipe, then the following is
+ acceptable:
+
+ However, as PIPESTATUS
will be overwritten as soon as you
+ do any other command, if you need to act differently on errors based on
+ where it happened in the pipe, you'll need to assign
+ PIPESTATUS
to another variable immediately after running
+ the command (don't forget that [
is a command and will
+ wipe out PIPESTATUS
).
+
+ We prefer the use of builtins such as the Parameter Expansion
+ functions in bash(1)
as it's more robust and portable
+ (especially when compared to things like sed).
+
+ Example:
+
+ Use common sense and BE CONSISTENT. +
++ Please take a few minutes to read the Parting Words section at the bottom + of the C++ Guide. +
++Revision 1.25 +
+ +