UnsplashのGuerrillaBuzzが撮影した写真
手で何度も行う作業を減らしたいとき、シェルスクリプトは有力な手段です。コマンドを順に書いておくことで、同じ手順を繰り返し実行できます。この記事では、意味、よく使う書き方、使いどころ、困ったときの見方、気を付けたい点までを順に説明します。
シェルスクリプトは、シェルが読み取りながら実行するコマンド列を、テキストファイルに書いたものです。bashやzsh、shなどで読み方に差はありますが、ファイルに処理の流れをまとめておける点は共通です。繰り返す手順を毎回手で打たずに済むため、運用、ファイル操作、簡単な集計などでよく使われます。
よく使われる理由は、既にあるコマンドをそのまま組み合わせやすいからです。主な点は次の通りです。
grep、sed、awk などを組み合わせて処理をつなげやすいただし、同じファイルがそのままどの環境でも動くとは限りません。使うシェルの違いに加え、OSに入っているコマンドや、そのオプションの違いも結果に影響します。
実行はおおむね次の流れです。
script.sh)。先頭に #!/bin/bash などのシバンを書くと、どのシェルで読むかを示せます。chmod +x ファイル名 で実行できる権限を付けます。./ファイル名 で実行します。あるいは bash ファイル名 のように、読むシェルを明示して動かすこともできます。cron などの仕組みと組み合わせれば、決まった時刻に動かすこともできます。人が毎回手で起動しなくてよい処理ほど、スクリプト化の利点が出やすくなります。
主な使いどころを表にまとめると、次のようになります。
| 分野 | 使い方の例 |
|---|---|
| 運用 | 利用者の追加、バックアップ、ログの整理、空き容量の確認 |
| ファイル操作 | 検索、複製、移動、削除、拡張子のまとめて名前を変える |
| データ処理 | テキストの加工、ログの抽出と集計、CSVの整形 |
| 通信まわり | 疎通の確認、監視、設定ファイルの配布 |
変数は、値に名前を付けて扱うための仕組みです。代入と参照で書き方が変わる点に注意します。
name=value のように、変数名と値の間に空白を入れません。先頭に $ は付けません。(例:message="Hello")$ を付けます。(例:echo "$message")ダブルクォートの中では変数の展開が行われますが、シングルクォートの中では文字列がそのまま扱われます。コマンドの結果を変数に入れるときは、$(コマンド) を使います。
シェルスクリプトでは、流れを変えるために次のような構文を使います。
例えば、簡単な分岐は次のように書けます。
if [ -f "$FILE" ]; then echo "ファイルが存在します"; fi
こうした構文を組み合わせると、単純な手順だけでなく、条件に応じて動きを変える処理も書けます。
関数を使うと、同じ処理を何度も書かずに済みます。基本の形は次の通りです。
function_name() { コマンド群; }function_namebashでは、何も付けずに関数内で代入した変数も広い範囲から見えることがあります。関数の中だけで使いたい変数は、bashでは local 変数名 のように書きます。一方、POSIXの sh では local は定められていないため、移しやすさを重視するなら、その点を踏まえて書き分ける必要があります。
パイプとリダイレクトを使うと、コマンド同士のつながりを作れます。
|):前のコマンドの標準の出力を、次のコマンドの入力元へ渡す(例:ls | grep ".log")> / >>):出力をファイルへ書く。> は上書き、>> は追記<):ファイルの中身を入力として使う2> / 2>&1):エラーを別ファイルへ出す、または標準の出力とまとめる単体では短いコマンドでも、組み合わせると実務で使える処理に育てやすいのが、この書き方の強みです。
特定の条件でファイルを探し、名前の変更、移動、複製、削除をまとめて行う場面で使えます。定期的なバックアップや、決まった場所への振り分けにも向いています。
利用者の管理、空き容量の確認、プロセスの見張り、通信の確認など、繰り返し行う手順を一つにまとめられます。毎回の操作を減らせるため、同じ流れを安定して回しやすくなります。
決まった時刻に走らせる処理にも向いています。例えば、データを集める、加工する、集計する、報告用のファイルを作る、といった流れを一つにまとめておけば、確認しやすくなります。終了コードやログを見れば、うまく終わったかどうかも追いやすくなります。
ログは状態の確認や原因の切り分けに欠かせません。シェルスクリプトを使うと、大量のログから必要な行を抜き出し、数を数え、報告用の形にまとめるところまで自動で進めやすくなります。
エラーが出たときに、どこで止めるか、何を残すかを先に決めておくと、後で追いやすくなります。代表的な設定には次のようなものがあります。
set -e:終了コードが0以外になった時点で止めるset -u:未定義の変数を読んだときにエラーにするset -o pipefail:bashやzshなどでは、パイプの途中で出たエラーも拾いやすくするtrap:シグナルや終了時に後片付けの処理を走らせる動きを追うときは、set -x や bash -x スクリプト名 で実行中のコマンドを表示できます。必要な場所に echo を入れて値を確認する方法もよく使われます。
処理が遅いときは、次の点を見直すと変わることがあります。
grep、sed、awk を役割に応じて使い分けるlocate を使うときは、見つかった結果が updatedb の時点に左右されることを前提にする便利でも、書き方を誤ると危険です。主な注意点は次の通りです。
sudo は必要な場面だけに絞る後で直しやすくするには、名前の付け方、コメント、字下げ、関数の切り方が効きます。設定値を冒頭あたりにまとめておくと、変更点も追いやすくなります。
シェルスクリプトは、シェルが読むコマンド列をファイルにまとめたものです。既にあるコマンドをつなぎ、繰り返す手順を減らせるため、運用、ファイル操作、決まった時刻の実行、ログの確認などで広く使われます。
大切なのは、書き方だけでなく、どのシェルで動かすか、エラー時にどう止めるか、安全に扱えるかまで考えることです。まずは身近な決まった手順の作業を一つ選び、小さなスクリプトから試すと入りやすくなります。
シェルが読むコマンド列をテキストファイルにまとめたもので、主に繰り返す作業を減らすために使います。
LinuxやmacOSで使いやすく、WindowsでもWSLやGit Bashで試せます。ただし、同じファイルがそのままどこでも動くとは限りません。
特別なソフトは要りません。テキストエディタがあれば作れます。
変数、if文やfor文、while文、パイプ、リダイレクトを先に押さえると入りやすくなります。
代入時に空白を入れること、未定義の変数を読むこと、クォートが足りずに意図しない展開が起きることがよくあります。
set -x や bash -x で動きを見ながら、必要な所で echo を出して確認する方法がよく使われます。
利用者入力の扱い、秘密の情報の置き方、権限の付け方、一時ファイルの扱いに注意します。
複数の手順をまとめて同じ形で動かせるため、かかる時間を減らし、抜けも減らしやすくなります。
既にあるコマンドを順につなぎ、ひとまとまりの流れとして実行しやすくする役目を持ちます。
OSのコマンドを多く使う決まった手順の作業、環境の準備、運用の補助などで力を出しやすい書き方です。