web-dev-qa-db-fra.com

Que fait 'exec'?

Je voulais récemment exécuter la commande pkexecname__, mais j'ai accidentellement réussi à exécuter la commande execpar elle-même, sans option ni argument. J'ai cherché dans les pages manla description de execname__, mais je n'ai toujours aucune idée de ce que cela signifie:

DESCRIPTION
       The  exec() family of functions replaces the current process image with
       a new process image.  The functions described in this manual  page  are
       front-ends  for execve(2).  (See the manual page for execve(2) for fur‐
       ther details about the replacement of the current process image.)

Et en fait, la description continue ... Mais le reste de la description ne m'a pas beaucoup aidé non plus ... C'est donc vraiment ma question: que fait la commande execname__? Et est-ce que j'ai fait quelque chose en l'exécutant lui-même sans options ni arguments, tout comme execname__? At-il un lien avec la commande pkexecname__?

4
user364819

"exec() famille de fonctions" ... sont, ainsi, des fonctions . Ils sont utilisés dans le code source. Ce ne sont pas des commandes à exécuter par les utilisateurs1. Ils sont généralement utilisés par les programmes qui doivent en exécuter un autre (par exemple, le shell lui-même, Sudo, pkexec, etc.). Un programme appelant directement exec se trouvera remplacé par le programme exec 'd; son utilisation typique est donc généralement fork et exec.

Un exemple artificiel ressemblerait à ceci:

$ cat foo.c 
#include <unistd.h>
int main()
{
    const char * path = "/bin/echo";
    char * args[] = {"echo", "Hello", "World!", NULL};
    execv(path, args);
}
$ gcc -o foo foo.c
$ ./foo           
Hello World!

Vous pouvez voir des exemples d'utilisation réelle de exec à l'aide de strace dans divers programmes, y compris strace lui-même:

$ strace -e execve ./foo
execve("./foo", ["./foo"], [/* 52 vars */]) = 0
execve("/bin/echo", ["echo", "Hello", "World!"], [/* 52 vars */]) = 0
Hello World!
+++ exited with 0 +++

Notez que strace lui-même utilise exec pour appeler le programme, puis que le programme appelle ensuite exec.


1 ... sauf pour le exec Shell intégré , qui est une fonctionnalité du shell.

exec le shell intégré est semblable aux fonctions exec dans le sens où l'appel de exec avec un nom de programme provoque le remplacement du shell par celui-ci. Cependant, l'utilisation courante de exec est généralement utilisée pour modifier ou ajouter des descripteurs de fichier .

Un autre exemple artificiel:

$ exec 3</dev/urandom
$ read -u 3 -n 10
$ echo "$REPLY" | base64 
oZN5Qsn3nAs+1GFUCg==

Vous pourriez penser que nous pourrions lire directement à partir de /dev/urandom. Oui, nous pourrions. Cependant, cela est utile lorsque:

  • nous devons lire/écrire dans plusieurs descripteurs de fichier
  • nous devons remplacer un ou plusieurs descripteurs de fichier standard (par exemple, envoyez stdout dans un fichier pour toute la session Shell).
4
muru

en plus de ce que muru a dit, exec est une commande intégrée de bash. La description suivante est copiée de la page de manuel bash (vous pouvez utiliser 'man bash' pour la voir):

 exec [-cl] [-a nom] [commande [arguments]] 
 Si la commande est spécifiée, elle remplace le shell. Aucun nouveau processus n'est créé. Les arguments deviennent 
 Les arguments à commander. Si l'option -l est fournie, le shell place un tiret au début 
 De l'argument zeroth transmis à commande. C'est ce que login (1) fait. L'option -c entraîne l'exécution de com - 
 Mand avec un environnement vide. Si -a est fourni, le shell transmet le nom en tant qu'argument 
 À la commande exécutée. Si la commande ne peut pas être exécutée pour une raison quelconque, un shell interactif non 
 Se ferme, sauf si l'option Shell execfail est activée, auquel cas elle renvoie un échec de 
. Un shell interactif renvoie un échec si le fichier ne peut pas être exécuté. Si la commande n'est pas spécifiée 
, Les redirections prennent effet dans le shell actuel et l'état de retour est 0. Si 
 Est une erreur de redirection, l'état de retour est 1. 
1
user448115

Pendant que vous exécutiez man exec, vous avez rencontré la famille de fonctions exec() qui, en gros, encapsule l’appel système execve(2).

Le execque vous avez exécuté est un shell intégré:

$ type -a exec 
exec is a Shell builtin

Maintenant de help exec:

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.

Normalement, un nouveau processus est créé par une combinaison d'appels système fork(2)-exec(). Ici, fork() créera un processus enfant avec un nouveau PID en dupliquant le processus parent, puis exec() remplacera le processus enfant par l'exécutable que nous souhaitons exécuter. Par exemple, lorsque nous voulons exécuter un exécutable nommé topname__, le shell appelle fork(2), créant ainsi un processus enfant exactement identique au shell avec un nouveau PID. Ce processus nouvellement créé est remplacé par /usr/bin/top à l'aide de l'appel exec().

Désormais, dans le shell intégré execname__, la fork() n'est pas appelée, mais plutôt exec(), de sorte que le shell est directement remplacé par l'exécutable et que le nouveau processus hérite du PID du shell.

Notez que seul execsans argument ni redirection ne fera rien.

1
heemayl