Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get process id from process name?

Tags:

grep

bash

macos

awk

I'm trying to create a shell script getting the process id of the Skype app on my Mac.

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

The above is working fine, but there are two problems:

1) The grep command would get all process if their name just contains "Skype". How can I ensure that it only get the result, if the process name is exactly Skype?

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

#!/bin/sh

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

This isn't returning anything. I think this is because the $2 in the awk is treated as an argument too. How can I solve this?

like image 261
dhrm Avatar asked Feb 23 '12 15:02

dhrm


People also ask

How do I list a process by name?

Open the terminal window or app. To see only the processes owned by a specific user on Linux run: ps -u {USERNAME} Search for a Linux process by name run: pgrep -u {USERNAME} {processName} Another option to list processes by name is to run either top -U {userName} or htop -u {userName} commands.

How do I find the current process ID in Linux?

You can get the process ID of a process by calling getpid . The function getppid returns the process ID of the parent of the current process (this is also known as the parent process ID).

Which is the process ID?

A process ID is a unique, positive number that represents a process. Because the process ID is a unique identifier, it can be used to direct signals between processes.


2 Answers

Your ps -cl1 output looks like this:

  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

Thus, the last entry in each line is your command. That means you can use the full power of regular expressions to help you.

The $ in a regular expression means the end of the string, thus, you could use $ to specify that not only does the output must have Skype in it, it must end with Skype. This means if you have a command called Skype Controller, you won't pull it up:

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 want:

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

And, you can eliminate head by simply using awk's ability to select your line for you. In awk, NR is your record number. Thus you could do this:

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

Heck, now that I think of it, we could eliminate the grep too:

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

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

The only problem is that if you had a command Foo Skype, this will also pick it up. To eliminate that, you'll have to do a bit more fancy footwork:

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

The while read is reading two variables. The trick is that read uses white space to divide the variables it reads in. However, since there are only two variables, the last one will contain the rest of the entire line. Thus if the command is Skype Controller, the entire command will be put into $command even though there's a space in it.

Now, we don't have to use a regular expression. We can compare the command with an equality.

This is longer to type in, but you're actually using fewer commands and less piping. Remember awk is looping through each line. All you're doing here is making it more explicit. In the end, this is actually much more efficient that what you originally had.

like image 95
David W. Avatar answered Sep 21 '22 15:09

David W.


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

You used the wrong quotes in your script:

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

or

pgrep "^$1$"
like image 39
Sven Marnach Avatar answered Sep 22 '22 15:09

Sven Marnach