Shell の基礎知識

【Shell-Tips】getoptsとusageを実装してみる。

シェルには、コマンドのオプシヨンを解析したリチェックしたりするための、getoptsというコマンドが用意されています。

レビュー時にいつも思うのは、この「getOpts」を使用するエンジニアが少ないこと・・

「getOpts」コマンドは、シェルに対して「-」と"アルファベット1文字"でオプションを指定された場合、それを解析するコマンドです。オプションによって挙動を変えたい時にcase文と共に用います。

実際には習うより慣れろが正しいため、下記にサンプルを実装します。

「getOpts」コマンド

「getOptsコマンドを使うと何がうれしいの?」とよく聞かれることがあります。特にうれしいことはありませんが(笑う・・楽です

もし、シェルスクリプトの引数処理で何かの制御をおなう場合、一番初めに考えれらるのが「if」文だと思いますが、「if」文で引数を制御する場合はパラメータの順番に気を遣わなければならなくなります。

仮にバックアップ用のシェルスクリプト「backup.sh」を作成した場合、必要となる要素は「バックアップ対象」と「バックアップ格納先」になると思います。

ハードコーディング(ソースべた書き)でも良いのですが、それだと「backup.sh」が汎用的に使用できないモノになってしまうため、通常はまず引数で情報の受け渡しを考えるはずです。

if文の場合

# バックアップシェル実行形式
$ backup.sh <バックアップ対象> <バックアップ先パス

# 「backup.sh」内部の引数チェックロジック
#!/bin/sh
checkArgs() {
  if [ -f ${1} ]; then
    src=<バックアップ対象
  fi
  if [ -d ${2} ]: then
    dst=<バックアップ先パス
  fi
}

上記がその際に考えられる実行形式になると思います。

この場合、もし第一引数の<バックアップ対象>に値がはいっていなかった場合どうなるでしょう。値が空であるため、第二引数の<バックアップ先>が第一引数として実行されてしまうのです。

# バックアップシェル実行形式
$ backup.sh <バックアップ対象(空)> <バックアップ先パス

# 「backup.sh」内部の引数チェックロジック
#!/bin/sh
checkArgs() {
  if [ -f ${1} ]; then
    src=<バックアップ先パス
  fi
  if [ -d ${2} ]: then
    dst=
  fi
}

チェックが甘くて正常終了してしまった場合、あるはずのバックアップが存在しないことになってしまいます。

getOptsの場合

判り易くバックアップ対象を「-s(source)」、バックアップ先パスを「-d(destination)」としておきます。

# バックアップシェル実行形式
$ backup.sh -s <バックアップ対象> -d <バックアップ先パス

#!/bin/sh
#-s /-d オプションを指定した場合に出すメッセージを変更する
while getopts s:d: opts
do
  case $opts in
    s ) src=$OPTARG ;;
    d) dst=$OPTARG ;;
    * ) usage
       exitLog ${JOB_WR} ;;
  esac
done;

while」文の隣に「getOpts」コマンドを記述します。getoptsの次に書かなくてはならない引数は、このシェルスクリプトで処理させようとするオプションを並べたものになります。

もしそのオプションが値を必要とするものならば、その直後に「:(コロン)」を付けます。つまり「while getopts s:d: opts」となります。

:(コロン)」を付けたオプションの値は、$OPTARGと言いう変数に自動的に格納されます。よって「while」文直下の「case」文の処理では、$OPTARGに代入された値をスクリプト内の変数へ代入します。「src=$OPTARG

上記のロジックの場合、「-s(source)」、バックアップ先パスを「-d(destination)」何方でもないオプション(例えば[ r ]など)が引数と渡された場合、「case」文の「*)」でキャッチされます。

上記の例では「usage」がコールされ、処理が「exitLog」へ引き渡されます。

「Usege」関数

この「Usage」関数は、特にシェルに用意されているモノでありません。「ヒアドキュメント」を使用して、作成したシェルの実行方法や引数などを表示する自作関数です。

記述方法は簡単で、「ヒアドキュメント」を関数かしただけです。

実際に作成してみます。

usage() {

cat <<EOUSAGE
-----------------------------------------------------------------
Usage: $0 [< options >]

Options:
-b backup_target : Specifies the target file or target to backcup.
-m destination_path : Specify the backup storage directory path.

------------------------------------------------------------------
EOUSAGE
}

これだけです。「$0」は実行しているスクリプト名を表示します。つまり自分の名前です。

EOUSAGEは「End Of Usage」の略です。特に制約等はありませんので開始と終了が同じ文字列なら「EOF」でもなんでもかまいません。

このように「ヒアドキュメント」以外に、特にロジックというロジックはありません。(笑

上記「usage」は、「case」文の「*)」でキャッチされ、実行されます。つまり間違えた引数を指定してシェルを実行した場合、エラーと一緒に出力される自作ヘルプメッセージです。

「usage」の実行結果

どうでしょう? それなりに見えませんか?

「オレ(ワタシ)って意外といけるんじゃね?」と思っていただけると嬉しいです。

最後に、上記を実行したシェルスクリプトを載せておきます。

実行シェルスクリプトを作成する

本スクリプト利用により発生した利用者の損害全てに対し、いかなる責任をも負わないものとし、損害賠償をする一切の義務はないものとします。

よく読まれている記事

1

Shellとは? Shellとは、人間の理解できる言葉を機会へ伝えるプログラムです。 Linux環境でコマンドプロンプト画面を開いているとき、常にShellは起動している状態です。 「Shell」とは ...

2

Linuxは主にサーバー用として利用されるOSです。大規模な基幹システムの開発者、ロボットや家電開発等の組み込み系エンジニア、ネットワーク機器やデータベースに携わるインフラエンジニアは触れることが多い ...

3

プログラミング言語を習得しようと思った時、必ずと言っていいほど候補として挙げられるのが「Java」というプログラミング言語です。 「Java」は、現在日本で最も使われている言語であり、非常に人気のある ...

4

この記事は、Linuxについて勉強している初心者の方向けに「Shellスクリプト」について解説します。最後まで読んで頂けましたら、Shellスクリプトはどのような役割を担っているのか?を理解出来るよう ...

-Shell の基礎知識