Launch.py :  » Web-Frameworks » Webware » Webware-1.0.2 » WebKit » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Webware 
Webware » Webware 1.0.2 » WebKit » Launch.py
#!/usr/bin/env python

"""Launch.py

DESCRIPTION

Python launch script for the WebKit application server.

This launch script will run in its standard location in the Webware/WebKit
directory as well as in a WebKit work directory outside of the Webware tree.

USAGE

Launch.py [StartOptions] [AppServer [AppServerOptions]]

StartOptions:
  -d, --work-dir=...     Set the path to the app server working directory.
                         By default this is the directory containing Lauch.py.
  -w, --webware-dir=...  Set the path to the Webware root directory.
                         By default this is the parent directory.
  -l, --library=...      Other directories to be included in the search path.
                         You may specify this option multiple times.
  -p, --run-profile      Set this to get profiling going (see Profiler.py).
  -o, --log-file=...     Redirect standard output and error to this file.
  -i, --pid-file=...     Set the file path to hold the app server process id.
                         This option is fully supported under Unix only.
  -u, --user=...         The name or uid of the user to run the app server.
                         This option is supported under Unix only.
  -g, --group=...        The name or gid of the group to run the app server.
                         This option is supported under Unix only.

AppServer:
  The name of the application server module.
  By default, the ThreadedAppServer will be used.

AppServerOptions:
  Options that shall be passed to the application server.
  For instance, the ThreadedAppServer accepts: start, stop, daemon
  You can also change configuration settings here by passing
  arguments of the form ClassName.SettingName=value

Please note that the default values for the StartOptions and the AppServer
can be easily changed at the top of the Launch.py script.
"""

# FUTURE
# * This shares a lot of code with ThreadedAppServer.py and Launch.py.
#   Try to consolidate these things. The default settings below in the
#   global variables could go completely into AppServer.config.
# CREDITS
# * Contributed to Webware for Python by Chuck Esterbrook
# * Improved by Ian Bicking
# * Improved by Christoph Zwerschke


## Default options ##

# You can change the following default values:

# The path to the app server working directory, if you do not
# want to use the directory containing this script:
workDir = None

# The path to the Webware root directory; by default this will
# be the parent directory of the directory containing this script:
webwareDir = None

# A list of additional directories (usually some libraries)
# that you want to include into the search path for modules:
libraryDirs = []

# To get profiling going, set runProfile = 1 (see also
# the description in the docstring of Profiler.py):
runProfile = 0

# The path to the log file, if you want to redirect the
# standard output and error to a log file:
logFile = None

# The pass to the pid file, if you want to check and terminate
# a running server by storing its server process id:
pidFile = None

# The name or uid of the server process user, if you want
# to run the server under a different user:
user = None

# The name or uid of the server process group, if you want
# to run the server under a different group:
group = None

# The default app server to be used:
appServer = 'ThreadedAppServer'


## Launch app server ##

import os, sys

def usage():
  """Print the docstring and exit with error."""
  sys.stdout.write(__doc__)
  sys.exit(2)

def launchWebKit(appServer=appServer, workDir=None, args=None):
  """Import and launch the specified WebKit app server.

  appServer  -- the name of the WebKit app server module
  workDir -- the server-side work directory of the app server
  args -- other options that will be given to the app server

  """
  # Set up the arguments for the app server:
  if args is None:
    args = []
  if workDir:
    args.append('workdir=' + workDir)
  # Allow for a .py on the server name:
  if appServer[-3:] == '.py':
    appServer = appServer[:-3]
  # Import the app server's main() function:
  try:
    appServerMain = __import__('WebKit.' + appServer, None, None, 'main').main
  except ImportError, e:
    print 'Error: Cannot import the AppServer module.'
    print 'Reason:', str(e)
    sys.exit(1)
  # Set Profiler.startTime if this has not been done already:
  from WebKit import Profiler
  if Profiler.startTime is None:
    from time import time
    Profiler.startTime = time()
  # Run the app server:
  return appServerMain(args) # go!


## Main ##

def main(args=None):
  """Evaluate the command line arguments and call launchWebKit."""
  global workDir, webwareDir, libraryDirs, runProfile, \
    logFile, pidFile, user, group, appServer
  if args is None:
    args = sys.argv[1:]
  # Accept AppServer even if placed before StartOptions:
  if args and not args[0].startswith('-'):
    arg2 = args.pop(0)
  else:
    arg2 = None
  # Accept AppServerOptions that look like StartOptions:
  args1 = []
  args2 = []
  while args:
    arg = args.pop(0)
    if arg.startswith('--') and \
      2 < arg.find('.', 2) < arg.find('=', 5):
      args2.append(arg)
    else:
      args1.append(arg)
  # Get all launch options:
  from getopt import getopt,GetoptError
  try:
    opts, args1 = getopt(args1, 'd:w:l:po:i:u:g:', [
      'work-dir=', 'webware-dir=', 'library=', 'run-profile',
      'log-file=', 'pid-file=', 'user=', 'group='])
  except GetoptError, error:
    print str(error)
    print
    usage()
  for opt, arg in opts:
    if opt in ('-d', '--work-dir'):
      workDir = arg
    elif opt in ('-w', '--webware-dir'):
      webwareDir = arg
    elif opt in ('-l', '--library'):
      libraryDirs.append(arg)
    elif opt in ('-p', '--run-profile'):
      runProfile = 1
    elif opt in ('-o', '--log-file'):
      logFile = arg
    elif opt in ('-i', '--pid-file'):
      pidFile = arg
    elif opt in ('-u', '--user'):
      user = arg
    elif opt in ('-g', '--group'):
      group = arg
  if arg2:
    appServer = arg2
  elif args1 and not args1[0].startswith('-') \
    and args1[0].find('=') < 0:
    appServer = args1.pop(0)
  args = args2 + args1
  # Figure out the group id:
  gid = group
  if gid is not None:
    try:
      gid = int(gid)
    except ValueError:
      try:
        import grp
        entry = grp.getgrnam(gid)
      except KeyError:
        print 'Error: Group %r does not exist.' % gid
        sys.exit(2)
      except ImportError:
        print 'Error: Group names are not supported.'
        sys.exit(2)
      gid = entry[2]
  # Figure out the user id:
  uid = user
  if uid is not None:
    try:
      uid = int(uid)
    except ValueError:
      try:
        import pwd
        entry = pwd.getpwnam(uid)
      except KeyError:
        print 'Error: User %r does not exist.' % uid
        sys.exit(2)
      except ImportError:
        print 'Error: User names are not supported.'
        sys.exit(2)
      if not gid:
        gid = entry[3]
      uid = entry[2]
  # Figure out the work directory and make it the current directory:
  if workDir:
    workDir = os.path.expanduser(workDir)
  else:
    scriptName = sys.argv and sys.argv[0]
    if not scriptName or scriptName == '-c':
      scriptName = 'Launch.py'
    workDir = os.path.dirname(os.path.abspath(scriptName))
  try:
    os.chdir(workDir)
  except OSError, error:
    print 'Error: Could not set working directory.'
    print 'The path %r cannot be used.' % workDir
    print error.strerror
    print 'Check the --work-dir option.'
    sys.exit(1)
  workDir = os.curdir
  # Expand user components in directories:
  if webwareDir:
    webwareDir = os.path.expanduser(webwareDir)
  else:
    webwareDir = os.pardir
  if libraryDirs:
    libraryDirs = map(os.path.expanduser, libraryDirs)
  # If this module is inside a package, make it a standalone module,
  # because otherwise the package path will be used for imports, too:
  global __name__, __package__
  name = __name__.split('.')[-1]
  if name != __name__:
    sys.modules[name] = sys.modules[__name__]
    del sys.modules[__name__]
    __name__ = name
    __package__ = None
  # Check the validity of the Webware directory:
  sysPath = sys.path # memorize the standard Python search path
  sys.path = [webwareDir] # now include only the Webware directory
  try: # check whether Webware is really located here
    from Properties import name
    from WebKit.Properties import name
  except ImportError:
    webwareName = None
  if webwareName != 'Webware for Python' or webKitName != 'WebKit':
    print 'Error: Cannot find the Webware directory.'
    print 'The path %r seems to be wrong.' % webwareDir
    print 'Check the --webware-dir option.'
    sys.exit(1)
  if not os.path.exists(os.path.join(webwareDir, 'install.log')):
    print 'Error: Webware has not been installed.'
    print 'Please run install.py in the Webware directory:'
    print '> cd', os.path.abspath(webwareDir)
    print '> python install.py'
    sys.exit(1)
  # Now assemble a new clean Python search path:
  path = [] # the new search path will be collected here
  webKitDir = os.path.abspath(os.path.join(webwareDir, 'WebKit'))
  for p in [workDir, webwareDir] + libraryDirs + sysPath:
    if not p:
      continue # do not include the empty ("current") directory
    p = os.path.abspath(p)
    if p == webKitDir or p in path or not os.path.exists(p):
      continue # do not include WebKit and duplicates
    path.append(p)
  sys.path = path # set the new search path
  # Prepare the arguments for launchWebKit:
  args = (appServer, workDir, args)
  # Handle special case where app server shall be stopped:
  if 'stop' in args[2]:
    print 'Stopping WebKit.%s...' % appServer
    errorlevel = launchWebKit(*args)
    if not errorlevel:
      if pidFile and os.path.exists(pidFile):
        try:
          os.remove(pidFile)
        except Exception:
          print 'The pid file could not be removed.'
          print
    sys.exit(errorlevel)
  # Handle the pid file:
  if pidFile:
    pidFile = os.path.expanduser(pidFile)
    # Read the old pid file:
    try:
      pid = int(open(pidFile).read())
    except Exception:
      pid = None
    if pid is not None:
      print 'According to the pid file, the server is still running.'
      # Try to kill an already running server:
      killed = 0
      try:
        from signal import SIGTERM,SIGKILL
        print 'Trying to terminate the server with pid %d...' % pid
        os.kill(pid, SIGTERM)
      except OSError, error:
        from errno import ESRCH
        if error.errno == ESRCH: # no such process
          print 'The pid file was stale, continuing with startup...'
          killed = 1
        else:
          print 'Cannot terminate server with pid %d.' % pid
          print error.strerror
          sys.exit(1)
      except (ImportError, AttributeError):
        print 'Cannot check or terminate server with pid %d.' % pid
        sys.exit(1)
      if not killed:
        from time import sleep
        try:
          for i in range(100):
            sleep(0.1)
            os.kill(pid, SIGTERM)
        except OSError, error:
          from errno import ESRCH
          if error.errno == ESRCH:
            print 'Server with pid %d has been terminated.' % pid
            killed = 1
      if not killed:
        try:
          for i in range(100):
            sleep(0.1)
            os.kill(pid, SIGKILL)
        except OSError, error:
          from errno import ESRCH
          if error.errno == ESRCH:
            print 'Server with pid %d has been killed by force.' % pid
            killed = 1
      if not killed:
        print 'Server with pid %d cannot be terminated.' % pid
        sys.exit(1)
    # Write a new pid file:
    try:
      open(pidFile, 'w').write(str(os.getpid()))
    except Exception:
      print 'The pid file %r could not be written.' % pidFile
      sys.exit(1)
  olduid = oldgid = stdout = stderr = log = None
  errorlevel = 1
  try:
    # Change server process group:
    if gid is not None:
      try:
        oldgid = os.getgid()
        if gid != oldgid:
          os.setgid(gid)
          if group:
            print 'Changed server process group to %r.' % group
        else:
          oldgid = None
      except Exception:
        if group:
          print 'Could not set server process group to %r.' % group
          oldgid = None
          sys.exit(1)
    # Change server process user:
    if uid is not None:
      try:
        olduid = os.getuid()
        if uid != olduid:
          os.setuid(uid)
          print 'Changed server process user to %r.' % user
        else:
          olduid = None
      except Exception:
        print 'Could not change server process user to %r.' % user
        olduid = None
        sys.exit(1)
    msg = 'WebKit.' + appServer
    if args[2]:
      msg = '%s %s' % (msg, ' '.join(args[2]))
    else:
      msg = 'Starting %s...' % msg
    print msg
    # Handle the log file:
    if logFile:
      logFile = os.path.expanduser(logFile)
      try:
        log = open(logFile, 'a', 1) # append, line buffered mode
        print 'Output has been redirected to %r...' % logFile
        stdout, stderr = sys.stdout, sys.stderr
        sys.stdout = sys.stderr = log
      except IOError, error:
        print 'Cannot redirect output to %r.' % logFile
        print error.strerror
        log = None
        sys.exit(1)
    else:
      print
    # Set up a reference to our profiler so apps can import and use it:
    from WebKit import Profiler
    if Profiler.startTime is None:
      from time import time
      Profiler.startTime = time()
    # Now start the app server:
    if runProfile:
      print 'Profiling is on.', \
        'See docstring in Profiler.py for more info.'
      print
      from profile import Profile
      profiler = Profile()
      Profiler.profiler = profiler
      errorlevel = Profiler.runCall(launchWebKit, *args)
      print
      print 'Writing profile stats to %s...' % Profiler.statsFilename
      Profiler.dumpStats()
      print 'WARNING: Applications run much slower when profiled,'
      print 'so turn off profiling in Launch.py when you are finished.'
    else:
      errorlevel = launchWebKit(*args)
  finally:
    print
    # Close the log file properly:
    if log:
      sys.stdout, sys.stderr = stdout, stderr
      log.close()
    # Restore server process group and user.
    # Note that because we changed the real group and
    # user id of the process (most secure thing), we
    # cannot change them back now, but we try anyway:
    if oldgid is not None:
      try:
        os.setgid(oldgid)
      except Exception:
        pass
      else:
        oldgid = None
    if olduid is not None:
      try:
        os.setuid(olduid)
      except Exception:
        pass
      else:
        olduid = None
    # Remove the pid file again.
    # Note that this may fail when the group or user id
    # has been changed, but we try anyway:
    if pidFile and os.path.exists(pidFile):
      try:
        os.remove(pidFile)
      except Exception:
        if oldgid is None and olduid is None:
          print 'The pid file could not be removed.'
          print
  sys.exit(errorlevel)

if __name__ == '__main__':
  main()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.