pywebexec 0.0.6__py3-none-any.whl → 0.0.8__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 CHANGED
@@ -1,3 +1,4 @@
1
+ import sys
1
2
  from flask import Flask, request, jsonify, render_template
2
3
  from flask_httpauth import HTTPBasicAuth
3
4
  import subprocess
@@ -10,13 +11,17 @@ import random
10
11
  import string
11
12
  from datetime import datetime
12
13
  import shlex
13
- from gunicorn.app.base import BaseApplication
14
+ from gunicorn.app.base import BaseApplication, Application
14
15
 
15
16
  app = Flask(__name__)
16
17
  auth = HTTPBasicAuth()
17
18
 
18
19
  # Directory to store the script status and output
19
20
  SCRIPT_STATUS_DIR = '.web_status'
21
+ CONFDIR = os.path.expanduser("~/")
22
+ if os.path.isdir(f"{CONFDIR}/.config"):
23
+ CONFDIR += '/.config'
24
+ CONFDIR += "/.pywebexec"
20
25
 
21
26
  if not os.path.exists(SCRIPT_STATUS_DIR):
22
27
  os.makedirs(SCRIPT_STATUS_DIR)
@@ -25,7 +30,7 @@ def generate_random_password(length=12):
25
30
  characters = string.ascii_letters + string.digits + string.punctuation
26
31
  return ''.join(random.choice(characters) for i in range(length))
27
32
 
28
- class StandaloneApplication(BaseApplication):
33
+ class StandaloneApplication(Application):
29
34
 
30
35
  def __init__(self, app, options=None):
31
36
  self.options = options or {}
@@ -44,16 +49,65 @@ class StandaloneApplication(BaseApplication):
44
49
  return self.application
45
50
 
46
51
 
47
- def start_gunicorn():
52
+ def start_gunicorn(daemon=False, baselog=None):
53
+ if daemon:
54
+ errorlog = f"{baselog}.log"
55
+ accesslog = None # f"{baselog}.access.log"
56
+ pidfile = f"{baselog}.pid"
57
+ else:
58
+ errorlog = "-"
59
+ accesslog = "-"
60
+ pidfile = None
48
61
  options = {
49
62
  'bind': '%s:%s' % (args.listen, args.port),
50
63
  'workers': 4,
51
64
  'timeout': 600,
52
65
  'certfile': args.cert,
53
66
  'keyfile': args.key,
67
+ 'daemon': daemon,
68
+ 'errorlog': errorlog,
69
+ 'accesslog': accesslog,
70
+ 'pidfile': pidfile,
54
71
  }
55
72
  StandaloneApplication(app, options=options).run()
56
73
 
74
+ def daemon_d(action, pidfilepath, hostname=None, args=None):
75
+ """start/stop daemon"""
76
+ import signal
77
+ import daemon, daemon.pidfile
78
+
79
+ pidfile = daemon.pidfile.TimeoutPIDLockFile(pidfilepath+".pid", acquire_timeout=30)
80
+ if action == "stop":
81
+ if pidfile.is_locked():
82
+ pid = pidfile.read_pid()
83
+ print(f"Stopping server pid {pid}")
84
+ try:
85
+ os.kill(pid, signal.SIGINT)
86
+ except:
87
+ return False
88
+ return True
89
+ elif action == "status":
90
+ status = pidfile.is_locked()
91
+ if status:
92
+ print(f"pywebexec running pid {pidfile.read_pid()}")
93
+ return True
94
+ print("pywebexec not running")
95
+ return False
96
+ elif action == "start":
97
+ print(f"Starting server")
98
+ log = open(pidfilepath + ".log", "ab+")
99
+ daemon_context = daemon.DaemonContext(
100
+ stderr=log,
101
+ pidfile=pidfile,
102
+ umask=0o077,
103
+ working_directory=os.getcwd(),
104
+ )
105
+ with daemon_context:
106
+ try:
107
+ start_gunicorn()
108
+ except Exception as e:
109
+ print(e)
110
+
57
111
  def parseargs():
58
112
  global app, args
59
113
  parser = argparse.ArgumentParser(description='Run the script execution server.')
@@ -77,8 +131,18 @@ def parseargs():
77
131
  )
78
132
  parser.add_argument("-c", "--cert", type=str, help="Path to https certificate")
79
133
  parser.add_argument("-k", "--key", type=str, help="Path to https certificate key")
134
+ parser.add_argument("action", nargs="?", help="daemon action start/stop/restart/status", choices=["start","stop","restart","status"])
80
135
 
81
136
  args = parser.parse_args()
137
+ if os.path.isdir(args.dir):
138
+ try:
139
+ os.chdir(args.dir)
140
+ except OSError:
141
+ print(f"Error: cannot chdir {args.dir}", file=sys.stderr)
142
+ sys.exit(1)
143
+ else:
144
+ print(f"Error: {args.dir} not found", file=sys.stderr)
145
+ sys.exit(1)
82
146
 
83
147
  if args.user:
84
148
  app.config['USER'] = args.user
@@ -281,6 +345,16 @@ def list_executables():
281
345
  def verify_password(username, password):
282
346
  return username == app.config['USER'] and password == app.config['PASSWORD']
283
347
 
348
+ def main():
349
+ basef = f"{CONFDIR}/pywebexec_{args.listen}:{args.port}"
350
+ if not os.path.exists(CONFDIR):
351
+ os.mkdir(CONFDIR, mode=0o700)
352
+ if args.action == "start":
353
+ return start_gunicorn(daemon=True, baselog=basef)
354
+ if args.action:
355
+ return daemon_d(args.action, pidfilepath=basef)
356
+ return start_gunicorn()
357
+
284
358
  if __name__ == '__main__':
285
- start_gunicorn()
286
- #app.run(host='0.0.0.0', port=5000)
359
+ main()
360
+ # app.run(host='0.0.0.0', port=5000)
pywebexec/version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.0.6'
16
- __version_tuple__ = version_tuple = (0, 0, 6)
15
+ __version__ = version = '0.0.8'
16
+ __version_tuple__ = version_tuple = (0, 0, 8)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 0.0.6
3
+ Version: 0.0.8
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -53,6 +53,7 @@ Classifier: Topic :: System :: Systems Administration
53
53
  Requires-Python: >=3.6
54
54
  Description-Content-Type: text/markdown
55
55
  License-File: LICENSE
56
+ Requires-Dist: python-daemon>=2.3.2
56
57
  Requires-Dist: cryptography>=40.0.2
57
58
  Requires-Dist: Flask>=3.0.3
58
59
  Requires-Dist: Flask-HTTPAuth>=4.8.0
@@ -127,5 +128,5 @@ $ pywebexec start
127
128
  $ pywebexec status
128
129
  $ pywebexec stop
129
130
  ```
130
- * log of server are stored in current directory `.web_status/pwexec_<listen>:<port>.log`
131
+ * log of server are stored in directory `[.config/].pywebexec/pywebexec_<listen>:<port>.log`
131
132
 
@@ -1,6 +1,6 @@
1
1
  pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
2
- pywebexec/pywebexec.py,sha256=1LUPOuZXoXqM17-Cu-rYL05lOJy_5HqtIGqhxVyzdZY,10306
3
- pywebexec/version.py,sha256=c6ZQWSJeXXzGZ3WoZWjkA-MiNkBFXMIRV9kZPo4MQ_M,411
2
+ pywebexec/pywebexec.py,sha256=0aHoPOPB2fIFtZfcCv9L2G6m9NY0ndfyFt6bF43Y3yg,12736
3
+ pywebexec/version.py,sha256=qP2QJpgwFu26Ia9si7LC7nYHaW0_mvxka84OVyOuIKg,411
4
4
  pywebexec/static/images/aborted.svg,sha256=_mP43hU5QdRLFZIknBgjx-dIXrHgQG23-QV27ApXK2A,381
5
5
  pywebexec/static/images/copy.svg,sha256=d9OwtGh5GzzZHzYcDrLfNxZYLth1Q64x7bRyYxu4Px0,622
6
6
  pywebexec/static/images/copy_ok.svg,sha256=mEqUVUhSq8xaJK2msQkxRawnz_KwlCZ-tok8QS6hJ3g,451
@@ -9,9 +9,9 @@ pywebexec/static/images/running.svg,sha256=vBpiG6ClNUNCArkwsyqK7O-qhIKJX1NI7MSjc
9
9
  pywebexec/static/images/success.svg,sha256=PJDcCSTevJh7rkfSFLtc7P0pbeh8PVQBS8DaOLQemmc,489
10
10
  pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  pywebexec/templates/index.html,sha256=2peDmBnxZQSw6OjDCjNqRCx1_grDlI_Xr1NMgAGv2OI,10163
12
- pywebexec-0.0.6.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
13
- pywebexec-0.0.6.dist-info/METADATA,sha256=DQZhxqwFQhVWYOnPU6CmyNgIPZm4owp5O4AJx_ZSZWQ,4698
14
- pywebexec-0.0.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
15
- pywebexec-0.0.6.dist-info/entry_points.txt,sha256=-6--c27U7RARJe0BiW5CkTuKljf6pRtnDzE0wfmD9TM,65
16
- pywebexec-0.0.6.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
17
- pywebexec-0.0.6.dist-info/RECORD,,
12
+ pywebexec-0.0.8.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
13
+ pywebexec-0.0.8.dist-info/METADATA,sha256=OTe9tzdB_fvrCvtK7DhYhU-D5JHkEvNLy9ofMDZX4hM,4738
14
+ pywebexec-0.0.8.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
15
+ pywebexec-0.0.8.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
16
+ pywebexec-0.0.8.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
17
+ pywebexec-0.0.8.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pywebexec = pywebexec.pywebexec:main
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- pywebexec = pywebexec.pywebexec:start_gunicorn