forked from mountainpenguin/pyrt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pyrt
executable file
·237 lines (195 loc) · 7.34 KB
/
pyrt
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#!/usr/bin/env python2.7
""" Copyright (C) 2012 mountainpenguin ([email protected])
<http://github.com/mountainpenguin/pyrt>
This file is part of pyRT.
pyRT is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
pyRT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with pyRT. If not, see <http://www.gnu.org/licenses/>.
"""
from __future__ import print_function
from modules import mkpasswd
# move imports to start() to speed up other functions
import os
import traceback
import glob
import time
import subprocess
import argparse
import signal
import psutil
__AUTHOR__ = "mountainpenguin ([email protected])"
__SITE__ = "http://github.com/mountainpenguin/pyrt"
__VERSION__ = "1.0.0"
__LICENSE__ = "GPLv3"
def _searchPID():
if os.path.exists("proc/pyrt.pid"):
PID = int(open("proc/pyrt.pid").read().strip())
# TODO: Find a way to check that PID belongs to Pyrt, if there exist a program with the same PID,
# because if the Pyrt crash (does not remove the PID file) and another program starts and gets the
# same PID, then _searchPID will think that Pyrt is already running.
if psutil.pid_exists(PID):
# check username of process corresponds to calling user
p = psutil.Process(PID)
if p.uids().real != os.getuid():
raise OSError("PID {0} is not owned by you".format(PID))
# check calling command includes python and pyrt as arguments
cmd = p.cmdline()
if "python" not in cmd[0] or "pyrt" not in cmd[1]:
raise OSError("PID {0} has been recycled!".format(PID))
return PID
def _searchBotPID():
PIDFiles = glob.glob("proc/bots/*.pid")
# e.g. proc/bots/12345.pid
pids = []
for PIDFile in PIDFiles:
with open(PIDFile) as doc:
pids.append(int(doc.read().strip()))
return pids
def _isGitRepo():
if os.path.exists(".git"):
return True
else:
return False
def _checkRepo():
p = subprocess.Popen(["git remote update"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print("Checking for updates...")
p.wait()
stdout, stderr = p.stdout.read(), p.stderr.read()
if "origin" in stderr:
return True
else:
p2 = subprocess.Popen(["git status"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2.wait()
stdout, stderr = p2.stdout.read(), p2.stderr.read()
if "Your branch is behind" in stdout:
return True
else:
print("Repository is up-to-date")
return False
def _updateRepo():
# update remote
os.system("git pull")
open(".uncache", "a").close()
def start(update=True):
if _searchPID():
print("pyRT has already been started and is running")
return
if update:
runUpdate()
from modules import server
from modules import config
from modules import daemon
print("Loading pyRT configuration from %s" % os.path.join(os.getcwd(), "config/.pyrtrc"))
c = config.Config()
c.loadconfig()
print("Starting daemon with log file %s" % c.get("logfile"))
STDOUT = open(c.get("logfile"), "a")
with daemon.DaemonContext(stdout=STDOUT, stderr=STDOUT, working_directory=os.getcwd()):
serv = server.Main()
PID = os.getpid()
open("proc/pyrt.pid", "w").write(str(PID))
serv.main(c)
def stop(force=False):
if not _searchPID():
print("pyRT is not running")
return
if force:
signum = signal.SIGKILL
signame = "SIGKILL"
else:
signum = signal.SIGTERM
signame = "SIGTERM"
bots = _searchBotPID()
for p in bots:
print("Sending %s to process bot PID %d" % (signame, p))
try:
os.kill(p, signum)
except OSError:
print("Couldn't kill bot, no process with PID %d" % p)
if os.path.exists("proc/bots/%d.pid" % p):
os.remove("proc/bots/%d.pid" % p)
except:
traceback.print_exc()
count = 0
while count < 3:
bots = _searchBotPID()
if len(bots) > 0:
print("Waiting for bots to die (%d)" % count)
time.sleep(2)
count += 1
else:
break
PID = _searchPID()
print("Sending %s to process PID %d" % (signame, PID))
try:
os.kill(PID, signum)
except OSError:
print("Something went horribly wrong, there is no process with PID %d" % PID)
print("To allow restarting, delete the file proc/pyrt.pid")
except:
traceback.print_exc()
else:
os.remove("proc/pyrt.pid")
if os.path.exists(".sockets/rss.interface"):
print("Removing RPC RSS socket file")
os.remove(".sockets/rss.interface")
for i in range(10):
pth = ".sockets/rpc%i.interface" % i
if os.path.exists(pth):
print("Removing RPC IRC socket file <%s>" % pth)
os.remove(pth)
def status():
if _searchPID():
print("pyRT is running with PID: %i" % _searchPID())
else:
print("pyRT is not running")
def runUpdate():
if _isGitRepo():
updateready = _checkRepo()
if updateready:
goahead = raw_input("An update is available, download? (Y/N): ")
if goahead.upper() == "Y":
_updateRepo()
return
else:
print("Ignoring update")
else:
print("Not a git repository")
if __name__ == "__main__":
# cmd line syntax
# ./pyrt start | stop | restart | status | mkpasswd
print("pyRT rtorrent webUI v%s" % (__VERSION__))
print("Copyright (C) 2012 mountainpenguin")
print("This program comes with ABSOLUTELY NO WARRANTY")
print("This is free software, and you are welcome to redistribute it under certain conditions")
print("See LICENCE for details", end="\n\n")
parser = argparse.ArgumentParser(description="PyRT rtorrent webUI")
parser.add_argument("action", choices=("start", "stop", "restart", "status", "mkpasswd", "update"), help="Control the webUI daemon")
parser.add_argument("-n", "--noupdate", help="Don't check for updates", action="store_false")
parser.add_argument("-f", "--force", help="Force the webUI to stop", action="store_true")
parser.add_argument("-u", "--uncache", help="Aggressively uncache for the next two refreshes", action="store_true")
args = parser.parse_args()
if args.uncache:
open(".uncache", "a").close()
if args.action == "start":
start(args.noupdate)
elif args.action == "stop":
stop(args.force)
elif args.action == "restart":
stop(args.force)
start(args.noupdate)
elif args.action == "status":
status()
elif args.action == "mkpasswd":
mkpasswd.main()
elif args.action == "update":
runUpdate()
else:
print("Syntax: pyrt start|stop|restart|status|mkpasswd")