シェルスクリプトと実行権限
シェルスクリプトは、いつも端末に打っているコマンドをファイルにまとめて一気に実行する仕組みです。1行目に #!/bin/bash のような「シバン」を書くと、どのインタプリタで動かすかをOSに伝えられます。作ったファイルには chmod +x で実行権限を付け、./script.sh のように実行します。権限を付けずに動かしたいときは bash script.sh と明示的にインタプリタを指定する方法もあります。
シェルスクリプトは、コマンドを上から順に並べたテキストファイルだ。そのファイルを呼び出すだけで、書いた手順を一気に流せる。
毎日同じコマンドを打ち直すのは手間だし、打ち間違いの危険も毎回ついて回る。一度ファイルに書いておけば、その手間も打ち間違いも減らせる。
実体はただのテキストなので、専用の開発環境は要らない。vi や nano のようなエディタと、実行するためのターミナルさえあれば今すぐ始められる。
簡単な定型作業の自動化から、条件分岐や繰り返しを織り込んだ小さなプログラムまで、同じ仕組みの延長で書けるのがシェルスクリプトの強みだ。
理屈を並べる前に、まず中身を1行か2行だけ持つ最小のスクリプトを作り、それを動かすところまで通してみるのが理解の近道だ。たとえば hello.sh という名前で、画面に文字を出すだけのファイルを作ってみよう。
echo は引数の文字列を標準出力へ表示するコマンドで、$USER は今ログインしているユーザ名に置き換わる変数だ。
📜 1行目に書く #! の役目
スクリプトファイルの1行目には、ほぼ必ず #!/bin/bash のような行を書く。これをシバン(shebang)と呼ぶ。
シバンは「このファイルの中身を、どのプログラム(インタプリタ)に解釈させるか」をOSへ伝える道しるべだ。#!/bin/bash と書いておけば、ファイルを直接起動したときに /bin/bash がその内容を読んで実行してくれる。
先頭の #! という2文字は特別な記号で、ここだけはコメントではなく命令として扱われる。2行目以降に出てくる # は、これとは違ってその行をコメント(説明用のメモ)にする普通の記号だ。
シバンを書かずに実行すると、どのシェルで動くかが環境任せになり、思わぬ誤動作の原因になる。だからこそ1行目のシバンは、習慣として必ず付ける。
シバンには #!/bin/bash のように絶対パスで bash を直接指す書き方のほかに、#!/usr/bin/env bash という書き方もよく使われる。
env を経由すると、PATH の通った場所から bash を探して起動する。そのため bash が置かれている場所が環境によって違っても動きやすくなる。どこでも動く移植性を重視するときに役立つ書き方として覚えておくとよい。
🔑 作っただけでは動かない理由
テキストファイルを作っただけでは、まだ「実行してよいファイル」とは見なされない。ここで一度つまずく人が多い。
スクリプトを起動できるようにするには、実行権限(x)を chmod +x で与える必要がある。chmod +x hello.sh と打てば、そのファイルに実行権限が付く。
権限が付いたかどうかは ls -l で確認でき、行頭のパーミッション表示に x が現れていれば実行可能な状態だ。
逆に実行権限が無いまま起動しようとすると Permission denied(許可がありません)というエラーが出る。これは初学者がほぼ必ず一度はつまずく場面だが、出たら落ち着いて chmod +x を実行すれば解決する。エラーの正体さえ分かっていれば、慌てることはない。
起動するときは、ファイル名の前に ./ を付けて ./hello.sh のように打つ。./ は「今いるフォルダ(カレントディレクトリ)にあるこのファイル」という意味だ。実際の流れは次のようになる。
$ chmod +x hello.sh / $ ./hello.sh と続けて打つと、画面に Hello, user01 のように、$USER が実際のユーザ名へ置き換わった結果が表示される。
ここで気になるのが、なぜ ./ をわざわざ付けるのかだ。./ を付け忘れて hello.sh とだけ打つと command not found(コマンドが見つかりません)になることがある。
シェルはコマンドを PATH に登録された場所からしか探さず、カレントディレクトリは自動では探しに行かない。そのため「ここにあるこれを実行して」と場所を明示する ./ が必要になる。
この挙動を知らないと「ファイルは確かにあるのに動かない」と戸惑いがちなので、最初に理解しておくと回り道が減る。
🚀 権限を付けずに走らせる手もある
実行権限を付けずにスクリプトを動かす方法もある。bash script.sh のように、インタプリタである bash を先に書き、その引数としてスクリプトファイル名を渡すやり方だ。
この場合はファイルに x が無くてもかまわないし、極端に言えば1行目のシバンが無くても bash が解釈してくれる。一時的に動作を試したいときや、他人から受け取ったスクリプトを実行権限を変えずに走らせたいときに便利だ。
同じように sh script.sh とすれば sh で実行できる。ただしその場合は bash 独自の機能が使えない、より素朴なシェルとして動く点には注意が要る。
似て非なるものに source(または .)がある。source script.sh は、新しいシェルを立ち上げずに「今いるシェルそのもの」でスクリプトの中身を読み込んで実行する。
./script.sh や bash script.sh が別プロセスのシェルを起動して実行するのに対し、source は現在のシェルに直接効く。そのため、スクリプト内で設定した変数や cd による移動が、実行後の手元のシェルにも残る。
設定ファイル(~/.bashrc など)を読み直すときに source ~/.bashrc とするのは、この性質を利用したものだ。
「別の場所で動かしたいなら ./ や bash、今のシェルに反映させたいなら source」と整理しておくと使い分けに迷わない。実務では、毎回 alias を打ち直す代わりに ~/.bashrc に書いておき、ログインのたびに自動で読み込ませる、といった形で source の性質が活きている。
⚠ つまずいたら、まずここ
ここまでをひとつの流れにまとめると、シェルスクリプトを動かす手順は「エディタで中身を書く→1行目にシバンを書く→chmod +x で実行権限を付ける→./ を付けて起動する」の4ステップになる。
動かないときの代表的な原因も決まっている。Permission denied なら実行権限の付け忘れ(chmod +x で解決)、command not found なら ./ の付け忘れ(場所の明示で解決)、思った挙動にならないならシバンの書き忘れや誤り、というように切り分けられる。
この対応関係を頭に入れておけば、最初のスクリプトでつまずいても自力で立て直せる。次は、そのスクリプトに値を覚えさせる「変数」へ進もう。