Skip to content

Instantly share code, notes, and snippets.

@bgth
Forked from TheWaWaR/gunicorn_service.py
Last active January 30, 2017 13:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bgth/9c692e21d9c67d9486c12925d7b65187 to your computer and use it in GitHub Desktop.
Save bgth/9c692e21d9c67d9486c12925d7b65187 to your computer and use it in GitHub Desktop.
Gunicorn service script {Start | Restart | Stop | Reload | Quit}
# python3 based gunicorn service
#!/usr/bin/env python3
#coding: utf-8
#####################################
# Sample Config file #
# pidfile='config/gunicornRun.pid'; #
# app='server:app'; #
# bind='127.0.0.1:8000' #
#####################################
import os
import imp
import time
import signal
import argparse
from subprocess import check_output, CalledProcessError
from subprocess import PIPE, STDOUT
# !!! You must specify this !!!
CONFIG_PATH = 'config/gunicorn_conf.py';
config = imp.load_source('config', CONFIG_PATH);
def getstatusoutput(cmd):
try:
data = check_output(cmd, shell=True, universal_newlines=True, stderr=STDOUT)
status = 0
except CalledProcessError as ex:
data = ex.output
status = ex.returncode
if data[-1:] == '\n':
data = data[:-1]
return status, data
def get_pid():
if os.path.exists(config.pidfile):
with open(config.pidfile, 'r') as f:
return int(f.read())
else:
print('[Error]: pid file not exists!');
return None
def rm_pidfile():
if os.path.exists(config.pidfile):
print('[Remove File]: %s' % config.pidfile);
os.remove(config.pidfile)
def status():
if os.path.exists(config.pidfile):
status, output = getstatusoutput('ls -l %s' % config.pidfile)
print(output);
print('[Pid File]: %s' % output);
pid = get_pid()
try:
os.kill(pid, 0)
print('[OK]: <pid: %d> is alive.' % pid);
except OSError as e:
print('[Error]: <pid: %d> has gone!' % pid);
rm_pidfile()
else:
print('[Pid File]: NOT exists!');
status_cmd = 'ps aux | grep [g]unicorn.*%s' % config.app
print('[Process List]: %s' % status_cmd);
status, output = getstatusoutput(status_cmd)
lines = [line for line in output.split('\n')]
print('''--------------------------------------------------
%s
--------------------------------------------------''' % '\n'.join(lines));
def Quit():
pid = get_pid()
if pid:
print('>>> Quiting ......');
try:
os.kill(pid, signal.SIGQUIT)
except OSError as e:
print('[Failed]: Server haven\'t start yet!');
finally:
time.sleep(1)
rm_pidfile()
def Stop():
pid = get_pid()
if pid:
print('>>> Stoping ......');
try:
os.kill(pid, signal.SIGTERM)
print('[Success]: ok!');
except OSError as e:
print('[Failed]: <pid: %d> has gone!' % pid);
finally:
rm_pidfile()
def Reload():
pid = get_pid()
if pid:
print('>>> Reloading ......');
try:
os.kill(pid, signal.SIGHUP)
except OSError as e:
print('[Failed]: Server haven\'t start yet!');
def start(bind):
if os.path.exists(config.pidfile):
pid = get_pid()
print('<< Server already started! >>');
else:
print('>>> Starting server ......');
if bind is None:
bind = config.bind
run_cmd = 'gunicorn --daemon -c %(config)s -b %(bind)s %(app)s ' % {
'config' : CONFIG_PATH,
'bind' : bind,
'app': config.app,
}
print('[Run Command]: %s' % run_cmd);
code, output = getstatusoutput(run_cmd)
print(code);
if code == 0:
time.sleep(8)
pid = get_pid()
try:
os.kill(pid, 0)
print('''
[Success]:
===========
pid = %d
pidfile = %s
address = %s
''' % (pid, config.pidfile, bind));
except OSError as e:
print('''
[Failed]:
========
Process start failed.
Permission denied? You may run this script as `root'.
''');
rm_pidfile()
else:
print('[Failed]: status=[%d], output=[%s]' % (code, output));
def restart(bind):
Quit()
start(bind)
def main():
parser = argparse.ArgumentParser(description='Manage the gunicorn(just like apache) server.')
parser.add_argument('--start', action='store_true', help='Start your wsgi application. (config = %s, app = %s)' % (CONFIG_PATH, config.app))
parser.add_argument('--quit', action='store_true', help='[Not Recommended!] Quick shutdown. ')
parser.add_argument('--stop', action='store_true', help='Graceful shutdown. Waits for workers to finish their current requests up to the graceful timeout.')
parser.add_argument('--reload', action='store_true', help='Reload the configuration, start the new worker processes with a new configuration and gracefully shutdown older workers.')
parser.add_argument('--restart', action='store_true', help='[Not Recommended!] Simply `quit\' the server then `start\' it')
parser.add_argument('--status', action='store_true', help='Show gunicorn processes.')
parser.add_argument('-b', '--bind', metavar='ADDRESS', help='The socket to bind. [[\'127.0.0.1:8000\']]')
args = parser.parse_args()
# `start' and `restart' are special.
if args.start:
start(args.bind)
return
elif args.restart:
restart(args.bind)
return
for label, func in {'status': status,
'quit': Quit,
'stop': Stop,
'reload': Reload }.items():
if getattr(args, label):
func()
break
else:
parser.print_help()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment