¿Cómo puedo matar un proceso y asegurarme de que el PID no se haya reutilizado?

40

Supongamos, por ejemplo, que tiene un script de shell similar a:

longrunningthing &
p=$!
echo Killing longrunningthing on PID $p in 24 hours
sleep 86400
echo Time up!
kill $p

Debería hacer el truco, ¿no? Excepto que el proceso puede haber terminado antes y su PID puede haber sido reciclado, lo que significa que algún trabajo inocente obtiene una bomba en su cola de señal. En la práctica, esto posiblemente importa, pero de todos modos me preocupa. Hackear algo largo para caer muerto por sí mismo, o mantener / eliminar su PID en el FS funcionaría, pero estoy pensando en la situación genérica aquí.

FJL
fuente
3
Te aseguras de que si tu proceso objetivo muere, mata a su asesino en el proceso.
mikeserv
2
Use killallqué coincidencias en el nombre, por lo que al menos solo está eliminando un proceso con el mismo nombre que longrunningthing. Asumiendo que solo tendrá uno de estos funcionando a la vez.
LawrenceC
8
Puede guardar la hora de inicio del proceso original y, antes de finalizar, verifique que la hora de inicio del proceso con ese pid coincida con lo que guardó. El par pid, start-time es un identificador único para los procesos en Linux.
Bakuriu
1
¿Puedo preguntarte por qué necesitas esto? ¿Qué es lo fundamental que estás tratando de lograr? (¿algo que se ejecuta continuamente pero se restablece cada 24 h?)
Olivier Dulac
2
@mikeserv Un proceso no puede garantizar que algo sucederá en caso de su propia muerte.
kasperd

Respuestas:

29

Lo mejor sería usar el timeoutcomando si lo tiene, que está destinado para eso:

timeout 86400 cmd

La implementación actual de GNU (8.23) al menos funciona utilizando alarm()o equivalente mientras espera el proceso secundario. No parece estar protegiendo contra la SIGALRMentrega entre el waitpid()regreso y la timeoutsalida (cancelando efectivamente esa alarma ). Durante esa pequeña ventana, timeoutincluso puede escribir mensajes en stderr (por ejemplo, si el niño arrojó un núcleo), lo que agrandaría aún más esa ventana de carrera (indefinidamente si stderr es una tubería completa, por ejemplo).

Personalmente, puedo vivir con esa limitación (que probablemente se solucionará en una versión futura). timeouttambién tendrá mucho cuidado de informar el estado de salida correcto, manejar otros casos de esquina (como SIGALRM bloqueado / ignorado en el inicio, manejar otras señales ...) mejor de lo que probablemente podría hacer a mano.

Como aproximación, podría escribirlo perlcomo:

perl -MPOSIX -e '
  $p = fork();
  die "fork: $!\n" unless defined($p);
  if ($p) {
    $SIG{ALRM} = sub {
      kill "TERM", $p;
      exit 124;
    };
    alarm(86400);
    wait;
    exit (WIFSIGNALED($?) ? WTERMSIG($?)+128 : WEXITSTATUS($?))
  } else {exec @ARGV}' cmd

Hay un timelimitcomando en http://devel.ringlet.net/sysutils/timelimit/ (precede a GNU timeoutpor unos meses).

 timelimit -t 86400 cmd

Ese usa un alarm()mecanismo similar pero instala un controlador SIGCHLD(ignorando a los niños detenidos) para detectar la muerte del niño. También cancela la alarma antes de ejecutar waitpid()(eso no cancela la entrega de SIGALRMsi estaba pendiente, pero por la forma en que está escrito, no puedo ver que sea un problema) y mata antes de llamar waitpid()(así que no puedo matar un pid reutilizado )

netpipes también tiene un timelimitcomando. Ese precede a todos los demás por décadas, adopta otro enfoque, pero no funciona correctamente para los comandos detenidos y devuelve un 1estado de salida al finalizar el tiempo de espera.

Como respuesta más directa a su pregunta, puede hacer algo como:

if [ "$(ps -o ppid= -p "$p")" -eq "$$" ]; then
  kill "$p"
fi

Es decir, verifique que el proceso todavía sea un hijo nuestro. Nuevamente, hay una pequeña ventana de carrera (entre psrecuperar el estado de ese proceso y killmatarlo) durante el cual el proceso podría morir y su pid será reutilizado por otro proceso.

Con algunas conchas ( zsh, bash, mksh), puede pasar especificaciones de trabajo en lugar de los PID.

cmd &
sleep 86400
kill %
wait "$!" # to retrieve the exit status

Eso solo funciona si genera un solo trabajo en segundo plano (de lo contrario, obtener la especificación de trabajo correcta no siempre es posible de manera confiable).

Si eso es un problema, simplemente inicie una nueva instancia de shell:

bash -c '"$@" & sleep 86400; kill %; wait "$!"' sh cmd

Eso funciona porque el shell elimina el trabajo de la tabla de trabajos cuando el niño muere. Aquí, no debería haber ninguna ventana de carrera ya que para cuando el shell llama kill(), o la señal SIGCHLD no se ha manejado y el pid no se puede reutilizar (ya que no se ha esperado), o se ha manejado y el el trabajo se ha eliminado de la tabla de procesos (e killinformaría un error). bash's killal menos bloquea SIGCHLD antes de acceder a su tabla de trabajo para expandirlo %y desbloquearlo después de kill().

Otra opción para evitar tener ese sleepproceso dando vueltas incluso después de que cmdhaya muerto, con basho ksh93es usar una tubería con en read -tlugar de sleep:

{
  {
    cmd 4>&1 >&3 3>&- &
    printf '%d\n.' "$!"
  } | {
    read p
    read -t 86400 || kill "$p"
  }
} 3>&1

Ese todavía tiene condiciones de carrera, y pierdes el estado de salida del comando. También supone cmdque no cierra su fd 4.

Podrías intentar implementar una solución libre de carrera en perl:

perl -MPOSIX -e '
   $p = fork();
   die "fork: $!\n" unless defined($p);
   if ($p) {
     $SIG{CHLD} = sub {
       $ss = POSIX::SigSet->new(SIGALRM); $oss = POSIX::SigSet->new;
       sigprocmask(SIG_BLOCK, $ss, $oss);
       waitpid($p,WNOHANG);
       exit (WIFSIGNALED($?) ? WTERMSIG($?)+128 : WEXITSTATUS($?))
           unless $? == -1;
       sigprocmask(SIG_UNBLOCK, $oss);
     };
     $SIG{ALRM} = sub {
       kill "TERM", $p;
       exit 124;
     };
     alarm(86400);
     pause while 1;
   } else {exec @ARGV}' cmd args...

(aunque necesitaría ser mejorado para manejar otros tipos de casos de esquina).

Otro método sin raza podría ser el uso de grupos de procesos:

set -m
((sleep 86400; kill 0) & exec cmd)

Sin embargo, tenga en cuenta que el uso de grupos de procesos puede tener efectos secundarios si hay E / S en un dispositivo terminal involucrado. Sin embargo, tiene el beneficio adicional de matar todos los demás procesos adicionales generados por cmd.

Stéphane Chazelas
fuente
44
¿Por qué no mencionar el mejor método primero?
deltab
2
@deltab: timeoutno es portátil, la respuesta mencionó primero una solución portátil.
Cuonglm
1
@deltab: da una idea de cómo funcionan las cosas y especialmente cómo puede fallar el enfoque del "sentido común" (Stephane prefiere enseñarle a pescar primero, lo que me gusta). Se espera que uno lea la respuesta completa
Olivier Dulac,
@Stephane: para "obtener la especificación de trabajo correcta no siempre es posible de manera confiable": ¿no se puede contar primero la salida jobsy luego saber que (ya que es su propio shell, en el que tiene control sobre lo que sucede a continuación) el próximo fondo trabajo será N + 1? [entonces puedes guardar N y luego matar a% N + 1])
Olivier Dulac
1
@OlivierDulac, eso supondría que ningún trabajo anterior ha finalizado para el momento en que comience uno nuevo (los shells reutilizan los números de trabajo).
Stéphane Chazelas
28

En general, no puedes. Todas las respuestas dadas hasta ahora son heurísticas con errores. Solo hay un caso en el que puede usar con seguridad el pid para enviar señales: cuando el proceso de destino es un hijo directo del proceso que enviará la señal, y el padre aún no lo ha esperado. En este caso, incluso si ha salido, el pid está reservado (esto es lo que es un "proceso zombie") hasta que el padre lo espere. No conozco ninguna forma de hacerlo limpiamente con el shell.

Una forma segura alternativa de eliminar procesos es iniciarlos con un conjunto de control tty en un pseudo-terminal para el cual es dueño del lado maestro. Luego puede enviar señales a través del terminal, por ejemplo, escribiendo el carácter para SIGTERMo SIGQUITsobre el pty.

Otra forma más conveniente de crear scripts es utilizar una screensesión con nombre y enviar comandos a la sesión de pantalla para finalizarla. Este proceso se lleva a cabo a través de una tubería o un conector Unix nombrado de acuerdo con la sesión de pantalla, que no se reutilizará automáticamente si elige un nombre único seguro.

R ..
fuente
44
No puedo ver por qué eso no se podía hacer en conchas. He dado varias soluciones.
Stéphane Chazelas
3
¿Podría por favor dar una explicación y algún tipo de discusión cuantitativa sobre las ventanas de carrera y otros inconvenientes? Sin eso, "Todas las respuestas dadas hasta ahora son heurísticas con errores" es una confrontación innecesariamente innecesaria sin ningún beneficio.
Peter
3
@peterph: en general, cualquier uso de un pid es una carrera TOCTOU; no importa cómo verifique si todavía se refiere al mismo proceso al que espera que se refiera, podría dejar de referirse a ese proceso y referirse a algunos nuevos procesar en el intervalo antes de usarlo (enviando la señal). La única forma de evitar esto es poder bloquear la liberación / reutilización del pid, y el único proceso que puede hacer esto es el padre directo.
R ..
2
@ StéphaneChazelas: ¿Cómo evita que el shell espere un pedido de un proceso en segundo plano que ha salido? Si puede hacer eso, el problema se puede resolver fácilmente en el caso de que OP lo necesite.
R ..
55
@peterph: "La ventana de la carrera es pequeña" no es una solución. Y la rareza de la raza depende de la asignación pid secuencial. Los errores que causan que algo muy malo suceda una vez al año son mucho peores que los que ocurren todo el tiempo porque son prácticamente imposibles de diagnosticar y corregir.
R ..
10
  1. Al iniciar el proceso, guarde su hora de inicio:

    longrunningthing &
    p=$!
    stime=$(TZ=UTC0 ps -p "$p" -o lstart=)
    
    echo "Killing longrunningthing on PID $p in 24 hours"
    sleep 86400
    echo Time up!
    
  2. Antes de intentar matar el proceso, deténgalo (esto no es realmente esencial, pero es una forma de evitar las condiciones de carrera: si detiene el proceso, su pid no se puede reutilizar)

    kill -s STOP "$p"
    
  3. Verifique que el proceso con ese PID tenga la misma hora de inicio y, en caso afirmativo, elimínelo; de lo contrario, deje que el proceso continúe:

    cur=$(TZ=UTC0 ps -p "$p" -o lstart=)
    
    if [ "$cur" = "$stime" ]
    then
        # Okay, we can kill that process
        kill "$p"
    else
        # PID was reused. Better unblock the process!
        echo "long running task already completed!"
        kill -s CONT "$p"
    fi
    

Esto funciona porque solo puede haber un proceso con el mismo PID y hora de inicio en un sistema operativo determinado.

Detener el proceso durante la verificación hace que las condiciones de carrera no sean un problema. Obviamente, esto tiene el problema de que algunos procesos aleatorios pueden detenerse durante algunos milisegundos. Dependiendo del tipo de proceso, esto puede o no ser un problema.


Personalmente, simplemente usaría python y psutilque maneja la reutilización de PID automáticamente:

import time

import psutil

# note: it would be better if you were able to avoid using
#       shell=True here.
proc = psutil.Process('longrunningtask', shell=True)
time.sleep(86400)

# PID reuse handled by the library, no need to worry.
proc.terminate()   # or: proc.kill()
Bakuriu
fuente
Python gobierna en UNIX ... No estoy seguro de por qué no comienzan más respuestas allí, ya que estoy seguro de que la mayoría de los sistemas no prohíben su uso.
Sr. Mascaro
He usado un esquema similar (usando el tiempo de inicio) antes, ¡pero sus habilidades de scripting sh son más claras que las mías! Gracias.
FJL
Eso significa que potencialmente estás deteniendo el proceso incorrecto. Tenga en cuenta que el ps -o start=formato cambia de 18:12 a 26 de enero después de un tiempo. Tenga cuidado con los cambios de horario de verano también. Si está en Linux, probablemente lo prefiera TZ=UTC0 ps -o lstart=.
Stéphane Chazelas
@ StéphaneChazelas Sí, pero dejas que continúe después. Dije explícitamente: dependiendo del tipo de tarea que esté realizando ese proceso, puede tener algunos problemas para detenerlo unos milisegundos. Gracias por el consejo lstart, lo
editaré
Tenga en cuenta que (a menos que su sistema limite la cantidad de procesos por usuario), es fácil para cualquiera llenar la tabla de procesos con zombies. Una vez que solo quedan 3 pids disponibles, es fácil para cualquiera iniciar cientos de procesos diferentes con el mismo pid en un solo segundo. Entonces, estrictamente hablando, su "solo puede haber un proceso con el mismo PID y hora de inicio en un SO dado" no es necesariamente cierto.
Stéphane Chazelas
7

En un sistema Linux, puede asegurarse de que un pid no se reutilizará manteniendo vivo su espacio de nombres pid. Esto se puede hacer a través del /proc/$pid/ns/pidarchivo.

  • man namespaces -

    El montaje de enlace (consulte mount(2)) uno de los archivos de este directorio en otro lugar del sistema de archivos mantiene vivo el espacio de nombres correspondiente del proceso especificado por pid, incluso si todos los procesos actualmente en el espacio de nombres finalizan.

    Al abrir uno de los archivos en este directorio (o un archivo que está montado en un enlace a uno de estos archivos) se devuelve un identificador de archivo para el espacio de nombres correspondiente del proceso especificado por pid. Mientras este descriptor de archivo permanezca abierto, el espacio de nombres permanecerá vivo, incluso si todos los procesos en el espacio de nombres finalizan. El descriptor de archivo se puede pasar a setns(2).

Puede aislar un grupo de procesos, básicamente cualquier número de procesos, espaciando sus nombres init.

  • man pid_namespaces -

    El primer proceso creado en un nuevo espacio de nombres (es decir, el proceso creado usando clone(2) el indicador CLONE_NEWPID , o el primer hijo creado por un proceso después de una llamada para unshare(2)usar el indicador CLONE_NEWPID ) tiene el PID 1 , y es el initproceso para el espacio de nombres ( ver init(1)) . Un proceso hijo que queda huérfano dentro del espacio de nombres será reparentado a este proceso en lugar de init(1) (a menos que uno de los antepasados ​​del niño en el mismo espacio de nombres PID emplee el comando prctl(2) PR_SET_CHILD_SUBREAPER para marcarse como el segador de procesos descendientes huérfanos) .

    Si el initproceso de un espacio de nombres PID termina, el núcleo termina todos los procesos en el espacio de nombres a través de una señal SIGKILL . Este comportamiento refleja el hecho de que el initproceso es esencial para el correcto funcionamiento de un espacio de nombres PID .

El util-linuxpaquete proporciona muchas herramientas útiles para manipular espacios de nombres. Sin unshareembargo, por ejemplo, si aún no ha organizado sus derechos en un espacio de nombres de usuario, requerirá derechos de superusuario:

unshare -fp sh -c 'n=
    echo "PID = $$"
    until   [ "$((n+=1))" -gt 5 ]
    do      while   sleep 1
            do      date
            done    >>log 2>/dev/null   &
    done;   sleep 5' >log
cat log; sleep 2
echo 2 secs later...
tail -n1 log

Si no ha organizado un espacio de nombres de usuario, aún puede ejecutar comandos arbitrarios de forma segura eliminando inmediatamente los privilegios. El runusercomando es otro binario (no setuid) provisto por el util-linuxpaquete e incorporarlo podría verse así:

sudo unshare -fp runuser -u "$USER" -- sh -c '...'

...y así.

En el ejemplo anterior dos interruptores se pasan a unshare(1)la --forkbandera que hace que la invoca sh -cproceso creó el primer hijo y asegura su initestado y la --pidbandera que indica a unshare(1)crear un espacio de nombres PID.

El sh -cproceso genera cinco shells secundarios en segundo plano, cada uno un whileciclo infinito que continuará agregando la salida dateal final de logmientras el tiempo sea sleep 1verdadero. Después de generar estos procesos, se shrequieren sleep5 segundos adicionales y luego finaliza.

Quizás valga la pena señalar que si -fno se usara la bandera, ninguno de los whilebucles de fondo terminaría, pero con él ...

SALIDA:

PID = 1
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:45 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:46 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:47 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
Mon Jan 26 19:17:48 PST 2015
2 secs later...
Mon Jan 26 19:17:48 PST 2015
mikeserv
fuente
Respuesta interesante que parece ser robusta. Probablemente un poco exagerado para el uso básico, pero vale la pena pensarlo.
Uriel
No veo cómo o por qué mantener vivo un espacio de nombres PID evita la reutilización de un PID. La misma página de manual que cita: mientras este descriptor de archivo permanezca abierto, el espacio de nombres permanecerá activo, incluso si todos los procesos en el espacio de nombres finalizan , sugiere que los procesos pueden terminar (y, por lo tanto, presumiblemente, se reciclará su ID de proceso). ¿Qué tiene que ver mantener vivo el espacio de nombres PID para evitar que el PID sea reutilizado por otro proceso?
davmac
5

Considera mejorar tu longrunningthingcomportamiento un poco, un poco más como un demonio. Por ejemplo, puede hacer que cree un archivo pid que permita al menos un control limitado del proceso. Hay varias formas de hacer esto sin modificar el binario original, todas involucrando un contenedor. Por ejemplo:

  1. un script de envoltura simple que iniciará el trabajo requerido en segundo plano (con redirección de salida opcional), escriba el PID de este proceso en un archivo, luego espere a que el proceso termine (usando wait) y elimine el archivo. Si durante la espera el proceso se mata, por ejemplo, por algo como

    kill $(cat pidfile)
    

    el contenedor solo se asegurará de que se elimine el archivo pid.

  2. un contenedor de monitor, que colocará su propio PID en algún lugar y capturará (y responderá) las señales que se le envíen. Ejemplo simple:

    #!/bin/bash
    p=0
    trap killit USR1

    killit () {
        printf "USR1 caught, killing %s\n" "$p"
        kill -9 $p
    }

    printf "monitor $$ is waiting\n"
    therealstuff &
    p=%1
    wait $p
    printf "monitor exiting\n"

Ahora, como señalaron @R .. y @ StéphaneChazelas, estos enfoques a menudo tienen una condición de carrera en algún lugar o imponen una restricción en la cantidad de procesos que puede generar. Además, no maneja los casos, donde la longrunningthingbifurcación puede separarse y los niños se separan (lo que probablemente no sea el problema en la pregunta original).

Con los núcleos de Linux recientes (leídos hace un par de años), esto se puede tratar muy bien mediante el uso de cgroups , a saber, el congelador , que, supongo, es lo que usan algunos sistemas modernos de inicio de Linux.

Peterph
fuente
Gracias y a todos. Estoy leyendo todo ahora. El punto longrunningthinges que no tienes control sobre lo que es. También di un ejemplo de script de shell porque explicaba el problema. Me gustan las suyas y todas las otras soluciones creativas aquí, pero si está usando Linux / bash, hay un "tiempo de espera" incorporado para eso. ¡Supongo que debería obtener la fuente de eso y ver cómo lo hace!
FJL
@FJL, notimeout es un shell incorporado. Ha habido varias implementaciones de un comando para Linux, una se agregó recientemente (2008) a GNU coreutils (por lo tanto, no es específica de Linux), y eso es lo que la mayoría de las distribuciones de Linux usan hoy en día. timeout
Stéphane Chazelas
@ Stéphane - Gracias - Posteriormente encontré referencia a GNU coreutils. Pueden ser portátiles, pero a menos que esté en el sistema base, no se puede confiar en él. Estoy más interesado en saber cómo funciona, aunque tomo nota de su comentario en otro lugar que sugiere que no es 100% confiable. Dada la forma en que se ha ido este hilo, ¡no me sorprende!
FJL
1

Si está ejecutando en Linux (y algunos otros * nixes), puede verificar si el proceso que pretende matar todavía se usa y si la línea de comando coincide con su largo proceso. Algo como :

echo Time up!
grep -q longrunningthing /proc/$p/cmdline 2>/dev/null
if [ $? -eq 0 ]
then
  kill $p
fi

Una alternativa puede ser verificar durante cuánto tiempo se está ejecutando el proceso que pretende matar, con algo así ps -p $p -o etime=. Puede hacerlo usted mismo extrayendo esta información /proc/$p/stat, pero esto sería complicado (el tiempo se mide en segundos y también deberá usar el tiempo de actividad del sistema /proc/stat).

De todos modos, generalmente no puede asegurarse de que el proceso no se reemplace después de su verificación y antes de matarlo.

Uriel
fuente
Eso todavía no es correcto porque no elimina la condición de la carrera.
strcat
@strcat De hecho, no hay garantía de éxito, pero la mayoría de los scripts ni siquiera se molestan en hacer esa verificación y solo matan sin rodeos un cat pidfileresultado. No recuerdo una manera limpia de hacerlo solo en shell. Sin embargo, la respuesta propuesta para el espacio de nombres parece interesante ...
Uriel
-1

Esta es realmente una muy buena pregunta.

La forma de determinar la unicidad del proceso es mirar (a) dónde está en la memoria; y (b) lo que contiene ese recuerdo. Para ser específicos, queremos saber en qué lugar de la memoria está el texto del programa para la invocación inicial, porque sabemos que el área de texto de cada hilo ocupará una ubicación diferente en la memoria. Si el proceso muere y se inicia otro con el mismo pid, el texto del programa para el nuevo proceso no ocupará el mismo lugar en la memoria y no contendrá la misma información.

Entonces, inmediatamente después de iniciar su proceso, haga md5sum /proc/[pid]/mapsy guarde el resultado. Más tarde, cuando desee matar el proceso, haga otro md5sum y compárelo. Si coincide, entonces mata al pid. Si no, no lo hagas.

Para ver esto por ti mismo, lanza dos proyectiles de bash idénticos. Examínelos /proc/[pid]/mapsy encontrará que son diferentes. ¿Por qué? Porque aunque es el mismo programa, ocupan diferentes ubicaciones en la memoria y las direcciones de su pila son diferentes. Entonces, si su proceso muere y su PID se reutiliza, incluso si el mismo comando se relanza con los mismos argumentos , el archivo "mapas" será diferente y sabrá que no está tratando con el proceso original.

Ver: página de manual de proc para más detalles.

Tenga en cuenta que el archivo /proc/[pid]/statya contiene toda la información que otros carteles han mencionado en sus respuestas: edad del proceso, padre pid, etc. Este archivo contiene información estática e información dinámica, por lo que si prefiere utilizar este archivo como base de comparación, luego, al iniciar su longrunningthing, debe extraer los siguientes campos estáticos del statarchivo y guardarlos para compararlos más tarde:

pid, nombre de archivo, pid de padre, id de grupo de proceso, terminal de control, proceso de tiempo iniciado después del inicio del sistema, tamaño del conjunto residente, la dirección del inicio de la pila,

tomados en conjunto, lo anterior identifica de manera única el proceso, por lo que esto representa otro camino a seguir. En realidad, podría salirse con la suya con solo "pid" y "proceso de tiempo iniciado después del arranque del sistema" con un alto grado de confianza. Simplemente extraiga estos campos del statarchivo y guárdelo en algún lugar al iniciar su proceso. Más tarde, antes de matarlo, extráigalo nuevamente y compárelo. Si coinciden, entonces está seguro de que está viendo el proceso original.

Michael Martinez
fuente
1
Eso generalmente no funcionará como /proc/[pid]/mapscambios a lo largo del tiempo a medida que se asigne memoria adicional o la pila crezca o se mapeen nuevos archivos ... ¿Y qué significa inmediatamente después del lanzamiento ? ¿Después de que todas las bibliotecas se hayan mapeado? ¿Cómo determinas eso?
Stéphane Chazelas
Estoy haciendo una prueba ahora en mi sistema con dos procesos, uno una aplicación de Java y el otro un servidor cfengine. Cada 15 minutos lo hago md5sumen sus archivos de mapas. Lo dejaré correr por un día o dos e informaré aquí con los resultados.
Michael Martinez
@ StéphaneChazelas: He estado revisando mis dos procesos durante 16 horas y no ha habido cambios en el md5sum
Michael Martinez
-1

Otra forma sería verificar la edad del proceso antes de matarlo. De esa manera, puede asegurarse de no matar un proceso que no se genera en menos de 24 horas. Puede agregar una ifcondición basada en eso antes de matar el proceso.

if [[ $(ps -p $p -o etime=) =~ 1-. ]] ; then
    kill $p
fi

Esta ifcondición verificará si la ID del proceso $pes inferior a 24 horas (86400 segundos).

PD: - El comando ps -p $p -o etime=tendrá el formato<no.of days>-HH:MM:SS

Sree
fuente
El mtimede /proc/$pno tiene nada que ver con la hora de inicio del proceso.
Stéphane Chazelas
Gracias @ StéphaneChazelas. Tienes razón. He editado la respuesta para cambiar la ifcondición. Por favor, siéntase libre de comentar si tiene errores.
Sree
-3

Lo que hago es, después de haber matado el proceso, hacerlo de nuevo. Cada vez que hago eso, la respuesta vuelve, "no hay tal proceso"

allenb   12084  5473  0 08:12 pts/4    00:00:00 man man
allenb@allenb-P7812 ~ $ kill -9 12084
allenb@allenb-P7812 ~ $ kill -9 12084
bash: kill: (12084) - No such process
allenb@allenb-P7812 ~ $ 

No podría ser más simple y he estado haciendo esto durante años sin ningún problema.

Allen
fuente
Eso responde a la pregunta "¿cómo puedo empeorarlo?", No a la pregunta "cómo puedo solucionarlo".
Stéphane Chazelas