Comment démarrer un script avec un environnement propre?


15

J'ai essayé ce qui suit mais cela ne semble pas fonctionner:

$ cat script.sh
#!/bin/env -i /bin/sh

/bin/env
$ script.sh
/bin/env: invalid option -- ' '
Try `/bin/env --help' for more information.

Trouvé des questions similaires mais ne montre pas comment faire à partir de shebang: unix.stackexchange.com/questions/48994/…
balki

5
Vous ne pouvez pas le faire depuis Shebang. Le shebang ne peut accepter qu'un seul argument.
jordanm

Réponses:


7

La raison pour laquelle cela ne fonctionne pas est qu'il considère -i /bin/shcomme un argument unique à env. Habituellement, ce serait 2 arguments, -iet /bin/sh. Ce n'est qu'une limitation du shebang. Pas question.


Cependant, vous pouvez toujours effectuer cette tâche, d'une manière différente.

Si vous voulez que cette tâche soit exécutée par le script lui-même et que vous n'ayez pas à faire quelque chose comme cela env -i script.sh, vous pouvez demander au script de se réexécuter lui-même.

#!/bin/sh
[ -z "$CLEANED" ] && exec /bin/env -i CLEANED=1 /bin/sh "$0" "$@"

Cela entraînera le script à se réexécuter si la CLEANEDvariable d'environnement n'est pas définie. Ensuite, lors de la réexécution, il définit la variable pour s'assurer qu'elle n'entre pas dans une boucle.


envdes coreutils GNU ont maintenant une option -Spour contourner les problèmes similaires à celui-ci mais pas exactement les mêmes. Par exemple #!/usr/bin/env -S perl -T.
Weijun Zhou

Je viens d'essayer. Cela fonctionne également pour la question d'origine. Utilisez simplement #!/usr/bin/env -S -i /bin/sh. Soyez conscient des problèmes de portabilité.
Weijun Zhou

3

Exécutez votre script avec env -i:

env -i script.sh

Et le script comme d'habitude:

#!/bin/sh
# ... your code here

Si vous voulez exécuter avec un environnement propre sans le dire explicitement lorsque vous exécutez. Eduardo Ivanec donne quelques idées dans cette réponse , vous pouvez appeler récursivement votre script execlorsque l'environnement n'est pas propre (par exemple $ HOME est défini):

[ "$HOME" != "" ] && exec -c $0

Agréable. Ne faites pas env -i bash comme je l'ai fait, puis demandez-vous pourquoi vos variables env sont toujours définies (bien sûr, bash resources .bashrc and friends 8)
Neil McGill

2

Avec bash, vous pouvez le faire comme ceci:

#!/usr/bin/bash

set -e
set -u

[ -v HOME ] && exec -c "$0" "$@"

# continue with the rest of the script
# e.g. print the cleaned environment:
export

Les commandes set -eet set -une sont pas strictement nécessaires, mais je les inclue pour démontrer que cette approche ne repose pas sur l'accès aux variables non définies (comme par exemple le [ "$HOME" != "" ]ferait) et est compatible avec un set -eparamètre.

Le test de la HOMEvariable doit être sûr car bash exécute des scripts en mode non interactif, c'est-à-dire que les fichiers de configuration comme ~/.bashrc(où les variables d'environnement peuvent être définies) ne sont pas fournis lors du démarrage.

Exemple de sortie:

declare -x OLDPWD
declare -x PWD="/home/juser"
declare -x SHLVL="1"

0

$ cat script.sh

#!/bin/env -i /bin/sh

Malheureusement, cela ne fonctionnera pas de cette façon - Linux considère -i /bin/shcomme un argument à passer env(voir Shebang ).


0

La limitation de shebang à 2 arguments Linux (interpètre + argument unique) est notée dans la plupart des réponses, mais dire que cela ne peut pas être fait est incorrect - il vous suffit de passer à un interpréteur qui peut faire quelque chose d'utile avec un seul argument:

#!/usr/bin/perl -we%ENV=();exec "/bin/sh " . join " ", map "'$_'", @ARGV;
# your sh script here

Ce que cela fait, c'est invoquer perlavec un script à une ligne ( -e) qui efface %ENV(moins cher que env -i) et invoque exec /bin/sh, en citant correctement les arguments. Plus loinperl logique peut être ajoutée, si nécessaire (mais pas beaucoup sur Linux car vous êtes limité aux BINPRM_BUF_SIZEcaractères, ce qui est probablement 128)

Malheureusement, ceci est spécifique à Linux, cela ne fonctionnera pas sur un système qui autorise plusieurs arguments shebang: - /

perltraite cette chaîne comme un seul argument, elle n'est donc pas citée ci-dessus comme vous le feriez normalement avecperl -e ... la ligne de commande (si vous deviez ajouter des guillemets, ceux-ci sont conservés, perl ne voit qu'une chaîne littérale, avec des avertissements dessus, il se plaindra d'une inutilité constant).

Notez également qu'il y a un léger changement de comportement lorsqu'il est utilisé de cette façon, @ARGVcontient normalement uniquement les arguments et $0contient le script, mais avec ce shebang $ARGV[0]est le nom du script (et$0 est -e) ce qui le rend un peu plus facile.

Vous pouvez également résoudre ce problème avec un interpréteur qui "retire" sa ligne de commande (sans -cargument supplémentaire ) que l'ancien AT&T ksh93fait:

#!/bin/ksh /usr/bin/env -i /bin/sh

mais peut-être ksh n'est - pas aussi courant de nos jours ;-)

( basha une fonctionnalité similaire avec --wordexp, mais il est "non documenté" dans les versions où il fonctionne, et n'est pas activé au moment de la compilation dans les versions où il est documenté: - / Il ne peut pas non plus être utilisé pour cela car il a besoin de deux arguments. ..)

Aussi, effectivement une variation sur les réponses de @Patrick et @ maxschlepzig:

#!/bin/bash
[ "$_" != bash ] && exec -c -a "bash" /bin/bash "$0" "$@"
# your script here

Plutôt que d'utiliser une nouvelle variable, cela utilise la variable spéciale " _", si elle n'est pas définie sur exactement "bash", remplacez le script en executilisant -apour faire ARGV[0](et donc $_) juste "bash", et en utilisant-c pour effacer l'environnement.

Alternativement, s'il est acceptable de nettoyer l'environnement au début du script (bash uniquement):

#!/bin/sh
unset $(compgen -e)
# your script here

Qui utilise compgen(aide à l'achèvement) pour répertorier les noms de toutes les variables d'environnement exportées, etunset s en une seule fois.

Voir aussi Arguments multiples dans shebang pour plus de détails sur le problème général du comportement de shebang.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.