Есть ли команда для запуска скрипта в соответствии со своей строкой shebang?

44

Если я хочу выполнить скрипт bash, который не имеет установленного разрешения на выполнение, я могу сделать:

bash script.sh

Что следует использовать вместо bash , если скрипт не является исполняемым, и я не знаю правильного интерпретатора? Есть ли команда, которая ищет интерпретатор из строки shebang и выполняет скрипт с ней?

    
задан Aivar 17.11.2016 в 09:57
источник

3 ответа

64

Угу. Он называется 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. Это немного странно, но помогает людям на машинах, которые не выполняют #! , потому что они могут сообщить программе, что их SHELL - / usr / bin / perl, а Perl отправит программу на правильный интерпретатор для них .

    
ответ дан Ole Tange 17.11.2016 в 20:06
источник
25

Скрипты не обязательно имеют shebang

Если скрипт был запущен из интерпретатора, вы не можете быть уверены, что у него есть shebang вообще . Скрипты, выполняемые из интерпретатора, не нуждаются в shebang , , если вы вызываете интерпретатор для запуска кода.

Поэтому нет ответа, нет команды, которая точно определит, что такое язык (интерпретатор) для запуска скрипта. Однако вы всегда можете заглянуть внутрь скрипта и посмотреть, есть ли у него shebang, чтобы узнать.

Короче говоря:

  1. Когда вы запускаете скрипт, вызов интерпретатора always перекрывает возможные shebangs, исполняемые или нет, shebang или нет.
  2. Если не исполняется и запускается из интерпретатор, скрипт не нуждается в shebang.
  3. Если сценарий запускается без вызова интерпретатора в первую очередь, ему требуется (и использует) shebang, чтобы узнать, какой интерпретатор для вызова, и он должен быть исполняемым иметь «разрешение» для вызова интерпретатора из его shebang.

Если в скрипте нет shebang, в скрипте нет (прямой *) информации, чтобы указать, какой интерпретатор использовать.

Сказав, что

Конечно, вы всегда можете написать сценарий-оболочку для try , чтобы узнать, есть ли скрипт в shebang и прочитать интерпретатор, затем запустите его из найденного интерпретатора.

Пример

#!/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")
  • Сохраните его как tryrun в $PATH (например, ~/bin , создайте каталог, если он не существует, выйдите из системы и обратно), сделайте его исполняемым . Затем выполните:

    tryrun /path/to/nonexecutablescript
    

    вызывает (проверяет) правильный интерпретатор на мои невыполняемые скрипты python и bash .

Объяснение

  • Скрипт просто читает первую строку скрипта, удаляет #! и использует остальное для вызова интерпретатора.
  • Если он не может вызвать действительный интерпретатор, он будет поднимать либо PermissionError , либо FileNotFoundError .

Примечание

Расширение ( .sh , .py и т. д.) не играет никакой роли в определении соответствующего интерпретатора в Linux.

(* Конечно, можно разработать «умный» алгоритм угадывания, чтобы определить синтаксис кода.)

    
ответ дан Jacob Vlijm 17.11.2016 в 10:01
6

Вы можете добиться этого с помощью скрипта следующим образом:

#!/bin/bash

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

Таким образом:

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

Я рекомендую не делать этого. Разрешения есть по какой-то причине. Это программа для разрешений на запрет.

Обратите внимание, что обработка shebang - это функция kernel (в исходном коде Linux - fs/binfmt_script.c ). По сути процесс, вызывающий скрипт напрямую, не знает о #! - ядро ​​использует его для разработки, чтобы запустить интерпретатор.

    
ответ дан slim 17.11.2016 в 17:48