Caso práctico / ejemplo práctico para el ejecutivo integrado de Bash

Respuestas:

18

execa menudo se usa en scripts de shell que actúan principalmente como envoltorios para iniciar otros binarios. Por ejemplo:

#!/bin/sh

if stuff;
    EXTRA_OPTIONS="-x -y -z"
else
    EXTRA_OPTIONS="-a foo"
fi

exec /usr/local/bin/the.real.binary $EXTRA_OPTIONS "$@"

de modo que una vez que el reiniciador termina de ejecutarse, el binario "real" se hace cargo y ya no queda ningún rastro del script del reiniciador que ocupó temporalmente el mismo espacio en la tabla de proceso. El binario "real" es un hijo directo de lo que sea que lo lanzó en lugar de un nieto.

También menciona la redirección de E / S en su pregunta. Ese es un caso de uso bastante diferente execy no tiene nada que ver con reemplazar el shell con otro proceso. Cuando execno tiene argumentos, así:

exec 3>>/tmp/logfile

luego, las redirecciones de E / S en la línea de comando surten efecto en el proceso actual del shell, pero el proceso actual del shell continúa ejecutándose y pasa al siguiente comando en el script.

Celada
fuente
1
Puede decir que los dos casos están relacionados en que, para ambos, execle dice al shell que no realice la acción (ejecutar un comando o realizar una redirección) en un proceso secundario, sino en el mismo proceso.
Stéphane Chazelas
5

He usado un shell execincorporado para obtener un ID de proceso (PID) para un programa Java. Puede haber una forma de obtener PID desde Java ahora, pero hace varios años, no la había. Una vez que un proceso tiene su propio PID, puede escribirlo en un archivo PID (busque /var/run/los nombres de archivo con un sufijo '.pid') para permitir que los programas de administración conozcan el PID del proceso en ejecución y eviten una segunda instancia del mismo servidor de la ejecución. Funciona algo como esto:

exec java -cp=YourServer.jar StartClass -p $$

El código en el main()método de clase StartClassmaneja el análisis de argumentos y puede encontrar su propio ID de proceso.

Bruce Ediger
fuente
2

Para divertirse, ejecute el siguiente programa (traducido al lenguaje de implementación que elija) en segundo plano en un sistema con contabilidad y límites de procesos de usuario.

while(true) fork();

Ahora que cada espacio en la tabla de proceso que puede usar está lleno de copias de ese programa en ejecución, ¿cómo piensa matarlo? Lanzar kill (1) requiere otra ranura de proceso, que no puede tener. Seguro que sería útil que el shell se reemplazara con el comando kill ...

exec /bin/kill -9 -1

(Asume que su sistema tiene kill (1) en / bin / kill. "Exec` which kill` -9 -1 "es potencialmente más seguro). Esto envía SIGKILL a cada proceso que pueda.

(Nota: no cierre sesión en su shell de inicio a menos que los límites del proceso siempre permitan un nuevo inicio de sesión en un espacio de proceso para su shell. Esto puede ser un poco más difícil de limpiar si lo hace. Ciertamente no hice esto en el principios de los 90. No.)

Eric Towers
fuente
3
(1) Esta respuesta sería un poco mejor si realmente mostrara el execcomando que sería útil en esta situación. (2) Esta respuesta es algo arcaica; El killcomando ha sido un comando incorporado en bash durante muchos años, en gran parte debido a esta preocupación.
G-Man dice 'Restablece a Mónica' el
@ G-Man: ¿Entiende que su elemento (2) hace que esta respuesta sea una respuesta precisa al OP?
Eric Towers
No, no entiendo eso. Por favor, explícamelo.
G-Man dice 'Reincorporar a Monica' el
44
Yo no te entiendo. La pregunta no pide ejemplos prácticos de todos los comandos incorporados de bash; pide ejemplos de exec, y el hecho de que killsea ​​una construcción no tiene nada que ver con la execconstrucción.
G-Man dice 'reinstalar a Monica' el
1
Acabo de leer su actualización a su respuesta. (1) ¿Adivina qué? Si la tabla de proceso está llena, la sustitución de comandos (por ejemplo, `which kill`) tampoco funcionará. (2) Por cierto, el $(…)formulario se recomienda sobre el `…`formulario. (3) Pero no hay nada peligroso en adivinar el directorio. Si escribe accidentalmente exec /binn/kill, simplemente recibirá un mensaje de error y su shell no desaparecerá. (4) Pero ni siquiera tiene que preocuparse por el directorio killen el que se executiliza . Al  $PATHigual que los comandos normales, exec kill …funciona (suponiendo que tenga /binen su ruta de búsqueda).
G-Man dice 'Reincorporar a Monica' el
1
  • Esto es similar al ejemplo de Bruce de la necesidad de conocer el PID de un proceso:

    (cmdpid = $ BASHPID; (sleep 300; kill "$ cmdpid") & exec long-running-command )

    en el que tu

    1. Comience una subshell (la externa (y )),
    2. Descubra el PID de la subshell. ( $$le dará el PID del shell principal).
    3. Separe una sub-subshell que mata su proceso después de un tiempo de espera, y
    4. Ejecute un comando en el proceso de la subshell que creó en el paso 1.

    Esto se ejecutará long-running-command, pero solo por un período de tiempo predeterminado y limitado. 

  • Esto es un poco frívolo, pero, si decides que quieres ser root (o algún otro usuario) durante el resto de tu sesión de inicio de sesión, podrías hacerlo exec su.

    En realidad, puedo imaginar un escenario en el que esto sería realmente útil. Suponga que ha iniciado sesión en un sistema remoto y, por alguna razón, hay un problema al interrumpir la conexión y comenzar una nueva conexión. Por ejemplo, suponga que el sistema remoto tiene un firewall que sigue un cronograma. Se le permitió conectarse cuando lo hizo, y las conexiones establecidas no se cierran, pero en este momento, no se aceptan nuevas conexiones.

    Has hecho lo que querías hacer y estás listo para cerrar sesión. Su amigo Bob está en la habitación con usted y quiere trabajar en el sistema remoto, pero no podrá conectarse. Entonces, escribe exec su - boby, cuando aparece el mensaje de contraseña, dele la estación de trabajo a él. Ahora no hay ningún proceso con su UID (a menos que haya ejecutado algo en segundo plano), por lo que Bob no podrá jugar con sus archivos. Él se habrá hecho cargo de su conexión (con su consentimiento y cooperación).

    Notas:

    • Por supuesto, esto no funcionará si no se te permite correr su.
    • Se registrará, por lo que es posible que deba explicar sus motivos a alguien. Dado que está eludiendo la política (la programación del firewall), podría tener problemas.
    • No garantizo que sea 100% seguro. Por ejemplo, whoprobablemente aún muestre su nombre. Es concebible que algún programa (mal escrito) lo use para pensar que Bob eres tú y darle acceso a tus recursos.
    • Si el sistema audita, las acciones de Bob podrían auditarse bajo su nombre.
G-Man dice 'restablecer a Mónica'
fuente
Tenga en cuenta que, en la práctica, en la mayoría de los shells, (a;b)ya es lo mismo (a;exec b)que los shells que optimizan la bifurcación para el último comando en un subshell. Las únicas excepciones parecen ser bashy mksh. Usar execayuda para garantizarlo.
Stéphane Chazelas