web-dev-qa-db-fra.com

Existe-t-il une commande permettant d'exécuter un script en fonction de sa ligne Shebang?

Si je veux exécuter un script bash dont les autorisations d'exécution ne sont pas définies, je peux faire:

bash script.sh

Que devrais-je utiliser à la place de bash si le script n'est pas exécutable et que je ne connais pas l'interprète correct? Existe-t-il une commande qui recherche l'interprète de la ligne Shebang et exécute le script avec?

45
Aivar

Oui. Il s'appelle 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)

Ceci est mentionné dans documentation de Perl :

Si la ligne #! ne contient pas le mot "Perl" ni le mot "indir", le programme nommé d'après le #! est exécuté à la place de l'interpréteur Perl. C'est un peu bizarre, mais cela aide les personnes sur des machines qui ne respectent pas #!, car elles peuvent dire à un programme que leur shell est/usr/bin/Perl, et Perl enverra ensuite le programme à l'interprète approprié.

66
Ole Tange

Les scripts n'ont pas nécessairement un Shebang

Si le script a été exécuté à partir de l'interprète, vous ne pouvez pas être sûr qu'il possède le Shebang du tout . () Les scripts exécutés à partir de l'interprète n'ont pas besoin du Shebang , if vous appelez l'interprète pour exécuter le code.

La réponse est donc non, aucune commande ne permet de savoir avec certitude quelle est la langue (interprète) avec laquelle exécuter le script. Vous pouvez cependant toujours regarder à l'intérieur du script et voir s'il a le Shebang à découvrir.

Les règles en bref:

  1. Lorsque vous exécutez le script, l'appel de l'interprète annule toujours les shebangs possibles, exécutables ou non, shebang ou non.
  2. S'il n'est pas exécutable et exécuté à partir de l'interpréteur, le script n'a pas besoin de Shebang.
  3. Si le script est exécuté sans appeler d’abord l’interprète, il a besoin de (et utilise) le Shebang pour rechercher l’interprète à appeler et il doit être exécutable pour avoir la "permission" d'appeler l'interpréteur depuis son Shebang.

Si le script n'a pas de Shebang, il n'y a pas d'information (directe *) à l'intérieur du script pour indiquer quel interpréteur utiliser.

Ayant dit cela

Vous pouvez bien sûr toujours écrire un script wrapper pour essayer de savoir si le script contient le Shebang et en lire l'interpréteur, puis l'exécuter à partir du trouvé interprète.

Un exemple

#!/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")
  • Enregistrez-le sous tryrundans $PATH (par exemple, ~/bin, créez le répertoire s'il n'existe pas, déconnectez-vous puis reconnectez-vous), rendez-le exécutable . Puis en cours d'exécution:

    tryrun /path/to/nonexecutablescript
    

    appelle (testé) l'interprète correct sur mes scripts pythonet bashnon exécutables.

Explication

  • Le script lit simplement la première ligne du script, supprime le #! et utilise le reste pour appeler l'interpréteur.
  • S'il ne parvient pas à appeler un interpréteur valide, il déclenchera soit un PermissionErrorou un FileNotFoundErrorname__.

Remarque

L'extension (.sh, .py etc.) ne joue aucun rôle dans la détermination de l'interpréteur approprié sous Linux.


(* Il est bien sûr possible de développer un algorithme "intelligent" de devin pour déterminer la syntaxe à partir du code.)

25
Jacob Vlijm

Vous pouvez y parvenir avec un script comme celui-ci:

#!/bin/bash

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

Ainsi:

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

Je recommande de ne pas faire cela. Les autorisations sont là pour une raison. Ceci est un programme pour subvertir les autorisations.

Notez que la gestion de Shebang est une fonction du noyau (dans le code source Linux - fs/binfmt_script.c ). Fondamentalement, le processus invoquant directement un script ne connaît pas le #! - le noyau l'utilise pour déterminer qu'il lui faut lancer un interpréteur.

6
slim