Bashスクリプトは、多くの困難なタスクを達成するのに役立ちます。
システム管理者は日常的に、長いか短いかにかかわらず、何らかのタスクを達成するためのスクリプトプログラムを書いています。
ソフトウェアパブリッシャが提供するインストール用のプログラムを見たことが ありますか?様々なユーザーのシステム構成に対応し、スムーズにインストールを完了するために、これらのスクリプトプログラムには多くの機能や論理分岐が含まれていることがよくあります。長年にわたり、私はスクリプトを改善するためのヒントをいくつか蓄積してきました。ここでは、スクリプトのサンプルを示すために、一連の短いスクリプト例のリストを示します。
最初の試み
cp january_schedule.tar.gz /usr/apache/home/calendar/cd /usr/apache/home/calendar/tar zvxf january_schedule.tar.gz
これで時間を節約でき、複数のコマンドを入力する必要も減りました。時間が経つにつれて、ソフトウェアパッケージの作成、ソフトウェアのインストール、ファイルシステムのバックアップなど、より難しいタスクにBashスクリプトを使用するスキルをさらに身につけました。
条件分岐構造
基本的な条件分岐構造は if 条件分岐構造です。特定の条件を満たすかどうかを判断することで、実行するスクリプトコマンドセグ メントを適切に選択するようにプログラムを制御できます。例えば、Javaがシステムにインストールされているかどうかを判断したい場合、システム上にJavaライブラリ・ディレクトリがあるかどうかを判断できます。そのようなディレクトリが見つかった場合、そのディレクトリ・パスを実行可能なプログラム・パスに追加し、Javaライブラリ・アプリケーションを呼び出すことができます。
if [ -d "$JAVA_HOME/bin" ] ; thenPATH="$JAVA_HOME/bin:$PATH"
以下は、限定された操作権限で実行できる操作の種類の例です。
スクリプトの実行を特定のユーザーだけに許可したい場合があります。ユーザーやグループに対するパーミッションの設定、SELinuxによる保護パーミッションの設定など、Linuxのパーミッション管理に加えて、スクリプトに論理的な判断を設定して実行パーミッションを設定することができます。同じような状況で、Web アプリケーションの所有者だけが Web サイトを初期化するスクリプトを実行できるようにしたい場合があります。スクリプトの実行をルート ユーザーに制限することもできます。これは、スクリプト・アプリケーションに論理的な判断を設定することで可能で、Linux にはその助けとなる環境変数がいくつか用意されています。そのうちのひとつが$USERで、これはユーザー名を保持し、もうひとつが$UIDで、これはユーザーの識別子を保持します。スクリプトでは、実行ユーザーのUID値が$UID変数に格納されます。
ユーザー名の決定
最初の例では、複数のアプリケーションサーバーのインスタンスがあるマルチユーザー環境で、ユーザー jboss1 だけがスクリプトを実行できるように指定しています。条件付き if 文は、本質的に "このスクリプトを要求しているユーザーは jboss1 ではないか" を判断します。この条件が true の場合、最初の echo 文が呼び出され、続いて exit 1 が呼び出され、スクリプトが終了します。
if [ "$USER" != 'jboss1' ]; thenecho "Sorry, this script must be run as JBOSS1!"exit 1echo "continue script"
ルートユーザー決定
次の例では、rootユーザーのみがスクリプトプログラムを実行でき るようにします。rootユーザーのユーザー識別子は0です。大なり小なり演算子を使用して条件判定が設定され、UID値が0より大きいすべてのユーザーがスクリプトを実行することが禁止されます。
if [ "$UID" -gt 0 ]; thenecho "Sorry, this script must be run as ROOT!"exit 1echo "continue script"
このプログラムは、パラメータを使って実施されます。
実行可能なプログラムには、コマンドライン・スクリプト・プログラムのように、実行オプションとして引数を指定することができます。ここでは、良いプログラムが書けるということは、単に実行させたいことを書けば良いということではなく、実行させたくない処理を実行させないようにする必要もあるということを示したいと思います。私は、プログラムを実行する際にパラメータを提供しないことで、十分な情報がない場合には破壊的なことをしないようなプログラムをスクリプト化したいと考えています。そのため、プログラムの最初のステップでは、コマンドラインに引数が与えられているかどうかをチェックします。これは、引数の数である$#が0かどうかで判断します。
if [ $# -eq 0 ]; thenecho "No arguments provided"exit 1echo "arguments found: $#"
複数の動作パラメータ
スクリプトプログラムに渡すことができるパラメータは1つではありません。スクリプトは、これらのパラメータを、名前が負でない整数のインクリメント、つまり$1、$2、$3といったインクリメントで識別される内部変数を使用して参照します。私は、前のプロシージャを拡張して、ユーザーから供給された最初の3つのパラメーターを次の行に出力しているだけです。明らかに、各パラメータに対する応答を持つには、もっと論理的な判断が必要です。したがって、ここでの例は、パラメータの使い方の簡単なデモンストレーションにすぎません。
echo $1 $2 $3
これらのパラメータ変数名について議論していると、"どうしてパラメータ変数名は$0をスキップするのだろう?"という疑問が出てくるかもしれません。
そうです、それには理由があります。変数名$0は確かに存在し、非常に便利なもので、実行中のスクリプト・プログラムの名前を格納します。
echo $0
プログラム実行中にプログラム名を参照する変数名を持つことが重要である理由の1つは、生成されるログファイルの名前にプログラム名を含めることが可能であり、これを行う最も簡単な方法はecho文を呼び出すことです。
echo test >> $0.log
もちろん、このログファイルが希望するパスに保存され、ログ名に有用な情報が含まれていることを確認するコードを追加したい場合もあるでしょう。
インタラクティブ入力
スクリプト・プログラムのもう1つの便利な機能は、実行中に入力を受け付ける機能です。最も単純なケースでは、ユーザーが何らかの情報を入力します。
echo "enter a word please:"read wordecho $word
また、プログラム実行中にユーザーが選択することもできます。
read -p "Install Software ?? [Y/n]: " answif [ "$answ" == 'n' ]; thenexit 1echo "Installation starting..."
スクリプト, エラーで実行終了
数年前、私は自分のコンピューターにJava Development Kitの最新バージョンをインストールするスクリプトを書きました。このスクリプトは、JDKファイルを特定のディレクトリに展開し、それらを更新するためにいくつかのシンボリックリンクを作成し、最新バージョンを使用するようにシステムに指示するためのちょっとしたセットアップを行いました。解凍プロセスにエラーがある場合、その後の操作を実行すると、システム全体がJava破損のために使用できなくなります。したがって、この場合はプログラムを終了する必要があります。解凍プロセスに失敗した場合、その後の更新を続行すべきではありません。次のステートメントがこれを実現します。
tar kxzmf jdk-8u221-linux-x64.tar.gz -C /jdk --checkpoint=.500; ec=$?if [ $ec -ne 0 ]; thenecho "Installation failed - exiting."exit 1
次の1行の文で、変数 $? の使い方を簡単に示します。
ls T; ec=$?; echo $ec
まず、touch Tコマンドを使ってTという名前のファイルを作成し、この1行コマンドを実行すると、変数ecの値は0になります。次に、rm Tコマンドを使ってファイルを削除し、この1行コマンドを実行すると、ファイルTが存在しないため、変数ecの値は2になり、lsコマンドは指定されたファイルが見つからないというエラーを報告します。
このエラーフラグを論理条件で使用し、先ほど使用した条件判定を参照することで、スクリプトファイルを希望通りにセットアップ操作を完了させることができます。
結論
複雑な機能を実行するには、PythonやC、Javaなどの高水準プログラミング言語を使用するのが適切だと感じるかもしれませんが、必ずしもそうではなく、スクリプトプログラミング言語も同様のタスクを実行するのに十分強力です。スクリプティングを最大限に活用するために学ぶべきことはたくさんありますが、ここで紹介するいくつかの例によって、スクリプティングがどれほど強力なものかを実感していただければ幸いです。





