Wouldn't a message passing approach be better? I ran into this same situation with a wireless gateway I'm in the process of designing. I want a web server to be able to open access to paying customers, but I don't want the sucker running as root.
My answer was to write a monitor daemon that ran as root, and sat in the background waiting for messages. The webserver communicates to the daemon by writing messages into a MySQL table. The daemon checks for messages periodically, but it can be waken up by opening a connection to port 8000 and closing it again. I also use this same mechanism to tell the daemon to shut down. Simply write QUIT to the socket before closing it. (Though the daemon only listens for the QUIT command from local connections.)
Here's the script in TCL:
Code:
#! /usr/bin/tclsh
###
# Preen Daemon
#
# This script sits in the background, listening for
# commands to be recieved.
#
# The poll time can be abbreviated by simply
# opening a connection to port 8000
#
# Local process can send a kill signal to the
# daemon by writing the string QUIT to 8000
###
set ::tfi(application) preend
###
# Check for updates every minute
###
set ::poll_time [expr 1 * 60 * 1000]
set ::block 0
proc tock {} {
if [info exists ::next_tock] {
# Cancel any pending polls
after cancel $::next_tock
}
if $::block {
# Grr, someone tried to wake me up
# while I was operating
return
}
set ::block 1
if [catch {
update_loop
} err] {
set fout [open /tmp/preen.err a]
puts $fout "[clock seconds] - $err"
close $fout
set fout [open /tmp/preen.errinfo w]
puts $fout $::errorInfo
close $fout
}
set ::block 0
set ::next_tock [after ${::poll_time} tock]
}
proc socket_wakeup {chan addr port} {
tock
fconfigure $chan -buffering line -translation crlf
if [info exists ::next_tock] {
after cancel $::next_tock
}
if { $addr == "127.0.0.1" } {
gets $chan line
if { $line == "QUIT" } {
exit
}
}
close $chan
}
###
# Your Code Here
###
proc update_loop {} {
# This is where it looks for commands
puts "UPDATE [clock format [clock seconds]]"
}
###
# Listen on port 8000 for the command to wake up
###
socket -server socket_wakeup 8000
# Start the monitor
tock
vwait forever