Les liens vers linux.about.com ne sont pas utiles. Ils ne précisent pas à distance en quoi l'exécution d'une commande ou d'un pipeline de commandes à l'aide de 'exec' diffère de leur exécution normale. D'où la question du PO "à quoi sert l'exec"?
Jonathan Hartley
2
Stack Overflow est un site pour les questions de programmation et de développement. Cette question semble être hors sujet car elle ne concerne pas la programmation ou le développement. Voir Quels sujets puis-je poser ici dans le centre d'aide. Peut-être que Super User ou Unix & Linux Stack Exchange seraient un meilleur endroit pour demander.
2018
Réponses:
281
La execcommande intégrée reflète les fonctions du noyau, il y en a une famille basée sur execve, qui est généralement appelée à partir de C.
execremplace le programme en cours dans le processus en cours, sans forking nouveau processus. Ce n'est pas quelque chose que vous utiliseriez dans chaque script que vous écrivez, mais cela peut être utile à l'occasion. Voici quelques scénarios que je l'ai utilisés;
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 nous souhaitons peut-être que le paramètre d'environnement soit utilisé à partir des fichiers de démarrage. Donc, dans (disons) .profile, la dernière déclaration dit quelque chose comme:
exec appln-program
alors maintenant, il n'y a pas de shell pour revenir. Même en cas de appln-programplantage, l'utilisateur final ne peut pas accéder à un shell, car il n'est pas là - il l'a execremplacé.
Nous voulons utiliser un shell différent de celui de / etc / passwd. Aussi stupide que cela puisse paraître, certains sites ne permettent pas aux utilisateurs de modifier leur shell de connexion. Un site que je connais a fait démarrer tout le monde csh, et tout le monde vient d' .loginappeler dans leur (fichier de démarrage csh) ksh. Bien que cela ait fonctionné, cela a laissé un cshprocessus errant en cours et la déconnexion était en deux étapes, ce qui pouvait prêter à confusion. Nous l'avons donc changé en exec kshremplaçant simplement le programme c-shell par le korn shell, et rendu tout plus simple (il y a d'autres problèmes avec cela, comme le fait que le kshn'est pas un login-shell).
Juste pour sauver des processus. Si nous appelons prog1 -> prog2 -> prog3 -> prog4etc. et ne revenons jamais en arrière, alors faisons de chaque appel un exécutable. Il économise des ressources (pas beaucoup, certes, sauf répétition) et rend l'arrêt plus simple.
Vous avez évidemment vu executilisé quelque part, peut-être que si vous montriez le code qui vous dérange, nous pourrions justifier son utilisation.
Edit : j'ai réalisé que ma réponse ci-dessus est incomplète. Il y a deux utilisations de execdans des shells comme kshet bash- utilisées pour ouvrir des 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 nombre fd et le symbole de redirection, puis execrevient à la signification d'origine:
exec 3< thisfile # oops, overwrite the current program with command "3"
Il y a plusieurs façons dont vous pouvez les utiliser, sur l' utilisation ksh read -uou print -u, sur bash, par exemple:
il y a aussi une autre utilisation que j'ai trouvée très pratique et qui mérite d'être mentionnée ici car elle concerne les applications Web en python et semble quelque chose entre vos réponses (géniales) 2 et 3. Je lance généralement des applications Web wsgi (disons django ou flask) via un superviseur appelant un gunicorn app: ce dernier nécessitant notoirement un certain nombre de variables d'environnement, il est beaucoup plus facile et plus facile de faire fonctionner gunicorn à partir d'un script shell qui configure tout et finalement exec gunicornredonne le bon pid au superviseur.
gru
1
Les docs disent que execpeut être utilisé pour la redirection:> Si la commande n'est pas spécifié, aucune redirections prennent effet dans la coquille en cours, et l'état de retour est 0. En cas d'erreur de redirection, l'état de retour est 1. Mais comment fait execfonctionne réellement pour changer un descripteur de fichier? Pourquoi cette commande particulière est-elle choisie pour cette tâche? (Markdown échoue en ce moment?)
Une autre utilisation: rediriger toutes les sorties d'un script vers un fichier journalexec >.\logfilename.log 2>&1
Hogan
1
@Carmageddon: &>est une bashextension (voir man bash) et votre exemple est équivalent à exec >/var/log/userdata.log 2>&1. En d'autres termes, il redirige stdout et stderr vers ce fichier. Les commandes qui suivent hériteront de ces redirections à moins qu'elles ne soient réinitialisées, mais elles seront exécutées.
cdarke le
41
Juste pour augmenter la réponse acceptée par une brève réponse courte adaptée aux débutants, vous n'avez probablement pas besoin 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 shinstance, puis démarrez en commandtant qu'enfant de cette shinstance. Une fois commandterminée, l' shinstance se termine également.
sh -c 'exec command'
exécute une shinstance, puis remplace cette shinstance par le commandbinaire et l'exécute à la place.
Bien entendu, ces deux éléments 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, d'une manière ou d'une autre, configure l'environnement comme préparation à l'exécution command. C'est à peu près la seule situation où exec commandest utile.
Cela fait des choses pour préparer l'environnement afin qu'il contienne ce qui est nécessaire. Une fois cela fait, l' shinstance n'est plus nécessaire, et c'est donc une optimisation (mineure) de simplement remplacer l' shinstance par le commandprocessus, plutôt que de l' shexécuter en tant que processus enfant et de l'attendre, puis de quitter dès qu'elle 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 pouvez souhaiter execcette commande comme optimisation.
Si quelque chose vous oblige à exécuter shmais que vous vouliez vraiment exécuter autre chose, exec something elsec'est bien sûr une solution de contournement pour remplacer l' shinstance indésirable (comme par exemple si vous vouliez vraiment exécuter votre propre spiffy goshau lieu de shmais le vôtre n'est pas répertorié /etc/shells, vous pouvez donc ne le spécifiez pas comme shell de connexion).
La deuxième utilisation de execpour manipuler les descripteurs de fichiers est un sujet distinct. La réponse acceptée couvre bien cela; pour garder ce contenu autonome, je vais simplement me reporter au manuel pour tout ce qui execest suivi d'une redirection au lieu d'un nom de commande.
Résister à la tentation d'appeler votre propre coquille spiffy bush. Bien sûr, cela s'applique à bashou généralement à tout shell Unix populaire; bien que, comme le note @anishsane , Bash optimise secrètement bash -c 'command'en le faisant exec command.
tripleee
1
Le code de sortie du shell est généralement le code de sortie de la dernière commande qu'il a exécutée. Bien sûr, si le shell ne s'exécute pas ou n'exécute pas la commande, l'état de sortie du shell reflétera cela avec un code d'erreur approprié.
tripleee
2
@JonathanLeffler Je documente délibérément un contre-modèle que je vois dans les questions des débutants. Celui-ci a été provoqué par ce doublon, mais je l'ai déjà vu, donc je voulais couvrir cela spécifiquement.
tripleee
2
@JonathanLeffler Tweak mineur de formulation; est-ce suffisant, pensez-vous? Merci pour les commentaires.
tripleee
2
Merci - J'ai ajouté un autre bref paragraphe sur cette optimisation. Ce n'est pas vraiment clair pour moi si vous avez d'autres objections, ou si vous souhaitez simplement expliquer les choses sous un angle différent.
Réponses:
La
exec
commande intégrée reflète les fonctions du noyau, il y en a une famille basée surexecve
, qui est généralement appelée à partir de C.exec
remplace le programme en cours dans le processus en cours, sansfork
ing nouveau processus. Ce n'est pas quelque chose que vous utiliseriez dans chaque script que vous écrivez, mais cela peut être utile à l'occasion. Voici quelques scénarios que je l'ai utilisés;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 nous souhaitons peut-être que le paramètre d'environnement soit utilisé à partir des fichiers de démarrage. Donc, dans (disons)
.profile
, la dernière déclaration dit quelque chose comme:alors maintenant, il n'y a pas de shell pour revenir. Même en cas de
appln-program
plantage, l'utilisateur final ne peut pas accéder à un shell, car il n'est pas là - il l'aexec
remplacé.Nous voulons utiliser un shell différent de celui de / etc / passwd. Aussi stupide que cela puisse paraître, certains sites ne permettent pas aux utilisateurs de modifier leur shell de connexion. Un site que je connais a fait démarrer tout le monde
csh
, et tout le monde vient d'.login
appeler dans leur (fichier de démarrage csh)ksh
. Bien que cela ait fonctionné, cela a laissé uncsh
processus errant en cours et la déconnexion était en deux étapes, ce qui pouvait prêter à confusion. Nous l'avons donc changé enexec ksh
remplaçant simplement le programme c-shell par le korn shell, et rendu tout plus simple (il y a d'autres problèmes avec cela, comme le fait que leksh
n'est pas un login-shell).Juste pour sauver des processus. Si nous appelons
prog1 -> prog2 -> prog3 -> prog4
etc. et ne revenons jamais en arrière, alors faisons de chaque appel un exécutable. Il économise des ressources (pas beaucoup, certes, sauf répétition) et rend l'arrêt plus simple.Vous avez évidemment vu
exec
utilisé quelque part, peut-être que si vous montriez le code qui vous dérange, nous pourrions justifier son utilisation.Edit : j'ai réalisé que ma réponse ci-dessus est incomplète. Il y a deux utilisations de
exec
dans des shells commeksh
etbash
- utilisées pour ouvrir des descripteurs de fichiers. Voici quelques exemples:Notez que l'espacement est très important ici. Si vous placez un espace entre le nombre fd et le symbole de redirection, puis
exec
revient à la signification d'origine:Il y a plusieurs façons dont vous pouvez les utiliser, sur l' utilisation ksh
read -u
ouprint -u
, surbash
, par exemple:la source
exec gunicorn
redonne le bon pid au superviseur.exec
peut être utilisé pour la redirection:> Si la commande n'est pas spécifié, aucune redirections prennent effet dans la coquille en cours, et l'état de retour est 0. En cas d'erreur de redirection, l'état de retour est 1. Mais comment faitexec
fonctionne réellement pour changer un descripteur de fichier? Pourquoi cette commande particulière est-elle choisie pour cette tâche? (Markdown échoue en ce moment?)exec >.\logfilename.log 2>&1
&>
est unebash
extension (voirman bash
) et votre exemple est équivalent àexec >/var/log/userdata.log 2>&1
. En d'autres termes, il redirige stdout et stderr vers ce fichier. Les commandes qui suivent hériteront de ces redirections à moins qu'elles ne soient réinitialisées, mais elles seront exécutées.Juste pour augmenter la réponse acceptée par une brève réponse courte adaptée aux débutants, vous n'avez probablement pas besoin
exec
.Si vous êtes toujours là, la discussion suivante devrait, espérons-le, révéler pourquoi. Quand tu cours, dis,
vous exécutez une
sh
instance, puis démarrez encommand
tant qu'enfant de cettesh
instance. Une foiscommand
terminée, l'sh
instance se termine également.exécute une
sh
instance, puis remplace cettesh
instance par lecommand
binaire et l'exécute à la place.Bien entendu, ces deux éléments sont inutiles dans ce contexte limité; tu veux simplement
Dans certaines situations marginales, vous souhaitez que le shell lise son fichier de configuration ou, d'une manière ou d'une autre, configure l'environnement comme préparation à l'exécution
command
. C'est à peu près la seule situation oùexec command
est utile.Cela fait des choses pour préparer l'environnement afin qu'il contienne ce qui est nécessaire. Une fois cela fait, l'
sh
instance n'est plus nécessaire, et c'est donc une optimisation (mineure) de simplement remplacer l'sh
instance par lecommand
processus, plutôt que de l'sh
exécuter en tant que processus enfant et de l'attendre, puis de quitter dès qu'elle 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 pouvez souhaiter
exec
cette commande comme optimisation.Si quelque chose vous oblige à exécuter
sh
mais que vous vouliez vraiment exécuter autre chose,exec something else
c'est bien sûr une solution de contournement pour remplacer l'sh
instance indésirable (comme par exemple si vous vouliez vraiment exécuter votre propre spiffygosh
au lieu desh
mais le vôtre n'est pas répertorié/etc/shells
, vous pouvez donc ne le spécifiez pas comme shell de connexion).La deuxième utilisation de
exec
pour manipuler les descripteurs de fichiers est un sujet distinct. La réponse acceptée couvre bien cela; pour garder ce contenu autonome, je vais simplement me reporter au manuel pour tout ce quiexec
est suivi d'une redirection au lieu d'un nom de commande.la source
bush
. Bien sûr, cela s'applique àbash
ou généralement à tout shell Unix populaire; bien que, comme le note @anishsane , Bash optimise secrètementbash -c 'command'
en le faisantexec command
.