pywebexec 1.4.13__py3-none-any.whl → 1.4.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pywebexec/pywebexec.py +54 -24
- pywebexec/version.py +2 -2
- {pywebexec-1.4.13.dist-info → pywebexec-1.4.15.dist-info}/METADATA +1 -1
- {pywebexec-1.4.13.dist-info → pywebexec-1.4.15.dist-info}/RECORD +8 -8
- {pywebexec-1.4.13.dist-info → pywebexec-1.4.15.dist-info}/LICENSE +0 -0
- {pywebexec-1.4.13.dist-info → pywebexec-1.4.15.dist-info}/WHEEL +0 -0
- {pywebexec-1.4.13.dist-info → pywebexec-1.4.15.dist-info}/entry_points.txt +0 -0
- {pywebexec-1.4.13.dist-info → pywebexec-1.4.15.dist-info}/top_level.txt +0 -0
pywebexec/pywebexec.py
CHANGED
@@ -13,7 +13,7 @@ import time
|
|
13
13
|
import shlex
|
14
14
|
from gunicorn.app.base import Application
|
15
15
|
import ipaddress
|
16
|
-
from socket import gethostname, gethostbyname_ex, gethostbyaddr, inet_aton, inet_ntoa
|
16
|
+
from socket import socket, gethostname, gethostbyname_ex, gethostbyaddr, inet_aton, inet_ntoa, AF_INET, SOCK_STREAM
|
17
17
|
import ssl
|
18
18
|
import re
|
19
19
|
import pwd
|
@@ -223,7 +223,7 @@ def start_gunicorn(daemonized=False, baselog=None):
|
|
223
223
|
if daemonized:
|
224
224
|
if daemon_d('status', pidfilepath=baselog, silent=True):
|
225
225
|
print(f"Error: pywebexec already running on {args.listen}:{args.port}", file=sys.stderr)
|
226
|
-
|
226
|
+
return 1
|
227
227
|
|
228
228
|
if sys.stdout.isatty():
|
229
229
|
errorlog = "-"
|
@@ -244,6 +244,7 @@ def start_gunicorn(daemonized=False, baselog=None):
|
|
244
244
|
'pidfile': pidfile,
|
245
245
|
}
|
246
246
|
PyWebExec(app, options=options).run()
|
247
|
+
return 0
|
247
248
|
|
248
249
|
def daemon_d(action, pidfilepath, silent=False, hostname=None, args=None):
|
249
250
|
"""start/stop daemon"""
|
@@ -254,10 +255,15 @@ def daemon_d(action, pidfilepath, silent=False, hostname=None, args=None):
|
|
254
255
|
if pidfile.is_locked():
|
255
256
|
pid = pidfile.read_pid()
|
256
257
|
print(f"Stopping server pid {pid}")
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
258
|
+
n = 20
|
259
|
+
while n > 0:
|
260
|
+
try:
|
261
|
+
os.kill(pid, signal.SIGINT)
|
262
|
+
time.sleep(0.25)
|
263
|
+
n -= 1
|
264
|
+
except ProcessLookupError:
|
265
|
+
return True
|
266
|
+
print("Failed to stop server", file=sys.stderr)
|
261
267
|
return True
|
262
268
|
elif action == "status":
|
263
269
|
status = pidfile.is_locked()
|
@@ -285,21 +291,42 @@ def daemon_d(action, pidfilepath, silent=False, hostname=None, args=None):
|
|
285
291
|
except Exception as e:
|
286
292
|
print(e)
|
287
293
|
|
288
|
-
def start_term():
|
294
|
+
def start_term(command_id):
|
289
295
|
os.environ["PYWEBEXEC"] = " (shared)"
|
290
296
|
os.chdir(CWD)
|
291
|
-
command_id = str(uuid.uuid4())
|
292
297
|
start_time = datetime.now().isoformat()
|
293
298
|
user = pwd.getpwuid(os.getuid())[0]
|
299
|
+
print(f"Starting terminal session for {user} : {command_id}")
|
294
300
|
update_command_status(command_id, 'running', command="term", params=[user,os.ttyname(sys.stdout.fileno())], start_time=start_time, user=user)
|
295
301
|
output_file_path = get_output_file_path(command_id)
|
296
302
|
res = script(output_file_path)
|
297
303
|
end_time = datetime.now().isoformat()
|
298
304
|
update_command_status(command_id, status="success", end_time=end_time, exit_code=res)
|
305
|
+
print("Terminal session ended")
|
299
306
|
return res
|
300
307
|
|
308
|
+
|
309
|
+
def print_urls(command_id=None):
|
310
|
+
protocol = 'https' if args.cert else 'http'
|
311
|
+
url_params = ""
|
312
|
+
token = os.environ.get("PYWEBEXEC_TOKEN")
|
313
|
+
if token:
|
314
|
+
url_params = f"?token={token}"
|
315
|
+
if command_id:
|
316
|
+
print(f"{protocol}://{hostname}:{args.port}/popup/{command_id}{url_params}")
|
317
|
+
print(f"{protocol}://{ip}:{args.port}/popup/{command_id}{url_params}")
|
318
|
+
else:
|
319
|
+
print(f"{protocol}://{hostname}:{args.port}{url_params}")
|
320
|
+
print(f"{protocol}://{ip}:{args.port}{url_params}")
|
321
|
+
|
322
|
+
|
323
|
+
def is_port_in_use(address, port):
|
324
|
+
with socket(AF_INET, SOCK_STREAM) as s:
|
325
|
+
return s.connect_ex((address, port)) == 0
|
326
|
+
|
327
|
+
|
301
328
|
def parseargs():
|
302
|
-
global app, args, COMMAND_STATUS_DIR
|
329
|
+
global app, args, COMMAND_STATUS_DIR, hostname, ip
|
303
330
|
|
304
331
|
parser = argparse.ArgumentParser(description='Run the command execution server.')
|
305
332
|
parser.add_argument('-u', '--user', help='Username for basic auth')
|
@@ -344,15 +371,14 @@ def parseargs():
|
|
344
371
|
os.mkdir(COMMAND_STATUS_DIR, mode=0o700)
|
345
372
|
if args.action == "term":
|
346
373
|
COMMAND_STATUS_DIR = f"{os.getcwd()}/{COMMAND_STATUS_DIR}"
|
347
|
-
sys.exit(start_term())
|
374
|
+
sys.exit(start_term(str(uuid.uuid4())))
|
375
|
+
|
348
376
|
(hostname, ip) = resolve(gethostname()) if args.listen == '0.0.0.0' else resolve(args.listen)
|
349
|
-
url_params = ""
|
350
377
|
|
351
378
|
if args.tokenurl:
|
352
379
|
token = os.environ.get("PYWEBEXEC_TOKEN", token_urlsafe())
|
353
380
|
os.environ["PYWEBEXEC_TOKEN"] = token
|
354
381
|
app.config["TOKEN_URL"] = token
|
355
|
-
url_params = f"?token={token}"
|
356
382
|
|
357
383
|
if args.gencert:
|
358
384
|
args.cert = args.cert or f"{CONFDIR}/pywebexec.crt"
|
@@ -375,12 +401,6 @@ def parseargs():
|
|
375
401
|
app.config['USER'] = None
|
376
402
|
app.config['PASSWORD'] = None
|
377
403
|
|
378
|
-
if args.action != 'stop':
|
379
|
-
print("Starting server:")
|
380
|
-
protocol = 'https' if args.cert else 'http'
|
381
|
-
print(f"{protocol}://{hostname}:{args.port}{url_params}")
|
382
|
-
print(f"{protocol}://{ip}:{args.port}{url_params}")
|
383
|
-
|
384
404
|
return args
|
385
405
|
|
386
406
|
def get_status_file_path(command_id):
|
@@ -700,18 +720,28 @@ def popup(command_id):
|
|
700
720
|
def main():
|
701
721
|
global COMMAND_STATUS_DIR
|
702
722
|
basef = f"{CONFDIR}/pywebexec_{args.listen}:{args.port}"
|
723
|
+
if args.action == "restart":
|
724
|
+
daemon_d('stop', pidfilepath=basef)
|
725
|
+
args.action = "start"
|
726
|
+
port_used = is_port_in_use(args.listen, args.port)
|
727
|
+
if args.action != "stop":
|
728
|
+
print("Starting server:")
|
729
|
+
print_urls()
|
730
|
+
if args.action != "stop" and port_used:
|
731
|
+
print(f"Error: port {args.port} already in use", file=sys.stderr)
|
732
|
+
return 1
|
703
733
|
if args.action == "shareterm":
|
704
734
|
COMMAND_STATUS_DIR = f"{os.getcwd()}/{COMMAND_STATUS_DIR}"
|
705
735
|
with open(basef + ".log", "ab+") as log:
|
706
736
|
pywebexec = subprocess.Popen([sys.executable] + sys.argv[:-1], stdout=log, stderr=log)
|
707
|
-
|
737
|
+
command_id = str(uuid.uuid4())
|
738
|
+
print_urls(command_id)
|
739
|
+
res = start_term(command_id)
|
740
|
+
print("Stopping server")
|
708
741
|
time.sleep(1)
|
709
742
|
pywebexec.terminate()
|
710
|
-
sys.exit()
|
743
|
+
sys.exit(res)
|
711
744
|
|
712
|
-
if args.action == "restart":
|
713
|
-
daemon_d('stop', pidfilepath=basef)
|
714
|
-
args.action = "start"
|
715
745
|
if args.action == "start":
|
716
746
|
return start_gunicorn(daemonized=True, baselog=basef)
|
717
747
|
if args.action:
|
@@ -720,5 +750,5 @@ def main():
|
|
720
750
|
|
721
751
|
|
722
752
|
if __name__ == '__main__':
|
723
|
-
main()
|
753
|
+
sys.exit(main())
|
724
754
|
# app.run(host='0.0.0.0', port=5000)
|
pywebexec/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
|
2
|
-
pywebexec/pywebexec.py,sha256=
|
3
|
-
pywebexec/version.py,sha256=
|
2
|
+
pywebexec/pywebexec.py,sha256=KDvV9_Gbp016p_3clO_-b59j0fSyk4nbPNJK1ehfKsc,28102
|
3
|
+
pywebexec/version.py,sha256=GV6XwJnZtaCHeM6MpSSHX9ZtGIZAtVvtA-5uewZQic0,413
|
4
4
|
pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
|
5
5
|
pywebexec/static/css/style.css,sha256=cGJHPFj23SQ_bFpesfUaFA3VFxhXtpRUOL_zzx3x_X8,5726
|
6
6
|
pywebexec/static/css/xterm.css,sha256=gy8_LGA7Q61DUf8ElwFQzHqHMBQnbbEmpgZcbdgeSHI,5383
|
@@ -23,9 +23,9 @@ pywebexec/static/js/xterm/xterm.js,sha256=Bzka76jZwEhVt_LlS0e0qMw7ryGa1p5qfxFyeo
|
|
23
23
|
pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
24
|
pywebexec/templates/index.html,sha256=DYtT555wSNhnFtzzHhPMWJireynCJNnAuTytpoORQeE,2321
|
25
25
|
pywebexec/templates/popup.html,sha256=T6_tAOUoA58sA1oxB5pb8i42RenoMdCsH8T86Gccb6Q,945
|
26
|
-
pywebexec-1.4.
|
27
|
-
pywebexec-1.4.
|
28
|
-
pywebexec-1.4.
|
29
|
-
pywebexec-1.4.
|
30
|
-
pywebexec-1.4.
|
31
|
-
pywebexec-1.4.
|
26
|
+
pywebexec-1.4.15.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
|
27
|
+
pywebexec-1.4.15.dist-info/METADATA,sha256=kak3uf5US-34yqqjx7GsyY_tW1AiUF9yJMDSs5n6TLY,7801
|
28
|
+
pywebexec-1.4.15.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
29
|
+
pywebexec-1.4.15.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
|
30
|
+
pywebexec-1.4.15.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
|
31
|
+
pywebexec-1.4.15.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|