スレッドメモ
MLやNewsのスレッドをメモする試み。
2006-01-05 (木)
◆ [linux-users] #!で始まるスクリプト
[106086] Shigeru Makino (1/5)
そこで、/bin/exeコマンドというものを作ってみることにしました。
http://www.line.to/mac/soft/exe/
#!/bin/exe gawk -f
#!/bin/exe perlのようにサーチパスに入っていれば、 コマンドの絶対パスを書く必要がありません。
ほかに同様の問題をもっとスマートに、 解決する方法があるでしょうか? この方法に重大な問題点はあるでしょうか?
[106087] matu (1/5)
良くわかっていないのですがひょっとして、
#!/usr/bin/env perl
みたいなものを実行したいという話でしょうか。
[106088] Shigeru Makino (1/5)
そうです。 perlの場合はそれでうまく行きます。 awkの場合は、
#!/usr/bin/env awk -f
となりますが、 /usr/bin/envの第一引数が、"awk -f"と一纏めに送られるため、
/usr/bin/env: awk -f: そのようなファイルやディレクトリはありません
とエラーになります。
[106089] Koyama Mituru (1/5)
ちょっと興味を持って調べてみました。
Linuxのようにshebankの複数の引数を、まとめてひとつとしてしまうもの。
古いFreeBSDのように引数をわけてくれるもの。
Solaris8のように最初の引数だけ渡してくれるもの。があるんだそうです。
[106093] Takeshi Kusune (1/5)
> 簡単なプログラムなのに、exeの同類のプログラムによるアプローチがなかったことに、
> 自分の見落とした弱点があるのではないかと実は躊躇しています。単純に、そこまで色々な環境での実行を想定している時点で、 PATH 変数に頼る危険性も避けるべきと考えてしまうのではないかと。
自作の script を自分のとこで動かす分には環境を自分であわせればいいし、 自分で好きにできない環境は個別に見ないと信用できない、ということかな? 自作 script 向けの環境差異吸収ツールとしてはありかもしれませんね。
[106094] Takashi SHIRAI (1/6)
そもそも「#!」の展開は、昔は system call ではなくて shell のお仕事でした。
なので、例えば Linux の標準 shell である bash でも、内部で 「#!」を処理するコードが実装されてますね。因みにこの実装では 最初の引数一個のみ評価します。
> 新しいFreeBSDは、一纏めに変更になっているのでしょうか?
「新しい」と言っても極最近の話のようですね。昨年の頭から旧 来実装に関する議論が勃発して、年末に正式リリースとなった新版 で採用された新仕様なんで。
コマンド名以降は行末まで全部が単一の引数になっていますが、 行末の空白文字は取除かれるみたいです。経緯の詳細は以下の URL から始まる thread を参照して下さい。
http://lists.freebsd.org/pipermail/freebsd-arch/2005-February/003525.html
> Solaris8の仕様は手の打ちようがありませんね。
> もっとも、
> #! /usr/local/bin/gawk -f
> とexeを使わずフルパスで書いても動かないのだから、
> もともとawk scriptを書けない仕様と言うことになりますね。最初の一個の引数は有効でしょう。二個目以降が無視されるだけ のことで。
そもそもコマンドに渡される引数はそのコマンドを呼出した時の 引数がそのまま渡される筈で、script 先頭行に記述された引数が その直前に挿入されるというのは特例措置だと見なすべきです。
ここに長々と引数を記述するような script は考え方が何か間違 っているんじゃないかと思いますよ。「#!」の後ろは「/bin/sh」 しか書かない、くらいの潔さがあってもいいかも。
因みに「#!」の後ろの空白文字を無視出来ない実装もあるので、 移植性を考えるなら「#!」の直後にパス名を記述する癖をつけた方 がいいかも。大昔の実装だとそういう仕様が多いです。
[106106] SUZUKI Yasuhiro (1/7)
出沢さんが[linux-users:106095] で、'#! 〜'の処理は シェルからカーネルに移ったというような発言をされて いますが、
# しらいさんの[linux-users:106094] でもそういう
# 印象を受けます。スクリプトファイルをコマンドラインなどで 実行する際に、まず初めに処理するのは、 相変わらずシェルではないでしょうか?
# execve()で、スクリプトファイルを直接実行
# 可能であるとは知りませんでしたが。
[106108] SUZUKI Yasuhiro (1/7)
MANページを'#!'で検索して読んでいたため 見落としましたが、
このファイルが実行可能フォーマットで
ないために実行が失敗し、かつディレクトリ
でもない場合には、このファイルはシェル
スクリプト(shell script)であると見なされます。とbashのMANページにありました。
'#! 〜〜'が第1行目のファイルは、execve()システム コールで処理され実行が成功するようになって いますので、シェルにシェルスクリプトと認識される 段階には至らず、シェルが '#! 〜〜'を処理することは ないようですね。
お騒がせしました。