Bashスクリプトをより実用的にする5つのテクニック
システム管理者は、さまざまなタスクを遂行するためにBashスクリプトを日常的に書いています。短い数行のものから、かなり長大なものまで幅広いでしょう。
ソフトウェアベンダーが提供するインストールスクリプトを見たことはありますか?顧客のシステムに損害を与えず、正しくインストールが完了することを保証するために、多くの関数やロジックが組み込まれています。筆者は長年の経験の中で、Bashスクリプトを強化するためのさまざまな手法を蓄積してきました。本記事では、その一部を紹介し、読者の皆さんの助けになれば幸いです。
はじまりは単純なコマンドの連結から
筆者が学び始めた頃のBashスクリプトは、コマンドを並べただけのものでした。主な目的は、Webコンテンツのデプロイといった定型的なシェル操作の時短でした。例えば、静的コンテンツをApache Webサーバーのホームディレクトリに展開するタスクは、次のようなものでした。
cp january_schedule.tar.gz /usr/apache/home/calendar/
cd /usr/apache/home/calendar/
tar zvxf january_schedule.tar.gz
確かに時間とタイピングの手間は節約できましたが、長期的に見ればあまり有用なスクリプトとは言えません。やがて筆者は、ソフトウェアパッケージの作成、ソフトウェアのインストール、ファイルサーバーのバックアップなど、より複雑なタスクをBashスクリプトで実現する方法を身につけていきました。
1. 条件分岐を活用する
他の多くのプログラミング言語と同様に、条件分岐は強力かつ不可欠な機能です。コンピュータープログラムがロジックを実行できるのは、この条件分岐のおかげです。以降で紹介する例の多くも、条件分岐のロジックが基盤となっています。
基本的な条件分岐には「if」文を使います。これにより、特定の条件をテストし、その結果に応じてスクリプトの動作を制御できます。例えば、Javaのbinディレクトリが存在するかどうかを確認すれば、Javaがインストール済みかどうかを判断できます。見つかった場合は、Javaアプリケーションから呼び出せるよう、実行可能ファイルのパスを更新します。
if [ -d "$JAVA_HOME/bin" ] ; then
PATH="$JAVA_HOME/bin:$PATH"
2. 実行できるユーザーを制限する
スクリプトを特定のユーザーだけが実行できるようにしたい場合があるでしょう。Linuxにはユーザーやグループの標準的なパーミッションがあり、SELinuxで同様の保護を強化することもできますが、スクリプト自体にロジックを組み込むという選択肢もあります。例えば、特定のWebアプリケーションの起動スクリプトを、その所有者だけが実行できるようにしたいケースが考えられます。rootユーザーのみに実行を限定するコードを書くこともできます。
このようなロジックで使える環境変数がLinuxにはいくつかあります。$USERはユーザー名を提供し、$UIDはユーザーID(UID)を返します。スクリプトの場合、$UIDは実行ユーザーのUIDになります。
特定のユーザーに限定する
最初の例は、複数のアプリケーションサーバーインスタンスが稼働するマルチホスティング環境で、jboss1ユーザーだけがスクリプトを実行できるようにするものです。「if」文は「実行ユーザーがjboss1ではないか?」を判定しています。条件が真の場合、最初のecho文が表示され、続くexit 1でスクリプトが終了します。
if [ "$USER" != 'jboss1' ]; then
echo "Sorry, this script must be run as JBOSS1!"
exit 1
fi
echo "continue script"
rootユーザーに限定する
次の例では、rootユーザーだけがスクリプトを実行できるようにしています。rootのUIDは0なので、if文で-gt(より大きい)オプションを使い、0より大きいUIDを持つすべてのユーザーの実行を禁止します。
if [ "$UID" -gt 0 ]; then
echo "Sorry, this script must be run as ROOT!"
exit 1
fi
echo "continue script"
3. 引数を受け取る
ほかの実行可能プログラムと同じように、Bashスクリプトも引数を入力として受け取れます。その例をいくつか紹介します。その前に、良いプログラミングとは「やりたいことを実行できるアプリケーション」だけでなく、「やりたくないことを実行できないアプリケーション」を書くことだと理解しておきましょう。
筆者は、引数がない場合にスクリプトが破壊的な操作を行わないよう必ずチェックを入れています。以下のコードは、引数の個数を表す$#が0であるかどうかを確認し、真であればスクリプトを終了させるものです。
if [ $# -eq 0 ]; then
echo "No arguments provided"
exit 1
fi
echo "arguments found: $#"
複数の引数を扱う
スクリプトには複数の引数を渡せます。各引数を参照する内部変数は$1、$2、$3のように番号が増えていきます。先ほどの例に次の行を追加すると、最初の3つの引数を表示できます。実際には、引数の総数に応じた適切なハンドリングのための追加ロジックが必要ですが、ここでは説明を簡単にするためシンプルな例としています。
echo $1 $2 $3
これらの引数変数について話していると、「0番は飛ばしたのか?」と思った方もいるかもしれません。
その通り、飛ばしました。しかし、それには理由があります。$0という変数は確かに存在し、非常に便利だからです。その値は、実行中のスクリプト名そのものです。
echo $0
実行時にスクリプト名を参照する重要な理由の一つは、スクリプト名を含む名前のログファイルを生成することです。最もシンプルな形は、echo文による追記でしょう。
echo test >> $0.log
ただし実際には、ログが自分のユースケースに役立つ場所・形式で記録されるよう、もう少しコードを追加することをおすすめします。
4. ユーザー入力を受け付ける
スクリプトの実行中にユーザー入力を受け付けられるのも便利な機能です。最もシンプルなのは、ユーザーに何かを入力してもらう形です。
echo "enter a word please:"
read word
echo $word
選択肢を提示することもできます。
read -p "Install Software ?? [Y/n]: " answ
if [ "$answ" == 'n' ]; then
exit 1
fi
echo "Installation starting..."
5. 失敗時には終了する
筆者は数年前、最新版のJava開発キット(JDK)をPCにインストールするスクリプトを書きました。このスクリプトは、JDKアーカイブを特定のディレクトリに展開し、シンボリックリンクを更新して、alternativesユーティリティで新しいバージョンをシステムに認識させます。もしJDKアーカイブの展開に失敗したまま処理を続けると、システム全体のJava環境が壊れる可能性があります。そこで筆者は、アーカイブの展開が成功しない限り、後続のシステム変更を行わずスクリプトを中断させるようにしました。以下はそのスクリプトからの抜粋です。
tar kxzmf jdk-8u221-linux-x64.tar.gz -C /jdk --checkpoint=.500; ec=$?
if [ $ec -ne 0 ]; then
echo "Installation failed - exiting."
exit 1
fi
$?変数の使い方は、次の短いワンライナーでも簡単に確認できます。
ls T; ec=$?; echo $ec
まずtouch Tでファイルを作成してから上記コマンドを実行すると、ecの値は0になります。次にrm Tでファイルを削除し、同じコマンドを再実行してみましょう。今度はTが見つからないためlsがエラーを報告し、ecの値は2になります。
このエラー報告の仕組みを利用すれば、前述のようなロジックを組み込み、スクリプトの挙動を自在に制御できます。
まとめ
高度な機能が必要ならPythonやC、Javaなどの言語を使うべきだと考えがちですが、必ずしもそうではありません。Bashスクリプト言語は非常に強力であり、その有用性を最大限に引き出すためには学ぶべきことがたくさんあります。本記事のいくつかの例が、Bashでのコーディングの可能性に気づくきっかけになれば幸いです。
-
Bash-it – スクリプトとエイリアスを一元管理できるBashフレームワーク
Bash-itは、Bash 3.2+向けに設計されたコミュニティ製のBashコマンド&スクリプト集です。自動補完、テーマ、エイリアス、カスタム関数などが最初から含まれており、日々の作業でシェルスクリプトや独自コマンドを開発・管理・活用するための実用的なフレームワークを提供します。 Bashシェルを日常的に使っていて、散らかりがちなスクリプト、エイリアス、関数を簡単に一元管理したいなら、Bash-itは最適な選択肢です。~/binディレクトリや.bashrcファイルを汚すことなく、Bash-itをフォーク/クローンして、快適なシェル環境づくりを始めましょう。 LinuxへのBash-itのインス
-
Linuxで効果的なBashスクリプトを書くための実践テクニック10選
シェルスクリプトは、Linuxで学べる最も手軽なプログラミング手法のひとつです。システム管理におけるタスクの自動化や、簡単なユーティリティ・ツールの開発など、管理者にとって必須のスキルとも言えます。 本記事では、効果的かつ信頼性の高いbashスクリプトを書くために役立つ、実用的な10のヒントを紹介します。 1. スクリプトには必ずコメントを書く これはシェルスクリプトに限らず、あらゆるプログラミングで推奨される基本プラクティスです。コメントを適切に記述しておけば、後から自分や他の人がスクリプトを読んだときに、各部分が何をしているのかを素早く理解できます。 コメントは # 記号で定義します。 #