pywebexec 0.0.7__tar.gz → 0.0.8__tar.gz
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-0.0.7/pywebexec.egg-info → pywebexec-0.0.8}/PKG-INFO +3 -2
- {pywebexec-0.0.7 → pywebexec-0.0.8}/README.md +1 -1
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pyproject.toml +1 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/pywebexec.py +40 -7
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/version.py +2 -2
- {pywebexec-0.0.7 → pywebexec-0.0.8/pywebexec.egg-info}/PKG-INFO +3 -2
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec.egg-info/requires.txt +1 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/.github/workflows/python-publish.yml +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/.gitignore +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/LICENSE +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/__init__.py +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/static/images/aborted.svg +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/static/images/copy.svg +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/static/images/copy_ok.svg +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/static/images/failed.svg +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/static/images/running.svg +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/static/images/success.svg +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/templates/__init__.py +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec/templates/index.html +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec.egg-info/SOURCES.txt +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec.egg-info/dependency_links.txt +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec.egg-info/entry_points.txt +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/pywebexec.egg-info/top_level.txt +0 -0
- {pywebexec-0.0.7 → pywebexec-0.0.8}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: pywebexec
|
|
3
|
-
Version: 0.0.
|
|
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
|
|
131
|
+
* log of server are stored in directory `[.config/].pywebexec/pywebexec_<listen>:<port>.log`
|
|
131
132
|
|
|
@@ -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(
|
|
33
|
+
class StandaloneApplication(Application):
|
|
29
34
|
|
|
30
35
|
def __init__(self, app, options=None):
|
|
31
36
|
self.options = options or {}
|
|
@@ -44,13 +49,25 @@ 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
|
|
|
@@ -86,7 +103,10 @@ def daemon_d(action, pidfilepath, hostname=None, args=None):
|
|
|
86
103
|
working_directory=os.getcwd(),
|
|
87
104
|
)
|
|
88
105
|
with daemon_context:
|
|
89
|
-
|
|
106
|
+
try:
|
|
107
|
+
start_gunicorn()
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print(e)
|
|
90
110
|
|
|
91
111
|
def parseargs():
|
|
92
112
|
global app, args
|
|
@@ -114,6 +134,15 @@ def parseargs():
|
|
|
114
134
|
parser.add_argument("action", nargs="?", help="daemon action start/stop/restart/status", choices=["start","stop","restart","status"])
|
|
115
135
|
|
|
116
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)
|
|
117
146
|
|
|
118
147
|
if args.user:
|
|
119
148
|
app.config['USER'] = args.user
|
|
@@ -317,10 +346,14 @@ def verify_password(username, password):
|
|
|
317
346
|
return username == app.config['USER'] and password == app.config['PASSWORD']
|
|
318
347
|
|
|
319
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)
|
|
320
354
|
if args.action:
|
|
321
|
-
daemon_d(args.action, pidfilepath=
|
|
322
|
-
|
|
323
|
-
start_gunicorn()
|
|
355
|
+
return daemon_d(args.action, pidfilepath=basef)
|
|
356
|
+
return start_gunicorn()
|
|
324
357
|
|
|
325
358
|
if __name__ == '__main__':
|
|
326
359
|
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: pywebexec
|
|
3
|
-
Version: 0.0.
|
|
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
|
|
131
|
+
* log of server are stored in directory `[.config/].pywebexec/pywebexec_<listen>:<port>.log`
|
|
131
132
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|