Comment exécuter un programme dans un environnement propre à Bash?

Réponses:

127

Vous pouvez le faire avec env:

env -i your_command

Contrairement aux commentaires ci-dessous, cela efface complètement l'environnement, mais n'empêche pas la your_commanddéfinition de nouvelles variables. En particulier, l’exécution d’un shell entraînera l’ /etc/profileexécution de celui-ci, qui peut également comporter certains paramètres intégrés.

Vous pouvez vérifier cela avec:

env -i env

c'est-à-dire essuyez l'environnement puis imprimez-le. La sortie sera vide.

ams
la source
4
Cela n'efface pas complètement l'environnement: les echo 'echo $PATH' > test.sh && chmod u+x test.sh && env -i test.shimpressions /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin.
l0b0
2
Cependant, il semble que ce soit le plus proche , vous pouvez obtenir - Il semble que des variables telles que PATH, PWDet SHLVLsont réglées automatiquement par Bash. +1
l0b0
3
@ I0b0: Voir mon édition.
ams
3
La variable PATH du script du premier commentateur n'est pas dans l'environnement et n'est donc pas une variable d'environnement. Apparemment, Bash définit sa propre variable shell appelée PATH s’il n’en existe pas d’exportée: env -i bash --norc -c "declare -p PATH"donne declare -- PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:.". Notez le "-x" pour l'export (et donc une partie de l'environnement) si vous l'exportez vous-même: env -i bash --norc -c "export PATH; declare -p PATH"donnedeclare -x PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:."
Binary Phile
34

Un bashenvironnement "propre" peut être créé avec

$ env -i bash --noprofile --norc
  • La env -icommande exécute la commande qui lui est donnée sur la ligne de commande sans transférer aucune des variables d’environnement exportées de l’ancien environnement shell vers l’environnement du programme exécuté.

  • L' --noprofileoption empêche la bashlecture des scripts d'initialisation de shell personnels ou à l'échelle du système qui seraient autrement lus pour un shell de connexion.

  • L' --norcoption empêche la bashlecture des scripts d'initialisation de shell personnels qui seraient autrement lus pour un shell interactif.

Kusalananda
la source
Mon env ne reconnaît pas ces options.
Paulo Carvalho
@PauloCarvalho Votre système ne supporte pas env -i? Vous êtes sur quel système?
Kusalananda
Désolé, ça marche dans le shell. J'ai essayé de le mettre dans un script et d'une manière ou d'une autre, cela a généré une erreur.
Paulo Carvalho
@PauloCarvalho Désolé, je ne vois pas quelle commande vous avez tapée ni quelle était l'erreur que vous avez eue.
Kusalananda
Super - exactement ce que je cherchais. envnettoyer mon environnement, --noprofileéviter d’approvisionner / etc / profile et mes amis, et --norcéviter d’approvisionner ~ / .bashrc et mes amis.
Felipe Alvarez
28

env -i somecommandexécute une commande dans un environnement vide, comme l' a déjà mentionné ams .

Beaucoup de programmes reposent sur des variables d'environnement importantes. Vous souhaiterez donc peut-être les conserver:

env -i HOME="$HOME" LC_CTYPE="${LC_ALL:-${LC_CTYPE:-$LANG}}" PATH="$PATH" USER="$USER" somecommand

Vous pouvez également vous connecter à un petit environnement de connexion.

ssh localhost somecommand
Gilles
la source
1
Fonctionne lors de l'exécution de la commande sur cmdline. Comment puis-je mettre cela en shebang? Ne semble pas fonctionner !
Balki
Étrange, mon envne supporte pas la --délimitation et les env -i FOO=bar -- envtentatives d'exécution d'une commande nommée --.
antak
@antak Cela devrait être env -i -- FOO=bar env, en fait. Ma faute. Non pas que le --soit utile puisque ce qui suit ne commence pas par -.
Gilles
Je ne savais pas que vous pouviez toujours utiliser ssh dans localhost, c'est un peu bizarre. Quel est le cas d'utilisation ici.
Edgar Aroutiounian
@ EdgarAroutiounian Vous pouvez SSH sur localhost s'il exécute un serveur SSH. Pourquoi les programmeurs tentent-ils de l'interdire?
Gilles
4

Bien que la réponse acceptée soit correcte, ce que vous voulez généralement faire est de:

env -i bash -l -c "printenv; and any other commands"

Cela vous donne un bash nu mais fonctionnel (identique à celui que vous obtiendriez si vous vous connectiez en mode non interactif). Cela permet par exemple de définir la langue, le fuseau horaire, HOME, etc.

Marcin Raczkowski
la source
Cela ne fonctionne pas tout à fait, car c’est env -ieffacé HOME, ce qui signifie que bash -lvous ne pouvez pas trouver votre .bash_profileetc. Si vous voulez un shell qui ressemble à ce que vous obtiendrez lors d’une nouvelle connexion, vous avez besoin d’un indirection supplémentaire à définir en HOMEpremier.
Elliott Slaughter
Voir cette réponse: unix.stackexchange.com/a/451389/157340
Elliott Slaughter
1

Le problème avec la plupart des réponses ici, c’est que ça env -iefface HOME, donc même si vous courez bash -là l’intérieur, il ne lira pas votre .bash_profileetc. Si vous recherchez un shell qui agit comme si vous veniez de vous connecter, Voudrais ceci à la place:

env -i HOME="$HOME" bash -l -c 'your_command'

Exemple:

$ export ABC=123
$ env -i HOME="$HOME" bash -l -c 'env' | grep ABC
$ env HOME="$HOME" bash -l -c 'env' | grep ABC
ABC=123
Elliott Slaughter
la source
1
Notez qu'un bashshell de connexion sera exécuté .bash_loginou .bash_profile. Pour obtenir un environnement propre, utilisez --noprofileou définissez HOMEun répertoire ne contenant pas ces fichiers. Je suppose que cela dépend de ce que vous entendez par «propre».
Kusalananda
1
Oui, si vous voulez un shell qui ne contient littéralement rien, suivez simplement la réponse originale env -i bash -c .... Cette réponse concerne spécifiquement le shell qui ressemble à une nouvelle connexion sur la machine.
Elliott Slaughter
0

Pour répondre au commentaire de balki (et répondre à ma propre question dans le processus :-):

% echo Environment in calling shell: vars: $(env |wc -l); echo; ./du; echo; cat du
Environment in calling shell: vars: 43

==> This is the environment: vars: 5
PATH="$PATH"
PWD=/Users/nick
SHLVL=1
SOMETHING_TO_KEEP="$USER"
_=/usr/bin/env
==> The end.

#!/usr/bin/env -i SOMETHING_TO_KEEP="$USER" PATH="$PATH" /bin/sh

echo "==> This is the environment: vars:" $(/usr/bin/env | /usr/bin/wc -l)
/usr/bin/env
echo "==> The end."
Coroos
la source
Quand j'essaye ceci dans ma ligne de shebang dans CentOS 7.6, j'obtiens cette erreur d'env:/usr/bin/env: invalid option -- ' ' Try '/usr/bin/env --help' for more information.
ScottJ
Si je change le script pour utiliser l'argument long, --ignore-environmentalors j'obtiens ceci:/usr/bin/env: unrecognized option '--ignore-environment SOMETHING_TO_KEEP="$USER" PATH="$PATH" /bin/sh' Try '/usr/bin/env --help' for more information.
ScottJ