Need help with rc.d script

Ian Smith smithi at
Thu Nov 9 09:02:19 UTC 2017

On Thu, 9 Nov 2017 04:04:52 +0100, Polytropon wrote:

Another night owl, hmm? :)

 > On Wed, 8 Nov 2017 19:42:36 -0600, Edgar Pettijohn wrote:
 > > On Wed, Nov 08, 2017 at 11:37:37AM -0500, Ernie Luzar wrote:
 > > > Ian Smith wrote:
 > > > > On Tue, 7 Nov 2017 13:11:36 -0500, Ernie Luzar wrote:
 > > > I tested with and without the enclosing ( and ) on the while loop 
 > > > and it made no difference. No pidfile exists before the "service 
 > > >  dynip start" is issued and non exists afterwards.

 > > I don't believe the rc system can write a pidfile for you. Most of if not all
 > > of the services being started by the rc system are written in c and take care
 > > of writing their own pidfile. I suspect you could overcome this by writing a c
 > > program that does so and executes your script every 10 minutes. Or some form of
 > > pgrep perhaps.

 > It's easy to create a pidfile from within the shell script for
 > the shell itself (and its subshells) as well as for an invoked
 > external program:
 > 	echo $$ > /var/run/${0##*/}.pid
 > 	myprog -foo -bar baz -meow
 > 	echo $! > /var/run/

In that case - unless myprog daemonised itself? - I believe you'd need:
 	myprog -foo -bar baz -meow &
so then $! is specifically the PID of the (now background) myprog

 > The documentation says:
 >      $$      Expands to the process ID of the invoked shell.  A subshell
 >              retains the same value of $ as its parent.
 >      $!      Expands to the process ID of the most recent background command
 >              executed from the current shell.  For a pipeline, the process ID
 >              is that of the last command in the pipeline.
 > See "man sh", section "Special Parameters", for details

Indeed.  I was trying to find out whether or not rc made the pidfile, or 
one had to do it in the program (here a sh script) being run; as Edgar 
indicated, seems the program|script needs to do it.  Even if rc had done 
so, for a bg subshell (and not $$) you'd need to overwrite it anyway.

I think what's needed here for Ernie's dynip script is like:

	# setup code ..
	# repeated loop subshell code, to be left running
		while true; do
			sleep $delay
	) &
	echo $! > /var/run/	# post PID of bg subshell
	echo ok or such confirmation	# if desired
	exit 0				# finished startup script

Then 'service dynip stop' should find and kill the correct process.

I generally go a bit further, finding sometimes that only the sleep in 
such a loop may get killed - since it's running 99.9%+ of the time - so 
usually take the trouble so any of the usual signals work to end it:

	(	done=0
		trap "done=1" int quit term	# signals set done=1
		while [ $done -eq 0 ]; do
			sleep $delay
		echo `basename $0` killed by signal int, quit or term
		trap - int quit term	# for tidyness, overkill here
	) &
	echo $! > /var/run/	# correct PID for external kill
	exit 0

Consult sh(1) regarding how to trap - and/or block - various signals.

cheers, Ian

More information about the freebsd-questions mailing list