Run a process to particular/dedicated pid only

26,105

Solution 1

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!).

Solution 2

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.

Solution 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.

Solution 4

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.

Share:
26,105

Related videos on Youtube

gangadhars
Author by

gangadhars

Updated on September 18, 2022

Comments

  • gangadhars
    gangadhars almost 2 years

    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.

    • Admin
      Admin about 10 years
      @Christopher. I think you didn't get my question. Even pkill also do same thing
    • Admin
      Admin about 10 years
      @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?
    • Admin
      Admin about 10 years
      @mreithub. If I have 2, 3 processes with same name, they all die
    • Admin
      Admin about 10 years
      @SGG Ok, use PID files then
    • Admin
      Admin about 10 years
      what do you mean by "PID files" @mreithub
    • Admin
      Admin about 10 years
      Could you first please tell us which processes you want to control? I might give you better guidance then..
    • Admin
      Admin about 10 years
      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
    • Admin
      Admin over 8 years
  • c4f4t0r
    c4f4t0r about 10 years
    i don't know any syscall for reserve a pid and i don't think this can be do it
  • goldilocks
    goldilocks about 10 years
    +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.
  • user131515
    user131515 about 10 years
    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.
  • user
    user about 10 years
    @goldilocks Good point, updated answer to incorporate that.
  • user
    user about 10 years
    +1 for the second half about checking where you are sending the signal.
  • Stéphane Chazelas
    Stéphane Chazelas about 10 years
    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).
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 10 years
    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.
  • goldilocks
    goldilocks about 10 years
    @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
    goldilocks about 10 years
    @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.
  • Stéphane Chazelas
    Stéphane Chazelas about 10 years
    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
    Stéphane Chazelas about 10 years
    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.
  • goldilocks
    goldilocks about 10 years
    @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).
  • Stéphane Chazelas
    Stéphane Chazelas about 10 years
    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)
  • goldilocks
    goldilocks about 10 years
    @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.
  • mr.spuratic
    mr.spuratic over 5 years
    Since (official) kernel v3.3. This method is used by CRIU for PID restoration in process checkpoint and restore, it's flock-able, and requires kernel option CONFIG_CHECKPOINT_RESTORE. See also the link added by Ciro to the question.
  • Admin
    Admin almost 2 years
    @StéphaneChazelas pid: command not found
  • Admin
    Admin almost 2 years
    @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).