¿Cuáles son los usos del comando exec en los scripts de shell?

250

¿Alguien puede explicar cuáles son los usos del comando exec en las secuencias de comandos de shell con ejemplos simples?

usuario2400564
fuente
31
Los enlaces a linux.about.com no son útiles. No dejan en claro de forma remota cómo la ejecución de un comando o una tubería de comandos usando 'exec' difiere de simplemente ejecutarlos normalmente. De ahí la pregunta del OP "¿de qué sirve el ejecutivo"?
Jonathan Hartley
2
Stack Overflow es un sitio para preguntas de programación y desarrollo. Esta pregunta parece estar fuera de tema porque no se trata de programación o desarrollo. Consulte los temas sobre los que puedo preguntar aquí en el Centro de ayuda. Quizás Super User o Unix & Linux Stack Exchange sería un mejor lugar para preguntar.
jww

Respuestas:

281

El execcomando incorporado refleja las funciones en el kernel, hay una familia basada en ellas execve, que generalmente se llama desde C.

execreemplaza el programa actual en el proceso actual, sin forkcrear un nuevo proceso. No es algo que usaría en cada script que escriba, pero en ocasiones resulta útil. Aquí hay algunos escenarios en los que lo he usado;

  1. Queremos que el usuario ejecute un programa de aplicación específico sin acceso al shell. Podríamos cambiar el programa de inicio de sesión en / etc / passwd, pero tal vez queremos que la configuración del entorno se use desde los archivos de inicio. Entonces, en (digamos) .profile, la última declaración dice algo como:

     exec appln-program

    así que ahora no hay ningún shell al que volver. Incluso si se appln-programbloquea, el usuario final no puede llegar a un shell, porque no está allí, lo execreemplazó.

  2. Queremos usar un shell diferente al de / etc / passwd. Por estúpido que parezca, algunos sitios no permiten a los usuarios alterar su shell de inicio de sesión. Un sitio que conozco hizo que todos comenzaran csh, y todos simplemente .loginllamaron a su (archivo de inicio de csh) ksh. Si bien eso funcionó, dejó un cshproceso perdido y el cierre de sesión fue de dos etapas, lo que puede ser confuso. Así que lo cambiamos por uno exec kshque simplemente reemplazó el programa c-shell con el shell korn, y lo simplificamos todo (hay otros problemas con esto, como el hecho de que kshno es un shell de inicio de sesión).

  3. Solo para guardar procesos. Si llamamos a prog1 -> prog2 -> prog3 -> prog4etc. y nunca regresamos, entonces haga que cada llamada sea un ejecutivo. Ahorra recursos (no mucho, es cierto, a menos que se repita) y simplifica el apagado.

Obviamente lo has visto execusado en alguna parte, quizás si mostraras el código que te está molestando podríamos justificar su uso.

Editar : me di cuenta de que mi respuesta anterior es incompleta. Hay dos usos de execshells como kshy bash: se utilizan para abrir descriptores de archivos. Aquí hay unos ejemplos:

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

Tenga en cuenta que el espacio es muy importante aquí. Si coloca un espacio entre el número fd y el símbolo de redirección, execvuelve al significado original:

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

Hay varias maneras de utilizar éstos, sobre el uso de ksh read -uo print -u, en bash, por ejemplo:

read <&3
echo stuff >&4
Cdarke
fuente
22
También hay otro uso que encontré bastante útil y vale la pena mencionar aquí porque se relaciona con las aplicaciones web de Python y parece algo entre sus respuestas (impresionantes) 2 y 3. Por lo general, ejecuto aplicaciones web wsgi (digamos django o frasco) a través del supervisor llamando a un gunicorn aplicación: esta última requiere notoriamente bastantes variables de entorno, es mucho más fácil y más fácil ejecutar gunicorn desde un script de shell que configura todo y eventualmente exec gunicorndevuelve el pedido correcto al supervisor.
gru
1
Los documentos no dicen que execse puede utilizar para la redirección:> Si no se especifica comando, cualquier redirección tengan efecto en el shell actual y el estado de retorno es 0. Si hay un error de redirección, el estado de salida es 1. Pero cómo lo hace exec¿Realmente funciona para cambiar un descriptor de archivo? ¿Por qué se elige este comando en particular para esta tarea? (¿Markdown está fallando en este momento?)
Ray
@Ray: mejor puedo hacerlo: pubs.opengroup.org/onlinepubs/009604599/utilities/exec.html . Si necesita saber cómo, mire el código fuente del shell.
cdarke
77
Otro uso: Redirigir toda la salida de un script a un archivo de registroexec >.\logfilename.log 2>&1
Hogan
1
@Carmageddon: &>es una bashextensión (ver man bash) y su ejemplo es equivalente a exec >/var/log/userdata.log 2>&1. En otras palabras, redirige stdout y stderr a ese archivo. Los comandos que siguen heredarán esas redirecciones a menos que se restablezcan, pero se ejecutarán.
cdarke
41

Solo para aumentar la respuesta aceptada con una breve respuesta breve amigable para los novatos, probablemente no sea necesario exec.

Si todavía está aquí, la siguiente discusión debería revelar por qué. Cuando corras, di:

sh -c 'command'

ejecuta una shinstancia, luego comienza commandcomo un hijo de esa shinstancia. Cuando commandfinaliza, la shinstancia también finaliza.

sh -c 'exec command'

ejecuta una shinstancia, luego reemplaza esa shinstancia con el commandbinario y la ejecuta en su lugar.

Por supuesto, ambos son inútiles en este contexto limitado; simplemente quieres

command

Hay algunas situaciones marginales en las que desea que el shell lea su archivo de configuración o, de alguna manera, configure el entorno como preparación para la ejecución command. Esta es la única situación en la que exec commandes útil.

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

Esto hace algunas cosas para preparar el entorno para que contenga lo que se necesita. Una vez hecho esto, la shinstancia ya no es necesaria, por lo que es una optimización (menor) simplemente reemplazar la shinstancia con el commandproceso, en lugar de shejecutarla como un proceso secundario y esperarla, luego salir tan pronto como termine.

Del mismo modo, si desea liberar tantos recursos como sea posible para un comando pesado al final de un script de shell, es posible que desee execese comando como una optimización.

Si algo lo obliga a ejecutar shpero realmente desea ejecutar otra cosa, exec something elsees , por supuesto, una solución alternativa para reemplazar la shinstancia no deseada (por ejemplo, si realmente desea ejecutar su propio spiffy en goshlugar de, shpero el suyo no aparece en la lista /etc/shellspara que pueda No lo especifique como su shell de inicio de sesión).

El segundo uso de execmanipular descriptores de archivo es un tema separado. La respuesta aceptada lo cubre muy bien; para mantener esto autónomo, solo remitiré al manual para cualquier cosa que execsea ​​seguida por una redirección en lugar de un nombre de comando.

tripleee
fuente
2
Resistiendo la tentación de llamar a tu propio caparazón spiffy bush. Por supuesto, esto también se aplica a bashcualquier shell Unix popular; aunque, como señala @anishsane , Bash se optimiza secretamente bash -c 'command'al hacerlo exec command.
tripleee
1
El código de salida del shell es generalmente el código de salida del último comando que ejecutó. Por supuesto, si el shell no se ejecuta o no ejecuta el comando, el estado de salida del shell reflejará eso con un código de error adecuado.
tripleee
2
@ JonathanLeffler Estoy documentando deliberadamente un antipatrón que veo en las preguntas de los novatos. Este fue impulsado por este duplicado, pero lo he visto antes, así que quería cubrirlo específicamente.
tripleee
2
@JonathanLeffler Ajuste de redacción menor; ¿Es esto suficiente? Gracias por la respuesta.
tripleee
2
Gracias. Agregué otro breve párrafo sobre esta optimización. No tengo muy claro si tienes otras objeciones, o si solo quieres explicar las cosas desde un ángulo diferente.
tripleee