シェルスクリプトとシバンについて
シェルスクリプトについて勉強中なのですが、
調べてもよくわからない状態なので、下記の疑問点について、皆様の知恵をお貸し頂ければ幸いです。
- test.shというファイルを実行する際に、
シバンを記述していてもしていなくても実行権限があれば./test.shだけで実行できてしまうのはなぜか。
- 実行権限がなくてもsh test.shと記述すると実行することができるのはなぜか。
以上、宜しくお願い致します。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
簡単な方から。
実行権限がなくてもsh test.shと記述すると実行することができるのはなぜか。
この場合、実行されているのはsh
でtest.sh
は読まれているだけです。
cat test.sh
と同じ構造です。
シバンを記述していてもしていなくても
これはsh/bash/zsh等のシェルの機能です。
シェルは実行可能ビットの立っているプログラムを実行する場合、まずOSに実行を依頼します。このとき、ファイルが、
・バイナリーの実行可能プログラム、つまり、file ファイル名
で見たときにELF 64-bit LSB executable~~
等のように(OSにより違います)表示される物
・shbang行のあるファイル
のどちらかの場合にOSによる実行が成功します(細かいことは割愛)。
OSによる実行が失敗した場合、シェルはそのファイルがシェルスクリプトだと勝手にみなして、sh ファイル名
というコマンドを実行します。
これはOSにshbang行が無い時代に書かれたシェルスクリプトをそのまま動かすための機能です。
なので、使っているシェルがzshやtcshであっても、古いシェルであるsh
が起動されます。
bashは何故かsh
でなく/bin/bash
が起動されますが、これはbashがshのほぼ上位互換だからでしょう。
シェルスクリプトでないファイルに実行可能ビットを立てて実行すると、shのエラーメッセージが出ます。
Bash
1$ chmod +x foo.png 2$ ls -l foo.png 3-rwxr-xr-x 1 aaaa aaaa 692 Dec 3 19:57 foo.png* 4$ ./foo.png 5: コマンドが見つかりません 6./foo.png: line 2: : コマンドが見つかりません 7./foo.png: line 3: 期待してない token `)' のあたりにシンタックスエラー 8?Cm?fu?P??)D??B?"?K?$A?'areAdobe ImageReadyq?e<FIDAT8??KH?A????-??K?C=? 9$
投稿2020/12/03 11:05
総合スコア85901
0
1.シェバンが省略されると(ファイルの先頭の2文字が「#!」以外だと)「/bin/sh」を実行するというロジックになっていた気がします。
2.シェル「sh」が、指定された引数「test.sh」をそのsh自身のスクリプトとして実行するという処理をします。この場合シェバンの仕組みを使いません。
#※追記
1の件、自分の理解があいまいだったので検証してみました。(環境: Linux Mint 19.3)
結果を先に書くと、
- execve()システムコールが、シェバンの処理を行う。シェバンが無い場合execve()システムコールはエラーとなる。
- 対話シェルを使って実行した場合は、上記エラーの場合にシェルスクリプトとして実行するような処理を行うことによってエラーにならずに実行するようになっている。
ということのようです。
$ls -lA 合計 16 -rw-rw-r-- 1 hidezzz hidezzz 273 12月 3 20:31 main.c -rwxr-xr-x 1 hidezzz hidezzz 11 12月 3 20:31 no-shbang.sh -rwxr-xr-x 1 hidezzz hidezzz 20 12月 3 20:20 shbang.sh $ cat main.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> int main( void ) { char* cmdline[ 2 ]; int r; cmdline[ 0 ] = "test.sh"; cmdline[ 1 ] = NULL; r = execve( "test.sh", cmdline, NULL ); if ( r < 0 ) { perror( "execve" ); } return 0; } $ make main cc main.c -o main
シェバンがある場合
$ cat shbang.sh #!/bin/sh echo test $ cp -p shbang.sh test.sh $ ./main test
シェバンが省略された場合
$ cat no-shbang.sh echo test $cp -p no-shbang.sh test.sh $ ./main execve: Exec format error
投稿2020/12/03 10:45
編集2020/12/03 12:08総合スコア1248
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/04 02:22
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/03 11:49