[SOLVED] Using "$!" to get the PID of the Last Ran Background Process

Hello All,

I was looking into creating a script that would be used only to start a Daemon and create a lock file...
F.Y.I. It's for Nagios' NRPE Daemon Plugin...

Anyway when I run the command to start the Daemon (below):

/usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d

And try to get the PID of that Command just ran by adding this to the end of that line above:

...-c nrpe.cfg & echo $!

The PID it prints out is NOT the PID of the NRPE Daemon. Am I not using the "echo $!" correctly...?

On one of the boxes im trying this on, which is SLES 11.1 (Bash), the PID it prints out is one number
less then what the actual PID of the Daemon is.

For Example:

 # /usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d & echo $!
[1] 27329
27329



# ps -ef | grep [/]usr/local/nagios/bin/nrpe
nagios   27330     1  0 15:20 ?        00:00:00 /usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d

I thought maybe it was just a coincidence, so I tried it a few more times, and still it does the same thing.
So I figured I would just implement this one and just subtract 1 from the PID it gives me to
get the real PID, but I then tried this same thing on an AIX server and the actual PID was completely random. So
I decided not to do that (probably wouldn't have been a good idea anyway)...

Does anyone know what I'm doing wrong, or if there is a better way to get this PID (without doing the 'ps -ef | grep ...')..??

Any thoughts would be great!

Thanks in Advance,
Matt

The "&" will background the task. The ";" will let you type another command on the same line.
Maybe try:

/usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d & ; echo $!

Btw. The output you were seeing did not come from the "echo" (which never executed), it came from the "&".

Hey Methyl, thanks for the reply.

Tried that on both different OS'es and still not getting it for that command just ran...

# /usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d ; echo $!
598184
# ps -ef | grep -v grep | grep nrpe
  nagios 585858      1   0 16:07:57      -  0:00 /usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d

Thanks Again,
Matt

Are you backgrounding the task with a "&" or not? The command just posted does not contain "&".
If you are not backgrounding the process, the value of "$!" is irrelevant in this context.

Hey Sorry must have had a typo when I entered it...
Now it gives an error. I guess you can't use "&" and ";" one right after the other?

# /usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d & ; echo $!
-bash: syntax error near unexpected token `;'

/usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d & ; echo $!
ksh: 0403-057 Syntax error: `newline or ;' is not expected.

Thanks Again,
Matt

When posting, please remember to post what Operating System and version your are running and what Shell you are using.

Though there is nothing obvious wrong with the original command, try:

nohup /usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d &
echo $!

The "nohup" is to answer the next post in advance.

Hey Methyl, thanks again for the reply.

In my original question I posted both Operating Systems that I have been testing on (i.e. SLES 11.1 (Bash v3.2.51) -and- AIX 6 (KSH))...
I guess I should have made it a little more noticeable, sorry about that...

Also, on the AIX one I have installed Bash version 3.2.16(1), which is what I've been using to write my scripts.

Thanks for your suggestion I'll give it a try and post back...
Also, before that, I wanted to mention that I'm ssh'ed into the SLES server and opened up my script using:

# gedit myScript &
# echo $!
30398
# ps -ef | grep [g]edit
root     30398 30317  0 09:42 pts/0    00:00:00 gedit checkNRPE

As you can see it actually worked this time!
This leads me to believe that possibly another "background process" (or something like that) is begin started when
I issue the command to start the Daemon...?

Does this sound like a possibility..?

Thanks Again,
Matt

---------- Post updated at 11:38 AM ---------- Previous update was at 09:59 AM ----------

Hello Again,

I just tried your command (with the 'nohup') and still getting the same results.

Here is the exact output when issuing those commands:

# nohup /usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d &
[1] 2927
nohup: ignoring input and appending output to `nohup.out`
# echo $!
2927
[1]+  Done                    nohup /usr/local/nagios/bin/nrpe -c /usr/local/nagios/etc/nrpe.cfg -d
# ps -ef | grep 2927
root      2937  2431  0 11:31 pts/4    00:00:00 grep 2927

So I'm guessing there is something weird going on within that command when I execute it...

I'm thinking of just starting the Daemon from within a Bash script, then within that script
just find the PID after it's started and write it to a file...

Thanks Again for Your Help,
Matt

I don't see anything wrong there. You see that [1]+ Done ? The command is completing and returning before you run ps.

It's probably forking a copy of itself so it can put itself in the background automatically and return instead of hanging your shell. Daemons do that so often they call it 'daemonizing'. You might need another way to find its PID.

Look in /var/run/ for a file which might belong to it. Daemon processes often store their PID in a file somewhere under there for reference.

p.s. Here's a trick to stop grep from matching itself in a ps listing. ps | grep '[1]234'

1 Like

I would agree with Corona688; the behaviour you describe fits to a process "forking itself into background". This means, you don't need the "&" in your command; run it, see it finish, and still see the daemon (with a PID higher by one on a calm system or "random" on a busy system) show up in ps.

1 Like

When you run a pipeline in the background with & , the value assigned to $! is the pid returned by the fork() system call that the shell used to create the pipeline's last command's process (nrpe in this simple, single-command case).

If that last command itself forks (as nrpe does during daemonization) the value of $! will be the pid of the parent resulting from this second fork.

From nrpe.c @ sourceforge

349 	/* else daemonize and start listening for requests... */
350 	else if(fork()==0){

After that fork(), the parent has nothing more to do and exits, while the child goes on to do the work of nrpe. This exiting parent process is the child process whose pid was saved in $! .

In the code there's a write_pid_file() function (line 1594) which refers to a "pid_file" config variable (line 581). You may want to have a look to see if you've set it to something. If not, do so and you can get the pid there.

I have never used nrpe. My pid config file suggestion is based solely on the code and not on experience.

Regards,
Alister

---------- Post updated at 04:49 PM ---------- Previous update was at 04:07 PM ----------

Some fork() implementations do not generate sequential pid values. I believe AIX is one of those. I am certain OpenBSD is.

Regards,
Alister

1 Like

Hey Corona, RudiC and alister, thanks for the replies!

Hey guys, great explanations!
Thanks alot for clarifying all this.... It makes much more sense to me now. I was kinda under the assumption that something
else was getting called from within the script (i.e. forking).

Alister,
Did you have to decompile nrpe in order to look at the code? I think I remember trying to look at it before and
it was definitely looking like compiled code (i.e. probably C, I think??)..?

Well anyway, thanks again guys for ALL your help with this..!!!

Thanks Again,
Matt

---------- Post updated at 10:35 AM ---------- Previous update was at 09:44 AM ----------

Ugghhh, Hey Corona, you were Correct!!!

I should have looked in here previously but guess what I found in "/var/run/..."?
Yup that's right lol, there is a PID file already in there for NRPE....
i.e. "/var/run/nrpe.pid"

Well, sorry for having to ask the question in the first place...
But I really appreciate ALL your guy's comments and help!

Thanks Again,
Matt

It certainly wasn't a dumb question. Glad we could help.

Yea... Thanks.

This is kinda how I feel right now --> :wall:
Haha....

Thanks Again,
Matt

No. I didn't even download nrpe. The code is browsable on the web at sourceforge. I linked it in my previous post.

Regards,
Alister

1 Like

alister,

Oh, ok cool... I see it now, thanks!

And you were correct, there is an option in the config file to enter a location for the *.pid file...

Thanks Again,
Matt