1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

シバン(shebang)にシェル以外のコマンドを指定してシバンの動作を確かめてみる

Last updated at Posted at 2021-07-11

今回の動作確認環境

  • Vagrant 2.2.14
  • CentOS 8
  • bash 4.4.19

shebangで指定可能な形式について

shebangとは実行可能権限が付与されたシェルスクリプトの先頭行に書かれている #!/bin/sh の部分のことを指します。

シェルスクリプトでよく見かける形式としては、以下のようなものではないでしょうか。

#!/bin/sh
#!/usr/bin/bash

スクリプト言語を利用する方であれば、こういった形式で書かれているかと思います。

#!/usr/bin/perl
#!/usr/local/bin/ruby
#!/usr/bin/env python3

/usr/bin/perl/usr/bin/env からわかるように、 /etc/shells に記載されているようなシェルのパス以外の実行ファイルでも指定できることに気づきます。

Wikipediaによると shebang として指定可能なのは「the file specified by interpreter must be an executable binary and cannot itself be a script.」とのこと。
つまり、実行可能なバイナリファイルで、shebangを書いてるシェルスクリプト自身以外であればOKみたいです。

Wikipedia内にexecveのマニュアルページへの参照リンクが貼られていたので man execve を見てみると以下のように DESCRIPTION に記述されていました。

DESCRIPTION
       execve()  executes  the  program pointed to by filename.  filename must be either a
       binary executable, or a script starting with a line of the form:

           #! interpreter [optional-arg]

shebang に指定できるのは、以下のいずれかのようです。

  1. 実行可能なバイナリ
  2. 「#!」で始まるシェルスクリプト

「1」については「/usr/bin/bash」、「/usr/bin/perl」、「/usr/bin/env」といった記述から理解できます。
「2」については、ちょっと試してみましょう。

vagrantユーザのホームディレクトリ直下に like_echo.sh という第1引数をechoするシェルスクリプトを準備して、実行権限を付与します。

$ pwd
/home/vagrant

$ cat like_echo.sh 
#!/bin/bash
echo $1

$ chmod +x like_echo.sh 

like_echo.sharg1 を渡して呼び出す call_like_echo.sh を準備して、これにも実行権限を付与します。

$ cat call_like_echo.sh 
#!/home/vagrant/like_echo.sh arg1

$ chmod +x call_like_echo.sh 

実行してみると arg1 が出力されました。これで「or a script starting with a line of the form:〜」の部分の検証ができたかと思います。

$ ./call_like_echo.sh
arg1

ちなみ call_like_echo.shshebang 行で渡す引数の数を増やすとこんな動きになります。

引数を2つ渡して実行。

$ cat call_like_echo.sh 
#!/home/vagrant/like_echo.sh arg1 arg2

$ ./call_like_echo.sh
arg1 arg2

引数を3つ渡して実行。

$ cat call_like_echo.sh 
#!/home/vagrant/like_echo.sh arg1 arg2 arg3

$ ./call_like_echo.sh
arg1 arg2 arg3

この動きから like_echo.sh で受け取った $1 には call_like_echo.shshebang 行で指定した「arg1 arg2 arg3」の部分すべてが第1引数として扱われているようです。

echoで実行状況を可視化

ここまでで shebang には /bin/sh のようなシェル以外でも man execve に記載されている条件を満たしていれば指定できることがわかりました。

また、さきほどの like_echo.sh の動作から、 shebang#!/bin/bash と指定すると、以下のような呼び出され方をしていることがわかります。

$ /bin/bash like_echo.sh 引数

当然と言えば当然の動きなんですが。。。この動きを echo コマンドを使って可視化してみましょう。

shebangecho コマンドのパスを記述して、実行権限を付与します。

$ cat echo.sh 
#!/usr/bin/echo

$ chmod +x echo.sh 

実行すると、シェルスクリプト自体のファイル名が出力されました。

$ ./echo.sh 
./echo.sh

ということは shebang 行に #!/usr/bin/echo と指定することで、実際にはこのように呼び出されたことがわかります。

$ /usr/bin/echo ./echo.sh

引数を渡してみると /usr/bin/echo ./echo.sh 引数 のように呼び出されていることが可視化できていますね。

引数が1つの場合。

$ ./echo.sh arg1
./echo.sh arg1

引数が2つの場合。

$ ./echo.sh arg1 arg2
./echo.sh arg1 arg2

wcで行数を数えてみる

shebangで指定したコマンド ./自身のファイル名 引数 の形式でシェルスクリプトが実行されることがわかったので、この仕組みを使ってファイルの行数を数えてみます。

こんなファイルを準備して、実行権限を付与します。

$ cat wc.sh 
#!/usr/bin/wc -l
# Comment1
# Comment2
# Comment3
# Comment4
# Comment5

$ chmod +x wc.sh

実行するとファイルの行数が出力されました。

$ ./wc.sh 
6 ./wc.sh

cpでシェルスクリプトのコピーを作成する

こうなってくると、自身のファイル名を使った操作が色々と可能ですね。
ファイルのコピーを行うスクリプトを準備して、実行権限を付与します。

$ cat cp.sh 
#!/usr/bin/cp

$ chmod +x cp.sh

引数に cp.sh.YYYYMMDDHHMMSS 形式のファイル名を渡すと cp.sh がコピーされて cp.sh.20210711042853 が作成されました。

$ ./cp.sh cp.sh.`date '+%Y%m%d%H%M%S'`
$ ls -l cp.sh.20210711042853 
-rwxrwxr-x. 1 vagrant vagrant 14 Jul 11 04:28 cp.sh.20210711042853

まとめ

  1. shebang は「実行可能なバイナリ」もしくは「#!で始まるシェルスクリプト」が指定できる。
  2. shebang#!/PATH/TO/コマンド コマンドの引数 と記述して ./シェルスクリプト名 シェルスクリプトの引数 のように実行すると、実際には /PATH/TO/コマンド コマンドの引数 ./シェルスクリプト名 シェルスクリプトの引数 のような形式で実行されている。

参考URL

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?