
Supongamos que ejecuta un comando que tarda algún tiempo en regresar y desea ejecutar un comando diferente después de ejecutarlo, pero no lo planeó de antemano.
Sé que existe la opción de presionar Ctrl + Zy luego enviar fg && otherCommand
. Sin embargo, esto tiene dos defectos importantes:
- No funciona si el primer comando es una composición de diferentes comandos (
command1 && command2
ocommand1; command2
) porque entonces los comandos posteriores de la primera línea enviada no se ejecutan. - La ejecución del primer comando se detiene mientras ingresa el siguiente comando. Con esos desagradables comandos de 30 segundos, el tiempo que dedica a ingresar el siguiente comando constituye una buena parte del tiempo de ejecución restante, si no todo.
También sé que puedes escribir el siguiente comando mientras se ejecuta un comando y luego presionar Enterpara enviarlo. Sin embargo, esto también tiene dos defectos importantes:
- No funciona si el comando que ejecuta primero lee
stdin
. - Si el comando que ejecuta primero produce un resultado, no podrá ver lo que ingresó.
¿Existe una forma rápida de poner en cola más comandos mientras se ejecuta un comando, posiblemente implicando el uso de un emulador de terminal especial o varios terminales?
Respuesta1
Presione Ctrl+ Zy ejecute inmediatamente bg
. Esto hace que el comando actual siga ejecutándose en segundo plano. Luego puede utilizar fg && otherCommand
para programar otherCommand
después del actual.
Para hacer esto más fácil, configuré Ctrl+ Zen mi shell para que se ejecute bg
cuando lo presiono en una línea de comando vacía. VerEn zsh, ¿cómo puedo repudiar más rápidamente el proceso de primer plano?y¿Cómo se envían aplicaciones de línea de comandos directamente al fondo?; No he comprobado si las versiones modernas de bash facilitan hacer lo mismo.
Respuesta2
Puede crear una canalización con nombre (esto debe hacerse una vez):
mkfifo ~/myfifo
Luego desde una terminal (llamémosla terminal A) puedes decir:
exec 10< ~/myfifo
Para asignar el extremo de lectura de la canalización al descriptor de archivo 10, puede usar cualquier otro número superior a 2 (de modo que la entrada, salida y error estándar permanezcan disponibles si otro comando lo necesita).
Luego desde otra terminal (llamémosla terminal B) puedes decir:
cat - > ~/myfifo
Para completar la conexión al terminal A que luego devuelve el mensaje. Este comando escribe lo que ingresa desde la entrada estándar en la tubería. Luego puede ingresar lo siguiente en la terminal A:
while read -u10 -r LINE; do eval "$LINE"; done
Entonces ejecutará los comandos que escriba en la terminal B. El read
comando leerá líneas del descriptor de archivo 10 y las ejecutará con eval
. eval
le permite ejecutar comandos de shell, como exportar variables.
Mientras la terminal A esté abierta, puede interrumpir el ciclo con Ctrl+C para poder ingresar comandos nuevamente y luego puede reiniciar el ciclo para comenzar a ejecutar los comandos restantes en cola.
Los comandos exec y while se pueden poner en un shellscript para que puedas usar Ctrl-Z fg && yourscript
para activar el modo canalización si olvidaste hacerlo al principio.
Respuesta3
Lo más probable es que quieras:
wait $pid
Si no está ejecutando el mismo shell, no podrá utilizar uno integrado y necesitará una solución alternativa. Ver discusiónaquí.
Respuesta4
EDITAR:Interpreté mal la pregunta, pero la siguiente técnica aún podría ser útil para las personas cuando ejecutan comandos en un script bash (para que tengan un PID único)
Esto es lo que uso (en Linux), cuando el comando1 imprime resultados útiles y solo quiero iniciar otro proceso en otro shell una vez que haya terminado (es decir, no quiero poner el comando1 en segundo plano):
tail --pid=$command1_pid -f /dev/null; command2
¿Dónde $command1_pid
está el PID del proceso que estás esperando finalizar?
(Creo que lo encontré originalmente aquí:https://stackoverflow.com/a/41613532/1676393. Consulte allí para obtener otros detalles útiles. Como una versión que funcionará en Darwin (macOS))
Paso a paso:
- detener comando1 con Ctrl+Z
- ejecutar
ps
, luego busque el proceso correspondiente al comando1 y encuentre su PID - luego reinicie el proceso de comando1 escribiendo
fg
y, en un nuevo shell, ejecute el comando anterior
De esta manera, comando2 se iniciará en el nuevo shell cuando comando1 se ejecute en el antiguo shell.