Mata todos los trabajos en segundo plano


63

¿Existe una forma más compacta de matar trabajos en segundo plano que:

for i in {1..5}; do kill %$i; done

Además, {1..5} obviamente tiene un número mágico codificado, ¿cómo puedo hacer que sea "N" con N siendo el número correcto, sin hacer un:

$(jobs | wc -l)

De hecho, uso \ j en PS1 para obtener el número de trabajos administrados, ¿es esto equivalente?


3
kill $(jobs -p)Parece más fácil
jw013

Preferiría matar trabajos individualmente, si es posible. (Aunque podría haber entendido mal su comentario)
Robottinosino

for pid in $(jobs -p); do kill $pid; done?
jw013

3
@ jw013 No solo es más fácil, en realidad es correcto (publíquelo como respuesta), a diferencia de una solución basada en contar las líneas de la salida de las jobscuales solo funciona si los trabajos se numeran consecutivamente. Ah, y "matar trabajos individualmente" no tiene sentido: pasar varios PID al killcomando hace exactamente lo mismo que pasarlos por separado.
Gilles 'SO- deja de ser malvado'

Estaba ingresando el comando incorrectamente, eliminé las palabras $ (jobs -p) y también me parece muy correcto. Listo para aceptar
Robottinosino

Respuestas:


101

Para killtodos los trabajos en segundo plano gestionados por bash, haga

kill $(jobs -p)

Tenga en cuenta que dado que ambos jobsy killestán incorporados en bash, no se debe ejecutar en cualquier otro error de la lista de argumentos demasiado larga tipo.


2
También para la posteridad, lo que piensa bahamat es la forma de hacerlo, zshdescalificándolos como cualquier autoridad sobre el tema.
Peth

Siento que debería saber esto, pero ¿cómo funciona el '$' aquí?
fersarr

1
@fersarr Aquí tienes
jw013

@bahamat Eso no funciona realmente ya que el PID puede estar en el campo 2 o 3 dependiendo de si el trabajo es uno de% + o% - o no. Lo que funciona es kill %${(k)^jobdirs}, que de hecho es más largo; si necesita enumerar los PID, puede usarlos por más tiempo ${${jobstates#*:*:}%%=*}.
Gilles 'SO- deja de ser malvado'

En CentOS, mi mensaje espera más información>
Janac Meena

15

Use en xargslugar del $(jobs -p)subcomando, porque si jobs -pestá vacío, el comando kill fallará.

jobs -p | xargs kill

1
Sin embargo, esto tiene el mismo efecto exacto, imprime la ayuda y sale con el código 123
cat

1
El comando funciona bien en OSX pero no funciona en Debian
brunocascio

Esto funciona muy bien en CentOS 6
Janac Meena

jobs -p | xargs -rn10 killfuncionará mejor si jobs -pno devuelve ningún PID. Tenga en cuenta que la -ropción es la extensión GNU.
NarūnasK

Como se mencionó anteriormente, -res el formato corto para la --no-run-if-emptyextensión GNU xargsque le indica que no ejecute el comando si stdin no tiene datos.
Anthony G - justicia para Monica

3

Prefiero verificar si hay trabajos que existan antes de eliminarlos, de esta manera el script no fallará si no hay nada en ejecución.

También es más corto de escribir. Lanza esto en tu .bash_profile:

function killjobs () {
    JOBS="$(jobs -p)";
    if [ -n "${JOBS}" ]; then;
        kill -KILL ${JOBS};
    fi
}

Entonces corre:

killjobs

Para matar cualquier trabajo en ejecución.


1

Tengo varios comandos compuestos en segundo plano que quiero terminar con gracia, enviando SIGINT a cada proceso, en macOS. Ninguna de las otras soluciones funcionó correctamente para eso, así que se me ocurrió esto:

jobs -p | xargs -n1 pkill -SIGINT -g

jobs -p enumera los procesos en segundo plano iniciados por el shell actual.

xargs -n1 ejecuta pkill una vez para cada trabajo.

pkill -SIGINT -g envía SIGINT (igual que ctrl + c) a todos los procesos en el grupo de procesos.


1

Supongo que dependiendo de lo que jobs -pdé la salida , la solución podría ser ligeramente diferente. En mi caso

$ jobs -p
[1]  - 96029 running    some job
[2]  + 96111 running    some other job

Por lo tanto, hacer lo siguiente no es bueno.

$ jobs -p | xargs kill
kill: illegal process id: [1]

Por otro lado, la ejecución kill $(jobs -p)sí funciona pero conlleva muchos mensajes de error, ya que las cadenas que no son PID también se pasan kill.

Por lo tanto, mi solución es grepprimero el PID y luego usarlo de la xargssiguiente manera:

$ jobs -p | grep -o -E '\s\d+\s' | xargs kill

1
¿Qué caparazón estás usando? ¿Qué echo $0muestra? ¿Qué help jobsmuestra? La salida ilustrada no es compatible con POSIX ; cualquier implementación de jobsdebería tener una -popción con el comportamiento deseado.
Comodín el

1
Gracias por señalar esto. Estoy usando zsh, y esa es la razón de la extraña salida. Cambié a bash y jobs -psolo hice salir PID. Acabo de enterarme de que zsh no es completamente compatible con POSIX.
Fanchen Bao

0

Parece que jobs -p | xargs killhace el trabajo, sin embargo, produce una salida no deseada canalizada para matar. Aquí estoy agrupando la salida de jobs -ptener / no tener + o - carácter

function killjobs() {
    JOBS=$(jobs -p)
    echo $JOBS | grep -v "+\|-"| awk '{print $2}' | xargs kill -9
    echo $JOBS | grep "+\|-"| awk '{print $3}' | xargs kill -9
}

Y luego puedes llamar killjobs

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.