そのシバンラインに従ってスクリプトを実行するためのコマンドはありますか?


46

実行許可が設定されていないbashスクリプトを実行する場合、次の操作を実行できます。

bash script.sh

bashスクリプトが実行可能でなく、正しいインタープリターがわからない場合、代わりに何を使用する必要がありますか?シェバン行からインタープリターを検索し、それを使用してスクリプトを実行するコマンドはありますか?


ウィットバッシュの何が問題になっていますか?
ステフェン

@steffen問題のファイルがbashスクリプトであることをどのように知るのですか?
ムル

質問からの@muruの引用:「bashスクリプトを実行したい場合...」さらに(bashスクリプトでなくても)bash whatever動作する場合、なぜ別のものを使用するのですか?bashは事実上すべての* ixシステムで使用できるため、わざわざ
...-steffen

1
@steffenは残りの質問を読みましたか?彼らは言う:「もし...なら私はできる:...」と「bashの代わりに何を使うべきか... 私は正しいインタプリタを知らないのか?」
ムル

@muru:多分私は明白なものを見ない。しかし、質問で述べられているように、ファイルがシェバン行である場合、bashは要求されたとおりに動作します。perlのように、以下の回答によると。それでは、bashを使用しないことの利点は何ですか?
ステフェン

回答:


67

うん。と呼ばれperlます:

perl foo.bash    # works
perl foo.lua     # works
perl foo.clisp   # works
perl foo.csh     # works
perl foo.php     # works
perl foo.gnuplot # works (no arguments)
perl foo.pl      # works (obviously)
perl foo.py      # works
perl foo.sh      # works
perl foo.tcl     # works
perl foo.rb      # works
perl foo.nodejs  # works
perl foo.r       # works
perl foo.oct     # works
perl foo.csharp  # works (no arguments)

これはPerlのドキュメントに記載されています

#!行に「perl」という単語も「indir」という単語も含まれていない場合、#!Perlインタプリタの代わりに「the」という名前のプログラムが実行されます。これは少し奇妙ですが#!、SHELLが/ usr / bin / perlであることをプログラムに伝えることができ、Perlがプログラムを適切なインタープリターにディスパッチするため、そうしないマシンのユーザーを助けます。


40
まあ、それは汚いだけです。
スリム

1
ファイル拡張子.jsも機能しますか?
-Pysis

1
また、マシンがしないこと#!。私は数人から数人になりましたが、この問題は発生していません。
-Pysis

1
わかりました、あなたの例は、ファイルからのいくつかのシバン行紹介するのではなく、多くのファイル拡張子を強調しているように見えます。
ピシス

2
私はman perlrun、それが「ちょっと奇妙」だと認めるのが好きです:)。これは、非UNIX環境および非常古いバージョンのUNIX を対象とした好奇心として扱われるべきだと思います。
スリム

25

スクリプトには必ずしもシバンがありません

スクリプトがインタプリタから実行された場合、あなたはそれがシェバングを持っていることを確認することはできませんすべてでインタプリタから実行するスクリプトは、シェバングを必要としない場合、あなたがコードを実行するインタプリタを呼び出します。

したがって、答えは「いいえ」です。スクリプトを実行する言語(インタープリター)を確実に確認するコマンドはありません。ただし、いつでもスクリプトの内部を調べて、調べるためのシバンがあるかどうかを確認できます。

要するにルール:

  1. スクリプトを実行するとき、インタープリターを呼び出すと、実行可能なシバン、シバンまたはシバンの可能性が常に無効になります。
  2. 実行可能でなく、インタープリターから実行する場合、スクリプトにはシバンは必要ありません。
  3. スクリプトは最初のインタプリタを呼び出さずに実行されている場合は、それが必要(および使用)シェバングがどのようなコールに通訳を見つけるために、そしてそれがそのシェバングからインタプリタを呼び出すための「権限」を持って実行する必要があります。

ただし、スクリプトにシバンがない場合は、使用するインタープリターを示す(直接*)情報がスクリプト内にありません。

そうは言っても

あなたはもちろん、常にするラッパースクリプトを書くことができ試みるスクリプトがシェバングを持っているかどうかを確認し、そのから通訳を読んで、その後FOUNDインタプリタからそれを実行します。

#!/usr/bin/env python3
import subprocess
import sys

args = sys.argv[1:]; script = args[0]

try:
    lang = open(script).readlines()[0].replace("#!", "").strip().split()[-1]
    cmd = [lang, script]+args[1:]
    subprocess.call(cmd)
except (PermissionError, FileNotFoundError, IndexError):
    print("No valid shebang found")
  • tryrunin として保存し$PATH(たとえば~/bin、ディレクトリが存在しない場合は作成し、ログアウトしてからログインし直します)、実行可能にします。次に実行します:

    tryrun /path/to/nonexecutablescript

    非実行可能ファイルpythonおよびbashスクリプトで正しいインタープリターを呼び出し(テスト済み)。

説明

  • スクリプトは、スクリプトの最初の行を読み取り#!、それを削除し、残りを使用してインタープリターを呼び出します。
  • 有効なインタープリターの呼び出しに失敗すると、a PermissionErrorまたはaを発生させFileNotFoundErrorます。

注意

拡張子(.sh.pyなど)は、Linux上で適切な通訳を決定する際に何の役割を全く果たしません。


(*「スマート」推測アルゴリズムを開発して、コードから構文を決定することはもちろん可能です。)


わかりました。つまり、Linuxはどこかでシバン抽出を実装していますが(実行可能なsrciptsの正しいインタープリターを選択できるように)、スタンドアロンの標準コマンドとしては提供されていません。
アイバル

シバンを抽出する@Aivarは問題ではありませんが、それなしでコードを実行することは完全に可能です。
ジェイコブVlijm

@Aivar Ah、あなたの言っていることがわかります。スクリプトが実行可能で、コマンドで言語なしで実行される場合、スクリプトはインタープリターを呼び出しますが、その逆ではありません。
ジェイコブVlijm

1
@JacobVlijm「スクリプトがインタープリターを呼び出す」とは言いません。「Linuxカーネルは、スクリプトを実行するときにどのインタープリターを呼び出すかを判断するためにシェバン行を使用します」と言います。
パエロエベルマン

@PaŭloEbermannありがとう!もちろんです。カーネルはどちらの方法でも全体の手順を処理しますが、比fig的には、理解しやすいと思いますが、スクリプトが「許可」されて、どのインタープリターを呼び出すかを処理します(そして実際に実行します)。言葉遣いについては定かではありませんが、イニシアチブがスクリプトにあり、カーネルが実際に仕事をしているように説明したいと思います。
ジェイコブVlijm

6

次のようなスクリプトでこれを実現できます。

#!/bin/bash

copy=/tmp/runner.$$
cp $1 ${copy}
chmod u+x ${copy}
${copy}
rm ${copy}

副<文>この[前述の事実の]結果として、それ故に、従って、だから◆【同】consequently; therefore <文>このような方法で、このようにして、こんなふうに、上に述べたように◆【同】in this manner <文>そのような程度まで<文> AひいてはB◆【用法】A and thus B <文>例えば◆【同】for example; as an example:

$ echo "echo hello" > myscript
$ ./myscript
bash: ./myscript: Permission denied
$ ./runscript myscript 
hello

これをしないことをお勧めします。許可には理由があります。これは、権限を破壊するためのプログラムです。

シバン処理はカーネル関数であることに注意してください(Linuxソースコードでは- fs/binfmt_script.c)。基本的に、スクリプトを直接呼び出すプロセスはそのことを知りません。#!カーネルはそれを使用して、インタープリターを起動する必要があることを判断します。


2
私はそれがカーネルではなくシェルの機能であると常に思っていました。今日何か新しいことを学びました。
ボートコーダー

1
@boatcoder-興味があるので、Linuxソースコードが処理する場所へのリンクを追加しました。
スリム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.