-
-
Save bgth/9c692e21d9c67d9486c12925d7b65187 to your computer and use it in GitHub Desktop.
Gunicorn service script {Start | Restart | Stop | Reload | Quit}
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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