Elimina todos los procesos que se ejecutan durante más de 5 minutos por un usuario determinado en Linux Bash Script

18

Necesito el comando para eliminar los procesos que se han estado ejecutando desde al menos 5 minutos para un proceso determinado.

Tendré que ejecutar ese comando cada cinco minutos más o menos.

Un millón de gracias !

(el sistema es Centos5)


fuente

Respuestas:

17
kill -9 $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print $2}}')

donde "procname" es un nombre de proceso y 300 es el umbral de tiempo de ejecución

Sombrero blanco
fuente
Gran línea. Lo utilicé sin -9ser un poco más amigable con mis procesos y agregué un grep -v defunct |antes awkcomo otro lo que puede ver procname <defunct>en su salida, lo que haría que el comando awk no devuelva un PID válido. Y esto rompería el comando de matar.
Michael Härtl
Yo diría que $(ps -eo comm,pid,etimes | awk '/^procname/ {if ($3 > 300) { print "kill "$2}}')es un poco más suave, pero la respuesta es excelente de todos modos
Yevgen
@WhiteHat, ¿cómo haría lo mismo pero para un proceso con cierto pid?
Petar Vasilev
Una cosa que desperdició mi tiempo es que: debería usar 'con awk NOT "
cn123h
6

¿Quizás ejecute el comando de ejecución larga como este en un crontab?

timeout -k 300 command
atx
fuente
5

Mi versión del script kill, aprovechando las dos respuestas anteriores:

#!/bin/bash

#Email to send report
MY_EMAIL="[email protected]"

#Process name to kill
NAME_KILL="php"

#UID to kill
UID_KILL=33.

#Time in seconds which the process is allowed to run
KILL_TIME=60

KILL_LIST=()
EMAIL_LIST=()
while read PROC_UID PROC_PID PROC_ETIMES PROC_ETIME PROC_COMM PROC_ARGS; do
    if [ $PROC_UID -eq $UID_KILL -a "$PROC_COMM" == "$NAME_KILL" -a $PROC_ETIMES -gt $KILL_TIME ]; then
    KILL_LIST+=("$PROC_PID");
    MSG="Killing '$PROC_ARGS' which runs for $PROC_ETIME";
    EMAIL_LIST+=("$MSG");
    echo "$MSG";
    fi
done < <(ps eaxo uid,pid,etimes,etime,comm,args | tail -n+2)
if [ ${#KILL_LIST[*]} -gt 0 ]; then
    kill -9 ${KILL_LIST[@]}
    printf '%s\n' "${EMAIL_LIST[@]}" | mail -s "Long running processes killed" $MY_EMAIL
fi

Filtra el proceso por UID, NOMBRE y, si el tiempo de ejecución excede el límite, mata los procesos y envía el informe por correo electrónico. Si no necesita ese correo electrónico, puede comentar la última línea.

Viperet
fuente
2

Encontré la solución en esta página: http://www.directadmin.com/forum/showthread.php?t=26179

Cree un archivo vacío y llámelo killlongproc.sh

Copia esto:

#!/bin/bash
# This script will kill process which running more than X hours
# egrep: the selected process; grep: hours
PIDS="`ps eaxo bsdtime,pid,comm | egrep "spamd|exim|mysqld|httpd" | grep " 1:" | awk '{print $2}'`"

# Kill the process
echo "Killing spamd, exim, mysqld and httpd processes running more than one hour..."
for i in ${PIDS}; do { echo "Killing $i"; kill -9 $i; }; done;

Para esto en tu cronjob

15 * * * * * root /{directory}/./killongproc.sh
Pausado hasta nuevo aviso.
fuente
44
Por lo general, es una mala idea hacer esto. ¿Qué problema realmente estás tratando de resolver? Además, no debe usarlo kill -9ya que no le da a los procesos la oportunidad de hacer una limpieza elegante antes de salir.
Pausado hasta nuevo aviso.
1
Esto mata los procesos que consumen una cierta cantidad de tiempo de CPU (usuario + sistema), no procesos que se ejecutan durante una cierta cantidad de tiempo real (por ejemplo, iniciado antes de 1 hora).
Marki555
2

Hay un script aquí que se puede modificar para hacer lo que quiera.

EDITAR agregó el script a continuación

#!/bin/bash
#
#Put the UID to kill on the next line
UID_KILL=1001

#Put the time in seconds which the process is allowed to run below
KILL_TIME=300

KILL_LIST=`{
ps -eo uid,pid,lstart | tail -n+2 |
    while read PROC_UID PROC_PID PROC_LSTART; do
        SECONDS=$[$(date +%s) - $(date -d"$PROC_LSTART" +%s)]
        if [ $PROC_UID -eq $UID_KILL -a $SECONDS -gt $KILL_TIME ]; then
        echo -n "$PROC_PID "
        fi
     done 
}`

if [[ -n $KILL_LIST ]]
then
        kill $KILL_LIST
fi
Ha llegado el momento
fuente
No tengo suficiente conocimiento para modificarlo, es por eso que te pregunto
2
Demasiado complicado. Puede usar la columna etimesde pspara mostrarle directamente los segundos transcurridos desde el inicio del proceso (no es necesario calcularlo desde la hora de inicio).
Marki555
@ Marki555 sí, esto es cierto. Sin embargo, en sistemas con versiones psque no son compatibles etimes(solo etime), esta es una gran alternativa. Solo lo usé cuando la respuesta principal me dio un errorps
Mike
0

Tuve que resolver una tarea similar y no necesita un script. Para terminar (señal SIGTERM) procesos del ejecutable "THECOMMAND":

killall -u $USER --older-than 5m THECOMMAND

La restricción para el usuario actual -u $USERes necesaria solo para evitar mensajes de error innecesarios si otros usuarios también ejecutan "THECOMMAND". En su propio crontab de usuario, ingresaría lo siguiente:

*/5 * * * *     killall -u $USER --older-than 5m THECOMMAND

En un crontab del sistema (usuario 'root'), agregaría lo siguiente:

*/5 * * * *     killall --older-than 5m THECOMMAND

Si desea matar (SIGKILL) los procesos en lugar de terminarlos (SIGTERM), envíe explícitamente la señal SIGKILL agregando --signal SIGKILLa los parámetros. Ejemplo para un crontab del sistema:

*/5 * * * *     killall --older-than 5m --signal SIGKILL THECOMMAND
t0r0X
fuente
-4

Para httpd

ps eaxo pid, hora, comunicación | cola -n + 2 | grep 'httpd' | awk 'substr ($ 0,9,1)> 0' | awk '{print $ 1}'

mente pura
fuente