2012-02-23 21 views
6

Sto provando a creare uno script di shell ricevendo l'ID processo dell'applicazione Skype sul mio Mac.Come ottenere l'ID del processo dal nome del processo?

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

Quanto sopra funziona bene, ma ci sono due problemi:

1) Il grep comando otterrebbe tutto il processo se il loro nome contiene solo "Skype". Come posso assicurarmi che ottenga solo il risultato, se il nome del processo è esattamente Skype?

2) desidero fare uno script shell da questo, che può essere usato dal terminale, ma il nome del processo dovrebbe essere un argomento di questo script:

#!/bin/sh 

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

Questo non è restituire qualsiasi cosa. Penso che questo sia dovuto al fatto che lo $ 2 nell'avk sia trattato anche come argomento. Come posso risolvere questo?

risposta

14

tuo ps -cl1 uscita è simile al seguente:

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 

Così, l'ultima voce in ogni linea è il vostro comando. Ciò significa che puoi utilizzare tutta la potenza delle espressioni regolari per aiutarti.

Il $ in un'espressione regolare significa che la fine della stringa, in tal modo, è possibile utilizzare $ per specificare che non solo l'uscita deve avere Skype in esso, deve terminare con Skype. Questo significa che se avete un comando chiamato Skype Controller, non sarà tirarlo su:

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

È inoltre possibile semplificare le cose utilizzando il formato ps -o di tirare solo le colonne che si desidera:

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

E, puoi eliminare head semplicemente usando la capacità di awk di selezionare la tua linea per te. In awk, NR è il numero del tuo record. Così si potrebbe fare questo:

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

Heck, ora che ci penso, potremmo eliminare il grep troppo:

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

Questo sta usando la capacità di awk di usare le espressioni regolari. Se la riga contiene l'espressione regolare, 'Skype $', stamperà la prima colonna, quindi uscirà

L'unico problema è che se si ha un comando Foo Skype, anche questo lo raccoglierà. Per eliminare questo, dovrete fare un po 'gioco di gambe più fantasia:

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

Il while read sta leggendo due variabili. Il trucco è che lo read utilizza lo spazio bianco per dividere le variabili che legge. Tuttavia, poiché ci sono solo due variabili, l'ultima conterrà il resto dell'intera linea. Pertanto, se il comando è Controller Skype, l'intero comando verrà inserito in $command anche se è presente uno spazio.

Ora, non è necessario utilizzare un'espressione regolare. Possiamo confrontare il comando con un'uguaglianza.

Questo è più lungo da digitare, ma in realtà stai utilizzando meno comandi e meno connessioni. Ricorda che awk sta scorrendo attraverso ogni linea. Tutto quello che stai facendo qui è renderlo più esplicito. Alla fine, questo è in realtà molto più efficiente di quello che avevi in ​​origine.

1

Se pgrep è disponibile su Mac, è possibile utilizzare pgrep '^Skype$'. Questo elencherà l'id di processo di tutti i processi chiamato Skype.

hai usato le virgolette sbagliato nello script:

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

o

pgrep "^$1$" 
1

Il problema con il secondo esempio è che il $ 1 è tra virgolette singole, che impedisce bash di espandersi variabile . Esiste già un'utilità che realizza ciò che vuoi senza analizzare manualmente l'output di ps.

pgrep "$1" 
0

Utilizzare le doppie virgolette per consentire a bash di eseguire la sostituzione variabile. Le virgolette singole disabilitano il meccanismo di sostituzione delle variabili bash.

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

sarei così qualcosa di simile:

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

==== ==== UPDATE

Utilizzare il parametro senza virgolette e utilizzare le virgolette singole per awk

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

È possibile farlo in AppleScript:

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

che significa che è possibile utilizzare 'osascript' per ottenere il PID dall'interno di uno script di 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

È possibile formattare l'output di ps con il -o [campo], ...e elenco nominativo processo utilizzando -C [command_name], tuttavia, ps ancora stampare l'intestazione di colonna, che può essere rimosso mediante tubazioni attraverso grep -v PID

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

dove $ 1 sarebbe il nome del comando (in questo caso Skype)

1

Metodo 1 - Utilizzare awk

Non vedo alcuna ragione per usare il flag -l (formato lungo), anche io non vedo alcuna ragione per usare grep e awk allo stesso tempo: awk ha funzionalità integrate in grep.Ecco il mio piano: utilizzare ps e l'uscita solo 2 colonne: PID e di comando, quindi utilizzare awk per scegliere ciò che si vuole:

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

Metodo 2 - Utilizzo bash

Questo metodo ha il vantaggio che se hai già scritto script in bash, non hai nemmeno bisogno di awk, che salva un processo. La soluzione è più lunga dell'altro metodo, ma molto semplice.

#!/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 
} 
Problemi correlati