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