Je ne comprends pas la commande bash exec
. Je l'ai vu utilisé dans des scripts pour rediriger toutes les sorties vers un fichier (comme indiqué dans this ). Mais je ne comprends pas comment ça marche ou ce que ça fait en général. J'ai lu les pages de manuel mais je ne les comprends pas.
man bash
dit:
exec [-cl] [-a name] [command [arguments]]
If command is specified, it replaces the Shell. No new process
is created. The arguments become the arguments to command. If
the -l option is supplied, the Shell places a dash at the
beginning of the zeroth argument passed to command. This is
what login(1) does. The -c option causes command to be executed
with an empty environment. If -a is supplied, the Shell passes
name as the zeroth argument to the executed command. If command
cannot be executed for some reason, a non-interactive Shell
exits, unless the execfail Shell option is enabled. In that
case, it returns failure. An interactive Shell returns failure
if the file cannot be executed. If command is not specified,
any redirections take effect in the current Shell, and the
return status is 0. If there is a redirection error, the return
status is 1.
Ce qui est important, ce sont les deux dernières lignes: si vous exécutez exec
seul, sans commande, les redirections s’appliqueront simplement au Shell en cours. Vous savez probablement que lorsque vous exécutez command > file
, la sortie de command
est écrite dans file
au lieu de sur votre terminal (cette opération s'appelle une redirection ). Si vous exécutez plutôt exec > file
, la redirection s'applique à l'ensemble du shell: toute sortie produite par le shell est écrite dans file
au lieu de celle de votre terminal. Par exemple ici
bash-3.2$ bash
bash-3.2$ exec > file
bash-3.2$ date
bash-3.2$ exit
bash-3.2$ cat file
Thu 18 Sep 2014 23:56:25 CEST
Je commence par un nouveau shell bash
. Ensuite, dans ce nouveau shell, j'exécute exec > file
, de sorte que toute la sortie soit redirigée vers file
. En effet, après cela, je lance date
mais je n’obtiens aucune sortie, car la sortie est redirigée vers file
. Ensuite, je quitte mon shell (pour que la redirection ne s'applique plus) et je constate que file
contient en effet le résultat de la commande date
que j'ai exécutée précédemment.
exec
est une commande avec deux comportements très distincts, selon qu’au moins un argument est utilisé avec elle ou pas du tout.
Si au moins un argument est passé, le premier est utilisé comme nom de commande et exec
tente de l'exécuter en tant que commande, en transmettant les arguments restants, le cas échéant, à cette commande et en gérant les redirections, le cas échéant.
Si la commande passée en tant que premier argument n'existe pas, le shell actuel, et pas seulement la commande exec, se termine en erreur.
Si la commande existe et qu'elle est exécutable, elle remplace le shell actuel. Cela signifie que si exec
apparaît dans un script, les instructions qui suivent l'appel exec ne sera jamais exécuté (sauf si exec
est lui-même dans un sous-shell). exec
ne retourne jamais. Les pièges tels que "EXIT" ne seront pas déclenchés non plus.
Si aucun argument n'est passé, exec
sert uniquement à redéfinir les descripteurs de fichier Shell actuels. Le shell continue après le exec
, contrairement au cas précédent, mais l'entrée standard, la sortie, l'erreur ou tout autre descripteur de fichier redirigé prend effet.
Si certaines des redirections utilisent /dev/null
, toute entrée de celle-ci renverra EOF et toute sortie y figurant sera supprimée.
Vous pouvez fermer les descripteurs de fichier en utilisant -
comme source ou destination, par exemple. exec <&-
. Les lectures ou écritures suivantes échoueront alors.
Voici deux exemples:
echo foo > /tmp/bar
exec < /tmp/bar # exec has no arguments, will only affect current Shell descriptors, here stdin
cat # simple command that read stdin and write it to stdout
Ce script affichera "foo" en tant que commande cat, au lieu d'attendre la saisie de l'utilisateur, comme cela aurait été le cas habituel, prendra son entrée dans le fichier/tmp/bar qui contient foo.
echo foo > /tmp/bar
exec wc -c < /tmp/bar # exec has two arguments, the control flow will switch to the wc command
cat
Ce script affiche 4
(le nombre d'octets dans/tmp/bar) et se termine immédiatement. La commande cat
ne sera pas exécutée.
Pour comprendre exec
vous devez d'abord comprendre fork
name__. J'essaie de rester bref.
Lorsque vous arrivez à un embranchement, vous avez généralement deux options. Les programmes Linux atteignent cette fourchette lorsqu'ils lancent un appel système fork()
.
Les programmes normaux sont des commandes système existant sous une forme compilée sur votre système. Lorsqu'un tel programme est exécuté, un nouveau processus est créé. Ce processus enfant a le même environnement que son parent, seul le numéro d'identification du processus est différent. Cette procédure s'appelle forking.
exec
est utilisé. exec
remplacera le contenu du processus en cours d'exécution par les informations d'un programme binaire.Dans bash
, si vous faites help exec
:
$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
Replace the Shell with the given command.
Execute COMMAND, replacing this Shell with the specified program.
ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified,
any redirections take effect in the current Shell.
Options:
-a name pass NAME as the zeroth argument to COMMAND
-c execute COMMAND with an empty environment
-l place a dash in the zeroth argument to COMMAND
If the command cannot be executed, a non-interactive Shell exits, unless
the Shell option `execfail' is set.
Exit Status:
Returns success unless COMMAND is not found or a redirection error occurs.
Le bit pertinent:
If COMMAND is not specified, any redirections take effect in the current Shell.
exec
est un Shell intégré , qui est l'équivalent Shell de la famille exec
de appels système dont G_P en parle (et dont vous paraissez la page de manuel ont lu). Il a juste la fonctionnalité POSIX mandaté d’affecter le shell actuel si aucune commande n’est spécifiée.