vssh 3.3.7__tar.gz → 3.3.9__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.
- {vssh-3.3.7/vssh.egg-info → vssh-3.3.9}/PKG-INFO +1 -1
- {vssh-3.3.7 → vssh-3.3.9}/pyproject.toml +1 -1
- {vssh-3.3.7 → vssh-3.3.9/vssh.egg-info}/PKG-INFO +1 -1
- {vssh-3.3.7 → vssh-3.3.9}/vssh.py +117 -71
- {vssh-3.3.7 → vssh-3.3.9}/LICENSE +0 -0
- {vssh-3.3.7 → vssh-3.3.9}/README.md +0 -0
- {vssh-3.3.7 → vssh-3.3.9}/setup.cfg +0 -0
- {vssh-3.3.7 → vssh-3.3.9}/vssh.egg-info/SOURCES.txt +0 -0
- {vssh-3.3.7 → vssh-3.3.9}/vssh.egg-info/dependency_links.txt +0 -0
- {vssh-3.3.7 → vssh-3.3.9}/vssh.egg-info/entry_points.txt +0 -0
- {vssh-3.3.7 → vssh-3.3.9}/vssh.egg-info/top_level.txt +0 -0
- {vssh-3.3.7 → vssh-3.3.9}/vssh_mcp_server.py +0 -0
- {vssh-3.3.7 → vssh-3.3.9}/vssh_p2p.py +0 -0
|
@@ -12,6 +12,8 @@ from pathlib import Path
|
|
|
12
12
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
13
13
|
from typing import Tuple, Optional
|
|
14
14
|
|
|
15
|
+
__version__ = '3.3.9'
|
|
16
|
+
|
|
15
17
|
# ========== Standalone Config (no mpop dependency) ==========
|
|
16
18
|
VSSH_DIR_CONF = Path.home() / '.vssh'
|
|
17
19
|
|
|
@@ -3339,113 +3341,157 @@ def server():
|
|
|
3339
3341
|
|
|
3340
3342
|
|
|
3341
3343
|
def _cmd_install(args):
|
|
3342
|
-
"""Install vssh as a system daemon
|
|
3343
|
-
import sys as _sys, os as _os, platform as _plat, subprocess as _sp,
|
|
3344
|
+
"""Install/upgrade vssh as a system daemon. Idempotent — safe to re-run."""
|
|
3345
|
+
import sys as _sys, os as _os, platform as _plat, subprocess as _sp, shutil as _sh
|
|
3344
3346
|
|
|
3345
3347
|
python_exe = _sys.executable
|
|
3346
|
-
vssh_py = _os.path.abspath(__file__)
|
|
3347
3348
|
secret = _load_vssh_secret()
|
|
3349
|
+
sf = VSSH_DIR_CONF / 'secret'
|
|
3350
|
+
secret_src = 'env' if _os.environ.get('VSSH_SECRET') else ('file' if sf.exists() else 'auto-generated')
|
|
3348
3351
|
|
|
3349
3352
|
print(f"[vssh install]")
|
|
3350
3353
|
print(f" python : {python_exe}")
|
|
3351
|
-
print(f"
|
|
3352
|
-
print(f" secret : {secret[:6]}...{secret[-4:]} ({'auto-generated' if not _os.environ.get('VSSH_SECRET') else 'from env'})")
|
|
3354
|
+
print(f" secret : {secret[:6]}...{secret[-4:]} ({secret_src})")
|
|
3353
3355
|
|
|
3356
|
+
# --- Step 1: Upgrade pip package ---
|
|
3357
|
+
print(f" pip : upgrading vssh...")
|
|
3358
|
+
pip_args = [python_exe, '-m', 'pip', 'install', 'vssh', '--upgrade', '-q']
|
|
3354
3359
|
if _plat.system() == 'Linux':
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3360
|
+
pip_args.append('--break-system-packages')
|
|
3361
|
+
r = _sp.run(pip_args, capture_output=True, text=True)
|
|
3362
|
+
if r.returncode == 0:
|
|
3363
|
+
print(f" pip : \u2713 ok")
|
|
3364
|
+
else:
|
|
3365
|
+
print(f" pip : \u2717 {r.stderr.strip()[:120]}")
|
|
3366
|
+
|
|
3367
|
+
# --- Step 2: Find installed vssh.py (after upgrade) ---
|
|
3368
|
+
import importlib, importlib.util as _ilu
|
|
3369
|
+
try:
|
|
3370
|
+
importlib.invalidate_caches()
|
|
3371
|
+
spec = _ilu.find_spec('vssh')
|
|
3372
|
+
installed_py = spec.origin if (spec and spec.origin) else _os.path.abspath(__file__)
|
|
3373
|
+
except Exception:
|
|
3374
|
+
installed_py = _os.path.abspath(__file__)
|
|
3375
|
+
|
|
3376
|
+
# --- Step 3: Copy vssh.py to /usr/local/bin/vssh.py ---
|
|
3377
|
+
target_py = '/usr/local/bin/vssh.py'
|
|
3378
|
+
try:
|
|
3379
|
+
_sh.copy2(installed_py, target_py)
|
|
3380
|
+
_os.chmod(target_py, 0o755)
|
|
3381
|
+
print(f" copied : {installed_py} \u2192 {target_py}")
|
|
3382
|
+
except PermissionError:
|
|
3383
|
+
print(f" warning : cannot write {target_py} (need root) — using {installed_py}")
|
|
3384
|
+
target_py = installed_py
|
|
3385
|
+
|
|
3386
|
+
# --- Step 4: Create /usr/local/bin/vssh wrapper with explicit python path ---
|
|
3387
|
+
wrapper = '/usr/local/bin/vssh'
|
|
3388
|
+
wrapper_txt = f'#!/bin/sh\nexec {python_exe} {target_py} "$@"\n'
|
|
3389
|
+
try:
|
|
3390
|
+
with open(wrapper, 'w') as _f:
|
|
3391
|
+
_f.write(wrapper_txt)
|
|
3392
|
+
_os.chmod(wrapper, 0o755)
|
|
3393
|
+
print(f" wrapper : {wrapper}")
|
|
3394
|
+
except PermissionError:
|
|
3395
|
+
print(f" warning : cannot write {wrapper} (need root)")
|
|
3396
|
+
|
|
3397
|
+
if _plat.system() == 'Linux':
|
|
3398
|
+
svc_lines = [
|
|
3399
|
+
"[Unit]", "Description=vssh daemon", "After=network.target", "",
|
|
3400
|
+
"[Service]", "Type=simple",
|
|
3401
|
+
f"ExecStart={python_exe} {target_py} server",
|
|
3402
|
+
f"Environment=\"VSSH_SECRET={secret}\"",
|
|
3403
|
+
"Restart=always", "RestartSec=5",
|
|
3404
|
+
"StandardOutput=journal", "StandardError=journal", "",
|
|
3405
|
+
"[Install]", "WantedBy=multi-user.target", "",
|
|
3406
|
+
]
|
|
3407
|
+
service = '\n'.join(svc_lines)
|
|
3371
3408
|
svc_path = '/etc/systemd/system/vssh.service'
|
|
3372
3409
|
try:
|
|
3373
|
-
with open(svc_path, 'w') as
|
|
3374
|
-
|
|
3375
|
-
print(f"
|
|
3410
|
+
with open(svc_path, 'w') as _f:
|
|
3411
|
+
_f.write(service)
|
|
3412
|
+
print(f" service : {svc_path}")
|
|
3376
3413
|
_sp.run(['systemctl', 'daemon-reload'], check=True, capture_output=True)
|
|
3377
3414
|
_sp.run(['systemctl', 'enable', 'vssh'], check=True, capture_output=True)
|
|
3378
3415
|
_sp.run(['systemctl', 'restart', 'vssh'], check=True, capture_output=True)
|
|
3379
3416
|
import time; time.sleep(1)
|
|
3380
3417
|
r = _sp.run(['systemctl', 'is-active', 'vssh'], capture_output=True, text=True)
|
|
3381
3418
|
status = r.stdout.strip()
|
|
3382
|
-
print(f"
|
|
3419
|
+
print(f" status : {status}")
|
|
3383
3420
|
if status == 'active':
|
|
3384
|
-
print("[vssh install]
|
|
3421
|
+
print("[vssh install] \u2713 Done. vssh daemon running.")
|
|
3385
3422
|
else:
|
|
3386
|
-
print("[vssh install]
|
|
3423
|
+
print("[vssh install] \u2717 Service not active — check: journalctl -u vssh -n 20")
|
|
3387
3424
|
except PermissionError:
|
|
3388
|
-
print("[vssh install]
|
|
3425
|
+
print("[vssh install] \u2717 Need root. Run: sudo vssh install")
|
|
3389
3426
|
except Exception as e:
|
|
3390
|
-
print(f"[vssh install]
|
|
3427
|
+
print(f"[vssh install] \u2717 Error: {e}")
|
|
3391
3428
|
|
|
3392
3429
|
elif _plat.system() == 'Darwin':
|
|
3393
3430
|
home = _os.path.expanduser('~')
|
|
3394
3431
|
plist_dir = _os.path.join(home, 'Library', 'LaunchAgents')
|
|
3395
3432
|
_os.makedirs(plist_dir, exist_ok=True)
|
|
3396
3433
|
plist_path = _os.path.join(plist_dir, 'com.vssh.server.plist')
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
<
|
|
3401
|
-
|
|
3402
|
-
<
|
|
3403
|
-
<
|
|
3404
|
-
<
|
|
3405
|
-
|
|
3406
|
-
<string>{
|
|
3407
|
-
<string>
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
<
|
|
3411
|
-
|
|
3412
|
-
<
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
<
|
|
3416
|
-
<
|
|
3417
|
-
<
|
|
3418
|
-
<
|
|
3419
|
-
<
|
|
3420
|
-
<
|
|
3421
|
-
<
|
|
3422
|
-
</
|
|
3423
|
-
</
|
|
3424
|
-
|
|
3434
|
+
plist_lines = [
|
|
3435
|
+
'<?xml version="1.0" encoding="UTF-8"?>',
|
|
3436
|
+
'<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">',
|
|
3437
|
+
'<plist version="1.0">',
|
|
3438
|
+
'<dict>',
|
|
3439
|
+
' <key>Label</key>',
|
|
3440
|
+
' <string>com.vssh.server</string>',
|
|
3441
|
+
' <key>ProgramArguments</key>',
|
|
3442
|
+
' <array>',
|
|
3443
|
+
f' <string>{python_exe}</string>',
|
|
3444
|
+
f' <string>{target_py}</string>',
|
|
3445
|
+
' <string>server</string>',
|
|
3446
|
+
' </array>',
|
|
3447
|
+
' <key>EnvironmentVariables</key>',
|
|
3448
|
+
' <dict>',
|
|
3449
|
+
' <key>VSSH_SECRET</key>',
|
|
3450
|
+
f' <string>{secret}</string>',
|
|
3451
|
+
' </dict>',
|
|
3452
|
+
' <key>RunAtLoad</key>',
|
|
3453
|
+
' <true/>',
|
|
3454
|
+
' <key>KeepAlive</key>',
|
|
3455
|
+
' <true/>',
|
|
3456
|
+
' <key>StandardOutPath</key>',
|
|
3457
|
+
' <string>/tmp/vssh.log</string>',
|
|
3458
|
+
' <key>StandardErrorPath</key>',
|
|
3459
|
+
' <string>/tmp/vssh.err</string>',
|
|
3460
|
+
'</dict>',
|
|
3461
|
+
'</plist>',
|
|
3462
|
+
]
|
|
3463
|
+
plist = '\n'.join(plist_lines)
|
|
3464
|
+
# Also fix pip entry point if it exists (may use wrong Python)
|
|
3465
|
+
for ep in [_os.path.join(_os.path.dirname(python_exe), 'vssh'),
|
|
3466
|
+
'/opt/homebrew/bin/vssh', '/usr/local/bin/vssh']:
|
|
3467
|
+
if ep != wrapper and _os.path.exists(ep):
|
|
3468
|
+
try:
|
|
3469
|
+
_sh.copy2(wrapper, ep)
|
|
3470
|
+
_os.chmod(ep, 0o755)
|
|
3471
|
+
print(f" fixed : {ep}")
|
|
3472
|
+
except Exception:
|
|
3473
|
+
pass
|
|
3425
3474
|
_sp.run(['launchctl', 'unload', plist_path], capture_output=True)
|
|
3426
|
-
with open(plist_path, 'w') as
|
|
3427
|
-
|
|
3428
|
-
print(f"
|
|
3475
|
+
with open(plist_path, 'w') as _f:
|
|
3476
|
+
_f.write(plist)
|
|
3477
|
+
print(f" plist : {plist_path}")
|
|
3429
3478
|
r = _sp.run(['launchctl', 'load', plist_path], capture_output=True, text=True)
|
|
3430
3479
|
if r.returncode == 0:
|
|
3431
3480
|
import time; time.sleep(1)
|
|
3432
|
-
r2 = _sp.run(['pgrep', '-f', '
|
|
3481
|
+
r2 = _sp.run(['pgrep', '-f', f'{target_py} server'], capture_output=True, text=True)
|
|
3433
3482
|
if r2.stdout.strip():
|
|
3434
|
-
print("[vssh install]
|
|
3483
|
+
print("[vssh install] \u2713 Done. vssh daemon running.")
|
|
3435
3484
|
else:
|
|
3436
|
-
print("[vssh install]
|
|
3485
|
+
print("[vssh install] \u2717 Process not found — check: cat /tmp/vssh.err")
|
|
3437
3486
|
else:
|
|
3438
|
-
print(f"[vssh install]
|
|
3487
|
+
print(f"[vssh install] \u2717 launchctl error: {r.stderr.strip()}")
|
|
3439
3488
|
else:
|
|
3440
|
-
print(f"[vssh install]
|
|
3489
|
+
print(f"[vssh install] \u2717 Unsupported OS: {_plat.system()}")
|
|
3441
3490
|
|
|
3442
3491
|
|
|
3443
3492
|
def _get_vssh_version():
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
return _v('vssh')
|
|
3447
|
-
except Exception:
|
|
3448
|
-
return '?'
|
|
3493
|
+
return __version__
|
|
3494
|
+
|
|
3449
3495
|
|
|
3450
3496
|
|
|
3451
3497
|
def main():
|
|
@@ -3456,7 +3502,7 @@ def main():
|
|
|
3456
3502
|
from importlib.metadata import version as _v
|
|
3457
3503
|
print(f"vssh v{_v('vssh')}")
|
|
3458
3504
|
except Exception:
|
|
3459
|
-
print("vssh
|
|
3505
|
+
print(f"vssh v{__version__}")
|
|
3460
3506
|
return
|
|
3461
3507
|
if not args:
|
|
3462
3508
|
print('''vssh v3 - Distributed command & file transport daemon for server meshes
|
|
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
|