8

I have a c program executable or shell script which I want to run very often. If I want to stop/pause or to notify something I will send signal to that process. So every time I have to check the pid of that process and I have to use kill to send a signal.

Every time I have to check pid and remembering that upto system shutdown, really bad. I want that process has to run on particular pid only like init always run on 1.

Is there any C api for that? and Also needed script for bash program.

imz -- Ivan Zakharyaschev
  • 15,113
  • 15
  • 61
  • 123
gangadhars
  • 697
  • 3
  • 15
  • 21
  • @Christopher. I think you didn't get my question. Even `pkill` also do same thing – gangadhars May 22 '14 at 12:16
  • 1
    @SGG There's no way to set a processes PID. That would cause all kinds of trouble. But you can use `killall` instead of `kill` which takes a program name instead of its PID. Or does your program name change that often? – mreithub May 22 '14 at 12:18
  • @mreithub. If I have 2, 3 processes with same name, they all die – gangadhars May 22 '14 at 12:21
  • 1
    @SGG Ok, use PID files then – mreithub May 22 '14 at 12:22
  • what do you mean by "PID files" @mreithub – gangadhars May 22 '14 at 12:23
  • Could you first please tell us which processes you want to control? I might give you better guidance then.. – mreithub May 22 '14 at 12:24
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/14671/discussion-between-sgg-and-mreithub). – gangadhars May 22 '14 at 12:25
  • In /var/run, daemons typically creates files by their own name containing their own PID. E.g. if the ftpd-deamon has 1234 as it's PID, then there is a file called /var/run/ftpd containing the text 1234. The file should be deleted by the deamon when it exits. This way the deamon itself, new instances which is attempting to start (but can't because a deamon already exists), and other programs which need to know about the daemon; can both see if the daemon is running and which PID it has. – Baard Kopperud May 22 '14 at 12:29
  • 1
    Note that just looking at the pid file is not enough to know if the process is running. If the power died, the file would be left behind so you should read the pid in the file and then check that a process with that pid is running. Of course, even this isn't fool-proof as another process may have started with the same pid... See Goldilock's answer for how to check it's the right process – Basic May 22 '14 at 18:35
  • http://stackoverflow.com/questions/18122592/how-to-set-process-id-in-linux-for-an-specific-program – Ciro Santilli OurBigBook.com Dec 19 '15 at 14:55

5 Answers5

13

I don't think you can reserve or assign PIDs. However, you could start your process in a script like this:

myprocess &
echo "$!" > /tmp/myprocess.pid

This creates a "pid file", as some other people have referred to it. You can then fetch that in bash with, e.g., $(</tmp/myprocess.pid) or $(cat /tmp/myprocess.pid).

Just beware when you do this that if the process died and the pid was recycled, you'll be signalling the wrong thing. You can check with:

pid=$(cat /tmp/myprocess.pid)
if [ "$(ps -o comm= -p "$pid")" = "myprocess" ]; then
    ...send your signal...
else echo "Myprocess is dead!"
fi

See comments if "$(ps -o comm= -p "$pid")" looks strange to you. You may want to do a more vigorous validation if there is a chance of someone doing something devious with the content of /tmp/myprocess.pid (which should not be writeable by other users!).

goldilocks
  • 86,451
  • 30
  • 200
  • 258
  • +1 for the second half about checking where you are sending the signal. – user May 22 '14 at 13:12
  • Why wouldn't you want to add a newline? Without it, you obtain a non-text file. Use `printf` instead of `echo -n`, not all implementations of `echo` support `-n`. Use `=` instead of `==`, `comm` instead of `cmd`, `$(cat<` instead of `$(<` for portability (and quote your variables). – Stéphane Chazelas May 22 '14 at 19:04
  • The `-n` switch to `echo` is pointless here. It's perfectly fine to have a newline after the number, and in fact it's preferable because otherwise the pidfile wouldn't be a text file and some utilities might choke on it. – Gilles 'SO- stop being evil' May 22 '14 at 23:10
  • @Gilles Dunno where I acquired this issue with newlines in pid files but after observing 1) they generally do have such and 2) I can't cause a problem with same, I've taken that bit out! – goldilocks May 23 '14 at 09:23
  • @StephaneChazelas Thx. Corrections made regarding POSIX-yness and obsolete sort keys, see also my preceding comment to Gilles. The only variables I did not quote were `$!` and `$pid` inside `"$(ps ....`, since if `$pid` is empty there the `if` will fail properly anyway. – goldilocks May 23 '14 at 09:27
  • Leaving a variable unquoted is the split+glob operator. You have no reason to invoke it here. Also bear in mind that the behaviour of the _split_ part of that operator varies with the current value of `$IFS`. – Stéphane Chazelas May 23 '14 at 10:24
  • 2
    Note that processes can change their names and another process can start with the same pid and name. Another option could be to record the output of `pid -o lstart= -p "$!"` (if on Linux) in the pid file and compare when it comes to killing the process. – Stéphane Chazelas May 23 '14 at 10:39
  • @StéphaneChazelas Are you saying that the `$pid` in `"$(ps -o comm= -p $pid)"` should be quoted? How can I do that? If there's a way, this should be a short Q&A... If not, I could see performing some other validation first, in case someone tries to do something exploitative with the pid file content (in fact, such validation might be the best idea). – goldilocks May 29 '14 at 11:40
  • Not sure what you mean. _I_ meant _quoted_ as in `"$(ps -o comm= -p "$pid")"` and `echo "$!"` (as the usual way to disable the split+glob operator) – Stéphane Chazelas May 29 '14 at 11:53
  • @StéphaneChazelas O_O -> `"$(ps -o comm= -p "$pid")"` I notice this works, but to me it looks like a concatenation with `$pid` still unquoted. So (instead of concatenation) the shell first expands `"$pid"` inside the rest of the expression? Anyway, I'll take your word on it and have applied the edits. – goldilocks May 29 '14 at 12:47
  • @StéphaneChazelas pid: command not found – TheTechRobo the Nerd Jul 14 '22 at 17:11
  • @TheTechRoboStandsforUkraine Based on the options (`-o lstart=`) I think it is safe to assume that should be `ps`, not `pid` (in SC's second comment above). – goldilocks Jul 16 '22 at 14:04
6

Fixing the pid is definitely the wrong solution to your problem, but note that with some versions of Linux, you can get a better chance to obtain the pid you'd like by writing a value to /proc/sys/kernel/ns_last_pid:

echo 9999 | sudo tee /proc/sys/kernel/ns_last_pid; ps -C ps
9999
  PID TTY          TIME CMD
10000 pts/3    00:00:00 ps

That only works if the pid 10000 is not already in use (and there's been no pid or thread creation between the time you write to ns_last_pid and you spawn a process/thread).

Otherwise, you can always fork until you get the pid you like.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • Since (official) kernel v3.3. This method is [used by CRIU for PID restoration](https://criu.org/Pid_restore) in process checkpoint and restore, it's flock-able, and requires kernel option `CONFIG_CHECKPOINT_RESTORE`. See also [the link added](https://stackoverflow.com/questions/18122592/how-to-set-process-id-in-linux-for-a-specific-program/24224902) by Ciro to the question. – mr.spuratic Sep 27 '18 at 13:01
3

Something similar to what you want to do is normally done by the process early in its lifecycle writing out its own pid (which can be obtained through getpid(2)) to a file with a known name. In general-use daemons the name of this file is often configurable, but in a special-use software you can probably get along with hardcoding it. (I strongly suggest at least using a macro for it, however.)

PID files are normally placed in /var/run or /run, but can be placed in other locations as well including /tmp. The "proper" location according to the Filesystem Hierarchy Standard is in /run, but /var/run also sees significant use (and on many modern systems is the same as /run) and /tmp don't require root privileges on startup (which system daemons very often have before they drop privileges).

That file can then be read through a variety of means to obtain the PID of the process in question, in order to send a signal to it process in question.

user
  • 28,161
  • 13
  • 75
  • 138
  • +1 Note `/var` and `/run` require privileges to write to (which system daemons usually have, at least at start-up). If you don't want to do that, `/tmp`, or some custom location, is fine. – goldilocks May 22 '14 at 12:49
  • @goldilocks Good point, updated answer to incorporate that. – user May 22 '14 at 13:12
1

You can not set the PID, but you can set the PGID: create or join a process group. Then you can send signals to this dedicated process group.


I had the impression that the new systemd init system has some automation on this part, which is superior to having the process to write its PID to a PID file and then using it for controlling it.

systemd seems to switch to a "process group" (as I can understand this) before starting a controlled process, and then everything is in this group. So, you can control all the child processes by remembering the special "group".

  • If it functions like, this is superior to having the process to write out its PID, because you don't need to modify the program.

  • It might also be better then:

    myprocess & echo $! > /tmp/myprocess.pid

because this approach captures all the children of that process, too.

I don't have a detailed documentation at hand to support my words, but here is the general idea of what systemd needs from cgroups,a nd this seems to match my impression:

Control Groups are two things: (A) a way to hierarchally group and label processes, and (B) a way to then apply resource limits to these groups. systemd only requires the former (A), and not the latter (B). That means you can compile your kernel without any control group resource controllers (B) and systemd will work perfectly on it. However, if you in addition disable the grouping feature entirely (A) then systemd will loudly complain at boot and proceed only reluctantly with a big warning and in a limited functionality mode.

imz -- Ivan Zakharyaschev
  • 15,113
  • 15
  • 61
  • 123
0

System level daemon are assigned as per the sequence of start during boot time. I believe assigning a fixed pid to particular process is not possible because it is getting assigned by the Kernel as per the system load and other dependencies.

But using system call we may assign a fixed PID to the process. But no idea how can it be achieved.

dina3e
  • 19
  • 1
  • i don't know any syscall for reserve a pid and i don't think this can be do it – c4f4t0r May 22 '14 at 12:34
  • 1
    This answer does not seem to add anything to answers already posted. Maybe you could add some detail in order to make it better than other answers. As it stands, it seems to be just a rephrasing of previous answers. –  May 22 '14 at 13:08
  • 1
    It is impossible to choose the PID of a process. The only exception is PID 1 which is assigned to the first process that is started when the system boots. – Gilles 'SO- stop being evil' May 22 '14 at 23:09