OpenSolaris
Collectives
Discussions
Documentation
Download
Source Browser
Free CD
Log-in
|
en
Community Group on
:
Bourne/Korn Shell Coding Conventions
Top Menu
Show
:
Comments
Attachments
History
Information
Print
:
Print
Print preview
Export as PDF
Export as RTF
Export as HTML
Export as XAR
Wiki code for
Bourne/Korn Shell Coding Conventions
Hide Line numbers
1: = Bourne/Korn Shell Coding Conventions 2: 3: [[Mike Shapiro>>mailto:mike.shapiro@sun.com]] 4: 5: This document describes the shell coding style used for all the init.d script changes integrated into Solaris. 6: 7: All new init.d shell code should conform to this coding standard, which is intended to match our existing C coding standard. 8: 9: When in doubt, think "what would be the C-Style equivalent?" 10: 11: |**Table of contents** 12: |[[1 Basic Format>>#Basic_Format]] 13: [[2 If, For, and While>>#If.2C_For.2C_and_While]] 14: [[3 Test Built-in>>#Test_Built-in]] 15: [[4 Single-line if-statements>>#Single-line_if-statements]] 16: [[5 Infinite Loops>>#Infinite_Loops]] 17: [[6 Exit Status and If/While Statements>>#Exit_Status_and_If.2FWhile_Statements]] 18: [[7 Variable References>>#Variable_References]] 19: [[8 Variable Naming>>#Variable_Naming]] 20: [[9 Quoting>>#Quoting]] 21: [[10 Testing for (Non-)Empty Strings>>#Testing_for_.28Non-.29Empty_Strings]] 22: [[11 Commenting>>#Commenting]] 23: [[12 Pathnames>>#Pathnames]] 24: [[13 Interpreter Magic>>#Interpreter_Magic]] 25: [[14 Use of the C shell>>#Use_of_the_C_shell]] 26: 27: == Basic Format 28: 29: 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. 30: 31: {{{ 32: cp foo bar 33: cp some_realllllllllllllllly_realllllllllllllly_long_path \ 34: to_another_really_long_path 35: 36: }}} 37: 38: == If, For, and While 39: 40: To match cstyle, the sh token equivalent to the C "{" should appear on the same line, separated by a ";", as in: 41: 42: {{{ 43: if [ $x = hello ]; then 44: echo $x 45: fi 46: 47: for i in 1 2 3; do 48: echo $i 49: done 50: 51: while [ $# -gt 0 ]; do 52: echo $1 53: shift 54: done 55: 56: }}} 57: 58: == Test Built-in 59: 60: **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: 61: 62: {{{ 63: if test $# -gt 0; then 64: 65: }}} 66: 67: instead use: 68: 69: {{{ 70: if [ $# -gt 0 ]; then 71: 72: }}} 73: 74: In the Korn shell, the [[ ]] syntax is preferred, as this adds additional operators not available in the Bourne shell, such as short-circuit && and ||: 75: 76: {{{ 77: if [[ $# -gt 0 && $? -eq 0 ]]; then 78: 79: }}} 80: 81: == Single-line if-statements 82: 83: 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: 84: 85: {{{ 86: [ $# -eq 0 ] && exit 0 87: 88: }}} 89: 90: instead of the longer: 91: 92: {{{ 93: if [ $# -eq 0 ]; then 94: exit 0 95: fi 96: 97: }}} 98: 99: **DO NOT** combine && with { }, as in: 100: 101: {{{ 102: [ $# -eq 0 ] && { 103: do something 104: do something else 105: } 106: 107: }}} 108: 109: Use a complete "if-then-fi" construct for this instead. 110: 111: == Infinite Loops 112: 113: The proper way to write an infinite loop in the 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 and thus runs /bin/true. 114: 115: {{{ 116: while :; do 117: echo infinite loop 118: done 119: 120: }}} 121: 122: == Exit Status and If/While Statements 123: 124: 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: 125: 126: {{{ 127: grep foo /etc/passwd >/dev/null 2>&1 128: if [ $? -eq 0 ]; then 129: echo found 130: fi 131: 132: }}} 133: 134: Instead, you can more concisely write: 135: 136: {{{ 137: if grep foo /etc/passwd >/dev/null 2>&1; then 138: echo found 139: fi 140: 141: }}} 142: 143: Or, when appropriate: 144: 145: {{{ 146: grep foo /etc/passwd >/dev/null 2>&1 && echo found 147: 148: }}} 149: 150: == Variable References 151: 152: 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: 153: 154: {{{ 155: foo=${bar} 156: 157: }}} 158: 159: This is kind of like writing all your C variable assignments like this: 160: 161: {{{ 162: foo = (bar); 163: 164: }}} 165: 166: It compiles, but it looks stupid. 167: 168: Braces are required around variable names in two specific cases: 169: 170: (1) when you are forming the string concatenation of your variable with another string: 171: 172: {{{ 173: [ $install = yes ] && root="/a/" || root="/" 174: hosts=${root}etc/inet/hosts 175: 176: }}} 177: 178: and (2) when you are using one of the various substitution/assignment operators: 179: 180: {{{ 181: echo ${BASEDIR:-/a} 182: 183: }}} 184: 185: == Variable Naming 186: 187: 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: 188: 189: {{{ 190: BASEDIR=/a; export BASEDIR 191: argc=$# 192: 193: }}} 194: 195: This helps your reader immediately understand the implication of modifying a given variable (i.e. whether it will be inherited by child processes). 196: 197: == Quoting 198: 199: Quick review of the quoting basics: 200: 201: {{{ 202: single quotes (’’) mean quote but do not expand variable or backquote substitutions. 203: Double quotes ("") mean quote but allow expansion. 204: Backquotes (``) mean execute the command and substitute its standard output 205: (note: stderr is unchanged and may "leak" through unless properly redirected) 206: 207: }}} 208: 209: Use whatever quotes are appropriate for your situation, but please do not unnecessarily quote everything (also see 7 above). 210: 211: For example, variable references do not have to be quoted unless you are expecting your variable to expand to multiple tokens, or to the empty string. 212: 213: == Testing for (Non-)Empty Strings 214: 215: 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): 216: 217: {{{ 218: if [ -z "$foo" ]; then 219: echo ’you forgot to set $foo’ 220: fi 221: 222: if [ -n "$BASEDIR" ]; then 223: echo "\$BASEDIR is set to $BASEDIR" 224: fi 225: 226: }}} 227: 228: == Commenting 229: 230: 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: 231: 232: {{{ 233: cp foo bar # Copy foo to bar 234: 235: # 236: # Modify the permissions on bar. We need to set them to root/sys 237: # in order to match the package prototype. 238: # 239: chown root bar 240: chgrp sys bar 241: 242: }}} 243: 244: == Pathnames 245: 246: 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. 247: 248: There are two acceptable ways to do this: 249: 250: (1) make *all* command references in your script use explicit pathnames: 251: 252: {{{ 253: /usr/bin/chown root bar 254: /usr/bin/chgrp sys bar 255: 256: }}} 257: 258: or (2) explicitly reset $PATH in your script: 259: 260: {{{ 261: PATH=/usr/bin; export PATH 262: 263: chown root bar 264: chgrp sys bar 265: 266: }}} 267: 268: **DO NOT** use a mixture of (1) and (2) in the same script. Pick one method and use it consistently. 269: 270: == Interpreter Magic 271: 272: The proper interpreter magic for your shell script should be one of these: 273: 274: {{{ 275: #!/bin/sh Standard Bourne shell script 276: 277: #!/sbin/sh Init.d script or other Bourne shell script which must run 278: early in single-user mode (when /usr is not mounted). 279: #!/bin/ksh -p Standard Korn shell script. You should always write ksh 280: scripts with -p so that $ENV (if set by the user) is not 281: sourced into your script by the shell. 282: 283: }}} 284: 285: == Use of the C shell 286: 287: Don’t use the C shell for any scripts. Executive decision. End of discussion.
Search
Collectives
Community Group
Academic and Research
Accessibility
Advocacy
Appliances
Approachability
Architecture Process and Tools
BrandZ
Chinese Users
Community Advisory Board
Databases
Desktop
Device Drivers
Distribution
Documentation
DTrace
Emerging Platforms
Fault Management
Games on OpenSolaris
HA Clusters
HPC Developer
Installation and Packaging
Internationalization and Localization
Laptop
Logical Domains
Modular Debugger (MDB)
Networking
NFS
Observability
OpenSolaris Governing Board (OGB)
OpenSolaris Printing
OS/Net (ON)
Performance
Power Management
PowerPC
Security
Service Management Facility (smf(5))
Software Porters
Solaris Volume Manager
Storage
Systems Administration Community Group
Testing
Tools Home
Unix File Systems (UFS)
Website Community
X Window System
Xen
ZFS
Zones
Project
ADSL Modem Enhancement
ARC Process Definition
ARM Platform Port
Automatic Data Migration
BIND Update
Bluetooth Stack & Drivers
Brocade FC HBA - Initiator
Brocade FC HBA - Target
Brussels - unified network link configuration
Caiman, Solaris Install Revisited
Celeste
Český portál
Chime Visualization Tool for DTrace
CIFS client for Solaris
CIFS Server
Clearview: Network Interface Coherence
Cluster Agent: Informix Dynamic Server
Cluster Agent: OpenSolaris Container
Cluster Agent: OpenSolaris xVM
Cluster Agent: Oracle E-Business Suite
Cluster agent: PostgreSQL
Cluster Agent: Samba
Cluster Agent: Tomcat
CMT
Coarse Data Flow Parallelism
Colorado: Open HA Cluster on OpenSolaris
Command Assistant
Common Array Manager
Companion - /opt/sfw: Free and Open Source software
COMSTAR: Common Multiprotocol SCSI Target
Content
Contest
CPU Observability
Credentials Process Groups
Crossbow: Network Virtualization and Resource Control
Crypto KMS Agent Toolkit
Cryptographic Framework
Data Migration Manager
Data Tethers
Deutsches Portal
Device Detection Tool
Device Driver Utility
Device Manager
Device Mapper
Direct Rendering Infrastructure & 3D drivers
DTrace Guide
Duckwater: Simplified name services management
Easy Tools
Emancipation
Emulex Fibre Channel Device Driver
Emulex Advanced Ethernet Device Driver
Enable/Enhance Solaris support for Intel Platform
Enhance the support of USB webcams
Enhanced SMF Profiles
Enhancements for AMD-based Platforms
Erlang DTrace Integration
Ethernet bridge module for Solaris
Evaluate Conary
Events Registry
Ext3 file system support
F/OSS Package Base
Facilitation
Fibre Channel over Ethernet
Fine Grained Access Policy (FGAP)
Fingerprint Authentication
Flexible Mandatory Access Control
Forensic Tools
Fully Open X Project
Fuse on Solaris
gcore
Generic Machine Check Architecture Improvements
Google SOC
HA-JBoss
HA-MySQL
Hadoop Live CD
Hitachi
HoneyComb Fixed Content Storage
HPC Stack
Image Packaging System
Improved Performance MIB
Indiana
Innovation Awards
Input Method
Intel Graphics
Internet Key Exchange, version 2
Interrupt Resource Management
IP Datapath Refactoring
IP over Infiniband
IPsec Tunnel Reform
iSCSI Extensions for Remote DMA (iSER)
iSNS Server
JeOS - Just enough Operating System
JKstat - a java binding for libkstat
Journaled File System (JFS)
K Desktop Environment
Kerberos
Kernel Sockets
Kernel SSL Enhancements
Key Management Framework
Korn Shell 93 integration/migration project
Labeled IPsec
LatencyTOP
Layer 2 Filtering
LDoms Manager
Lending
libMicro - portable microbenchmarks
Link Layer Discovery
Live Media: Technologies for distributions running from CD and other media
Locale Data
lofi compression and cryptography support
lx64 brand
Media Management System
Mega_sas
Mexico
MilaX minimal Live Distribution
MIPS Platform Port
Mozilla DTrace
MRSL.NONsharedDevice
Multi-lingual Glossary
Multi-pathing software (MPxIO)
Multiple disk sector size support
Multiple DOI
Muskoka: An open repository for OpenSolaris technical content
Navigator
Nemo: A Framework for High-Performance Networking
Network Auto-Magic
Network Data Management Protocol
Network MIBs
Network Storage
Network Time Protocol (NTP)
Nevada Globalization
New Design of 4over6 Mechanism Based on OpenSolaris
NFS RDMA transport update and performance analysis
NFS Server in non-Global Zones
NFS version 4.1 pNFS
NFSv4 namespace extensions
Nightingale: Port Songbird to OpenSolaris
NPort ID Virtualization (NPIV)
NUMA
Object Storage Device (OSD) support for Solaris
OHACGE Script Based Plug-in
ON/Nevada (ONNV) Project
Open Development Infrastructure
Open HA Cluster Utilities
Open Sound System
OpenGrok
OpenPegasus CIM Server
OpenRTI
OpenSolaris Busybox
OpenSolaris Desktop
OpenSolaris Hispano
OpenSolaris Security Audit
OpenSolaris support for the QEMU processor emulator: host and guest
PEF: Packet Event Framework
Performance Wrappers
Pkgfactory
Polski Portal
Portail Francophone
Portal Brasil
Portals
Power Management Usability Interfaces
Presto: Automatic Printing Configuration
Printable Many Page Solaris Manuals
Promise SuperTrak RAID HBA Driver
QLogic Converged Network Adapter GLDv3 NIC Driver
Quagga Routing Protocol Suite Integration
RAID Configuration Utility
RBridge (IETF TRILL) support
RDMA Offload Framework
Reno: Login Process Enhancements for Interop
Resource Management
s10brand
SAM/QFS
SCM Migration Project
SCSI RDMA Protocol
SDcard Drivers
Sensor Abstraction Layer
Session Initiation Protocol
SFW
Shell: bourne shell, korn shell, C shell, etc.
Sierra: Intel WiFi Chipsets Support
Simple Panels
SM-HBA Based SAS HBA Management
SMF Documentation
Solaris iSCSI Target
Solaris PowerPC Port
SourceJuicer
Sparks: name service switch/nscd enhancements
Squashfs
Star integration/migration project
Starfish
Starter Kit
Storage Power Management
Sun Security Toolkit
Sun StorageTek Availability Suite
Support for OpenFabrics User Verbs / API on OpenSolaris OS
Support gcc4/GCCfss in Solaris
Suspend/Resume
SVR4 Packaging
Systemz
Tamarack: Removable Media Enhancements in Solaris
Tesla: OpenSolaris Enhanced Power Management
Test Development
Tickless Kernel Architecture
TIPC
Trademarks
Trusted networking interface policy database for Trusted Extensions
Trusted Platform Module support
Use Case
Validated Execution Project
Virtual Console
Virtual Network Machines
Visual Panels
Visualization for HPC
Volo
VRRP: Virtual Router Redundancy Protocol Implementation
VSCAN service
Web Stack
Website
Winchester: Schema mapping and ID mapping for AD Interoperability
Wireless USB Support
Wireless Wide Area Network
X Consolidation
x86 Generic FMA Topology Enumerator
Xen Gate
Xfce: A lightweight desktop environment
ZFS Boot and Install
ZFS on disk encryption support
Zone Manager
Zone Statistics
Русский портал
البوابة العربية
भारतीय पोर्टल
中国门户
日本ポータル
한국 포탈
User Group
Adelaide
Argentina
Arizona
Atlanta
Baltimore-Washington
Bangalore
Bangkok
Bangladesh
Beijing
Bélem
Berlin
Bhimavaram
Bloomington
Campus Ambassadors
Capital Region
Cardiff
Charlotte
Chengdu
Chennai
Chihuahua
Chile
Cleveland
Colombia
Columbus
Connecticut
Cracow
Czech
Dallas/Ft. Worth
Danish
Delaware
Edinburgh
Egypt
Finland
Florida
Front Range
FuZhou
Great Lakes
Greece
Hangzhou
Hawaii
HeFei
Houston
Hyderabad
Indonesia
Irish
Israel
Italian
Jinan
Kabul
Kansas City
Latvia
London
Madurai
Manchester
Mato Grosso
Melbourne
Minas Gerais
Minnesota
Montreal
Moscow
Mumbai
Munich
NEA
Netherlands
New England
New York City
New Zealand
NIT Hamirpur
Noroeste
Oklahoma City
Osnabrück
Peru
Philadelphia
Piaski
Pittsburgh
Porto Alegre
Puget Sound
Pune
Queensland
Research Triangle Park
Romania
Russia
San Antonio
San Diego
San Francisco
São Paulo
Scottish
Serbia
Shanghai
Shenzhen
Silicon Valley
Singapore
Slovak
South African
Southern Connecticut
St. Louis
Sweden
Switzerland
Sydney
Szczecin
Taiwan
Tecum
Thames Valley
Tokyo
Toronto
Trondheim
Tulsa
Turkey
Ukraine
University of Melbourne
Vale do Paraíba
Vancouver
Venezuela
Welsh - Cymru
Wisconsin
Xi'an
Subsites
Code Reviews
Code Repositories
Package Search
Bugster
Bugzilla
Test Machines
Planet
Mailing Lists
Elections & Polls
ARC Case Logs
Source Juicer
Package Factory
User Authentication
Community Group on Pages
CRT
Advocates & Sponsors
Becoming a Sponsor
Becoming a CRT Advocate
Charter
RTI nits to avoid
Sponsor Tasks
Developing Solaris
Quality Death Spiral
Developer's Reference
Introduction
Prerequisites
The Source Tree, part 1
The Source Tree, part 2
Building OpenSolaris
Installing and Testing OpenSolaris
Integration Procedure
Best Practices and Requirements
Glossary
findunref and unreferenced files
ONNV Flag Days, Heads Ups, and Project Integration History
Builds 101-105
Builds 106-110
Builds 111-115
Builds 116-120
Builds 121-125
Builds 126-130
Builds 21-25
Builds 26-30
Builds 31-35
Builds 36-40
Builds 41-45
Builds 46-50
Builds 51-55
Builds 56-60
Builds 61-65
Builds 66-70
Builds 71-75
Builds 76-80
Builds 81-85
Builds 86-90
Builds 91-95
Builds 96-100
Installation (from source) Quickstart
Annotated nightly(1) Mail Example
Currently Known Issues
Putback Logs
Development Process
Schedule
Bourne/Korn Shell Coding Conventions
wx