47 votes

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 script dont la permission d'exécution n'est pas définie, je peux le faire :

bash script.sh

Que dois-je utiliser à la place de bash si le script n'est pas exécutable et que je ne connais pas l'interpréteur correct ? Existe-t-il une commande qui recherche l'interpréteur à partir de la ligne shebang et qui exécute le script avec celui-ci ?

74voto

Ole Tange Points 1518

Yep. Il s'appelle perl . Quelques exemples, avec l'interpréteur correspondant dans la ligne shebang du fichier (l'extension du fichier n'a pas d'importance) :

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 La documentation de Perl :

Si le #! ne contient ni le mot "perl" ni le mot "indir", le programme nommé d'après le mot "perl". #! 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 font pas de #! Ils peuvent dire à un programme que leur Shell est /usr/bin/perl, et Perl enverra alors le programme à l'interpréteur correct pour eux.

25voto

Jacob Vlijm Points 78990

Les scripts n'ont pas nécessairement de shebang

Si le script a été exécuté à partir de l'interpréteur, vous ne pouvez pas être sûr qu'il possède le shebang à tous . Les scripts, exécutés à partir de l'interpréteur, n'ont pas besoin du shebang. , si vous appelez l'interpréteur pour exécuter le code.

La réponse est donc non, il n'existe pas de commande qui permette de savoir avec certitude quel est le langage (interpréteur) avec lequel le script doit être exécuté. Vous pouvez cependant toujours regarder à l'intérieur du script et voir s'il a le shebang pour le savoir.

Les règles en bref :

  1. Lorsque vous exécutez le script, l'appel de l'interpréteur toujours annule les éventuels shebangs, qu'ils soient exécutables ou non, qu'il s'agisse d'un shebang ou non.
  2. S'il n'est pas exécutable et exécuté 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éteur, il besoins (et utilise) le shebang pour savoir quel interprète appeler, et il doit être exécutable pour avoir la "permission" d'appeler l'interpréteur à partir de son shebang.

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

Ceci étant dit

Vous pouvez bien sûr toujours écrire un script pour 為す pour savoir si le script a le shebang et lire l'interpréteur à partir de celui-ci, puis l'exécuter à partir de l'interpréteur trouvé.

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")
  • Sauvegarder en tant que tryrun en $PATH (par exemple ~/bin (créer le répertoire s'il n'existe pas, se déconnecter et se reconnecter), le rendre exécutable . Puis en courant :

    tryrun /path/to/nonexecutablescript

    appelle (testé) l'interpréteur correct sur mon fichier non exécutable python y bash scripts.

Explication

  • Le script lit simplement la première ligne du script, supprime l'élément #! et utilise le reste pour appeler l'interprète.
  • S'il ne parvient pas à appeler un interprète valide, il lèvera soit un PermissionError ou un FileNotFoundError .

Note

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


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

6voto

slim Points 169

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 vous déconseille de le faire. Les autorisations sont là pour une raison. Il s'agit d'un programme permettant de contourner les autorisations.

Notez que la gestion du shebang est un Noyau (dans le code source de Linux - fs/binfmt_script.c ). Fondamentalement, le processus qui invoque directement un script n'a pas connaissance de la fonction #! -- Le noyau l'utilise pour déterminer s'il doit lancer un interprète.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X