はじめに
シェルで実行するコマンドをあらかじめファイルにまとめたものがシェルスクリプトですが、一種のプログラミング言語であると言われることもあるシェルスクリプトの複数の実行方法について勉強したことを自分の備忘録として残しておきます。
シバンについて
初めてシェルスクリプトを見たときに謎だったのがシバン
と呼ばれるおまじないです。
#!/bin/bash
ls -alF
この1行目に書かれている#!/bin/bash
がシバン
と呼ばれるもので、
「このシェルスクリプトは/bin/bashで動かします」、という宣言になるそうです。
#
から始まっているため、コメント行という扱いです。
% ./test.sh
と実行すると、シバンのおかげで実質的には以下のコマンドとして実行されます。
% /bin/bash ./test.sh
以下のようにシェルの引数として実行する場合と同じ動作となります。
% bash test.sh
普段、自分はmacでzshを使っていますが、シェルスクリプトに上記のようなシバンを書くことにより、zshからbashスクリプトを直接実行できるということですね。
sourceコマンドと.コマンド
先ほどのように、相対パスでファイル名を指定してシェルスクリプトを実行する方法以外だと、
source
コマンドを使ってシェルスクリプトを実行することができます。
ここで初見殺しなのが、ファイル名指定による実行とsource
コマンドによる実行では、動作が変わるということです。
source
コマンドは、指定したファイル(シェルスクリプト)に書かれているコマンドを1行ずつコマンドラインに入力して実行するときと同じように実行されるそうです。最初はへぇそーなんだぐらいにしか思ってませんでしたが、ここが意外と重要ポイントらしく、source
コマンドを使うと今自分が使っているシェル(カレントシェル)においてコマンドが実行されるため、シェルスクリプトにシバンは必要ないとのことです。しかも、もし仮にシェルスクリプトにシバンが書いてあったとしても、source
コマンドを使った場合はコメント行として無視されます。また、シェルスクリプトは実行されるファイルであるため、
% chmod +x test.sh
というように、ファイルに実行権限がいるのですが、source
コマンドではシェルスクリプトを直接実行するわけではないため、ファイルに実行権限がなくても問題ないです。
そして僕が一番ハマったのは、source
コマンドと同じ意味を持つ.
コマンドです。
% source ./test.sh
% . ./test.sh
この2つの実行結果は同じらしいのですが、初めて見たときに.
がコマンドとは思わなかったですね。。カレントディレクトリか何かだと思ってました...。
カレントシェル or サブシェル
source
コマンドを使うと、カレントシェルでシェルスクリプトが実行されるのに対して、ファイル名だけ指定して実行した場合はカレントシェルで実行されないのかと思ったのですが、この場合はサブシェルでシェルスクリプトが実行されるそうです。サブシェルとは、カレントシェルから新しく起動される子プロセスのシェルのことです。
#!/bin/bash
ls -alF
% ./test.sh
これを実行すると、シバンに指定したbashがサブシェルとして起動され、サブシェルにてls
コマンドが実行され、実行後にはもとのカレントシェルに戻るそうです。カレントシェルとサブシェルは別物のため、環境変数は引き継がれるものの、エイリアスなどの設定は引き継がれないようです。
逆に、source
コマンドではカレントシェルで実行するため、エイリアスの登録などのシェルスクリプトを実行すると、実行後にエイリアスがカレントシェルに登録されることになります。ファイル名だけ指定して実行するとサブシェルにエイリアスが登録されてカレントシェルに戻るので、カレントシェルには何の影響も及ぼさない結果となります。
そのため、シェルにログインする際に読み込まれる環境設定ファイル.bashrc
などのシェルスクリプトは、設定変更した後にわざわざログインし直す必要はなく、
% source ~/.bashrc
と実行すれば、変更した設定をすぐにカレントシェルに反映することができます。
まとめ
シェルスクリプトは実行する方法によって動作が変わるということを学びました。
まさか複数の実行パターンがあるとは思ってませんでした...。