evaly execambos están integrados en comandos de bash (1) que ejecutan comandos.
También veo que exectiene algunas opciones, pero ¿es esa la única diferencia? ¿Qué pasa con su contexto?
bash
shell
shell-builtin
Willian Paixao
fuente
fuente

Respuestas:
evalyexecson bestias completamente diferentes. (Aparte del hecho de que ambos ejecutarán comandos, pero también todo lo que haces en un shell).Lo que
exec cmdhace es exactamente lo mismo que solo ejecutarcmd, excepto que el shell actual se reemplaza con el comando, en lugar de que se ejecute un proceso separado. Internamente, ejecutar say/bin/lsllamaráfork()para crear un proceso secundario y luegoexec()en el secundario para ejecutar/bin/ls.exec /bin/lspor otro lado no se bifurcará, sino que simplemente reemplazará la carcasa.Comparar:
con
echo $$imprime el PID del shell que comencé, y el listado/proc/selfnos da el PID dellsque se ejecutó desde el shell. Por lo general, las ID de proceso son diferentes, pero conexecel shell ylstienen la misma ID de proceso. Además, el siguiente comandoexecno se ejecutó, ya que se reemplazó el shell.Por otra parte:
evalejecutará los argumentos como un comando en el shell actual. En otras palabras,eval foo bares lo mismo que justofoo bar. Pero las variables se expandirán antes de la ejecución, por lo que podemos ejecutar comandos guardados en variables de shell:Será no crear un proceso hijo, por lo que la variable se establece en el shell actual. (Por supuesto
eval /bin/ls, creará un proceso hijo, de la misma manera que lo/bin/lsharía un viejo ).O podríamos tener un comando que genere comandos de shell. La ejecución
ssh-agentinicia el agente en segundo plano y genera un montón de asignaciones variables, que podrían establecerse en el shell actual y ser utilizadas por los procesos secundarios (lossshcomandos que ejecutaría). Porssh-agentlo tanto, se puede comenzar con:Y el shell actual obtendrá las variables para que otros comandos hereden.
Por supuesto, si la variable
cmdcontiene algo asírm -rf $HOME, entonces ejecutareval "$cmd"no sería algo que querría hacer. Incluso cosas como sustituciones de mando dentro de la cadena serían procesados, por lo que uno debe realmente estar seguro de que la entradaevales seguro antes de usarla.A menudo, es posible evitar
evaly evitar incluso mezclar accidentalmente código y datos de manera incorrecta.fuente
evalen primer lugar a esta respuesta también. Cosas como modificar variables indirectamente se pueden hacer en muchos shells a través dedeclare/typeset/namerefy expansiones como${!var}, por lo que usaría esas en lugar de aevalmenos que realmente tuviera que evitarlo.execNo crea un nuevo proceso. Se reemplaza el proceso actual con el nuevo comando. Si hizo esto en la línea de comando, finalizará efectivamente su sesión de shell (¡y tal vez cierre la sesión o cierre la ventana de terminal!)p.ej
Aquí estoy
ksh(mi caparazón normal). Comienzobashy luego dentro de fiesta Iexec /bin/echo. Podemos ver que luego volví a entrarkshporque elbashproceso fue reemplazado por/bin/echo.fuente
TL; DR
execse usa para reemplazar el proceso actual del shell con nuevo y manejar la redirección de flujo / descriptores de archivo si no se ha especificado ningún comando.evalse usa para evaluar cadenas como comandos. Ambos pueden usarse para construir y ejecutar un comando con argumentos conocidos en tiempo de ejecución, peroexecreemplaza el proceso del shell actual además de ejecutar comandos.ejecutivo incorporado
Sintaxis:
Según el manual, si hay un comando especificado, este incorporado
En otras palabras, si estaba ejecutando
bashcon PID 1234 y si tuviera que ejecutarexec top -u rootdentro de ese shell, eltopcomando tendrá PID 1234 y reemplazará su proceso de shell.¿Dónde es esto útil? En algo conocido como scripts de envoltura. Tales scripts crean conjuntos de argumentos o toman ciertas decisiones sobre qué variables pasar al entorno, y luego se usan
execpara reemplazarse con cualquier comando que se especifique, y, por supuesto, proporcionan esos mismos argumentos que el script de envoltura ha desarrollado a lo largo del camino.Lo que también dice el manual es que:
Esto nos permite redirigir cualquier cosa desde las secuencias de salida de shells actuales a un archivo. Esto puede ser útil para fines de registro o filtrado, donde no desea ver los
stdoutcomandos, sino solostderr. Por ejemplo, así:Este comportamiento lo hace útil para iniciar sesión en scripts de shell , redirigir secuencias a archivos o procesos separados y otras cosas divertidas con descriptores de archivo.
En el nivel del código fuente, al menos para la
bashversión 4.3, elexecincorporado está definido enbuiltins/exec.def. Analiza los comandos recibidos, y si hay alguno, pasa cosas a lashell_execve()función definida en elexecute_cmd.carchivo.Para resumir, existe una familia de
execcomandos en lenguaje de programación C, yshell_execve()es básicamente una función de envoltura deexecve:eval incorporado
Los estados del manual bash 4.3 (énfasis agregado por mí):
Tenga en cuenta que no se produce un reemplazo del proceso. A diferencia de
execdonde el objetivo es simular laexecve()funcionalidad, la funciónevalincorporada solo sirve para "evaluar" argumentos, como si el usuario los hubiera escrito en la línea de comandos. Como tal, se crean nuevos procesos.¿Dónde podría ser útil? Como Gilles señaló en esta respuesta , "... eval no se usa muy a menudo. En algunos shells, el uso más común es obtener el valor de una variable cuyo nombre no se conoce hasta el tiempo de ejecución". Personalmente, lo he usado en un par de secuencias de comandos en Ubuntu donde era necesario ejecutar / evaluar un comando basado en el espacio de trabajo específico que el usuario estaba usando actualmente.
En el nivel del código fuente, se define
builtins/eval.defy pasa la cadena de entrada analizada aevalstring()funcionar.Entre otras cosas,
evalpuede asignar variables que permanecen en el entorno actual de ejecución de shell, mientrasexecque no puede:fuente
¿Cómo? El punto
evales que de ninguna manera crea un proceso hijo. Si lo hagoen un shell, luego el shell actual habrá cambiado de directorio. Tampoco
execcrea un nuevo proceso hijo, sino que cambia el ejecutable actual (es decir, el shell) para el dado; la identificación del proceso (y los archivos abiertos y otras cosas) permanecen igual. A diferencia deeval, unexecno volverá al shell de llamada a menos que elexecmismo falle debido a que no puede encontrar o cargar el ejecutable o morir por problemas de expansión de argumentos.evalbásicamente interpreta sus argumentos como una cadena después de la concatenación, es decir, hará una capa adicional de expansión de comodines y división de argumentos.execno hace nada de esofuente
Evaluación
Estos trabajan:
Sin embargo, estos no:
Procesar reemplazo de imagen
Este ejemplo demuestra cómo
execreemplaza la imagen de su proceso de llamada:¡Observe que se
exec echo $$ejecutó con el PID de la subshell! Además, después de que se completó, volvimos a nuestrosh$shell original .Por otro lado,
evalno no sustituir la imagen del proceso. Más bien, ejecuta el comando dado como lo haría normalmente dentro del shell. (Por supuesto, si ejecuta un comando que requiere que se genere un proceso ... ¡lo hace!)fuente
exec)