検索条件
全2件
(1/1ページ)
ここでは、自分が使いやすい規約にしてみました。
臨機応変に変更してください。
Google Shell guide といったものも存在します。
https://google.github.io/styleguide/shellguide.html
[Tips]
たとえば、Linux の for 文で C 言語のような ( i=0 ; i < x ; i++ ) という形式を利用できます。これは便利なのですが bash の独自実装なので汎用性が下がります。
[Tips]
csh / tcsh / fish / bash / dash といった、シェルを複数利用するようなプロジェクトでは、拡張子をそれぞれに合わせた方が良いと思います。
bash しか利用しないことが分かっている環境で、シバンにも bash 指定のみの場合は .sh でも不都合はないと思います。
.src は、内容として bash なのですが source コマンド (ビルトインでは . コマンド) で呼ぶことを意図しています。
[Tips]
権限を 755 や 700 で運用することは多いのですが、セキュリティを考慮すると、権限は最小限にすべきでしょう。
ここでは本番環境を想定していて、作成するユーザと、実行するユーザが異なることを考慮しています。
所有者は、更新できるが実行できない。前提条件を満たさない、不用意な実行を阻止できる。
グループ(実行者)は、更新できないが実行できる。JP1 のような自動実行ユーザのスクリプト改変を阻止できる。
段落 | 内容 | 備考 |
---|---|---|
ヘッダ | シバンやスクリプトの目的などを記載する。 | |
変数宣言 | スクリプトが利用する変数を宣言もしくは指定する。 | source (.) での指定も可 |
関数宣言 | スクリプトが利用する関数を宣言する。 | source (.) での指定も可 |
メイン処理 | スクリプトが目的とする処理を行う。 | |
終了処理 | 一時利用のために展開していたテンポラリファイルの削除などを行う。 |
[Tips]
コメントに日本語を使わない場合は ASCII を指定してもよいです。
むしろ ASCII として認識されるでしょう。
[Tips]
Windows でスクリプトを書くと、改行コードは考慮から漏れがちです。
Linux や UNIX 上で書くと気にしなくても良いのですが、プロジェクトの進行状況や管理方法次第で、どうしても Windows 端末での開発を行わなければならない状況もあります。
致命的ではない文字コードやインデントも指定するのですから、致命的エラーとなる改行コードは指定しておきましょう。
[Tips]
タブ (半角スペース4つもしくは8つ) だと、横に広がりすぎて視認性が悪くなることがあります。
#!/bin/bash
[Tips]
シバンとヘッダは、ひとまとめにしてしまっても良いかもしれません。
もしくは、拡張子の指定でシバンも固定することになるでしょう。
項目 | 内容 | 備考 | |
---|---|---|---|
スクリプト名 | Script name | ファイル名称を記載する。 | |
変更 | Modify | 変更日・変更者・変更内容を記録する。 |
項目 | 内容 | 備考 | |
---|---|---|---|
スクリプト名 | Script name | ファイル名称を記載する。 | |
目的 | Purpose | スクリプトの目的を記載する。 | |
引数 | Option | 指定可能なオプションを記載する。 | |
変更 | Modify | 作成日を記録する。 | 日付と担当者をひとまとめにしてもよい。 |
作成者 | Auther | 作成者を記載する。 | |
更新日 | Update | 更新日を記載する。 | 更新内容も併記するとなおよい。 |
権限 | Permission | 実行者や権限を記載する。 |
# Script name: example.shサンプル 2
# スクリプト名: example.sh # 目的: スクリプトサンプル
# システム
[Tips]
私がスネークケースよりキャメルケースのほうが読みやすいと感じるタイプなので、キャメルケースを指定しています。
メリット・デメリットを考慮して、規定するのが良いです。
変数名はスクリプト上部にまとめて宣言しておくので、エディタの画面分割機能でコピペすることが前提としてあります。
画面分割は vim でも可能です。
変数名が短くても、何回も手入力していればタイポする可能性は高いです。
文字 | 用途 | 備考 |
---|---|---|
p | 汎用パラメータ | Parameter を意図 |
n | 数値用パラメータ | Number を意図 |
f | 0 を真としたフラグ情報 | Flag を意図 |
t | ループで頻繁に書き換える使い捨てパラメータ | Temporary を意図 |
i | ループ用に予約 | Integer を意図 (while/until での数値ループに使用) |
s | ループ用に予約 | String を意図(for での文字列ループに使用) |
文字 | 用途 | 備考 |
---|---|---|
Path | 絶対パスでファイル情報を指定する場合に利用 | |
Dir | ディレクトリ情報の場合に利用 | 文字列の最後は / で終わること。 |
Name | ファイル情報の場合に利用 | ディレクトリは含めないこと。 |
Enable | フラグ管理など、0 で有効とする場合に利用 |
文字 | 用途 | 備考 |
---|---|---|
fn | 関数 (ファンクション) であることを示す |
fnLog "Sample message"
fnDebug "Debug message"
fnErr "Standard Error message"
[ -d "/etc" ] || fnErrEnd 14 "/etc" [ -f "/etc/hosts" ] || fnErrEnd 15 "/etc/hosts" [ -x "/bin/ps" ] || fnErrEnd 13 "/bin/ps"
[Tips]
- help といったロングオプションを使いたい場合は、getopts ではなく、引数そのものを case で解析するほうがよいと思います。
#!/bin/bash ############################################################ # Script name: example.sh # Modify : yyyy.mm.dd 名前 初版作成 ############################################################ ### Parameter and Variable ################################# pCommon=./src/common.src if [ -f "${pCommon}" ]; then . ${pCommon} else echo "${pCommon} not exist." exit 1 fi ### Function ############################################### fnEnd() { # スクリプト内で異常終了する際の Exit Status と、メッセージ内容の定義 nExitStatus=$1 case "${nExitStatus}" in 0 ) fnLog "Script ${0##*/} end.";; * ) fnErr "Unknown error ($2)"; nExitStatus=1;; esac exit ${nExitStatus} } ### Main ################################################### fnLog "Script ${0##*/} start." ## オプション解析 while getopts h OPT; do case ${OPT} in h ) fnDebug "Option h used." echo "Usage ${0##*/} [-h]" echo " [-h] help messages." fnEnd 0 ;; * ) fnDebug "Unknown option used." fnErrEnd 10 "${OPT}" ;; esac done # xxx 処理 ### End #################################################### fnEnd 0 ############################################################
# 共通ファイル (common.src) ### Parameter and Variable ################################# ## ディレクトリ pLogDir="/var/log/script/" ## ファイル pLogName=$(basename ${0%.*}.log) ## パス # ログファイル pLogPath="${pLogDir}${pLogName}" # ヌルクリア i="" s="" # Exit Status nExitStatus=0 ## フラグ fDebugEnable=0 ### Function ############################################### # 目的:ログ出力 fnLog() { echo "$(date +'%Y/%m/%d %H:%M:%S') $*" >> ${pLogPath} } # 目的:デバッグ出力 fnLog() { [ "${fDebugEnable}" -eq "0" ] && fnLog "[Debug] $*" } # 目的:エラー出力 fnErr() { # ログ出力 fnLog "$*" # 標準エラー出力 echo "$(date +'%Y/%m/%d %H:%M:%S') $*" >&2 } # 目的: エラー終了 fnErrEnd() { nExitStatus=${1} # 引数確認 if [ -z "${nExitStatus}" ]; then fnErr "Not argument." exit 1 fi case "${nExitStatus}" in 0 ) fnErr "Function (fnErrEnd) argument error."; nExitStatus=1;; 10 ) fnErr "Argument error ($2)";; 11 ) fnErr "Read permission not exist ($2)";; 12 ) fnErr "Write permission not exist ($2)";; 13 ) fnErr "Exec permission not exist ($2)";; 14 ) fnErr "Directory not exist ($2)";; 15 ) fnErr "File not exist ($2)";; * ) fnErr "Unknown error ($2)";; esac exit ${nExitStatus} } ||
#!/bin/bashsleep で待ち時間が発生している間に、End を書き換えたり、追記したり、ファイルを消したりすればよいわけです。
echo "Start"
sleep 30
echo "End"
$ sudo chmod -w sample.sh
#!/bin/bash before="$(ls -l $0)" functionDiff() { after="$(ls -l $0)" [ "${before}" == "${after}" ] || echo "NG" } functionDiffまた、md5sum といった、ファイルの破損や編集を検知するためのチェックサム関係コマンドを利用するのも良いです。
### example.conf # Parameter or Variable example="EXAMPLE" # Function exFunction() { echo "${example}" }
#!/bin/bash ### Script name: example.sh # Include . ./example.conf # Main exFunction
#!/bin/bash # script name : example.sh echo a echo b echo c
envbar=$(cat /tmp/example.sh) $ echo ${envbar} #!/bin/bash # script name : example.sh echo a echo b echo c $ $ $ echo "${envbar}" #!/bin/bash # script name : example.sh echo a echo b echo c
envbar=$(cat /tmp/example.sh) $ echo "${envbar}" | bash - a b c