¿Manera rápida de verificar si un proceso ya se está ejecutando en segundo plano (y omitir la re-ejecución basada en eso)?


11

¿Puedo hacer una línea de comando bash que solo ejecute cierto comando si el proceso no se está ejecutando (en segundo plano)?

¿Cómo verifico *, si ya se está ejecutando un comando?

(entonces puedo agregar el siguiente comando &&entre ellos para que el siguiente solo se ejecute si el primero es verdadero).

*: prueba, determinar, descubrir, descubrir


3
ps -ef | grep -v grep | grep "process_name" || run_command_here
Rahul Patil

1
@RahulPatil puede usar solo en pgrep "process_name"lugar deps | grep | grep
apresurarse el

hmm, lo olvido ..: D
Rahul Patil

1
¿Por qué no utiliza un archivo de "bloqueo", y cuando se inicia la segunda vez, solo se iniciará cuando desaparezca el archivo de bloqueo.
BitsOfNix

La mejor manera de verificar si existe un proceso: stackoverflow.com/questions/3043978/…
Trevor Boyd Smith

Respuestas:



3

He usado esta técnica de vez en cuando:

$ pgrep <process name> || <process name>

Antes de pgrepque se hiciera de esta manera:

$ ps -eaf | grep -q <[p]rocess name> || <process name>

ejemplo

El bit con el [p]hace que grepno se encuentre como resultado.

$ ps -eaf | grep -q [s]leep || sleep 10

2

Esto puede ser complicado, porque puede tener instancias separadas del mismo proceso que viven independientemente. Por ejemplo, servidores que escuchan en diferentes puertos o servicios que se ejecutan como diferentes usuarios. Para distinguir entre estas instancias, debe asignar a cada una de ellas una etiqueta única. La etiqueta a menudo es un archivo, pero puede ser un socket local en el espacio de nombres abstracto, un puerto TCP, etc., cualquier identificador único servirá. Cuando la etiqueta es un archivo, puede ser un archivo normal que contiene una ID de proceso (un archivo pid) o una tubería o socket con nombre que el archivo está escuchando, etc. Idealmente, la etiqueta es un punto final de comunicación que permite a los clientes conectarse a ese proceso.

Cada uno de estos diferentes tipos de etiquetas da como resultado una forma diferente de verificar si la instancia que está buscando está en funcionamiento. Por ejemplo, con un socket de archivo local, intente conectarse a él e inicie el proceso si no hay ningún proceso escuchando en ese socket. Si la etiqueta es un archivo pid, verifique si hay un proceso con esa ID de proceso, pero tenga en cuenta que es frágil, ya que si el proceso ha muerto, puede haber un proceso no relacionado que haya reutilizado su ID. Tenga en cuenta que si dos clientes intentan alcanzar el proceso en un corto período de tiempo, ambos pueden encontrar que el proceso no existe y ambos intentan iniciarlo; Proteger adecuadamente de esta condición de carrera puede ser complicado.

Es más fácil administrar instancias cuando todas son iniciadas por el mismo proceso de supervisor, y ese proceso de supervisor detecta cuándo mueren las instancias y reacciona en consecuencia. Muchos programas de monitoreo de servicios que pueden hacer esto.

Si el programa no responde en un punto final de comunicación conocido y no es administrado por un programa supervisor, la etiqueta del pobre es un archivo pid: un archivo que contiene la ID del proceso. Cuando comience el proceso, escriba el pid en un archivo con un nombre predeterminado. Cuando necesite que exista el proceso, lea el archivo pid y vea si hay un proceso con ese pid. Cuando elimine el proceso, borre el archivo pid. El problema más importante con un archivo pid no supervisado es que si el proceso muere, su pid puede ser reutilizado por algún proceso no relacionado. Al menos debe verificar el nombre del proceso o el ejecutable del proceso para asegurarse de que está hablando con el proceso correcto. Muchas variantes de Unix tienen un comando pgrep :pgrep SOMENAME enumera los procesos cuyo nombre contiene SOMENAME como una subcadena, con opciones adicionales para limitar a un usuario en particular, para requerir una coincidencia exacta, para cambiar cuál de las varias nociones posibles de "nombre de proceso" se usa, etc.


1

Podrías usar este enfoque:

if [[ -z $(ps -C appname -opid=) ]]; then
    appname && secondapp
fi

1

Otras opciones:

  • pgrep -xq processname
    • Solo coincide con los primeros 15 caracteres en GNU / Linux
    • No incluye ancestros en OS X
  • ps -eo comm= | sed 's|.*/||' | grep -xq processname
    • Solo coincide con los primeros 15 caracteres en GNU / Linux
    • sed 's|.*/||' elimina las partes de nombre de directorio en OS X

En GNU / Linux ps -o commtrunca los nombres de los comandos a 15 caracteres pgrepyyps -C solo coinciden con los primeros 15 caracteres.

ps -C (nombres de comando de coincidencia) no es compatible con OS X.

En OS X ps -o commimprime las rutas absolutas de los comandos y ps -co commsolo imprime los nombres de los comandos. En GNU ps -o commsolo imprime nombres de comandos y -ctiene un significado diferente.

El pgrep de OS X no incluye procesos ancestrales (como bash, Terminal o launchd) sin ellos -a. El pgrep de GNU los incluye por defecto y no es compatible -a.

grep -xy pgrep -xno implique -F, así que úselo -Fxsi el nombre del proceso puede contener caracteres regex.


-C tampoco está disponible en mi cygwin :)
n611x007

1

Lo siento, pero todas estas soluciones no admiten contab ya que la misma línea de comando aparecerá dos veces en el resultado 'ps'.

Entonces aquí está el mío:

## Test pour voir si le même script tourne déjà
## Un fichier .pid est utilisé pour stocké le numéro de process
## Si le pid est en train de tourner alors on sort.
lock_file=$0".pid"
[ -r $lock_file ] && read pid <$lock_file
if [ "$pid" -gt 1 ] && [ `ps --no-headers -p "$pid" | wc -l` -gt 0 ] ; then
    echo "WARNING : le process $pid tourne deja : $0"
    ps -edf | grep `basename $0` | grep -v grep
    echo "WARNING : Arrêt de cette instance ($$)."
    exit 7
fi
echo $$ >$lock_file

¿De qué te arrepientes? ¿Qué es contab? ¿Te refieres a revisar desde un crontrabajo?
Anthon

0

Con Bash

#!/usr/bin/env bash

[[ $# -eq 0 ]] && { echo -e "Usage:\t\t $0 <Process_name>  <Command here>"; exit 1;  }

ifnotrun(){
        local p=$1
        if ! ps -C "$1" -opid=
        then
                cmd=($@)
                echo ${cmd[@]:1}
        else
                echo "Process \"$p\" Already Running.."
                exit 1
        fi

}

ifnotrun $*

Nota: - eliminar echosi la salida se ve bien.


0

Explicaré el caso en el que ejecutas el comando en beckgreoud. El "$!" guarde el PID del último proceso en segundo plano. Por lo tanto, puede usarlo para encontrarlo en las tablas de proceso siguiendo las respuestas anteriores:

sleep 4 &
ps -ef | grep -w  $!  ...

El comando incorporado "jobs" - intente esto:

sleep 4&
J=`jobs`
while [ "$J" ]; do
        sleep 1
        jobs # This line flush the jobs' bufer.
        J=`jobs`
done

En cuanto a la opción "&&"

En lugar de && use el comando wait. En el siguiente ejemplo, myproc2 no se ejecutará hasta que myproc1 termine:

myproc1 &
wait
myproc2

0

Obtenga el estado de su proceso:

ps -lp $(pgrep <YOUR_PROCESS_NAME>) | tail -1 | awk '{print $11}'

Referencia:

D    uninterruptible sleep (usually IO)
R    running or runnable (on run queue)
S    interruptible sleep (waiting for an event to complete)
T    stopped, either by a job control signal or because it is being traced
W    paging (not valid since the 2.6.xx kernel)
X    dead (should never be seen)
Z    defunct ("zombie") process, terminated but not reaped by its parent

Por ejemplo, lo he usado para reproducir o pausar condicionalmente mi proceso de sox en una sesión de tmux:

/usr/local/bin/tmux if-shell -t sox "[ $(ps -lp $(pgrep sox) | tail -1 | awk '{print $11}') == 'T' ]" \
  'send -t sox "fg" Enter' \
  'send -t sox C-z'

-1

Puedes usarlo dentro de un script:

if [ `ps -ef | grep "script.sh" | grep -v grep | wc -l` -gt 1 ] ; then
echo "RUNNING...."
else
echo "NOT RUNNING..."
fi
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.