21 votes

Écrire des Shell Shell qui s'exécuteront sur n'importe quel Shell (en utilisant plusieurs lignes shebang ?).

Je viens de commencer à m'intéresser de plus près aux scripts Shell, et j'ai toujours jeté mon Shell dans un fichier, en le marquant chmod +x et ensuite fait /path/to/script.sh et laisser l'interpréteur par défaut s'en occuper, ce que j'ai supposé être zsh parce que c'est ce que j'ai utilisé pour mon Shell. Apparemment, il semble que c'est juste /bin/sh par défaut, même si j'exécute le script à partir d'une invite zsh, parce que j'ai commencé à mettre des choses spécifiques à zsh dans mes script et cela échoue à moins que je n'exécute zsh /path/to/script.sh .

Pour en venir au fait, voici mes questions :

  1. Quel Shell exécute Shell quand il n'y a pas de ligne shebang ( #!/path/to/shell ) au début ? Je suppose que /bin/sh mais je ne peux pas confirmer.
  2. Qu'est-ce qui est considéré comme les "meilleures pratiques" en termes d'écriture de Shell Shell qui fonctionneront sur n'importe quelle plate-forme ? (ok, c'est une sorte de question ouverte)
  3. Est-il possible d'écrire un script qui essaie d'utiliser zsh et se rabat sur bash si zsh n'est pas disponible ? J'ai essayé de mettre deux lignes shebang, comme ci-dessous, mais il y a juste une erreur avec bad interpreter: /bin/zsh: no such file or directory si je l'essaie sur une machine sans zsh.

    #!/bin/zsh

    #!/bin/bash

28voto

James Mertz Points 390

Quel Shell exécute les Shell quand il n'y a pas de ligne shebang (#!/path/to/Shell) au début ? Je suppose /bin/sh mais je ne peux pas confirmer.

Le noyau refuse d'exécuter de tels scripts et renvoie ENOEXEC, donc le comportement exact dépend du programme dans lequel vous exécutez un tel scripts. de .

  • bash 4.2.39 - s'utilise lui-même
  • busybox-ash 1.20.2 - s'utilise lui-même
  • dash 0.5.7 - exécute /bin/sh
  • fish 1.23.1 - se plaint de ENOEXEC, puis accuse le mauvais fichier
  • AT&T ksh 93u+2012.08.01 - s'utilise tout seul
  • mksh R40f - exécute /bin/sh
  • pdksh 5.2.14 - exécute /bin/sh
  • sh-heirloom 050706 - s'utilise lui-même
  • tcsh 6.18.01 - exécute /bin/sh
  • zsh 5.0.0 - exécute /bin/sh
  • cmd.exe 5.1.2600 - vous regarde bizarrement.

Sur glibc , fonctions execv() o execve() il suffit de renvoyer ENOEXEC. Mais execvp() masque ce code d'erreur et invoque automatiquement /bin/sh. (Ceci est documenté dans exécution (3p) .)

Qu'est-ce qui est considéré comme les "meilleures pratiques" en termes d'écriture de Shell Shell qui fonctionneront sur n'importe quelle plate-forme ? (ok, c'est une sorte de question ouverte)

Soit vous vous en tenez à sh et seulement les fonctionnalités définies par POSIX, ou simplement faire le plein de bash (qui est largement disponible) et le mentionner dans vos exigences si vous le distribuez.

(Maintenant que j'y pense, Perl - ou peut-être Python - serait encore plus portable, sans compter qu'il aurait une meilleure syntaxe).

Toujours ajouter la ligne shebang. Si vous utilisez bash ou zsh, utilisez #!/usr/bin/env bash au lieu de coder en dur le chemin du Shell. (Cependant, le Shell POSIX est garanti pour être à /bin/sh donc passez votre chemin env dans ce cas).

(Malheureusement, même /bin/sh n'est pas toujours la même. La norme GNU autoconf Le programme doit faire face à de nombreuses bizarreries différentes .)

Est-il possible d'écrire un script qui essaie d'utiliser zsh et se rabat sur bash si zsh n'est pas disponible ? J'ai essayé de mettre deux lignes shebang, comme ci-dessous, mais ça ne fait qu'une erreur avec mauvais interprète : /bin/zsh : aucun fichier ou répertoire de ce type si je l'essaie sur une machine sans zsh.

Il ne peut y avoir qu'une seule ligne shebang ; tout ce qui suit le caractère newline n'est même pas lu par le noyau, et est traité comme un commentaire par les shells.

C'est possible pour écrire un script qui s'exécute en tant que #!/bin/sh , vérifie quel Shell est disponible, et exécute exec zsh "$0" "$@" o exec bash "$0" "$@" en fonction du résultat. Cependant, la syntaxe utilisée par bash et zsh est tellement différente à plusieurs endroits que je voudrais je ne recommande pas de le faire pour votre propre santé.

2voto

TheCompWiz Points 10142

1) Le Shell actuel dans lequel vous vous exécutez. (quel que soit le Shell en question)

2) Restez avec le même type de Shell (bash/dash/ash/csh/quel que soit votre saveur) et assurez-vous que vos "plateformes supportées" installent le Shell que vous souhaitez utiliser par défaut. De plus, essayez d'utiliser des commandes communément disponibles sur les systèmes. Évitez les options spécifiques à la machine.

3) Il n'y a pas vraiment de logique "if-then-else" dans le processus d'évaluation de l'impact sur l'environnement. interpreter directive . Vous devez spécifier un Shell qui doit exister sur tous les systèmes que vous souhaitez prendre en charge ... c'est-à-dire. #!/bin/bash ou spécifier un générique #!/bin/sh tant que votre script est assez générique pour tous les shells.

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