pywebexec 1.4.10__py3-none-any.whl → 1.4.11__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
@@ -22,6 +22,7 @@ import signal
22
22
  import fcntl
23
23
  import termios
24
24
  import struct
25
+ import subprocess
25
26
 
26
27
 
27
28
  if os.environ.get('PYWEBEXEC_LDAP_SERVER'):
@@ -40,6 +41,7 @@ app.config['LDAP_BIND_DN'] = os.environ.get('PYWEBEXEC_LDAP_BIND_DN')
40
41
  app.config['LDAP_BIND_PASSWORD'] = os.environ.get('PYWEBEXEC_LDAP_BIND_PASSWORD')
41
42
 
42
43
  # Directory to store the command status and output
44
+ CWD = os.getcwd()
43
45
  COMMAND_STATUS_DIR = '.web_status'
44
46
  CONFDIR = os.path.expanduser("~/")
45
47
  if os.path.isdir(f"{CONFDIR}/.config"):
@@ -216,17 +218,19 @@ def get_last_non_empty_line_of_file(file_path):
216
218
 
217
219
 
218
220
  def start_gunicorn(daemonized=False, baselog=None):
221
+ pidfile = f"{baselog}.pid"
219
222
  if daemonized:
220
- errorlog = f"{baselog}.log"
221
- accesslog = None # f"{baselog}.access.log"
222
- pidfile = f"{baselog}.pid"
223
223
  if daemon_d('status', pidfilepath=baselog, silent=True):
224
224
  print(f"Error: pywebexec already running on {args.listen}:{args.port}", file=sys.stderr)
225
225
  sys.exit(1)
226
- else:
226
+
227
+ if sys.stdout.isatty():
227
228
  errorlog = "-"
228
229
  accesslog = None #"-"
229
- pidfile = None
230
+ else:
231
+ errorlog = f"{baselog}.log"
232
+ accesslog = None # f"{baselog}.access.log"
233
+
230
234
  options = {
231
235
  'bind': '%s:%s' % (args.listen, args.port),
232
236
  'workers': 4,
@@ -280,6 +284,18 @@ def daemon_d(action, pidfilepath, silent=False, hostname=None, args=None):
280
284
  except Exception as e:
281
285
  print(e)
282
286
 
287
+ def start_term():
288
+ os.chdir(CWD)
289
+ command_id = str(uuid.uuid4())
290
+ start_time = datetime.now().isoformat()
291
+ user = pwd.getpwuid(os.getuid())[0]
292
+ update_command_status(command_id, 'running', command="term", params=[user,os.ttyname(sys.stdout.fileno())], start_time=start_time, user=user)
293
+ output_file_path = get_output_file_path(command_id)
294
+ res = script(output_file_path)
295
+ end_time = datetime.now().isoformat()
296
+ update_command_status(command_id, status="success", end_time=end_time, exit_code=res)
297
+ return res
298
+
283
299
  def parseargs():
284
300
  global app, args, COMMAND_STATUS_DIR
285
301
 
@@ -306,10 +322,10 @@ def parseargs():
306
322
  parser.add_argument("-k", "--key", type=str, help="Path to https certificate key")
307
323
  parser.add_argument("-g", "--gencert", action="store_true", help="https server self signed cert")
308
324
  parser.add_argument("-T", "--tokenurl", action="store_true", help="generate safe url to access")
309
- parser.add_argument("action", nargs="?", help="daemon action start/stop/restart/status/term", choices=["start","stop","restart","status","term"])
325
+ parser.add_argument("action", nargs="?", help="daemon action start/stop/restart/status/shareterm/term",
326
+ choices=["start","stop","restart","status","shareterm", "term"])
310
327
 
311
328
  args = parser.parse_args()
312
- cwd = os.getcwd()
313
329
  if os.path.isdir(args.dir):
314
330
  try:
315
331
  os.chdir(args.dir)
@@ -325,21 +341,13 @@ def parseargs():
325
341
  os.mkdir(CONFDIR, mode=0o700)
326
342
  if args.action == "term":
327
343
  COMMAND_STATUS_DIR = f"{os.getcwd()}/{COMMAND_STATUS_DIR}"
328
- os.chdir(cwd)
329
- command_id = str(uuid.uuid4())
330
- start_time = datetime.now().isoformat()
331
- user = pwd.getpwuid(os.getuid())[0]
332
- update_command_status(command_id, 'running', command="term", params=[user,os.ttyname(sys.stdout.fileno())], start_time=start_time, user=user)
333
- output_file_path = get_output_file_path(command_id)
334
- res = script(output_file_path)
335
- end_time = datetime.now().isoformat()
336
- update_command_status(command_id, status="success", end_time=end_time, exit_code=res)
337
- sys.exit(res)
344
+ sys.exit(start_term())
338
345
  (hostname, ip) = resolve(gethostname()) if args.listen == '0.0.0.0' else resolve(args.listen)
339
346
  url_params = ""
340
347
 
341
348
  if args.tokenurl:
342
- token = token_urlsafe()
349
+ token = os.environ.get("PYWEBEXEC_TOKEN", token_urlsafe())
350
+ os.environ["PYWEBEXEC_TOKEN"] = token
343
351
  app.config["TOKEN_URL"] = token
344
352
  url_params = f"?token={token}"
345
353
 
@@ -688,12 +696,25 @@ def popup(command_id):
688
696
  return render_template('popup.html', command_id=command_id)
689
697
 
690
698
  def main():
699
+ global COMMAND_STATUS_DIR
691
700
  basef = f"{CONFDIR}/pywebexec_{args.listen}:{args.port}"
701
+ if args.action == "shareterm":
702
+ COMMAND_STATUS_DIR = f"{os.getcwd()}/{COMMAND_STATUS_DIR}"
703
+ with open(basef + ".log", "ab+") as log:
704
+ pywebexec = subprocess.Popen([sys.executable] + sys.argv[:-1], stdout=log, stderr=log)
705
+ start_term()
706
+ pywebexec.terminate()
707
+ sys.exit()
708
+
709
+ if args.action == "restart":
710
+ daemon_d('stop', pidfilepath=basef)
711
+ args.action = "start"
692
712
  if args.action == "start":
693
713
  return start_gunicorn(daemonized=True, baselog=basef)
694
714
  if args.action:
695
715
  return daemon_d(args.action, pidfilepath=basef)
696
- return start_gunicorn()
716
+ return start_gunicorn(baselog=basef)
717
+
697
718
 
698
719
  if __name__ == '__main__':
699
720
  main()
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 = '1.4.10'
16
- __version_tuple__ = version_tuple = (1, 4, 10)
15
+ __version__ = version = '1.4.11'
16
+ __version_tuple__ = version_tuple = (1, 4, 11)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 1.4.10
3
+ Version: 1.4.11
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -113,6 +113,18 @@ $ pywebexec --dir ~/myscripts --listen 0.0.0.0 --port 8080 --title myscripts
113
113
  $ pywebexec -d ~/myscripts -l 0.0.0.0 -p 8080 -t myscripts
114
114
  ```
115
115
 
116
+ ## Sharing terminals
117
+
118
+ * start server and share tty in one command
119
+ ```shell
120
+ $ pywebexec -d ~/webshare shareterm
121
+ ```
122
+ * share tty with an already pywebexec server started
123
+ ```shell
124
+ $ pywebexec -d ~/webshare term
125
+ ```
126
+ if another user need to share his terminal, he need to have write permission on `<dir>/.web_status` directory.
127
+
116
128
  ## Safe url token
117
129
 
118
130
  * generate safe url, use the url to access the server
@@ -1,6 +1,6 @@
1
1
  pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
2
- pywebexec/pywebexec.py,sha256=7N8cq8qDn7z9mXXWVAOd-eijNAkd-EYvWBGKKSOWeTQ,26211
3
- pywebexec/version.py,sha256=PSfQzSIY-TCmDuz8UpHfMXvNhO-iyRNDmP7WVYUSfx8,413
2
+ pywebexec/pywebexec.py,sha256=gZNUbNeFI2TWimUXmHva9ABHv8S4QH_xiUXOWKlswJM,26843
3
+ pywebexec/version.py,sha256=CiEe7E8jVlrB3YZUumeEso6PXucVNqiDDQfL8kleYok,413
4
4
  pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
5
5
  pywebexec/static/css/style.css,sha256=sDBhZ-csW5THIKfTDsHqxCSg6rIJ91Oh15sjw_HjJo4,5702
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=6kmZKb0tGJ7jsr9DqDEriSMlbkW-PJTtCiUE9U5_FOE,837
26
- pywebexec-1.4.10.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
27
- pywebexec-1.4.10.dist-info/METADATA,sha256=_S8L2p92CQ1byTr4-reMaJRQZ2V14zem_j65ZUawpgU,7400
28
- pywebexec-1.4.10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
29
- pywebexec-1.4.10.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
30
- pywebexec-1.4.10.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
31
- pywebexec-1.4.10.dist-info/RECORD,,
26
+ pywebexec-1.4.11.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
27
+ pywebexec-1.4.11.dist-info/METADATA,sha256=g3K50Awl5n3qkU5zltFdfS_d5w7GbV_pRbhrsKO2HPo,7724
28
+ pywebexec-1.4.11.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
29
+ pywebexec-1.4.11.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
30
+ pywebexec-1.4.11.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
31
+ pywebexec-1.4.11.dist-info/RECORD,,