Existe-t-il une commande pour exécuter un script en fonction de sa ligne shebang?

45

Si je veux exécuter un script bash qui n’a pas son autorisation d’exécution, 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 le bon interpréteur? Existe-t-il une commande qui recherche l'interpréteur à partir de la ligne shebang et exécute le script avec celui-ci?

    
posée Aivar 17.11.2016 - 09:57
la source

3 réponses

66

Ouais. 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 la documentation de Perl :

  

Si la ligne #! ne contient pas le mot "perl" ni le mot "indir", le programme nommé après le #! est exécuté à la place de l’interpréteur Perl. C'est un peu bizarre, mais cela aide les gens sur des machines qui ne font pas #! , car ils peuvent dire à un programme que leur SHELL est / usr / bin / perl, et Perl enverra alors le programme à l'interpréteur approprié pour eux. .

    
réponse donnée Ole Tange 17.11.2016 - 20:06
la source
25

Les scripts n'ont pas nécessairement un shebang

Si le script a été exécuté par l'interpréteur, vous ne pouvez pas être sûr qu'il contient le . 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'y a pas de commande pour 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 y a le shebang à découvrir.

Les règles en bref:

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

Si le script n'a pas de shebang, il n'y a pas d'informations (directes *) dans le script pour indiquer quel interpréteur utiliser.

Cela dit,

Vous pouvez bien sûr toujours écrire un script wrapper sur try pour savoir si le script a le shebang et lire l'interpréteur à partir de celui-ci, puis l'exécuter depuis 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")
  • Enregistrez-le sous tryrun dans $PATH (par exemple ~/bin , créez le répertoire s'il n'existe pas, déconnectez-vous et reconnectez-vous), rendez-le exécutable . Puis en cours d'exécution:

    tryrun /path/to/nonexecutablescript
    

    appelle (testé) le bon interpréteur sur mes scripts non exécutables python et bash .

Explication

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

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 de prédiction "intelligent" pour déterminer la syntaxe à partir du code.)

    
réponse donnée Jacob Vlijm 17.11.2016 - 10:01
la source
6

Vous pouvez réaliser ceci avec un script comme celui-ci:

#!/bin/bash

copy=/tmp/runner.$$
cp  ${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 le faire. Les autorisations sont là pour une raison. Ceci est un programme pour subvertir les autorisations.

Notez que la gestion de shebang est une fonction kernel (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 s'il doit lancer un interpréteur.

    
réponse donnée slim 17.11.2016 - 17:48
la source

Lire d'autres questions sur les étiquettes