ОС: Ubuntu.
Для примера "поднимем" web-сервер на Pyhton.
Определим директорию нашего проекта: /home/webserver/
Скрипт для запуска web-сервера /home/webserver/webserver.py
Сделаем данные файлы исполняемые командой:
Запустим скрипт
Набрав в браузере: http://127.0.0.1:8082/ увидим: "Hello, word"
Однако стоит закрыть терминал и скрипт перестанет работать.
Создаем файл-заготовку для старта демона /home/webserver/daemon.py с содержимым:
Скрипт для запуска в качестве дeмона /home/webserver/webserverdaemon.py:
Стартовые скрипты при запуске Системы находятся в /etc/init.d
Создаем файл /etc/init.d/webserver со следующим содержимым:
Не забываем сделать файлы исполняемыми:
Теперь управлять скриптом можно как дeмон командами:
Для примера "поднимем" web-сервер на Pyhton.
Определим директорию нашего проекта: /home/webserver/
Скрипт для запуска web-сервера /home/webserver/webserver.py
#!/usr/bin/python
#! _*_ coding: UTF-8 _*_
from BaseHTTPServer import BaseHTTPRequestHandler
from BaseHTTPServer import HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write('Hello, word')
def start():
server = HTTPServer(('',8082), Handler)
server.serve_forever()
if __name__ == '__main__':
start()
#! _*_ coding: UTF-8 _*_
from BaseHTTPServer import BaseHTTPRequestHandler
from BaseHTTPServer import HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write('Hello, word')
def start():
server = HTTPServer(('',8082), Handler)
server.serve_forever()
if __name__ == '__main__':
start()
Сделаем данные файлы исполняемые командой:
sudo chmod 777 -R /home/webserver
Запустим скрипт
/home/webserver/webserver.py
Набрав в браузере: http://127.0.0.1:8082/ увидим: "Hello, word"
Однако стоит закрыть терминал и скрипт перестанет работать.
Создаем файл-заготовку для старта демона /home/webserver/daemon.py с содержимым:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os, time, atexit
from signal import SIGTERM
class Daemon:
"""
Родительский класс дeмона
Использование: создайте подкласс и переопределите метод run()
"""
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
def daemonize(self):
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
os.chdir(".")
os.setsid()
os.umask(0)
# делаем второй fork
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# перенаправление стандартного ввода/вывода
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# записываем pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
file(self.pidfile,'w+').write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self):
"""
Запуск дeмона
"""
# Проверяем pidfile, чтоб узнать не запущен ли уже процесс
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
message = "pidfile %s already exist. Daemon already running?\n"
sys.stderr.write(message % self.pidfile)
sys.exit(1)
# Запуск дeмона
self.daemonize()
self.run()
def stop(self):
"""
Остановка дeмона
"""
# Берем pid из pidfile
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist. Daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # не считается ошибкой при перезапуске
# Убиваем процесс дeмона
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
def restart(self):
"""
Перезапуск дeмона
"""
self.stop()
self.start()
def run(self):
"""
Вы должны переопределить данный метод в подклассе. Он должен быть вызван
после вызова метода daemonize() в методе start().
"""
# -*- coding: utf-8 -*-
import sys, os, time, atexit
from signal import SIGTERM
class Daemon:
"""
Родительский класс дeмона
Использование: создайте подкласс и переопределите метод run()
"""
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
def daemonize(self):
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
os.chdir(".")
os.setsid()
os.umask(0)
# делаем второй fork
try:
pid = os.fork()
if pid > 0:
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# перенаправление стандартного ввода/вывода
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# записываем pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
file(self.pidfile,'w+').write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self):
"""
Запуск дeмона
"""
# Проверяем pidfile, чтоб узнать не запущен ли уже процесс
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
message = "pidfile %s already exist. Daemon already running?\n"
sys.stderr.write(message % self.pidfile)
sys.exit(1)
# Запуск дeмона
self.daemonize()
self.run()
def stop(self):
"""
Остановка дeмона
"""
# Берем pid из pidfile
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist. Daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # не считается ошибкой при перезапуске
# Убиваем процесс дeмона
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
def restart(self):
"""
Перезапуск дeмона
"""
self.stop()
self.start()
def run(self):
"""
Вы должны переопределить данный метод в подклассе. Он должен быть вызван
после вызова метода daemonize() в методе start().
"""
Скрипт для запуска в качестве дeмона /home/webserver/webserverdaemon.py:
#!/usr/bin/env python
# -*- coding: utf8 -*-
import sys
import webserver
from daemon import Daemon
class MyDaemon(Daemon):
def run(self):
webserver.start()
if __name__ == "__main__":
my_daemon = MyDaemon('/var/run/webserver.pid')
if len(sys.argv) >= 2:
if 'start' == sys.argv[1]:
print 'starting webserver'
my_daemon.start()
elif 'stop' == sys.argv[1]:
print 'stoping webserver'
my_daemon.stop()
elif 'restart' == sys.argv[1]:
print 'restarting webserver'
my_daemon.restart()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
# -*- coding: utf8 -*-
import sys
import webserver
from daemon import Daemon
class MyDaemon(Daemon):
def run(self):
webserver.start()
if __name__ == "__main__":
my_daemon = MyDaemon('/var/run/webserver.pid')
if len(sys.argv) >= 2:
if 'start' == sys.argv[1]:
print 'starting webserver'
my_daemon.start()
elif 'stop' == sys.argv[1]:
print 'stoping webserver'
my_daemon.stop()
elif 'restart' == sys.argv[1]:
print 'restarting webserver'
my_daemon.restart()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
Стартовые скрипты при запуске Системы находятся в /etc/init.d
Создаем файл /etc/init.d/webserver со следующим содержимым:
#!/bin/sh
# Description: Starts Python scripts
### BEGIN INIT INFO
# Provides: Scripts
# Required-Start: $network $local_fs $syslog
# Required-Stop: $local_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Start Python scripts
### END INIT INFO
case $1 in
start)
/home/webserver/webserverdaemon.py start
;;
stop)
/home/webserver/webserverdaemon.py stop
;;
restart)
/home/webserver/webserverdaemon.py restart
;;
*)
echo "Usage: scripts {start|stop|restart}"
exit 1
esac
# Description: Starts Python scripts
### BEGIN INIT INFO
# Provides: Scripts
# Required-Start: $network $local_fs $syslog
# Required-Stop: $local_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Start Python scripts
### END INIT INFO
case $1 in
start)
/home/webserver/webserverdaemon.py start
;;
stop)
/home/webserver/webserverdaemon.py stop
;;
restart)
/home/webserver/webserverdaemon.py restart
;;
*)
echo "Usage: scripts {start|stop|restart}"
exit 1
esac
Не забываем сделать файлы исполняемыми:
sudo chmod 777 -R /home/webserver
sudo chmod 777 /etc/init.d/webserver
sudo chmod 777 /etc/init.d/webserver
Теперь управлять скриптом можно как дeмон командами:
sudo /etc/init.d/webserver start
sudo /etc/init.d/webserver restart
sudo /etc/init.d/webserver stop
Для того чтобы скрипт запускался с загрузкой системы введите команду:
sudo /etc/init.d/webserver restart
sudo /etc/init.d/webserver stop
sudo update-rc.d webserver defaults
Для того чтобы удалить скрипт из автозагрузки :
sudo update-rc.d webserver remove
Слово "Демон" пишется через "е".
ОтветитьУдалитьА классы сейчас попробую ))
Исправил. Буду рад другим замечаниям.
ОтветитьУдалить# Убиваем процесс дeмона
ОтветитьУдалитьtry:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
здесь висит. Добавил break
try:
while 1:
print("try_kill")
os.kill(pid, SIGTERM)
time.sleep(0.1)
break