web-dev-qa-db-fra.com

Quelles sont les utilisations de la commande exec dans les scripts Shell?

Quelqu'un peut-il expliquer les utilisations de la commande exec dans les scripts Shell à l'aide d'exemples simples?

236
user2400564

La commande intégrée exec reflète les fonctions du noyau. Il en existe une famille basée sur execve, généralement appelée à partir de C.

exec remplace le programme en cours dans le processus en cours, sans forking un nouveau processus. Ce n’est pas quelque chose que vous utiliseriez dans tous les scripts que vous écrivez, mais il est utile à l’occasion. Voici quelques scénarios que je l'ai utilisé;

  1. Nous voulons que l'utilisateur exécute un programme d'application spécifique sans accès au shell. Nous pourrions changer le programme de connexion dans/etc/passwd, mais peut-être voudrions-nous que les paramètres d’environnement soient utilisés à partir des fichiers de démarrage. Ainsi, dans (par exemple) .profile, la dernière déclaration dit quelque chose comme:

     exec appln-program
    

    alors maintenant, il n’ya plus de Shell sur lequel revenir. Même si appln-program se bloque, l'utilisateur final ne peut pas accéder à un shell, car il n'y est pas - le exec l'a remplacé.

  2. Nous voulons utiliser un autre shell que celui de/etc/passwd. Aussi stupide que cela puisse paraître, certains sites n'autorisent pas les utilisateurs à modifier leur shell de connexion. Un site que je connais avait tout le monde commencé par csh, et tout le monde venait de mettre dans leur .login (fichier de démarrage csh) un appel à ksh. Pendant que cela fonctionnait, cela laissait un processus errant csh en marche, et la déconnexion était en deux étapes, ce qui pouvait prêter à confusion. Nous l'avons donc changé en exec ksh, qui vient de remplacer le programme c-Shell par le korn Shell, et simplifie tout (il y a d'autres problèmes, comme le fait que la ksh ne soit pas un login. -Coquille).

  3. Juste pour sauvegarder les processus. Si nous appelons prog1 -> prog2 -> prog3 -> prog4 etc. et ne revenons jamais, alors faites de chaque appel un exec. Cela permet d'économiser des ressources (pas beaucoup, certes, à moins de les répéter) et simplifie les arrêts.

Vous avez évidemment vu exec utilisé quelque part. Peut-être que si vous montriez le code qui vous dérange, nous pourrons en justifier l'utilisation.

Edit: Je me suis rendu compte que ma réponse ci-dessus est incomplète. Il y a deux utilisations de exec dans des shells tels que ksh et bash - utilisés pour ouvrir les descripteurs de fichiers. Voici quelques exemples:

exec 3< thisfile          # open "thisfile" for reading on file descriptor 3
exec 4> thatfile          # open "thatfile" for writing on file descriptor 4
exec 8<> tother           # open "tother" for reading and writing on fd 8
exec 6>> other            # open "other" for appending on file descriptor 6
exec 5<&0                 # copy read file descriptor 0 onto file descriptor 5
exec 7>&4                 # copy write file descriptor 4 onto 7
exec 3<&-                 # close the read file descriptor 3
exec 6>&-                 # close the write file descriptor 6

Notez que l'espacement est très important ici. Si vous placez un espace entre le numéro fd et le symbole de redirection, alors exec revient à la signification originale:

  exec 3 < thisfile       # oops, overwrite the current program with command "3"

Vous pouvez les utiliser de différentes manières: sur ksh, utilisez read -u ou print -u, sur bash, par exemple:

read <&3
echo stuff >&4
267
cdarke

Juste pour compléter la réponse acceptée par une réponse courte et brève, vous n’avez probablement pas besoin de exec.

Si vous êtes toujours là, la discussion suivante devrait, espérons-le, révéler pourquoi. Quand tu cours, dis,

sh -c 'command'

vous exécutez une instance sh, puis démarrez command en tant qu'enfant de cette instance sh. Lorsque command se termine, l'instance sh se termine également.

sh -c 'exec command'

exécute une instance sh, puis remplace cette instance sh avec le binaire command, et l'exécute à la place.

Bien sûr, les deux sont inutiles dans ce contexte limité; tu veux simplement

command

Dans certaines situations marginales, vous souhaitez que le shell lise son fichier de configuration ou configure d’une autre manière l’environnement comme préparation à l’exécution de command. C'est à peu près la seule situation où exec command est utile.

#!/bin/sh
ENVIRONMENT=$(some complex task)
exec command

Cela permet de préparer l’environnement afin qu’il contienne ce qui est nécessaire. Une fois que cela est fait, l'instance sh n'est plus nécessaire, c'est donc une optimisation (mineure) qui consiste simplement à remplacer l'instance sh par le processus command, plutôt que de la laisser exécuter par sh et l'exécuter dès que possible. comme il se termine.

De même, si vous souhaitez libérer autant de ressources que possible pour une commande lourde à la fin d'un script Shell, vous souhaiterez peut-être exec cette commande en tant qu'optimisation.

Si quelque chose vous oblige à exécuter sh mais que vous vouliez vraiment exécuter autre chose, exec something else est bien sûr une solution de contournement pour remplacer l'instance non désirée sh (comme par exemple si vous vouliez réellement exécuter votre propre pseudonyme gosh à la place de sh le vôtre n'est pas répertorié dans /etc/shells donc vous ne pouvez pas le spécifier comme shell de connexion).

La deuxième utilisation de exec pour manipuler les descripteurs de fichier est un sujet séparé. La réponse acceptée couvre bien cela; pour que cela reste autonome, je me contenterai du manuel pour tout ce où exec est suivi d'une redirection au lieu d'un nom de commande.

39
tripleee