How can I find a process ID for a process given its name?
Usually a process is referred to using its process ID (PID), and the ps(1) command can display the information for any process given its process ID, e.g.
$ echo $$ # my process id 21796 $ ps -p 21796 PID TTY TIME CMD 21796 pts/5 00:00:00 ksh
But frequently the process ID for a process is not known, but only its name. Some operating systems, e.g. Solaris, BSD, and some versions of Linux have a dedicated command to search a process given its name, called pgrep(1):
$ pgrep init 1
Often there is an even more specialized program available to not just find the process ID of a process given its name, but also to send a signal to it:
$ pkill myprocess
Some systems also provide pidof(1). It differs from pgrep in that multiple output process IDs are only space separated, not newline separated.
$ pidof cron 5392
If these programs are not available, a user can search the output of the ps command using grep.
The major problem when grepping the ps output is that grep may match its own ps entry (try: ps aux | grep init). To make matters worse, this does not happen every time; the technical name for this is a RaceCondition. To avoid this, there are several ways:
- Using grep -v at the end
ps aux | grep name | grep -v grep
will throw away all lines containing "grep" from the output. Disadvantage: You always have the exit state of the grep -v, so you can't e.g. check if a specific process exists. - Using grep -v in the middle
ps aux | grep -v grep | grep name
This does exactly the same, except that the exit state of "grep name" is accessible and a representation for "name is a process in ps" or "name is not a process in ps". It still has the disadvantage of starting a new process (grep -v). - Using [] in grep
ps aux | grep [n]ame
This spawns only the needed grep-process. The trick is to use the []-character class (regular expressions). To put only one character in a character group normally makes no sense at all, because [c] will always match a "c". In this case, it's the same. grep [n]ame searches for "name". But as grep's own process list entry is what you executed ("grep [n]ame") and not "grep name", it will not match itself.
greycat rant: daemon management
All the stuff above is OK if you're at an interactive shell prompt, but it should not be used in a script. It's too unreliable.
Most of the time when someone asks a question like this, it's because they want to manage a long-running daemon using primitive shell scripting techniques. Common variants are "How can I get the PID of my foobard process.... so I can start one if it's not already running" or "How can I get the PID of my foobard process... because I want to prevent the foobard script from running if foobard is already active." Both of these questions will lead to seriously flawed production systems.
If what you really want is to restart your daemon whenever it dies, just do this:
while true; do mydaemon --in-the-foreground done
where --in-the-foreground is whatever switch, if any, you must give to the daemon to PREVENT IT from automatically backgrounding itself. (Often, -d does this and has the additional benefit of running the daemon with increased verbosity.) Self-daemonizing programs may or may not be the target of a future greycat rant....
If that's too simplistic, look into daemontools or runit, which are programs for managing services.
If what you really want is to prevent multiple instances of your program from running, then the only sure way to do that is by using a lock. For details on doing this, see ProcessManagement or FAQ 45.
ProcessManagement also covers topics like "I want to divide my batch job into 5 'threads' and run them all in parallel." Please read it.