2012-02-23 31 views
6

Estoy tratando de crear un script de shell obteniendo el ID de proceso de la aplicación Skype en mi Mac.¿Cómo obtener el ID del proceso del nombre del proceso?

ps-clx | grep 'Skype' | awk '{print $ 2}' | cabeza -1

Lo anterior está trabajando muy bien, pero hay dos problemas:

1) El comando grep obtendría todo proceso si su nombre solo contiene "Skype". ¿Cómo puedo asegurarme de que solo obtenga el resultado si el nombre del proceso es exactamente Skype?

2) Me gustaría hacer un script de shell de esto, que puede ser utilizado desde el terminal, pero el nombre del proceso debería ser un argumento de este script:

#!/bin/sh 

ps -clx | grep '$1' | awk '{print $2}' | head -1 

Esto no es devolviendo algo Creo que esto se debe a que el $ 2 en el awk se trata como un argumento también. ¿Como puedo resolver esto?

Respuesta

14

su salida ps -cl1 se ve así:

UID PID PPID  F CPU PRI NI  SZ RSS WCHAN  S    ADDR TTY   TIME CMD 
    501 185 172  104 0 31 0 2453272 1728 -  S ffffff80145c5ec0 ??   0:00.00 httpd 
    501 303  1 80004004 0 31 0 2456440 1656 -  Ss ffffff8015131300 ??   0:11.78 launchd 
    501 307 303  4004 0 33 0 2453456 7640 -  S ffffff8015130a80 ??   0:46.17 distnoted 
    501 323 303 40004004 0 33 0 2480640 9156 -  S ffffff80145c4dc0 ??   0:03.29 UserEventAgent 

por lo tanto, la última entrada de cada línea es su comando. Eso significa que puedes usar toda la potencia de las expresiones regulares para ayudarte.

El $ en una expresión regular significa el final de la cadena, por lo tanto, se puede utilizar para especificar $ que no sólo la salida debe tener Skype en ella, se debe terminar con Skype. Esto significa que si tiene un comando llamado Skype Controller, no se tire hacia arriba:

ps -clx | grep 'Skype$' | awk '{print $2}' | head -1 

También puede simplificar las cosas mediante el formato de ps -o simplemente tire hacia arriba de las columnas que desea:

ps -eo pid,comm | grep 'Skype$' | awk '{print $1}' | head -1 

Y, puede eliminar head por el simple uso awk 's capacidad de seleccionar su línea para usted. En awk, NR es su número de registro. De esta manera usted puede hacer esto:

ps -eo pid,comm | grep 'Skype$' | awk 'NR == 1 {print $1}' 

Heck, ahora que pienso en ello, podríamos eliminar la grep también:

ps -eo pid,comm | awk '/Skype$/ {print $1; exit}' 

Se trata de utilizar la capacidad de awk para utilizar expresiones regulares. Si la línea contiene la expresión regular, 'Skype $', imprimirá la primera columna, luego saldrá de

El único problema es que si tiene un comando Foo Skype, también lo recuperará. Para eliminar eso, usted tiene que hacer un poco juego de piernas más elegante:

ps -eo pid,comm | while read pid command 
do 
    if [[ "$command" = "Skype" ]] 
    then 
     echo $pid 
     break 
    fi 
done 

El while read es la lectura de dos variables. El truco es que read usa espacios en blanco para dividir las variables que lee. Sin embargo, dado que solo hay dos variables, la última contendrá el resto de la línea completa. Así, si el comando es controlador Skype, todo el comando será puesto en $command a pesar de que hay un espacio en él.

Ahora, no tenemos que usar una expresión regular. Podemos comparar el comando con una igualdad.

Esto es más largo para escribir, pero en realidad está usando menos comandos y menos tuberías. Recuerde awk está pasando por cada línea. Todo lo que haces aquí es hacerlo más explícito. Al final, esto es en realidad mucho más eficiente que lo que originalmente tenías.

1

Si pgrep está disponible en Mac, puede usar pgrep '^Skype$'. Esto mostrará la identificación del proceso de todos los procesos llamados Skype.

Se utilizan las comillas equivocadas en el script:

ps -clx | grep "$1" | awk '{print $2}' | head -1 

o

pgrep "^$1$" 
1

El problema con el segundo ejemplo es que el $ 1 es entre comillas simples, lo que impide fiesta de la expansión de la variable . Ya existe una utilidad que logra lo que desea sin analizar manualmente la salida ps.

pgrep "$1" 
0

Usa las comillas dobles para permitir que bash realice la sustitución de variables. Comillas simples deshabilitan el mecanismo de sustitución de variables bash.

ps -clx | grep "$1" | awk "{print $2}" | head -1 
1

que había así que algo como:

ps aux | grep Skype | awk 'NR==1 {print $2}' 

ACTUALIZACIÓN ==== ====

Utilice el parámetro sin comillas y utilizar comillas simples para awk

#!/bin/bash 
ps aux | grep $1 | awk 'NR==1 {print $2}' 
1

Puede hacer esto en AppleScript:

tell application "System Events" 
    set skypeProcess to the process "Skype" 
    set pid to the unix id of skypeProcess 
    pid 
end tell 

que significa que puede utilizar 'osascript' para obtener el PID de un script de shell:

$ osascript -e "tell application \"System Events\"" -e "set skypeProcess to the process \"Skype\"" -e "set pid to the unix id of skypeProcess" -e "pid" -e "end tell" 
3873 
1

puede dar formato a la salida de ps utilizando el -o [campo], ...y lista por nombre de proceso utilizando -C [command_name], sin embargo, ps todavía imprimir el encabezado de la columna, que puede ser eliminado por tuberías a través de -v grep PID

ps -o pid -C "$1" |grep -v PID 

donde $ 1 sería el nombre del comando (en este caso Skype)

1

Método 1 - Utilice awk

No veo ninguna razón para utilizar la opción -l (formato largo), también no ven ninguna razón para utilizar grep y awk al mismo tiempo: awk tiene capacidad grep integrada.Aquí está mi plan: utilizar ps y de salida sólo 2 columnas: PID y de comandos, a continuación, utilizar awk para escoger lo que quiere:

ps -cx -o pid,command | awk '$2 == "Skype" { print $1 }' 

Método 2 - Uso fiesta

Este método tiene la ventaja de que si ya tienes el script en bash, ni siquiera necesitas awk, lo que salva un proceso. La solución es más larga que el otro método, pero muy directa.

#!/bin/bash 

ps -cx -o pid,command | { 
    while read pid command 
    do 
     if [ "_$command" = "_$1" ] 
     then 
      # Do something with the pid 
      echo Found: pid=$pid, command=$command 
      break 
     fi 
    done 
} 
Cuestiones relacionadas