summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/roadmap.txt13
-rw-r--r--paste/app_setup.py91
-rwxr-xr-xpaste/server.py5
-rwxr-xr-xscripts/paste-setup2
4 files changed, 104 insertions, 7 deletions
diff --git a/docs/roadmap.txt b/docs/roadmap.txt
index e0f313d..fab8e69 100644
--- a/docs/roadmap.txt
+++ b/docs/roadmap.txt
@@ -32,8 +32,6 @@ paste-setup
* An application could be mapped to a particular URL, given a
configuration file that describes the application.
-* **``--daemon`` option for running as background process**
-
* Template files should have optional ``.ext_tmpl`` extension, where
``_tmpl`` gets stripped. This way the currently-invalid ``.py``
template files wouldn't be recognized as Pythohn files.
@@ -41,6 +39,13 @@ paste-setup
* Allow applications to easily add their own commands, e.g.,
``add-user``.
+* Better PID management when in daemon mode (don't clobber a PID file
+ of a running process)
+
+* Add options to manage the daemon process, like force
+ reloading/restarting (HUP?) and stopping; make init.d scripts as
+ minimal as possible.
+
paste.docsupport
----------------
@@ -178,5 +183,5 @@ No module yet, so these are listed generally.
Done
====
-I just wrote this, so nothing that's shown up on this list is done
-yet!
+25 May 2005:
+ **``--daemon`` option for running as background process**
diff --git a/paste/app_setup.py b/paste/app_setup.py
index 6516c1c..06ef3cf 100644
--- a/paste/app_setup.py
+++ b/paste/app_setup.py
@@ -270,10 +270,98 @@ class CommandServe(Command):
name = 'serve'
summary = 'Run server'
parser = standard_parser(simulate=False)
+ parser.add_option(
+ '--daemon',
+ help="Run in daemon (background) mode",
+ dest="daemon",
+ action="store_true")
+ parser.add_option(
+ '--user',
+ metavar="USER_OR_UID",
+ help="User to run as (only works if started as root)",
+ dest="user")
+ parser.add_option(
+ '--group',
+ metavar="GROUP_OR_GID",
+ help="Group to run as (only works if started as root)",
+ dest="group")
+ parser.add_option(
+ '--pid-file',
+ metavar="FILENAME",
+ help="Write PID to FILENAME",
+ dest="pid_file")
+ parser.add_option(
+ '--log-file',
+ metavar="FILENAME",
+ help="File to write stdout/stderr to (other log files may still be generated by the application)",
+ dest="log_file")
def command(self):
+ conf = self.config
+ verbose = conf.get('verbose') or 0
+ if conf.get('daemon'):
+ # We must enter daemon mode!
+ if verbose > 1:
+ print 'Entering daemon mode'
+ pid = os.fork()
+ if pid:
+ sys.exit()
+ # Always record PID and output when daemonized
+ if not conf.get('pid_file'):
+ conf['pid_file'] = 'server.pid'
+ if not conf.get('log_file'):
+ conf['log_file'] = 'server.log'
+ if conf.get('pid_file'):
+ # @@: We should check if the pid file exists and has
+ # an active process in it
+ if verbose > 1:
+ print 'Writing pid %s to %s' % (os.getpid(), conf['pid_file'])
+ f = open(conf['pid_file'], 'w')
+ f.write(str(os.getpid()))
+ f.close()
+ if conf.get('log_file'):
+ if verbose > 1:
+ print 'Logging to %s' % conf['log_file']
+ f = open(conf['log_file'], 'a', 1) # 1==line buffered
+ sys.stdout = sys.stderr = f
+ f.write('-'*20
+ + ' Starting server PID: %s ' % os.getpid()
+ + '-'*20 + '\n')
+ self.change_user_group(conf.get('user'), conf.get('group'))
sys.exit(server.run_commandline(self.args))
+ def change_user_group(self, user, group):
+ if not user and not group:
+ return
+ uid = gid = None
+ if group:
+ try:
+ gid = int(group)
+ except ValueError:
+ import grp
+ try:
+ entry = grp.getgrnam(group)
+ except KeyError:
+ raise KeyError(
+ "Bad group: %r; no such group exists" % group)
+ gid = entry[2]
+ try:
+ uid = int(user)
+ except ValueError:
+ import pwd
+ try:
+ entry = pwd.getpwnam(user)
+ except KeyError:
+ raise KeyError(
+ "Bad username: %r; no such user exists" % user)
+ if not gid:
+ gid = entry[3]
+ uid = entry[2]
+ if gid:
+ os.setgid(gid)
+ if uid:
+ os.setuid(uid)
+
def parse_args(self, args):
# Unlike most commands, this takes arbitrary options and folds
# them into the configuration
@@ -287,8 +375,9 @@ class CommandServe(Command):
self.list_servers(conf)
sys.exit()
CONFIG.push_process_config(conf)
- sys.exit(server.run_server(conf, app))
self.config = conf
+ self.options = None
+ self.args = []
def help(self, config):
# Here we make a fake parser just to get the help
diff --git a/paste/server.py b/paste/server.py
index 1f82124..2db0ed7 100755
--- a/paste/server.py
+++ b/paste/server.py
@@ -63,7 +63,7 @@ def load_commandline(args, allow_reload=True):
conf = pyconfig.Config(with_default=True)
conf.load_commandline(
args, bool_options=['help', 'verbose', 'reload', 'debug', 'quiet',
- 'no_verbose', 'list_servers'],
+ 'no_verbose', 'list_servers', 'daemon'],
aliases={'h': 'help', 'v': 'verbose', 'f': 'config_file',
'D': 'debug', 'q': 'quiet'})
if conf.get('no_verbose'):
@@ -198,7 +198,8 @@ def restart_with_reloader(conf):
args, new_environ)
if exit_code != 3:
return None, exit_code
- print "Exit code 3; restarting server"
+ if conf['verbose']:
+ print '-'*20, 'Restarting', '-'*20
if __name__ == '__main__':
sys.exit(run_commandline(sys.argv[1:]))
diff --git a/scripts/paste-setup b/scripts/paste-setup
index 16eaac5..79d589b 100755
--- a/scripts/paste-setup
+++ b/scripts/paste-setup
@@ -13,6 +13,8 @@ relative_paste = os.path.join(
if os.path.exists(relative_paste):
sys.path.insert(0, os.path.dirname(relative_paste))
+import paste.app_setup
+print paste.app_setup.__file__
from paste import app_setup
sys.exit(app_setup.run(sys.argv))