|
|
Original version by Mike Shapiro
Updated with contributions from the OpenSolaris Shell Project
This document describes the shell coding style used for all the ON shell script changes integrated into Solaris.
All new shell code should conform to this coding standard, which is intended to match our existing C coding standard.
When in doubt, think "what would be the C-Style equivalent?"
Similar to cstyle, the basic format is that all lines are indented by TABs, and continuation lines (which in the shell end with "\") are indented by an equivalent number of TABs and then an additional four spaces, e.g.
To match cstyle, the sh token equivalent to the C "{" should appear on the same line, separated by a ";", as in:
DO NOT use the test built-in. Sorry, executive decision. In our Bourne shell, the test built-in is the same as the "[" built-in (if you don't believe me, try "type test" or refer to usr/src/cmd/sh/msg.c). So please do not write:
instead use:
In the Korn shell, the [[ ]] syntax is preferred, as this adds additional operators not available in the Bourne shell, such as short-circuit && and ||:
In the Korn shell, you may also use the (( )) syntax for more natural arithmetic expressions, for instance you may replace:
with
It is permissible to use && and || to construct shorthand for an "if" statement in the case where the if statement has a single consequent line:
instead of the longer:
DO NOT combine && with { }, as in:
Use a complete "if-then-fi" construct for this instead.
The proper way to write an infinite loop in the Bourne shell is to use the ":" built-in, which evaluates to true (exit status 0). This is better than using "true", because that is *not* a built-in in the Bourne shell and thus runs /bin/true.
Recall that "if" and "while" operate on the exit status of the statement to be executed. In the shell, zero (0) means true and non-zero means false. The exit status of the last command which was executed is available in the $? variable. When using "if" and "while", it is typically not necessary to use $? explicitly, as in:
Instead, you can more concisely write:
Or, when appropriate:
DO NOT attempt to make pseudo-booleans by setting variables to "true" and "false" and then running the variable as a command instead of using a comparison test. This is non-idiomatic and confusing to many long-time shell programmers.
Use:
Not:
Variable references begin with $ and *may* have their name enclosed in {}'s. I prefer to only see the {}'s when required. Do not spuriously enclose all your variable names in braces, like this:
This is kind of like writing all your C variable assignments like this:
It compiles, but it looks stupid.
Braces are required around variable names in two specific cases:
(1) when you are forming the string concatenation of your variable with another string:
and (2) when you are using one of the various substitution/assignment operators:
For our init scripts, I prefer that you adopt a shell variable naming scheme where capitalization provides additional meaning (as in our C style): use CAPITAL letters for variables that are exported into the environment, or are equivalent to C constants or #defines. Use lowercase letters for other variable names:
This helps your reader immediately understand the implication of modifying a given variable (i.e. whether it will be inherited by child processes).
Quick review of the quoting basics:
single quotes ('') mean quote but do not expand variable or backquote substitutions.
Double quotes ("") mean quote but allow expansion.
Backquotes (``) mean execute the command and substitute its standard output
(note: stderr is unchanged and may "leak" through unless properly redirected)
Use whatever quotes are appropriate for your situation, but please do not unnecessarily quote everything (also see 7 above).
For example, references to variables controlled by your script do not have to be quoted unless you are expecting your variable to expand to multiple tokens, or to the empty string.
However, any variable which contains values from outside the script, such as user input or filenames, should be quoted to avoid errors from special characters, including whitespace. Remember that an increasing number of filenames will contain spaces on Solaris systems used as CIFS file servers from Windows hosts.
In ksh scripts, $(command) syntax is preferred over `command` for better nesting and fewer issues with escaping special characters.
DO NOT test for (non-)/empty strings by comparing to "" or ''. ALWAYS use the test operators -n (non-zero-length string) and -z (zero-length string):
Shell comments are preceded by the '#' character. Place single-line comments in the right-hand margin. Use an extra '#' above and below the comment in the case of multi-line comments:
It is always a good idea to be careful about $PATH settings and pathnames when writing shell scripts. This allows them to function correctly even when the user invoking your script has some strange $PATH set in their environment.
There are two acceptable ways to do this:
(1) make *all* command references in your script use explicit pathnames:
or (2) explicitly reset $PATH in your script:
DO NOT use a mixture of (1) and (2) in the same script. Pick one method and use it consistently.
When passing user input to commands, if the first operand of a command is a variable, use -- for any command that accepts this to flag the end of arguments to avoid problems if the variable expands to a value starting with -.
The proper interpreter magic for a Solaris 11 shell script should be simply either #!/bin/sh
or #!/bin/ksh. The -p flag is not necessary with ksh93.
For Solaris 10 and older, it should be one of these:
On Solaris 10 and later, use mktemp(1) to generate temporary files and directories in /tmp or /var/tmp instead of relying on $$ to generate unique filenames.
Don't use the C shell for any scripts. Executive decision. End of discussion.
Terms of Use
|
Privacy
|
Trademarks
|
Copyright Policy
|
Site Guidelines
|
Site Map
|
Help
Your use of this web site or any of its content or software indicates your agreement to be bound by these Terms of Use.
© 2012, Oracle Corporation and/or its affiliates.