How to get process id from process name?

I am trying to create a shell script to get the Skype application process id on my Mac.

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

The above works fine, but there are two problems:

1) The grep command will get the whole process if their name just contains "Skype". How can I guarantee that it will only get the result if the process name exactly matches Skype?

2) I would like to make a shell out of it that can be used from the terminal, but the process name should be an argument to this script:

#!/bin/sh ps -clx | grep '$1' | awk '{print $2}' | head -1 

This does not return anything. I think this is due to the fact that $ 2 in awk is considered as an argument. How can i solve this?

+6
source share
8 answers

Your ps -cl1 output is as follows:

  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 

So the last entry on each line is your team. This means that you can use the full power of regular expressions to help you.

$ in the regular expression means the end of the line, so you can use $ to indicate that not only the output should have Skype in it, it should end in Skype . This means that if you have a command called Skype Controller , you wonโ€™t pull it:

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

You can also simplify things by using the ps -o format to just pull up the columns you need:

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

And you can eliminate the head simply by using awk ability to choose your line for you. In awk , NR is your entry number. So you can do this:

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

Damn, now that I think about it, we could also eliminate grep :

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

This is using awk to use regular expressions. If the line contains a regular expression, "Skype $", it will print the first column, and then exit

The only problem is that if you had the Foo Skype team, it would also pick it up. To fix this, you need to do a bit more bizarre work:

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

while read reads two variables. The trick is that read uses a space to separate the variables it reads. However, since there are only two variables, the latter will contain the rest of the entire string. Thus, if the command is a Skype controller, the entire command will be placed in $command , although there is a space in it.

Now we do not need to use a regular expression. We can compare the team with equality.

It is longer to enter, but in reality you use fewer commands and fewer connections. Remember that awk loops through each line. Everything you do here makes it more explicit. In the end, it is actually much more effective than what you originally had.

+14
source

If pgrep available on the Mac, you can use pgrep '^Skype$' . This will display the process ID of all processes called Skype .

You used the wrong quotes in the script:

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

or

 pgrep "^$1$" 
+1
source

The problem with your second example is that $ 1 is in single quotes, which prevents the extension of the bash variable. There is already a utility that does what you want, without manually analyzing ps output.

 pgrep "$1" 
+1
source

I would like to:

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

==== UPDATE ====

Use parameter without quotes and use single quotes for awk

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

You can do this in AppleScript:

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

which means you can use "osascript" to get the PID from the shell script:

 $ 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
source

You can format ps output with -o [field], ... and list by process name with -C [command_name], however ps will still print the column header, which can be removed by linking it with grep -v PID

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

where $ 1 will be the name of the team (in this case Skype)

+1
source

Method 1 - Use awk

I see no reason to use the -l flag (long format), I also see no reason to use grep and awk at the same time: awk has a built-in grep function. Here is my plan: use ps and print only 2 columns: pid and command, then use awk to select what you want:

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

Method 2 - use bash

This method has the advantage that if you are already a script in bash, you do not even need awk, which saves one process. The solution is longer than the other method, but very straightforward.

 #!/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 } 
+1
source

Use double quotes to allow bash to do variable replacements. Single quotes disable the bash variable replacement mechanism.

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

Source: https://habr.com/ru/post/909192/


All Articles