シェルスクリプトテンプレート[定休日]
質問
このご提案をいbash/kshスクリプトテンプレートを使用してすべての新規作成されたスクリプト?
または、後の #!
ライン)が行ヘッダとファイル名をタイプ概要、利用、戻り値は、author(s),戦い場合は80文字ます。
すべての書類をラインとともに起動ダブルハッシュ記号 ##
いgrepして簡単に地var名前に追加され、"__".
その他のベス?ヒント?命名規則?うを返しコード?
コメントをバージョン管理:を使用していまSVNも部のエンタープライズは別のレポ、ここでしか記述します。からの問合せ先Qの場合はありません@author。用件と同様javadocsにはメリットでもシェルの文脈で、まぁ、私が間違っています。
解決
ノーマンの回答を6行に拡張しますが、最後の行は空白です:
#!/bin/ksh
#
# @(#)$Id$
#
# Purpose
3行目はバージョン管理識別文字列です-実際には、(SCCS)プログラム@(#)
で識別できるSCCSマーカー「what
」と、ファイルは、私が個人的に使用するデフォルトのVCSであるRCSの下に置かれます。 RCSプログラムident
は、$Id$
のように見える拡張形式の$Id: mkscript.sh,v 2.3 2005/05/20 21:06:35 jleffler Exp $
を選択します。 5行目は、スクリプトの上部にその目的の説明が必要であることを思い出させます。この単語をスクリプトの実際の説明に置き換えます(たとえば、その後にコロンがありません)。
その後、基本的にシェルスクリプトの標準はありません。表示される標準フラグメントはありますが、すべてのスクリプトに表示される標準フラグメントはありません。 (私の議論は、スクリプトがBourne、Korn、またはPOSIX(Bash)シェル表記で書かれていることを前提としています。#!
印章の後にCシェル派生物を置く人が罪を犯している理由についてはまったく別の議論があります。)
たとえば、このコードは、スクリプトが中間(一時)ファイルを作成するたびに何らかの形または形式で表示されます。
tmp=${TMPDIR:-/tmp}/prog.$$
trap "rm -f $tmp.?; exit 1" 0 1 2 3 13 15
...real work that creates temp files $tmp.1, $tmp.2, ...
rm -f $tmp.?
trap 0
exit 0
最初の行は一時ディレクトリを選択し、ユーザーが代替を指定しなかった場合のデフォルトは/ tmpです($ TMPDIRは非常に広く認識されており、POSIXによって標準化されています)。次に、プロセスIDを含むファイル名プレフィックスを作成します。これはセキュリティ対策ではありません。これは、スクリプトの複数のインスタンスが互いのデータを踏みつけないようにする単純な同時実行性の尺度です。 (セキュリティのために、非公開ディレクトリで予測不可能なファイル名を使用してください。)2行目は、シェルがSIGHUP(1)のいずれかのシグナルを受信した場合に、 'rm
'および 'exit
'コマンドが実行されるようにします、SIGINT(2)、SIGQUIT(3)、SIGPIPE(13)、またはSIGTERM(15)。 「trap
」コマンドは、テンプレートに一致する中間ファイルを削除します。 exit $exitval
コマンドは、ステータスがゼロ以外であることを保証し、何らかのエラーを示します。 0の「$arg0
」は、何らかの理由でシェルが終了した場合にもコードが実行されることを意味します-「実際の作業」とマークされたセクションの不注意をカバーします。最後のコードは、終了時にトラップを解除する 前に残っている一時ファイルを削除し、最終的にゼロ(成功)ステータスで終了します。明らかに、別のステータスで終了する場合は、usage
およびgetopts
行を実行する前に変数に設定してから、$(...)
を使用してください。
通常、スクリプトからパスとサフィックスを削除するには以下を使用します。そのため、エラーを報告するときにsed
を使用できます。
arg0=$(basename $0 .sh)
エラーを報告するためにシェル関数をよく使用します:
error()
{
echo "$arg0: $*" 1>&2
exit 1
}
エラー出口が1つまたは2つしか存在しない場合、この関数は気にしません。これ以上ある場合は、コーディングを簡素化するためです。また、$PERL
という多かれ少なかれ精巧な関数を作成して、コマンドの使用方法の概要を示します-使用する場所が複数ある場合のみ。
もう1つのかなり標準的なフラグメントは、 $SED
シェル組み込み:
vflag=0
out=
file=
Dflag=
while getopts hvVf:o:D: flag
do
case "$flag" in
(h) help; exit 0;;
(V) echo "$arg0: version $Revision$ ($Date$)"; exit 0;;
(v) vflag=1;;
(f) file="$OPTARG";;
(o) out="$OPTARG";;
(D) Dflag="$Dflag $OPTARG";;
(*) usage;;
esac
done
shift $(expr $OPTIND - 1)
または:
shift $(($OPTIND - 1))
<!> quot; $ OPTARG <!> quot;を囲む引用符;引数内のスペースを処理します。 Dflagは累積されますが、ここで使用される表記法は、引数内のスペースの追跡を失います。その問題を回避する(非標準の)方法もあります。
最初のシフト表記は、どのシェルでも機能します(または '${VAR:=value}
'の代わりにバックティックを使用した場合に機能します。2番目は現代のシェルで機能します。括弧の代わりに角括弧で代替することもできますが、これは機能するので、それが何であるかを気にすることはありません。
最後の秘Oneは、GNUと非GNUの両方のバージョンのプログラムがよくあることです。使用するプログラムを選択できるようにしたいです。したがって、私のスクリプトの多くはvariを使用しています次のような能力:
: ${PERL:=perl}
: ${SED:=sed}
そして、Perlまたは<=>を呼び出す必要がある場合、スクリプトは<=>または<=>を使用します。これは、動作が異なる場合-動作バージョンを選択できる場合-またはスクリプトの開発中に役立ちます(スクリプトを変更せずにコマンドにデバッグ専用オプションを追加できます)。 (詳細については、シェルパラメーターの展開をご覧ください。 <=>および関連する表記法。)
他のヒント
使用法のドキュメントには、##行の最初のセットを使用します。これを最初に見た場所を思い出せません。
#!/bin/sh
## Usage: myscript [options] ARG1
##
## Options:
## -h, --help Display this message.
## -n Dry-run; only show what would be done.
##
usage() {
[ "$*" ] && echo "$0: $*"
sed -n '/^##/,/^$/s/^## \{0,1\}//p' "$0"
exit 2
} 2>/dev/null
main() {
while [ $# -gt 0 ]; do
case $1 in
(-n) DRY_RUN=1;;
(-h|--help) usage 2>&1;;
(--) shift; break;;
(-*) usage "$1: unknown option";;
(*) break;;
esac
done
: do stuff.
}
任意のコードですが、それにより発売されるのは以下の短いヘッダ:
# Script to turn lead into gold
# Copyright (C) 2009 Joe Q Hacker - All Rights Reserved
# Permission to copy and modify is granted under the foo license
# Last revised 1/1/2009
常に変化をログになってコードのヘッダーを常時からバージョン管理システムがものすごく不便です。最終更新日を示す人の方のスクリプトです。
ばかなか出会えないおいしさに頼るbashisms、#!/bin/bashは/bin/shとしてshはPOSIX呼び出しの任意しています。ば/bin/shポイントbashは、多くの機能がoffのままで/bin/sh.最Linuxディストリビューションのなかに依存するスクリプトbashismsてみてきました。
く、コメントはシェルスクリプトのような愚かなの読みのようなもの:
# I am not crazy, this really is the only way to do this
シェルスクリプティングするという単純なものである場合を書くのデモンストレーションを教える人かい)のコードがほとんどobviatesそのものです。
一部の貝殻ないようにフィードを入力地区)に変数です。私はこの日Busybox(共通救助シェル)も例外ではありません。作GLOBALS_OBVIOUSその代わりに、読みや、デバッグ経由で/bin/sh-x./script.sh.
私個人的に好きない論理を自分自身を仕事のパーサです。例えば、多くの人が書き:
if [ $i = 1 ]; then
... some code
fi
がんば:
[ $i = 1 ] && {
... some code
}
同様に、誰かが書き:
if [ $i -ne 1 ]; then
... some code
fi
...がん:
[ $i = 1 ] || {
... some code
}
の時間を使ってい従来の場合/その次に/elseがある場合は、その場合にスローします。
を決狂った例も携帯型のシェルコードについて学習することができます。での閲覧にconfigureスクリプトをほとんど無料ソフトウェアを使用しているパッケージautoconf.私は狂ったので6300ラインのコードに対応できるシステム毎されるとUNIXシェルです。いるような膨張がなかなかおもしろい研究の様々な携帯性hacks内..子どもの方がポイント/bin/shをzsh:)
はつだけアドバイスを日本語訳を見てもわかりませんで見なが拡大するこのドキュメント、すなわち
cat << EOF > foo.sh
printf "%s was here" "$name"
EOF
...が拡大$名、きれいに可変できます。解決す:
printf "%s was here" "\$name"
る休暇$名変数としてではなく、拡大します。
私もお勧めの学習に使うトラップに捕捉..利用者のハンドラとして定型コードです。語りランニングスクリプトを簡単にSIGUSR1はかなりお手軽:)
最新プログラムを書いているツール/コマンドライン指向の開始としてシェルスクリプト、その方法をプロトタイプにUNIXツールです。
きもののようにSHCのシェルスクリプトをコンパイラ、 ここにクリック!.
これは、スクリプトシェル(bashまたはksh)に使用するヘッダーです。
man
に似ており、usage()の表示にも使用されます。
#!/bin/ksh
#================================================================
# HEADER
#================================================================
#% SYNOPSIS
#+ ${SCRIPT_NAME} [-hv] [-o[file]] args ...
#%
#% DESCRIPTION
#% This is a script template
#% to start any good shell script.
#%
#% OPTIONS
#% -o [file], --output=[file] Set log file (default=/dev/null)
#% use DEFAULT keyword to autoname file
#% The default value is /dev/null.
#% -t, --timelog Add timestamp to log ("+%y/%m/%d@%H:%M:%S")
#% -x, --ignorelock Ignore if lock file exists
#% -h, --help Print this help
#% -v, --version Print script information
#%
#% EXAMPLES
#% ${SCRIPT_NAME} -o DEFAULT arg1 arg2
#%
#================================================================
#- IMPLEMENTATION
#- version ${SCRIPT_NAME} (www.uxora.com) 0.0.4
#- author Michel VONGVILAY
#- copyright Copyright (c) http://www.uxora.com
#- license GNU General Public License
#- script_id 12345
#-
#================================================================
# HISTORY
# 2015/03/01 : mvongvilay : Script creation
# 2015/04/01 : mvongvilay : Add long options and improvements
#
#================================================================
# DEBUG OPTION
# set -n # Uncomment to check your syntax, without execution.
# set -x # Uncomment to debug this shell script
#
#================================================================
# END_OF_HEADER
#================================================================
次に、使用する機能を示します。
#== needed variables ==#
SCRIPT_HEADSIZE=$(head -200 ${0} |grep -n "^# END_OF_HEADER" | cut -f1 -d:)
SCRIPT_NAME="$(basename ${0})"
#== usage functions ==#
usage() { printf "Usage: "; head -${SCRIPT_HEADSIZE:-99} ${0} | grep -e "^#+" | sed -e "s/^#+[ ]*//g" -e "s/\${SCRIPT_NAME}/${SCRIPT_NAME}/g" ; }
usagefull() { head -${SCRIPT_HEADSIZE:-99} ${0} | grep -e "^#[%+-]" | sed -e "s/^#[%+-]//g" -e "s/\${SCRIPT_NAME}/${SCRIPT_NAME}/g" ; }
scriptinfo() { head -${SCRIPT_HEADSIZE:-99} ${0} | grep -e "^#-" | sed -e "s/^#-//g" -e "s/\${SCRIPT_NAME}/${SCRIPT_NAME}/g"; }
入手するものは次のとおりです。
# Display help
$ ./template.sh --help
SYNOPSIS
template.sh [-hv] [-o[file]] args ...
DESCRIPTION
This is a script template
to start any good shell script.
OPTIONS
-o [file], --output=[file] Set log file (default=/dev/null)
use DEFAULT keyword to autoname file
The default value is /dev/null.
-t, --timelog Add timestamp to log ("+%y/%m/%d@%H:%M:%S")
-x, --ignorelock Ignore if lock file exists
-h, --help Print this help
-v, --version Print script information
EXAMPLES
template.sh -o DEFAULT arg1 arg2
IMPLEMENTATION
version template.sh (www.uxora.com) 0.0.4
author Michel VONGVILAY
copyright Copyright (c) http://www.uxora.com
license GNU General Public License
script_id 12345
# Display version info
$ ./template.sh -v
IMPLEMENTATION
version template.sh (www.uxora.com) 0.0.4
author Michel VONGVILAY
copyright Copyright (c) http://www.uxora.com
license GNU General Public License
script_id 12345
ここで完全なスクリプトテンプレートを取得できます: http:/ /www.uxora.com/unix/shell-script/18-shell-script-template
エラー検出を有効にすると、スクリプトの問題を早期に検出しやすくなります。
set -o errexit
最初のエラーでスクリプトを終了します。そうすれば、おそらくスクリプトの初期段階で何かに依存していたことを続けず、おそらく奇妙なシステム状態になってしまうでしょう。
set -o nounset
未設定変数への参照をエラーとして扱います。設定されていないrm -you_know_what "$var/"
で$var
などを実行しないようにすることは非常に重要です。変数を設定解除できることがわかっており、これが安全な状況である場合、${var-value}
を使用して、設定されていない場合は別の値を使用するか、設定されていない場合は${var:-value}
を使用して別の値を使用できますまたは空。
set -o noclobber
>
を挿入するつもりだった場所に<
を挿入する間違いを犯しやすくなり、読みたいファイルを上書きしてしまいます。スクリプト内のファイルを上書きする必要がある場合は、関連する行の前でこれを無効にし、後で再度有効にすることができます。
set -o pipefail
一連のコマンドの最初のゼロ以外の終了コード(ある場合)を、コマンドの完全なセットの終了コードとして使用します。これにより、パイプコマンドのデバッグが容易になります。
shopt -s nullglob
その表現に一致するファイルがない場合、/foo/*
globが literally として解釈されることを避けます。
これらすべてを2行で組み合わせることができます。
set -o errexit -o nounset -o noclobber -o pipefail
shopt -s nullglob
私のbashテンプレートは以下のとおりです(私の vim設定で設定します):
#!/bin/bash
## DESCRIPTION:
## AUTHOR: $USER_FULLNAME
declare -r SCRIPT_NAME=$(basename "$BASH_SOURCE" .sh)
## exit the shell(default status code: 1) after printing the message to stderr
bail() {
echo -ne "$1" >&2
exit ${2-1}
}
## help message
declare -r HELP_MSG="Usage: $SCRIPT_NAME [OPTION]... [ARG]...
-h display this help and exit
"
## print the usage and exit the shell(default status code: 2)
usage() {
declare status=2
if [[ "$1" =~ ^[0-9]+$ ]]; then
status=$1
shift
fi
bail "${1}$HELP_MSG" $status
}
while getopts ":h" opt; do
case $opt in
h)
usage 0
;;
\?)
usage "Invalid option: -$OPTARG \n"
;;
esac
done
shift $(($OPTIND - 1))
[[ "$#" -lt 1 ]] && usage "Too few arguments\n"
#==========MAIN CODE BELOW==========
お勧めします
#!/bin/ksh
それだけです。シェルスクリプトのヘビーウェイトブロックコメント?ウィリーズを取得します。
提案:
-
ドキュメントは、コメントではなくデータまたはコードである必要があります。少なくとも
usage()
関数。すべてのコマンドで--manオプションを使用して、kshおよびその他のASTツールがどのように文書化するかを見てください。 (Webサイトがダウンしているためリンクできません。) -
typeset
でローカル変数を宣言します。それが目的です。厄介なアンダースコアは不要です。
できることは、スクリプト<!> ampのヘッダーを作成するスクリプトを作成することです。お好みのエディターで自動的に開きます。私はこのサイトでそれをしている男を見ました:
#!/bin/bash -
#title :mkscript.sh
#description :This script will make a header for a bash script.
#author :your_name_here
#date :20110831
#version :0.3
#usage :bash mkscript.sh
#notes :Vim and Emacs are needed to use this script.
#bash_version :4.1.5(1)-release
#===============================================================================
一般的に、私は書くスクリプトごとに固執したいいくつかの規則を持っています。 私はすべてのスクリプトを、他の人が読むかもしれないという前提で書いています。
ヘッダーですべてのスクリプトを開始します、
#!/bin/bash
# [ID LINE]
##
## FILE: [Filename]
##
## DESCRIPTION: [Description]
##
## AUTHOR: [Author]
##
## DATE: [XX_XX_XXXX.XX_XX_XX]
##
## VERSION: [Version]
##
## USAGE: [Usage]
##
grep / searchを簡単にするために、この日付形式を使用します。 「[」ブレースを使用して、ユーザーが自分で入力する必要があるテキストを示します。 コメント外で発生する場合は、「#[」で開始しようとします。 そうすれば、誰かがそれらをそのまま貼り付けても、入力やテストコマンドと間違えられません。このスタイルを例として確認するには、manページの使用方法セクションを確認してください。
1行のコードをコメントアウトする場合は、単一の「#」を使用します。メモとしてコメントをするときは、二重の「##」を使用します。 /etc/nanorc
もその規則を使用します。実行しないように選択されたコメントを区別するのに役立ちます。注釈として作成されたコメントの詩。
すべてのシェル変数、CAPSで行うことを好みます。特に必要な場合を除き、4〜8文字を保持しようとします。名前は、可能な限り、その使用法に関連しています。
成功した場合は常に0で終了し、エラーの場合は1で終了します。スクリプトにさまざまな種類のエラーがある場合(実際に誰かを助けたり、何らかの方法で何らかのコードで使用できる場合)、1よりも文書化されたシーケンスを選択します。 一般に、終了コードは* nixの世界ではそれほど厳密には適用されません。残念ながら、私は良い一般的な番号スキームを見つけたことがありません。
引数を標準的な方法で処理するのが好きです。私はgetoptよりもgetoptsの方が好きです。 「読み取り」コマンドやifステートメントを使ってハックすることはありません。ネストされたifを避けるために、caseステートメントを使用することも好きです。長いオプションには翻訳スクリプトを使用しているため、-helpは-hがgetoptsを意味することを意味します。すべてのスクリプトをbash(受け入れられる場合)または汎用shで記述します。
bashで解釈されたシンボル(または解釈されたシンボル)をファイル名で使用したり、その名前を使用したりすることはありません。 具体的には... <!> quot; '`$ <!> amp; *#(){} []-、スペースには_を使用しています。
これらは単なる慣習であることに注意してください。粗雑なベストプラクティスですが、場合によってはラインの外に追い出されることがあります。最も重要なのは、プロジェクト全体およびプロジェクト内で一貫性を保つことです。