2009-03-27 7 views
1

J'écris des scripts shell pour faire différentes choses sous OSX et Linux, mais j'ai toujours le même problème. Le script s'exécute mais les modifications apportées à l'environnement (à l'exception des disques, bien sûr) ne "collent" pas. Lorsque le script se termine, les modifications sont rétablies.Scripting de shell extraordinairement simple Question: Faire des changements collants?

Comment puis-je faire en sorte que mes modifications restent?

Éditer: Beaucoup de réponses ont été excellentes, mais elles n'ont pas aidé la situation à laquelle je suis confrontée ce soir. Je suis en train de lancer pour obtenir mon interface TAP travail

sudo bash # we go superuser 
exec 4<>/dev/tap0 # opens device, creates interface tap0 
ifconfig tap0 10.10.10.1 10.10.10.255 
ifconfig tap0 up 

qui fonctionne à merveille si je le coller, mais pas si je la source ou sh il. BTW, je ne peux pas fermer la fenêtre du terminal après que je perds l'interface tap0.

Dernière modification: Merci à tous, la réponse était d'utiliser la source comme vous l'avez tous suggéré mais de supprimer la commande sudo du script lui-même.

Répondre

3

Les modifications apportées à l'environnement dans un processus enfant ne porte pas atteinte au processus parent. Heureusement, vous pouvez exécuter un script shell dans le processus actuel en disant

. /path/to/script.sh 

ou

source /path/to/script.sh 

Attention cependant, si vous exécutez exit dans le script, il quitte le shell en cours.

+0

Droite. Ou si je lance sudo, il quittera également cette commande sudo depuis le shell. Merci. –

2

Voulez-vous dire l'environnement comme dans les variables d'environnement? Vous ne pouvez pas, pas la façon dont vous voulez dire. Cet 'environnement' est une chose de contexte de processus; Ce n'est pas global pour votre système, c'est une partie de l'environnement d'exécution spécifique du script. Il peut être transmis aux processus que le script démarre, mais c'est tout. Si vous souhaitez configurer des paramètres fiables pour les variables d'environnement, vous le faites dans les fichiers d'initialisation partagés du système, tels que/etc/profile et /etc/bash.bashrc (noms réels OS et installation dépendante). Différents scripts d'initialisation sont exécutés dans différentes circonstances (shells de connexion par rapport aux shunts générés, des choses comme ça), mais l'idée est que vous pré-initialisez les shells avec le contexte d'environnement que vous voulez avoir autour.

+0

merci. J'ai fait une modification à la question qui montre la chose que j'essaie de faire fonctionner. Je ne pense pas qu'il peut être préinitialisé (ce n'est pas non plus un logiciel serveur sérieux). –

2

Si vous définissez des variables d'environnement dans votre script, elles ne resteront visibles que pendant l'exécution de votre script. Si vous avez besoin de variables d'environnement pour l'ensemble de votre session shell, vous devez les définir dans votre fichier .profile, .bashrc, .tcshrc ou le fichier .rc pour le shell que vous utilisez. Voir "man <your shell>" (par exemple man bash) pour des exemples sur la façon de procéder.

+0

Merci. J'ai édité la question pour montrer ce que j'essaie de faire. Je ne pense pas pouvoir le mettre dans un script shell. –

4

Ce comportement est inhérent à la conception - au moins dans bash, ce que j'utilise, mais je pense que la plupart des shells fonctionnent de la même manière. En général, il n'y a aucun moyen pour un processus d'exporter des choses comme des variables d'environnement vers son processus parent. Ce que vous pouvez faire, si vous voulez exécuter une série de commandes pour changer l'environnement dans le processus actuel du shell, est d'écrire les commandes dans un fichier et source. Dans bash si vous tapez

$ source commands.sh 

ou

$ . commands.sh 
+0

Excellent. Je ne le savais pas, et dans la plupart des cas cela aiderait, mais pas ce soir: voir la question (révisée) ci-dessus. Merci! –

+0

Merci, maintenant, le sudo dans le script causait des problèmes avec l'utilisation de la source. –

1

C'est de par sa conception.

Vous pouvez écrire vos variables d'environnement "collantes" dans un fichier et les lire lors de la prochaine exécution. Par exemple:

#!/bin/sh 

# load from ~/.my_env 
[ -r ~/.my_env ] && . ~/.my_env 

# replace or add new entries to ~/.my_env 
for i in "[email protected]"; do 
    [ "${i/=/}" = "$i" ] && continue 
    touch ~/.my_env 
    sed -i -e "\|^export ${i%%=*}=|d" ~/.my_env 
    echo "export $i" >> ~/.my_env 
    eval export "$i" 
done 
+0

Excusez mon ignorance, mais qui le lirait lors du prochain passage? Parlons-nous d'écrire un fichier .my_env? Le shell va-t-il le ramasser au lancement? –

+0

Non, seulement ce script shell qui utilise explicitement ~/.my_env. Ce n'était pas clair (à moi) de la question que vous vouliez n'importe quoi d'autre. – ephemient

1

Votre vraie question semble concerner uniquement l'interface de prise. Vous devriez changer la question pour refléter cela.

Lisez la documentation sur tap sous Linux/Documentation/networking/tuntap.txt. Voici une courte citation:

« Pour utiliser le pilote un programme doit ouvrir/dev/net/tun et émettre un ioctl correspondant() pour enregistrer un périphérique réseau avec le noyau d'un réseau dispositif sera. apparaît comme tunXX ou tapXX, selon les options choisies.Quand le programme ferme le descripteur de fichier, le périphérique réseau et tous les itinéraires correspondants disparaissent. "

Assez simple je dirais. Rien de mystérieux à ce sujet. Votre script ouvre l'interface du robinet et lorsque le script se termine, ferme le descripteur de fichier.

+0

Merci pour votre réponse utile. La vraie question concerne les scripts shell, pas l'interface tap: comment obtenir un descripteur de fichier qui soit persistant au-delà du script shell? Ou est-ce impossible (ce qui est bien aussi). –

1

Lorsque vous sudo, vous devez comprendre que vous exécutez un autre programme, un autre shell dans ce cas. C'est un malentendu que de coller ces commandes sur le terminal serait le même que de les mettre sur un script. Qu'est-ce qui se passe est que, après sudo, le terminal est connecté à une autre session shell, et la deuxième et d'autres commandes sont envoyées à cette autre session shell. Si vous placez toutes les commandes sur un script, les quatre commandes sont exécutées sur la même session shell, ce qui donne des résultats indésirables.

Dans ce cas précis, je vous suggère de mettre les trois dernières commandes sur un autre script (par exemple setup-tap.sh), puis appelez ce script comme

sudo bash setup-tap.sh 

Sourcing, comme le suggère, est une alternative persister les changements d'une invocation d'un script dans le shell actuel, mais cela ne fonctionnerait pas dans ce cas. C'est un niveau au dessus, il peut te chercher comme un script, puisque le terminal est le même, mais ce qui se passe c'est qu'après le sudo, tu n'es plus dans le même shell.

Il est comme de faire un script comme celui-ci:

vi file.txt 
iThe quick brown fox jumps over the lazy dog.<ESC>:wq 

Bien sûr, la deuxième ligne (commandes vi) ne seront pas en vi dactylographiées, il sera toujours dans le script original.

Une autre option serait d'utiliser ici-documents, et passer les commandes privilégiées à sudo bash entrée standard:

sudo bash <<-EOF 
    exec 4<>/dev/tap0 
    ifconfig tap0 10.10.10.1 10.10.10.255 
    ifconfig tap0 up 
EOF 
+0

Merci. Je ne savais pas à propos d'ici-documents, et bien qu'ils ne fonctionnent pas dans ce cas (au moins dans mes tests: l'interface de robinet se ferme lorsque le document ici est terminé), ils étaient une bonne trouvaille pour moi. –

+0

Vous êtes les bienvenus. A propos de l'interface de robinet, c'est le comportement prévu. Une interface de robinet est habituellement attachée à un démon qui la contrôlera. Il est inhabituel d'avoir un script shell pour cela. – Juliano