2

シバン行から呼び出され、条件に基づいて (私の場合は OS バージョンに基づいて) 適切なインタープリターを返すスクリプトを作成しようとしていますが、なぜ機能しないのか理解できません。
例を挙げて説明します:
実行可能ファイル 1: /home/orens/dynamically_select_interpreter/select_interpreter.sh:

#!/usr/bin/env bash
echoerr() { echo "$@" 1>&2; }

interpreter=`cat /home/orens/dynamically_select_interpreter/interpreter`
if [ -z "$interpreter" ]; then
  echoerr "Could not find interpreter!"
  exit 1
fi

echoerr "Found interpreter: $interpreter"

exec "$interpreter" "$@"

このスクリプトは、いくつかのファイルの内容 (この場合、内容は: ) に基づいてインタープリターを選択します/usr/bin/python。次に、 を呼び出して、自分自身を適切なインタープリターに置き換えますexec
コマンドラインから呼び出すと、次のようになります。

$ /home/orens/dynamically_select_interpreter/select_interpreter.sh
Found interpreter: /usr/bin/python
Python 2.4.3 (#1, Dec 10 2010, 17:24:35)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

ただし、次のように、シバン行内で使用しようとすると:

#!/home/orens/dynamically_select_interpreter/select_interpreter.sh


echo $SHELL # should be an error # LINE 1
import sys; print "HERE"; print sys.version # this is the actual error # LINE 2

スクリプトは、python スクリプトではなくシェル スクリプトとして実行されます。LINE 1 は正しく実行されますが、LINE 2 ではエラーが発生します。シバン行が黙って無視されているようです (そして、stderr への出力でさえ画面に表示されません)。

基本的に、私は と同じことをしようとしていますenvが、スクリプトからです。C/C++ で記述してコンパイルすると、必要なものが得られると思いますが、このスクリプトは、複数のカーネル バージョンの状況を克服するためのツールとして使用されるため、実行可能ファイルを OS にしたいと考えています。独立していて、これを達成する唯一の方法はスクリプトです。

誰かがこの動作を説明したり、解決するのを手伝ってくれたりできますか?

ありがとう!

4

3 に答える 3

2

execveマニュアルページを確認してください:

インタープリターは、それ自体がスクリプトではない実行可能ファイルの有効なパス名でなければなりません。

(私のものを強調)

于 2013-01-20T19:10:13.337 に答える
1

追加のリダイレクトが機能するかどうかは、OS によって異なります。あなたの例(少し単純化されていますが、アイデアは同じままです)は、私のDebianインストールで機能します。ただし、一部のオペレーティング システムでは、コマンドの長さ、コマンドが受け取る引数の数などの制限など、シバン行の解釈方法に制限があります。いくつかの例については、このディスカッションを参照してください - 彼らは PERL を使用しますが、基本的にはあなたと同じこと。sourceforgeには、役立つかもしれないshebang-wrapperと呼ばれるプロジェクトがありますが、実際にはテストしておらず、まだプレアルファ版です。

于 2013-01-20T18:31:36.373 に答える
0

あなたの行: exec "$interpreter" "$@" には、実行されるスクリプトは含まれず、引数のみが含まれます。

試してみてください: exec "$interpreter" $0 $@

#!/bin/bash
echo "PRE:$0 $@"
if [ "$1" != "--" ]; then
  i=$1
  exec $i $0 -- $@
else
  shift; shift
fi
echo "POST:$0 $@"

bll-desktop:bll$ ./t.sh /bin/sh b c
PRE:./t.sh /bin/sh b c
PRE:./t.sh -- /bin/sh b c
POST:./t.sh b c
bll-desktop:bll$ ./t.sh /bin/bash b c
PRE:./t.sh /bin/bash b c
PRE:./t.sh -- /bin/bash b c
POST:./t.sh b c
bll-desktop:bll$
于 2013-01-21T02:51:24.057 に答える