linux でコマンドを実行する shebang
shebang を指定すると、そのコマンドでプログラムが実行されますよね。
#!/usr/bin/env ruby puts 1
このとき、shebangの1行目に指定したコマンドにはどのように引数が渡されているのだろうか。 ちょっと試してみよう。
shebangで実行できるもの
shebang に指定できるものは、実行可能な「バイナリ」だけ。*1
shebang に指定した shebang を使ったファイルは無効になる。
そこで、バイナリを用意する
引数を表示するsample.c
#include <stdio.h> int main ( int argc, char** argv ){ for( int idx=0; idx<argc; idx++){ printf("argv[%d]= %s \n" , idx, argv[idx]); } }
これをコンパイルして実行可能なプログラムを作る
gcc sample.c -o sample
shebang に指定
今作ったプログラムをshebang に指定する。
shebang-test
#!./sample This is test. This body will not be executed
shebang の書き方がよく見るものと違っていますが、これは相対パスです。フルパスで指定するのが面倒くさいので相対パスで指定しています。
実行してみる
それでは、このファイルに実行可能フラグをくっつけて実行してみましょうか。
takuya@~$ chmod a+x shebang-test
実行した結果
takuya@~$ ./shebang-test argv[0]= ./sample argv[1]= ./shebang-test
- 引数0に、作ったプログラムが表示されており、
- 引数1に、作ったファイル名が指定されている。
オプションを付けた場合
オプションを付けてみましょう
takuya@~$ ./shebang-test this is argument from command line argv[0]= ./sample argv[1]= ./shebang-test argv[2]= this argv[3]= is argv[4]= argument argv[5]= from argv[6]= command argv[7]= line
ファイル名の後ろに追加されたのがわかります。
shebang 行にオプションを付けてみましょう
では、shebang行にオプションを付けてみます。
#!./sample from-shebang arguments 1 2 3 this is test
これで実行してみます。
shebang 行にオプションを付けた場合
takuya@~$ ./shebang-test argv[0]= ./sample argv[1]= from-shebang argv[2]= arguments argv[3]= 1 argv[4]= 2 argv[5]= 3 argv[6]= ./shebang-test
すると、コマンドー引数ーファイル名の順番になっていることがわかります。
両方に引数を付けてみる。
最後に両方にオプションを付けてみる。
takuya@~$ ./shebang-test a bc argv[0]= ./sample argv[1]= from-shebang argv[2]= arguments argv[3]= 1 argv[4]= 2 argv[5]= 3 argv[6]= ./shebang-test argv[7]= a argv[8]= bc
今度は、コマンド-引数ーファイル名ー引数になっていることがわかります。
shebang が実行されるまで
シェル(sh/bash)はexecv でコマンドを実行する。execv がコマンドを実行するときに、 shebang があればインタプリタだとして1行目を処理してくれる。
execv を直接コールすれば少しわかる気がする
execv-test-01.c
execvを使って最初に作ったコマンド sample を実行してみます。
#include <stdio.h> #include <unistd.h> int main (){ char* argv[2] = {"aaaaaaaaa", NULL }; execv("./sample", argv ); }
実行結果
takuya@~$ gcc exec-test-01.c && ./a.out argv[0]= aaaaaaaaa
shebangファイルをexecvで実行
shebang ファイルをexecv で実行してみると。
exec-test-02.c
#include <stdio.h> #include <unistd.h> int main (){ char* argv[2] = {"aaaaaaaaa", NULL }; execv("./shebang-test", argv ); }
これを実行すると
takuya@~$ gcc exec-test02.c && ./a.out argv[0]= ./sample argv[1]= ./shebang-test
引数 aaaaaa を与えたはずだけど消えてしまった。ということは 最初の引数を重ね合わせはシェルの機能だったぽい (実験環境がmacOSで試したからこうなったという可能性もあるが、unistdがそんなにきょどうかわる??)
shebang の重ね合わせ
Since Linux 2.6.28, the kernel permits the interpreter of a script to itself be a script. This permission is recursive, up to a limit of four recursions, so that the interpreter may be a script which is interpreted by a script, and so on.
Linuxの最新版に限り、Shebangの重ね合わせが可能になっている。
参考資料
http://man7.org/linux/man-pages/man3/exec.3.html
広告
tasc PerformanceレディースShebang Stretch Woven Runningテニスパフォーマンススカート XL ピンク
- 出版社/メーカー: TASC
- メディア: スポーツ用品
- この商品を含むブログを見る