Je me demande s'il existe un moyen général de transmettre plusieurs options à un exécutable via la ligne shebang (#!
).
J'utilise NixOS, et la première partie du shebang dans n'importe quel script que j'écris est généralement /usr/bin/env
. Le problème que je rencontre alors est que tout ce qui suit est interprété comme un seul fichier ou répertoire par le système.
Supposons, par exemple, que je veuille écrire un script à exécuter par bash
en mode posix. La façon naïve d'écrire le shebang serait :
#!/usr/bin/env bash --posix
mais essayer d'exécuter le script résultant produit l'erreur suivante :
/usr/bin/env: ‘bash --posix’: No such file or directory
Je suis au courant de ce message, mais je me demandais s'il existait une solution plus générale et plus propre.
MODIFIER :Je sais que pour les scripts Guile, il existe un moyen d'obtenir ce que je veux, documenté dans la section 4.3.4 du manuel :
#!/usr/bin/env sh
exec guile -l fact -e '(@ (fac) main)' -s "$0" "[email protected]"
!#
L'astuce, ici, est que la deuxième ligne (commençant par exec
) est interprété comme du code par sh
mais, étant dans le #!
… !#
block, en tant que commentaire, et donc ignoré, par l'interpréteur Guile.
Ne serait-il pas possible de généraliser cette méthode à n'importe quel interpréteur ?
Deuxième MODIFICATION :Après avoir joué un peu, il semble que, pour les interprètes qui peuvent lire leur entrée depuis stdin
, la méthode suivante fonctionnerait :
#!/usr/bin/env sh
sed '1,2d' "$0" | bash --verbose --posix /dev/stdin; exit;
Ce n'est probablement pas optimal, car le sh
le processus vit jusqu'à ce que l'interprète ait terminé son travail. Tout commentaire ou suggestion serait apprécié.
Réponse acceptée :
Il n'y a pas de solution générale, du moins pas si vous devez prendre en charge Linux, car le noyau Linux traite tout ce qui suit le premier "mot" de la ligne shebang comme un seul argument.
Je ne sais pas quelles sont les contraintes de NixOS, mais en général, j'écrirais simplement votre shebang comme
#!/bin/bash --posix
ou, si possible, définissez des options dans le script :
set -o posix
Alternativement, vous pouvez faire redémarrer le script avec l'invocation appropriée du shell :
#!/bin/sh -
if [ "$1" != "--really" ]; then exec bash --posix -- "$0" --really "[email protected]"; fi
shift
# Processing continues
Cette approche peut être généralisée à d'autres langages, tant que vous trouvez un moyen pour que les deux premières lignes (qui sont interprétées par le shell) soient ignorées par le langage cible.
En relation :Comment ajouter plusieurs lignes à un fichier ?
GNU coreutils
' env
fournit une solution de contournement depuis la version 8.30, voir la réponse d'unode pour plus de détails. (Ceci est disponible dans Debian 10 et versions ultérieures, RHEL 8 et versions ultérieures, Ubuntu 19.04 et versions ultérieures, etc.)