Bashスクリプトのテスト方法:変数、定数、サニティチェック
このシリーズの第1回では、最初の1行だけの小さなBashスクリプトを作成し、シェルスクリプトを作成する理由を探りました。第2回では、他のBashプログラムの出発点となるシンプルなテンプレートの作成を始め、そのテストを行いました。第3回では、シンプルなHelp関数の作成と使用、関数の使い方、-hなどのコマンドラインオプションの処理方法を学びました。
この第4回(最終回)では、変数とその初期化、そしてプログラムが適切な条件下で実行されることを保証するためのサニティチェック(健全性チェック)について解説します。このシリーズの目的は、将来のBashプログラミングプロジェクトのテンプレートとして使える動作するコードを構築することです。共通要素をテンプレートにあらかじめ用意しておくことで、新しいプログラミングプロジェクトを容易に開始できるようにするのが狙いです。
変数
Bashシェルは、すべてのプログラミング言語と同様に変数を扱えます。変数とは、何らかの値を格納しているメモリ上の特定の場所を指す象徴的な名前です。変数の値は変更可能、つまり「変数」です。変数の使用に慣れていない場合は、先に拙記事「How to program with Bash: Syntax and tools」をお読みください。
では、変数を使用する際の良い習慣を見ていきましょう。
私はスクリプトで使用するすべての変数に初期値を設定するようにしています。これはテンプレートスクリプトの手続きセクションの直後、メインプログラム本体の最初の部分、オプション処理の前にあります。各変数を適切な値で初期化しておくことで、未初期化変数が比較や算術演算でエラーを引き起こすのを防げます。また、変数の一覧を一箇所にまとめることで、スクリプトに想定されるすべての変数とその初期値を一目で把握できます。
現時点では、この小さなスクリプトには$optionという単一の変数しかありません。以下の行を挿入して設定します:
################################################################################ ################################################################################ # Main program # ################################################################################ ################################################################################ # Initialize variables option="" ################################################################################ # Process the input options. Add options as needed. # ################################################################################
この変更によって何も壊れていないか、正常に動作するかテストしてください。
定数
定数も変数の一種です。少なくともそう扱うべきです。コマンドラインインターフェース(CLI)プログラムでは、ハードコードされた値の代わりに、可能な限り変数を使用してください。特定の値(ディレクトリ名、ファイル名、テキスト文字列など)を一度しか使わないと思っても、変数を作成し、ハードコードされた値を置く場所でその変数を使ってください。
例えば、プログラムのメイン本体で出力されるメッセージは、文字列リテラルのecho "Hello world!"です。これを変数に変更しましょう。まず、変数初期化セクションに以下のステートメントを追加します:
Msg="Hello world!"
そして、プログラムの最後の行を以下のように変更します:
echo "$Msg"
結果をテストしてください。
サニティチェック(健全性チェック)
サニティチェックとは、プログラムが正しく動作するために真である必要がある条件をテストするものです。例えば、「プログラムはrootユーザーとして実行されなければならない」「特定のディストリビューションとリリースで実行されなければならない」といった条件です。ここでは、実行ユーザーがrootであるかをチェックする機能をシンプルなプログラムテンプレートに追加します。
プログラムはそれを起動したユーザーとして実行されるため、rootユーザーが実行しているかどうかのテストは簡単です。
idコマンドを使うと、プログラムが実行されている数値ユーザーID(UID)を特定できます。オプションなしで実行すると、いくつかの情報が返されます:
[student@testvm1 ~]$ id uid=1001(student) gid=1001(student) groups=1001(student),5000(dev)
-uオプションを使うと、ユーザーのUIDのみが返され、Bashプログラムで容易に利用できます:
[student@testvm1 ~]$ id -u 1001 [student@testvm1 ~]$
以下の関数をプログラムに追加します。Help手続きの後に追加しましたが、手続きセクションのどこにでも配置できます。ロジックは、UIDがゼロ(常にrootユーザーのUID)でない場合、プログラムを終了するというものです:
################################################################################
# Check for root. #
################################################################################
CheckRoot()
{
if [ `id -u` != 0 ]
then
echo "ERROR: You must be root user to run this program"
exit
fi
}
次に、変数の初期化の直前にCheckRoot手続きの呼び出しを追加します。まず、studentユーザーとしてプログラムを実行してテストします:
[student@testvm1 ~]$ ./hello ERROR: You must be root user to run this program [student@testvm1 ~]$
次に、rootユーザーとして実行します:
[root@testvm1 student]# ./hello Hello world! [root@testvm1 student]#
この特定のサニティテストが常に必要というわけではないため、CheckRootの呼び出しはコメントアウトしておきますが、すべてのコードはテンプレートに残しておきます。こうすることで、将来のプログラムでこのコードを使う際は、呼び出しのコメントを外すだけで済みます。
完成したコード
上記の変更を加えた後のコードは以下のようになります:
#!/usr/bin/bash
################################################################################
# #
# scriptTemplate #
# #
# Use this template as the beginning of a new program. Place a short #
# description of the script here. #
# #
# Change History #
# 11/11/2019 David Both Original code. This is a template for creating #
# new Bash shell scripts. #
# Add new history entries as needed. #
# #
################################################################################
################################################################################
################################################################################
# #
# Copyright (C) 2007, 2019 David Both #
# LinuxGeek46@both.org #
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #
# #
################################################################################
################################################################################
################################################################################
################################################################################
# Help #
################################################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
################################################################################
# Check for root. #
################################################################################
CheckRoot()
{
# If we are not running as root we exit the program
if [ `id -u` != 0 ]
then
echo "ERROR: You must be root user to run this program"
exit
fi
}
################################################################################
################################################################################
# Main program #
################################################################################
################################################################################
################################################################################
# Sanity checks #
################################################################################
# Are we running as root?
# CheckRoot
# Initialize variables
option=""
Msg="Hello world!"
################################################################################
# Process the input options. Add options as needed. #
################################################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # incorrect option
echo "Error: Invalid option"
exit;;
esac
done
echo "$Msg"
最後の演習
お気づきかもしれませんが、コード内のHelp機能は、コードに存在しない機能を参照しています。最後の演習として、作成したコードテンプレートにそれらの機能を追加する方法を考えてみてください。
まとめ
この記事では、プログラムがrootとして実行されているかどうかをチェックするサニティテストを行う関数をいくつか作成しました。プログラムが少し複雑になってきたため、テストの重要性が増し、完全なテストにはより多くのテストパスが必要になります。
このシリーズでは、最小限のBashプログラムを見て、スクリプトを少しずつ構築していく方法を学びました。その結果、他のより有用なBashスクリプトの出発点となり、新しいスクリプトの開始を容易にする有用な要素を含むシンプルなテンプレートが完成しました。
ここまででお分かりいただけたかと思います:コンパイル済みプログラムは必要であり、非常に重要なニーズを満たします。しかしシステム管理者にとっては、常により良い方法があります。業務の自動化ニーズを満たすには、常にシェルスクリプトを使用してください。シェルスクリプトは開かれており、その内容と目的は知ることができます。異なる要件に容易に対応できます。私はシスアドミンの役割で必要なことで、シェルスクリプトでは達成できないものを見つけたことがありません。
このシリーズで作成したものはあくまで始まりに過ぎません。より多くのBashプログラムを書くにつれて、頻繁に使用するコードの断片がさらに見つかり、それらをプログラムテンプレートに含めるべきだと気づくでしょう。
参考資料
- How to program with Bash: Syntax and tools
- How to program with Bash: Logical operators and shell expansions
- How to program with Bash: Loops
この記事シリーズは、David Bothの3部構成Linux自己学習コース「Using and Administering Linux—Zero to SysAdmin」の第2巻、第10章に一部基づいています。
-
星空観察の夜に役立つ!Linuxのナイトビジョン用Bashスクリプト「redscreen.sh」の使い方
Linuxはサーバーや開発者の環境で使われることがよく話題になりますが、実は天文学の分野でも幅広く活用されています。Linux向けには、星図やスカイマップ、望遠鏡駆動システムを制御するインターフェースなど、天体観測に役立つツールが数多く存在します。しかし、天文学者にとって大きな課題のひとつが、暗闇の中で目の順応を保ちながらコンピューターを操作することです。 なぜ「暗順応」を守る必要があるのか 夜間の屋外で観測を行う際、天文学者は「暗順応(ダークアダプテーション)」と呼ばれる目の状態を維持しなければなりません。人間の目が薄暗い環境に完全に慣れるまでには、最大で30分ほどかかるとされています。とこ
-
PCの不要なプログラムを完全にアンインストールする6つの方法
整理整頓されたクリーンなPCは、散らかったPCよりも常に快適です。高いパフォーマンスとセキュリティを維持するためには、PCを常に最適な状態に保つことが大切です。不要なプログラムが溜まると動作が重くなり、ハードディスクの容量も圧迫されてしまいます。 そのため、定期的なお掃除は必須ですが、実は簡単な作業ではありません。不要なプログラムをアンインストールしようとしても、痕跡が残ってしまったり、さまざまな理由で削除できないことも少なくありません。 そんなときはどうすればいいのでしょうか?この記事では、不要なプログラムを完全にアンインストールするためのさまざまな方法をご紹介します。 最も一般的で手軽な