- How to get process ID of background process?
- 9 Answers 9
- linux — get pid of process
- 2 Answers 2
- How to Find the PID and PPID of a Process in Linux
- Linux process basics
- What is a PID?
- What is a PPID?
- Getting the PID of a process
- Getting PPID from a child process’s PID
- Checking the PID and PPID of the currently running process
- Wrapping up
How to get process ID of background process?
I start a background process from my shell script, and I would like to kill this process when my script finishes. How to get the PID of this process from my shell script? As far as I can see variable $! contains the PID of the current script, not the background process.
9 Answers 9
You need to save the PID of the background process at the time you start it:
foo & FOO_PID=$! # do other stuff kill $FOO_PID
You cannot use job control, since that is an interactive feature and tied to a controlling terminal. A script will not necessarily have a terminal attached at all so job control will not necessarily be available.
Since $! returns the last background process’s pid. Is it possible that something starts between foo and $! , and we get that something’s pid instead of foo ‘s?
@WiSaGaN: No. There is nothing between those lines. Any other activity on the system will not affect this. $! will expand to the PID of the last background process in that shell.
. which hoses you if foo happens to be multiple piped commands (eg. tail -f somefile.txt | grep sometext ). In such cases, you will get the PID of the grep command from $! rather than the tail command if that’s what you were looking for. You will need to use jobs or ps or the likes in this instance.
@JohnRix: Not necessarily. You will get the pid of grep , but if you kill that, tail will get a SIGPIPE when it tries to write to the pipe. But as soon as you try to get into any tricky process management/control, bash/shell becomes quite painful.
Another worthy solution is suggested in (a comment to an answer to) How to get pid of just started process: oh, and the «oneliner»: /bin/sh -c ‘echo $$>/tmp/my.pid && exec program args’ & – sysfault Nov 24 ’10 at 14:28
You can use the jobs -l command to get to a particular jobL
^Z [1]+ Stopped guard my_mac:workspace r$ jobs -l [1]+ 46841 Suspended: 18 guard
In this case, 46841 is the PID.
-l Report the process group ID and working directory of the jobs.
jobs -p is another option which shows just the PIDs.
@Phil To list pids only : jobs -p. To list pid of a certain job: jobs -p %3. No need to process output.
@Erik with different commands / arguments you change the context of my comment. Without the additional argument suggested the output requires processing. Suggest an improvement to the answer!
Saving the PID from $! just after you started it is more portable and more straightforward in most situations. That’s what the currently accepted answer does.
@Calimo I agree that jobs is the way to go in an interactive session, but this is posted as an answer to a question specifically about how to do this programmatically from a script.
Here’s a sample transcript from a bash session ( %1 refers to the ordinal number of background process as seen from jobs ):
$ echo $$ 3748 $ sleep 100 & [1] 192 $ echo $! 192 $ kill %1 [1]+ Terminated sleep 100
Note that $$ is not always the current PID. For example, if you define a new function in bash and run the function in the background, the $$ within that function contains the PID of the process that started the function in the background. If you need PID of the actual process running any given code, you have to use $BASHPID , instead.
An even simpler way to kill all child process of a bash script:
The -P flag works the same way with pkill and pgrep — it gets child processes, only with pkill the child processes get killed and with pgrep child PIDs are printed to stdout.
@lepe: Not quite. If you are a grandparent, this won’t work: after bash -c ‘bash -c «sleep 300 &»‘ & running pgrep -P $$ shows nothing, because the sleep will not be a direct child of your shell.
@AlexeyPolonsky: it should be: kill all child procs of a shell, not a script. Because $$ refers to the current shell.
performing bash -c ‘bash -c «sleep 300 &»‘ & ; pgrep -P $$ , I get on stdout [1]
Even processes can deattach them from parent process. Simple trick is to call fork (create a grandchild) and then just let the child process exit while grandchild continues doing the work. (daemonization is the keyword) But even if child keeps running too pkill -P isn’t enough to propagate signal to grandchilds. Tool like pstree is required to follow whole dependant process tree. But this won’t catch daemons started from the process as their parent is process 1. eg: bash -c ‘bash -c «sleep 10 & wait $!»‘ & sleep 0.1; pstree -p $$
this is what I have done. Check it out, hope it can help.
#!/bin/bash # # So something to show. echo "UNO" > UNO.txt echo "DOS" > DOS.txt # # Initialize Pid List dPidLst="" # # Generate background processes tail -f UNO.txt& dPidLst="$dPidLst $!" tail -f DOS.txt& dPidLst="$dPidLst $!" # # Report process IDs echo PID=$$ echo dPidLst=$dPidLst # # Show process on current shell ps -f # # Start killing background processes from list for dPid in $dPidLst do echo killing $dPid. Process is still there. ps | grep $dPid kill $dPid ps | grep $dPid echo Just ran "'"ps"'" command, $dPid must not show again. done
Then just run it as: ./bgkill.sh with proper permissions of course
root@umsstd22 [P]:~# ./bgkill.sh PID=23757 dPidLst= 23758 23759 UNO DOS UID PID PPID C STIME TTY TIME CMD root 3937 3935 0 11:07 pts/5 00:00:00 -bash root 23757 3937 0 11:55 pts/5 00:00:00 /bin/bash ./bgkill.sh root 23758 23757 0 11:55 pts/5 00:00:00 tail -f UNO.txt root 23759 23757 0 11:55 pts/5 00:00:00 tail -f DOS.txt root 23760 23757 0 11:55 pts/5 00:00:00 ps -f killing 23758. Process is still there. 23758 pts/5 00:00:00 tail ./bgkill.sh: line 24: 23758 Terminated tail -f UNO.txt Just ran 'ps' command, 23758 must not show again. killing 23759. Process is still there. 23759 pts/5 00:00:00 tail ./bgkill.sh: line 24: 23759 Terminated tail -f DOS.txt Just ran 'ps' command, 23759 must not show again. root@umsstd22 [P]:~# ps -f UID PID PPID C STIME TTY TIME CMD root 3937 3935 0 11:07 pts/5 00:00:00 -bash root 24200 3937 0 11:56 pts/5 00:00:00 ps -f
linux — get pid of process
How can I get the PID of a service called abc using C++ on Linux without using a system call? I would appreciate any examples that you care to offer.
The only way you can learn information about the world outside your process’s address space is by making a system call. What are you really trying to achieve?
2 Answers 2
Since use of sysctl has been discouraged for ages now, the recommended way of doing this is by examining each of the process entries in /proc and reading the comm file in each folder. If, for your example, the contents of that file are abc\n , that’s the process you’re looking for.
I don’t really speak C++, but here’s a possible solution in POSIX C89:
#include #include #include #include pid_t find_pid(const char *process_name) < pid_t pid = -1; glob_t pglob; char *procname, *readbuf; int buflen = strlen(process_name) + 2; unsigned i; /* Get a list of all comm files. man 5 proc */ if (glob("/proc/*/comm", 0, NULL, &pglob) != 0) return pid; /* The comm files include trailing newlines, so. */ procname = malloc(buflen); strcpy(procname, process_name); procname[buflen - 2] = '\n'; procname[buflen - 1] = 0; /* readbuff will hold the contents of the comm files. */ readbuf = malloc(buflen); for (i = 0; i < pglob.gl_pathc; ++i) < FILE *comm; char *ret; /* Read the contents of the file. */ if ((comm = fopen(pglob.gl_pathv[i], "r")) == NULL) continue; ret = fgets(readbuf, buflen, comm); fclose(comm); if (ret == NULL) continue; /* If comm matches our process name, extract the process ID from the path, convert it to a pid_t, and return it. */ if (strcmp(readbuf, procname) == 0) < pid = (pid_t)atoi(pglob.gl_pathv[i] + strlen("/proc/")); break; >> /* Clean up. */ free(procname); free(readbuf); globfree(&pglob); return pid; >
Caveat: if there are multiple running processes with the name you’re looking for, this code will only return one. If you’re going to change that, be aware that with the naive glob written, you’ll also examine /proc/self/comm , which could potentially lead to a duplicate entry.
If there are multiple processes with the same name, there isn’t really a way to ensure you got the right one. Many daemons have the ability to save their pids to a file for this reason; check your documentation.
How to Find the PID and PPID of a Process in Linux
Knowing the PID and PPID of a process can be helpful if you need to manage or interact with a process running on your system.
There are numerous ways to get the PID (Process ID) and PPID (Parent Process ID) of a given process in Linux.
Command | Description |
---|---|
pidof process_name | Works with exact process name |
pgrep process_name | Returns PID of all matches |
ps -o ppid= -p PID | Get the PPID from PID |
$$ | PID of current process/shell |
$ | PID of current process’s parent |
I’ll explain these commands in detail but before that a quick recap of process, PID and PPID.
Linux process basics
Everything that runs on your system is ran via something known as a process, with that simply being the running instance of a program.
All the processes that run on your system are assigned identifiers. These can be helpful if you want to monitor the process (for example, such as to see how much memory or CPU it is using), or maybe if you want to end it if it starts to hang or just act a bit funky.
The identifiers that get attached to all these processes are known as PIDs and PPIDs.
What is a PID?
PID stands for «process ID». Again, this is simply the identifier that gets attached to a program when it starts running, and can be helpful if you need to interact with the process in one way or another.
What is a PPID?
PPID is quite closely related to a PID. PPID stands for «parent process ID», and if you didn’t get it already, it simply stands for the process that created the process you are checking.
For example, let’s say that we have two processes. One is named «spawner», and has a process ID (or PID) of 7234. Our second process, «email client», has a process ID of 7456 when we create it. Our spawner program starts our email client, resulting in our email client having a PID of 7456, and a PPID of 7234, since the spawner (which had the PID of 7234) is what spawned the email client.
Now that you have brushed up your basic, let’s see how to get the process ID in Linux.
Getting the PID of a process
The important thing here is to know the name of the process whose PID you want to find.
If you know the exact process name, you can get its process ID using the pidof command:
Easier said than done because you may not always know the exact process name. Good thing here is that pidof command works with tab completion so if you know the starting few letters of the process name, you can hit tab to get matching suggestions.
However, that may not always work if the process name doesn’t match to what you think it is called. For example, the process for Edge browser on Linux is called msedge . It doesn’t start with ‘edge’ and the tab completion won’t work if you focus on ‘edge’.
So, what you can do is to resort to the ps command in Linux to list all the running processes from all users and then use grep on the output to filter the result.
ps aux | grep -i partial_process_name
There is a dedicated command that combines the features ps and grep command and it is unsurprisingly called pgrep:
pgrep partial_or_exact_process_name
The default output shows only the PIDs without any information on the process. This could be troublesome if there is more than one process IDs returned for your searched term.
Hence, I suggest using the listing feature to make sure that you are getting the PID of the desired process.
pgrep -l partial_or_exact_process_name
You may also use the top command to get the process information but it cannot be used in scripts.
You can use the pstree command to get the PIDs of all running process on your Linux system: pstree -p -a
Getting PPID from a child process’s PID
Once you know the PID of a process, it is effortless to find the PPID for that process.
You can simply run the following command, replacing PID with the current process (child) ID:
In a shell, the above command and $ should both return the same output:
And that’s about everything there is to finding PIDs and PPIDs!
Checking the PID and PPID of the currently running process
If you’re in a shell such as Bash, it’s extremely easy to find the PID and PPID of the calling process (which will usually be the shell).
Bash stores the PID’s value under the $$ variable, and the PPID under the $ variable:
And it’s that easy! Finding the PIDs and PPIDs of other processes isn’t much harder either.
Wrapping up
You should now know everything you need to find both PIDs and PPIDs for running processes on your system.
If you need any help getting something working, or just got some remaining questions, feel free to leave that and anything else in the comments below.