わたしの名はフレイ 作家・デザイナー見習い
神々とともに生きる詩人 一等星シリウスの導きを信じて

シェルスクリプト

簡単な定型処理やバッチ処理、コマンド行のメモに使える

シェルスクリプトは、簡単な定型処理やバッチ処理、そしてコマンド行のメモに使えます。

たとえば、ホームページのデータを更新して、gitコミットし、lftpでサーバーに送信し、rsyncで同期し、tarでアーカイブしてコピーすると言った具合です。

行をたくさん書く必要は必ずしも無く、コマンドのヒストリーをカーソルキーで参照するように、「数行だけ書かれたシェルスクリプト」を作って、それをbashから実行すれば、まるでWindowsでショートカットアイコンをダブルクリックするように、ひとつのアクションでコマンドを実行できます。シェルでは「./hoge.sh」と実行するか、GNOMEなどではダブルクリックで実行できます。

lftpについては専用のスクリプト記法があるのでそれを参照すれば良いでしょう。lftpを参照のこと。他のUNIXコマンドについてはただそのコマンドを一行に書けばそれで実行できます。変数や条件分岐、繰り返しや関数呼び出しなどもできます。特に引数を指定してそれを変数として使えるようにスクリプトを書けば、状況によって別の処理を実行させられます。

また、システムの内部では、bashX11の初期化スクリプトや、デーモンやサービスを適切に実行させるRCスクリプト(SysV initの場合)でシェルスクリプトが使われているほか、automake/autoconfでもソフトウェアのコンパイル・インストールの際にシステムの構成をチェックして移植性を高めるためにシェルスクリプトが多用されています。またGentoo LinuxPortagePythonで書かれていますが、それぞれのパッケージのビルドやインストール情報を記述したebuildファイルはbashで書かれています。

ファイルのバックアップなどは、きちんと端末で入力するとさまざまなコマンドを覚えなければなりませんが、面倒ならシェルスクリプトに一度書いてしまいましょう。何度でも手軽に使えます。シェルスクリプトの利用は強制ではないので、使いたいコマンドだけ好きに使ってください。

シェルスクリプトは上手く使おう

シェルスクリプトは、上手く使いましょう。

たとえば、大事なファイルをUSBハードディスクにrsyncで同期しているとします。この時、対話型シェルでrsyncをかけると、コマンド行を間違えるかもしれません。ファイルが多いと、大変なことになります。

こうした時に、「間違えることのないようにシェルスクリプトに記述して、それを実行する」といったことができます。

コマンドで実行できることはシェルスクリプトに書ける

シェルスクリプトは、シェルのスクリプトです。よって、シェルの中でコマンドで実行できることは、シェルスクリプトに書いて実行できます。「シェルにおけるコマンド実行は、シェルスクリプトに書くのと同じ」であるため、「シェルで自分が行うことは全てスクリプトに書ける」と言えます。

たとえば、メールの送信は、sendmailコマンドをシェルスクリプトに記述することで可能です。

応用すれば、「何かのタイミングでメールを送信する」といったことも可能です。たとえばcronデーモンでスクリプトを定期実行したり、サーバーのCGIからエラーが発生した時にスクリプトを実行して、異常を感知した時にメールを管理者に送信する、といった用途が考えられます。

変数

#!/bin/bash
VAR=Hello
echo $VAR

シェルに引数を渡すには、シェルの後ろにスペースで区切って、引数を並べていきます。この引数が$1(第一引数)や$2(第二引数)としてスクリプトから操作できます。

関数

function hello()
{
    echo "Hello."
}

functionは省略可能。

hello()
{
    echo "Hello."
}

関数を実行するには「関数の名前 引数」とする。引数を取る場合は、シェルスクリプトの引数と同様$1, $2, ...とアクセスできる。

Bashの記法

BashはCシェルと違い独特の記法がある。

たとえば、if文やwhile文は

if [ 式 ]; then
    ~
fi

while [ 式 ]; do
    ~
done

のようにブラケットを使い、case文は閉じ括弧を使って

case $A in
    "a") echo a;;
    "b") echo b;;
esac

のように用いる。

比較式も特殊であり、

数値1 -eq 数値2

のように独自の短縮されたキーワードを使う。

ifブロックを閉じるのはfi、caseブロックを閉じるのはesac、forブロックを閉じるのはdoneと、訳が分からない。

まるでジョークのようだが、むしろbashで操作中にコマンドのような形で制御を行いたい、という視点から見ると逆にこれが良いのかもしれない。

コマンドでls -aを打つ感覚で、

if [ $A = $B ]; then
    echo Hello
fi

とか、

if [ $var -eq 0 ]; then
    echo "Don't use zero."
fi

のように、「コマンドラインのコマンド行ライクなスクリプト記法」であると言える。