-
-
Notifications
You must be signed in to change notification settings - Fork 69
/
utils.py
128 lines (101 loc) · 4.28 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""
Mostly utility functions Salmon uses internally that don't
really belong anywhere else in the modules. This module
is kind of a dumping ground, so if you find something that
can be improved feel free to work up a patch.
"""
from salmon import server, routing
import sys, os
import logging
if sys.platform != 'win32': # Can daemonize
import daemon
try:
from daemon import pidlockfile
except ImportError:
from lockfile import pidlockfile
import imp
import signal
def import_settings(boot_also, from_dir=None, boot_module="config.boot"):
"""Used to import the settings in a Salmon project."""
if from_dir:
sys.path.append(from_dir)
settings = __import__("config.settings", globals(), locals()).settings
if boot_also:
__import__(boot_module, globals(), locals())
return settings
def daemonize(pid, chdir, chroot, umask, files_preserve=None, do_open=True):
"""
Uses python-daemonize to do all the junk needed to make a
server a server. It supports all the features daemonize
has, except that chroot probably won't work at all without
some serious configuration on the system.
"""
context = daemon.DaemonContext()
context.pidfile = pidlockfile.PIDLockFile(pid)
context.stdout = open(os.path.join(chdir, "logs/salmon.out"),"a+")
context.stderr = open(os.path.join(chdir, "logs/salmon.err"),"a+")
context.files_preserve = files_preserve or []
context.working_directory = os.path.expanduser(chdir)
if chroot:
context.chroot_directory = os.path.expanduser(chroot)
if umask != False:
context.umask = umask
if do_open:
context.open()
return context
def drop_priv(uid, gid):
"""
Changes the uid/gid to the two given, you should give utils.daemonize
0,0 for the uid,gid so that it becomes root, which will allow you to then
do this.
"""
logging.debug("Dropping to uid=%d, gid=%d", uid, gid)
daemon.daemon.change_process_owner(uid, gid)
logging.debug("Now running as uid=%d, gid=%d", os.getgid(), os.getuid())
def make_fake_settings(host, port):
"""
When running as a logging server we need a fake settings module to work with
since the logging server can be run in any directory, so there may not be
a config/settings.py file to import.
"""
logging.basicConfig(filename="logs/logger.log", level=logging.DEBUG)
routing.Router.load(['salmon.handlers.log', 'salmon.handlers.queue'])
settings = imp.new_module('settings')
settings.receiver = server.SMTPReceiver(host, port)
settings.relay = None
logging.info("Logging mode enabled, will not send email to anyone, just log.")
return settings
def check_for_pid(pid, force):
"""Checks if a pid file is there, and if it is sys.exit. If force given
then it will remove the file and not exit if it's there."""
if os.path.exists(pid):
if not force:
print "PID file %s exists, so assuming Salmon is running. Give -FORCE to force it to start." % pid
sys.exit(1)
return # for unit tests mocking sys.exit
else:
os.unlink(pid)
def start_server(pid, force, chroot, chdir, uid, gid, umask, settings_loader, debug, daemon_proc):
"""
Starts the server by doing a daemonize and then dropping priv
accordingly. It will only drop to the uid/gid given if both are given.
"""
check_for_pid(pid, force)
if not debug and daemon_proc:
daemonize(pid, chdir, chroot, umask, files_preserve=[])
sys.path.append(os.getcwd())
settings = settings_loader()
if uid and gid:
drop_priv(uid, gid)
elif uid or gid:
logging.warning("You probably meant to give a uid and gid, but you gave: uid=%r, gid=%r. Will not change to any user.", uid, gid)
settings.receiver.start()
if debug:
print "Salmon started in debug mode. ctrl-c to quit..."
import time
try:
while True:
time.sleep(100000)
except KeyboardInterrupt:
# hard quit, since receiver starts a new thread. dirty but works
os._exit(1)