Existe um comando para executar um script de acordo com sua linha shebang?

45

Se eu quiser executar um script bash que não tenha seu conjunto de permissões de execução, posso fazer:

bash script.sh

O que devo usar em vez de bash se o script não for executável e não souber o interpretador correto? Existe um comando que procura o intérprete da linha shebang e executa o script com ele?

    
por Aivar 17.11.2016 / 09:57

3 respostas

65

Sim. É chamado 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)

Isso é mencionado na documentação do Perl :

  

Se a linha #! não contiver a palavra "perl" nem a palavra "indir", o programa com o nome de #! será executado em vez do interpretador Perl. Isso é um pouco bizarro, mas ajuda pessoas em máquinas que não fazem #! , porque elas podem dizer a um programa que seu SHELL é / usr / bin / perl, e o Perl irá despachar o programa para o interpretador correto para eles .

    
por Ole Tange 17.11.2016 / 20:06
25

Scripts não têm necessariamente um shebang

Se o script foi executado a partir do intérprete, Você não pode ter certeza de que ele tem o shebang em tudo . Scripts, executados a partir do interpretador, não precisam do shebang , se você chamar o interpretador para executar o código.

A resposta é, portanto, não, não há nenhum comando que descubra com certeza qual é a linguagem (interpretador) para executar o script. Você pode, no entanto, sempre olhar dentro do script e ver se ele tem o shebang para descobrir.

As regras resumidas:

  1. Quando você executa o script, chamar o intérprete sempre anula possíveis shebangs, executáveis ou não, shebang ou não.
  2. Se não for executável e executado a partir do interpretador, o script não precisa de shebang.
  3. Se o script é executado sem chamar primeiro o intérprete, ele precisa (e usa) o shebang para descobrir qual interpretador chamar, e ele precisa ser executável ter a "permissão" para chamar o intérprete de sua shebang.

Se o script não tiver shebang, no entanto, não há informações (diretas *) dentro do script para dizer qual interpretador usar.

Tendo dito isso

Você poderia sempre escrever um script wrapper para tentar descobrir se o script tem o shebang e ler o interpretador a partir dele, e depois executá-lo a partir do interpretador encontrado.

Um exemplo

#!/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")
  • Salve como tryrun em $PATH (por exemplo, ~/bin , crie o diretório se ele não existir, efetue logout e volte), torne-o executável . Em seguida, executando:

    tryrun /path/to/nonexecutablescript
    

    chama (testou) o interpretador correto em meus scripts python e bash não executáveis.

Explicação

  • O script simplesmente lê a primeira linha do script, remove o #! e usa o resto para chamar o interpretador.
  • Se não conseguir chamar um intérprete válido, ele aumentará um PermissionError ou um FileNotFoundError .

Nota

A extensão ( .sh , .py etc) não desempenha nenhum papel na determinação do intérprete apropriado no Linux.

(* É claro que é possível desenvolver um algoritmo de adivinhação "inteligente" para determinar a sintaxe do código.)

    
por Jacob Vlijm 17.11.2016 / 10:01
6

Você pode conseguir isso com um script como este:

#!/bin/bash

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

Assim:

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

Eu não recomendo fazer isso. Permissões estão lá por um motivo. Este é um programa para subverter permissões.

Note que o manuseio shebang é uma função kernel (no código-fonte do Linux - fs/binfmt_script.c ). Fundamentalmente, o processo que invoca diretamente um script não sabe sobre o #! - o kernel o usa para descobrir que precisa iniciar um interpretador.

    
por slim 17.11.2016 / 17:48