feat: add pos usb server (USB Redirector control); fix doc/code drift
- new bin/pos-usb-server: flag-style control of usbsrv (--ls, --share, --unshare, --auto-share, --callback, --close-callback, --auto-connect, --disconnect, --nickname, --timeout, --port, --info, --version); interactive prompts fall back to args; command -v usbsrv guard - wire into bin/pos: usb category, example, INTERACTIVE_CMDS - completions: usb-server flag completion - docs: POS.md usb section, AGENT_Context tree/dispatch/table, README - fix: add pos-network-hotspot to no-common.sh list (was omitted) - fix: stale pos-docker-compose line count 317 -> 363 - fix: DEV.md/AGENT_Context note non-apt deps (command -v guard, not PACKAGES) - fix: document INTERACTIVE_CMDS all-or-nothing per-script trade-off - fix: usage() shows docker health (was missing from cheat-sheet)
This commit is contained in:
@@ -39,12 +39,13 @@ Linux_post_install/
|
|||||||
│ ├── pos-network-scan # Parallel ping sweep of CIDR subnet
|
│ ├── pos-network-scan # Parallel ping sweep of CIDR subnet
|
||||||
│ ├── pos-docker-ps # Enhanced docker ps (health, IPs, ports, uptime)
|
│ ├── pos-docker-ps # Enhanced docker ps (health, IPs, ports, uptime)
|
||||||
│ ├── pos-docker-health # Quick one-glance health dashboard
|
│ ├── pos-docker-health # Quick one-glance health dashboard
|
||||||
│ ├── pos-docker-compose # Docker Compose service manager (largest script, 317 lines)
|
│ ├── pos-docker-compose # Docker Compose service manager (largest script, 363 lines)
|
||||||
│ ├── pos-media-mp3 # Audio downloader (yt-dlp → MP3)
|
│ ├── pos-media-mp3 # Audio downloader (yt-dlp → MP3)
|
||||||
│ ├── pos-media-mp4 # Video downloader (yt-dlp → MP4, interactive format select)
|
│ ├── pos-media-mp4 # Video downloader (yt-dlp → MP4, interactive format select)
|
||||||
│ ├── pos-system-firewall # Interactive UFW manager (menu-driven, 284 lines)
|
│ ├── pos-system-firewall # Interactive UFW manager (menu-driven, 284 lines)
|
||||||
│ ├── pos-system-backup # Encrypted folder snapshots (tar + gpg AES-256, --service) (115 lines)
|
│ ├── pos-system-backup # Encrypted folder snapshots (tar + gpg AES-256, --service) (115 lines)
|
||||||
│ ├── pos-ssh-load-keys # Load SSH keys into ssh-agent
|
│ ├── pos-ssh-load-keys # Load SSH keys into ssh-agent
|
||||||
|
│ ├── pos-usb-server # USB Redirector server control (usbsrv)
|
||||||
│ ├── pos-communication-telegram # Send Telegram messages via Bot API
|
│ ├── pos-communication-telegram # Send Telegram messages via Bot API
|
||||||
│ ├── pos-docker-vbox # Disposable Docker-based "VMs" (pos docker vbox)
|
│ ├── pos-docker-vbox # Disposable Docker-based "VMs" (pos docker vbox)
|
||||||
│ ├── pos-network-hotspot # Wi-Fi hotspot (create_ap + wihotspot-gui)
|
│ ├── pos-network-hotspot # Wi-Fi hotspot (create_ap + wihotspot-gui)
|
||||||
@@ -207,6 +208,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
|
|||||||
| system | firewall | `pos-system-firewall` | Interactive UFW management |
|
| system | firewall | `pos-system-firewall` | Interactive UFW management |
|
||||||
| system | backup | `pos-system-backup` | Encrypted folder snapshots (`tar` + gpg AES-256; `--service` picks from `/srv` and `~/srv`) |
|
| system | backup | `pos-system-backup` | Encrypted folder snapshots (`tar` + gpg AES-256; `--service` picks from `/srv` and `~/srv`) |
|
||||||
| ssh | load-keys | `pos-ssh-load-keys` | Load SSH keys into agent |
|
| ssh | load-keys | `pos-ssh-load-keys` | Load SSH keys into agent |
|
||||||
|
| usb | server | `pos-usb-server` | USB Redirector server control: `--ls`, `--share`, `--unshare`, `--auto-share`, `--callback`, `--disconnect`, `--nickname`, `--timeout`, `--port`, `--info`, `--version` (flag-style, prompts when args omitted) |
|
||||||
| communication | telegram | `pos-communication-telegram` | Send Telegram messages via Bot API (`--send`, `test`, `config set`); config in `~/.config/linux_post_install/telegram.env` |
|
| communication | telegram | `pos-communication-telegram` | Send Telegram messages via Bot API (`--send`, `test`, `config set`); config in `~/.config/linux_post_install/telegram.env` |
|
||||||
| docker | vbox | `pos-docker-vbox` | Disposable Docker "VMs" (`create/enter/start/stop/rm/ls`; label-filtered, auto-enter prompt) |
|
| docker | vbox | `pos-docker-vbox` | Disposable Docker "VMs" (`create/enter/start/stop/rm/ls`; label-filtered, auto-enter prompt) |
|
||||||
|
|
||||||
@@ -250,7 +252,7 @@ Sourced by most scripts. Provides:
|
|||||||
source "$(dirname "$0")/../lib/common.sh"
|
source "$(dirname "$0")/../lib/common.sh"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Scripts that do NOT source common.sh** (self-contained): `bin/pos`, `pos-network-ip`, `pos-network-checkport`, `pos-network-scan`, `pos-media-mp3`, `pos-media-mp4`, `pos-ssh-load-keys`, `pos-system-firewall`, `pos-communication-telegram`.
|
**Scripts that do NOT source common.sh** (self-contained): `bin/pos`, `pos-network-ip`, `pos-network-checkport`, `pos-network-scan`, `pos-network-hotspot`, `pos-media-mp3`, `pos-media-mp4`, `pos-ssh-load-keys`, `pos-system-firewall`, `pos-communication-telegram`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -458,7 +460,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| `bin/flag-set` | 21 | Set a flag (optionally with a value) |
|
| `bin/flag-set` | 21 | Set a flag (optionally with a value) |
|
||||||
| `bin/flag-clear` | 21 | Unset a flag |
|
| `bin/flag-clear` | 21 | Unset a flag |
|
||||||
| `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
| `features/autostart.sh` | 14 | Boot-time feature (moved from `bin/`, flag-gated service) |
|
||||||
| `bin/pos` | 191 | CLI dispatcher with smart arg matching + logging + category help |
|
| `bin/pos` | 195 | CLI dispatcher with smart arg matching + logging + category help |
|
||||||
| `bin/pos-docker-compose` | 363 | Largest script — full compose management |
|
| `bin/pos-docker-compose` | 363 | Largest script — full compose management |
|
||||||
| `bin/pos-system-firewall` | 284 | Interactive UFW manager |
|
| `bin/pos-system-firewall` | 284 | Interactive UFW manager |
|
||||||
| `bin/pos-system-backup` | 115 | Encrypted folder snapshots: path mode + `--service` (`/srv`, `~/srv` picker), tar + gpg AES-256 |
|
| `bin/pos-system-backup` | 115 | Encrypted folder snapshots: path mode + `--service` (`/srv`, `~/srv` picker), tar + gpg AES-256 |
|
||||||
@@ -467,7 +469,8 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| `bin/pos-docker-vbox` | 156 | Docker-based disposable VMs (`pos docker vbox`; label-filtered, auto-enter prompt) |
|
| `bin/pos-docker-vbox` | 156 | Docker-based disposable VMs (`pos docker vbox`; label-filtered, auto-enter prompt) |
|
||||||
| `bin/pos-network-hotspot` | 91 | Wi-Fi hotspot: `create_ap` (start with background prompt/`--foreground`, stop, status) + `wihotspot-gui` |
|
| `bin/pos-network-hotspot` | 91 | Wi-Fi hotspot: `create_ap` (start with background prompt/`--foreground`, stop, status) + `wihotspot-gui` |
|
||||||
| `bin/pos-communication-telegram` | 138 | Telegram sender via Bot API: `--send`, `test`, `config set`; token masked; config `~/.config/linux_post_install/telegram.env` |
|
| `bin/pos-communication-telegram` | 138 | Telegram sender via Bot API: `--send`, `test`, `config set`; token masked; config `~/.config/linux_post_install/telegram.env` |
|
||||||
| `completions/pos.bash` | 122 | Dynamic bash completion |
|
| `bin/pos-usb-server` | 216 | USB Redirector server control (`usbsrv`): `--ls`, `--share` (interactive picker), `--unshare`, `--auto-share`, `--callback`, `--close-callback`, `--auto-connect`, `--disconnect`, `--nickname`, `--timeout`, `--port`, `--info`, `--version` |
|
||||||
|
| `completions/pos.bash` | 129 | Dynamic bash completion |
|
||||||
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
|
| `apps/install.sh` | 171 | App install/uninstall picker/orchestrator |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -476,7 +479,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
|
|
||||||
| Task | Where to Edit |
|
| Task | Where to Edit |
|
||||||
|------|---------------|
|
|------|---------------|
|
||||||
| Add a new CLI tool | Create `bin/pos-<cat>-<cmd>`, add deps in `preinstall.sh` |
|
| Add a new CLI tool | Create `bin/pos-<cat>-<cmd>`, add apt deps in `preinstall.sh` (non-apt/manual installers: add a `command -v` guard in the tool instead) |
|
||||||
| Add a new app installer | Create `apps/<name>.sh` (auto-discovered) |
|
| Add a new app installer | Create `apps/<name>.sh` (auto-discovered) |
|
||||||
| Add a feature | Create `features/<name>.sh` (installed on demand via `./install.sh --feature`) |
|
| Add a feature | Create `features/<name>.sh` (installed on demand via `./install.sh --feature`) |
|
||||||
| Add a systemd service | Create `systemd/<name>.service` (auto-installed by postinstall; gate on a flag if it backs a feature) |
|
| Add a systemd service | Create `systemd/<name>.service` (auto-installed by postinstall; gate on a flag if it backs a feature) |
|
||||||
@@ -489,6 +492,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
|||||||
| Modify Docker Compose logic | Edit `bin/pos-docker-compose` |
|
| Modify Docker Compose logic | Edit `bin/pos-docker-compose` |
|
||||||
| Modify Docker health check | Edit `bin/pos-docker-health` |
|
| Modify Docker health check | Edit `bin/pos-docker-health` |
|
||||||
| Modify vbox (Docker VM) logic | Edit `bin/pos-docker-vbox` |
|
| Modify vbox (Docker VM) logic | Edit `bin/pos-docker-vbox` |
|
||||||
|
| Modify USB forwarding logic | Edit `bin/pos-usb-server` |
|
||||||
| Modify UFW/firewall logic | Edit `bin/pos-system-firewall` |
|
| Modify UFW/firewall logic | Edit `bin/pos-system-firewall` |
|
||||||
| Modify pos logging | Edit log setup in `bin/pos` |
|
| Modify pos logging | Edit log setup in `bin/pos` |
|
||||||
| Modify install phases/flags | Edit arg parsing in `install.sh` |
|
| Modify install phases/flags | Edit arg parsing in `install.sh` |
|
||||||
|
|||||||
+3
-1
@@ -54,7 +54,7 @@ All non-interactive commands log to `~/.local/share/linux_post_install/logs/`.
|
|||||||
**When adding a command, `bin/pos` itself has two things to keep in sync:**
|
**When adding a command, `bin/pos` itself has two things to keep in sync:**
|
||||||
|
|
||||||
- **The usage text** (`usage()` function) — the CATEGORIES and EXAMPLES blocks are the built-in cheat-sheet (`pos --help`). Add the new command there or it stays invisible.
|
- **The usage text** (`usage()` function) — the CATEGORIES and EXAMPLES blocks are the built-in cheat-sheet (`pos --help`). Add the new command there or it stays invisible.
|
||||||
- **`INTERACTIVE_CMDS`** (space-separated list above the dispatch loop) — commands that **read stdin** (password prompts, selection menus: `media-mp4`, `system-backup`) must be added here. Everything else is piped through `tee` for logging, which would hang or swallow an interactive prompt. sudo's own password prompt is unaffected — it reads from `/dev/tty`.
|
- **`INTERACTIVE_CMDS`** (space-separated list above the dispatch loop) — commands that **read stdin** (password prompts, selection menus: `media-mp4`, `system-backup`, `usb-server`) must be added here. Everything else is piped through `tee` for logging, which would hang or swallow an interactive prompt. sudo's own password prompt is unaffected — it reads from `/dev/tty`. Trade-off: it's all-or-nothing **per script** — adding a flag-style tool with *any* prompting subcommand (e.g. `usb-server --share`) means *every* subcommand of that script skips output logging (e.g. `usb server --ls` loses the `tee` log too).
|
||||||
|
|
||||||
### Shared Library (`lib/common.sh`)
|
### Shared Library (`lib/common.sh`)
|
||||||
|
|
||||||
@@ -135,6 +135,8 @@ PACKAGES=(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Not in apt?** If the dependency ships as a manual installer (no package — e.g. `usbsrv`, the USB Redirector server), do **not** put it in `PACKAGES` (that would break `preinstall.sh`). Instead, add a `command -v <binary> || err "… install from <URL>"` guard in the tool itself and note the manual install in `usage()`/`DOC/POS.md`.
|
||||||
|
|
||||||
### 4. Config files (if needed)
|
### 4. Config files (if needed)
|
||||||
|
|
||||||
Two kinds of config, don't mix them up:
|
Two kinds of config, don't mix them up:
|
||||||
|
|||||||
+24
@@ -10,6 +10,7 @@
|
|||||||
- [media](#media)
|
- [media](#media)
|
||||||
- [system](#system)
|
- [system](#system)
|
||||||
- [ssh](#ssh)
|
- [ssh](#ssh)
|
||||||
|
- [usb](#usb)
|
||||||
- [communication](#communication)
|
- [communication](#communication)
|
||||||
- [flags](#flags)
|
- [flags](#flags)
|
||||||
- [Legacy wrappers](#legacy-wrappers)
|
- [Legacy wrappers](#legacy-wrappers)
|
||||||
@@ -159,6 +160,29 @@ The standalone `vbox` command still works and forwards to `pos docker vbox` (see
|
|||||||
|---------|------|---------|---------------|
|
|---------|------|---------|---------------|
|
||||||
| `pos ssh load-keys` | `bin/pos-ssh-load-keys` | Load all `~/.ssh/id_*` private keys into the ssh-agent | Uses `SSH_AUTH_SOCK` (default `/run/ssh-agent/socket`, provided by `ssh-agent.service`); skips `.pub`, `known_hosts`, `authorized_keys`, `config`; validates keys before adding |
|
| `pos ssh load-keys` | `bin/pos-ssh-load-keys` | Load all `~/.ssh/id_*` private keys into the ssh-agent | Uses `SSH_AUTH_SOCK` (default `/run/ssh-agent/socket`, provided by `ssh-agent.service`); skips `.pub`, `known_hosts`, `authorized_keys`, `config`; validates keys before adding |
|
||||||
|
|
||||||
|
### usb
|
||||||
|
|
||||||
|
**File:** `bin/pos-usb-server`
|
||||||
|
**Purpose:** control the USB Redirector server (`usbsrv`) — share local USB devices over the network and manage connected clients. Requires `usbsrv` (manual install from incentivespro.com — not in `PACKAGES`).
|
||||||
|
|
||||||
|
| Command | Behavior |
|
||||||
|
|---------|----------|
|
||||||
|
| `pos usb server --ls` | List host USB devices and connected clients |
|
||||||
|
| `pos usb server --ls-shared` | List shared or in-use devices only |
|
||||||
|
| `pos usb server --share [dev-id] [client-id]` | Share a device and connect it to a client; interactive picker when IDs are omitted (`-share` + `-connect-to CLIENT-DEV`) |
|
||||||
|
| `pos usb server --unshare [dev-id]` | Stop sharing a device |
|
||||||
|
| `pos usb server --auto-share on\|off` | Toggle automatic sharing of new devices |
|
||||||
|
| `pos usb server --callback [addr:port]` | Create a callback connection to a client |
|
||||||
|
| `pos usb server --close-callback [target\|all]` | Close a client callback |
|
||||||
|
| `pos usb server --auto-connect on\|off [client]` | Toggle remote auto-connect for a client |
|
||||||
|
| `pos usb server --disconnect [dev-id\|all]` | Disconnect a device from its clients |
|
||||||
|
| `pos usb server --nickname [dev-id] [nick]` | Set a device nickname (empty nick removes it) |
|
||||||
|
| `pos usb server --timeout [dev-id] [sec]` | Set device inactivity timeout (0 disables) |
|
||||||
|
| `pos usb server --port [num]` | Set the TCP port (restart server to apply) |
|
||||||
|
| `pos usb server --info` / `--version` | Show server info / version |
|
||||||
|
|
||||||
|
Subcommands that need input prompt interactively when args are omitted.
|
||||||
|
|
||||||
### communication
|
### communication
|
||||||
|
|
||||||
| Command | File | Purpose | Configuration |
|
| Command | File | Purpose | Configuration |
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ It is a **personal toolkit** — a bootstrap script, a unified `pos` CLI for eve
|
|||||||
**What you get:**
|
**What you get:**
|
||||||
|
|
||||||
- 25+ system packages installed automatically
|
- 25+ system packages installed automatically
|
||||||
- The `pos` CLI: network, Docker (compose + vbox VMs), media, system, SSH, and communication (Telegram) tools
|
- The `pos` CLI: network, Docker (compose + vbox VMs), media, system, SSH, USB, and communication (Telegram) tools
|
||||||
- Wi-Fi hotspot tools (`create_ap`, `wihotspot-gui`) via `pos network hotspot`
|
- Wi-Fi hotspot tools (`create_ap`, `wihotspot-gui`) via `pos network hotspot`
|
||||||
- 15 optional desktop apps (VS Code, Brave, OBS, Tailscale, …) — pick what you want
|
- 15 optional desktop apps (VS Code, Brave, OBS, Tailscale, …) — pick what you want
|
||||||
- 119+ self-hosted services with Tailscale access (Jellyfin, Home Assistant, …)
|
- 119+ self-hosted services with Tailscale access (Jellyfin, Home Assistant, …)
|
||||||
|
|||||||
@@ -68,10 +68,11 @@ USAGE
|
|||||||
|
|
||||||
CATEGORIES
|
CATEGORIES
|
||||||
network ip | checkport | scan | hotspot
|
network ip | checkport | scan | hotspot
|
||||||
docker ps | compose | vbox
|
docker ps | compose | health | vbox
|
||||||
media mp3 | mp4
|
media mp3 | mp4
|
||||||
system firewall | backup
|
system firewall | backup
|
||||||
ssh load-keys
|
ssh load-keys
|
||||||
|
usb server
|
||||||
communication
|
communication
|
||||||
telegram
|
telegram
|
||||||
|
|
||||||
@@ -84,6 +85,7 @@ EXAMPLES
|
|||||||
pos docker ps List containers (health, IPs, ports)
|
pos docker ps List containers (health, IPs, ports)
|
||||||
pos docker compose ls List available ScaleTail services
|
pos docker compose ls List available ScaleTail services
|
||||||
pos docker compose up jellyfin Deploy a service with Tailscale
|
pos docker compose up jellyfin Deploy a service with Tailscale
|
||||||
|
pos docker health One-glance health dashboard
|
||||||
|
|
||||||
pos media mp3 <url> Download audio as MP3
|
pos media mp3 <url> Download audio as MP3
|
||||||
pos media mp4 <url> Download video as MP4
|
pos media mp4 <url> Download video as MP4
|
||||||
@@ -94,6 +96,8 @@ EXAMPLES
|
|||||||
|
|
||||||
pos ssh load-keys Load all SSH keys into agent
|
pos ssh load-keys Load all SSH keys into agent
|
||||||
|
|
||||||
|
pos usb server --ls List USB devices + connected clients
|
||||||
|
|
||||||
pos communication telegram --send "Backup done"
|
pos communication telegram --send "Backup done"
|
||||||
Send a Telegram message
|
Send a Telegram message
|
||||||
|
|
||||||
@@ -155,7 +159,7 @@ MAIN_LOG="$LOG_DIR/pos.log"
|
|||||||
log_cmd() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $* → exit $2" >> "$MAIN_LOG"; }
|
log_cmd() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $* → exit $2" >> "$MAIN_LOG"; }
|
||||||
|
|
||||||
# Commands that read from stdin interactively — only log invocation
|
# Commands that read from stdin interactively — only log invocation
|
||||||
INTERACTIVE_CMDS="system-firewall media-mp4 system-backup"
|
INTERACTIVE_CMDS="system-firewall media-mp4 system-backup usb-server"
|
||||||
|
|
||||||
for ((i=n-1; i>=0; i--)); do
|
for ((i=n-1; i>=0; i--)); do
|
||||||
cmd="pos"
|
cmd="pos"
|
||||||
|
|||||||
Executable
+216
@@ -0,0 +1,216 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: pos usb server [flag] [args]
|
||||||
|
|
||||||
|
Control the USB Redirector server (usbsrv) — share local USB devices
|
||||||
|
over the network and manage connected clients.
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
--ls List host USB devices and connected clients
|
||||||
|
--ls-shared List shared or in-use devices only
|
||||||
|
--share [dev-id] [client-id] Share a device and connect it to a client
|
||||||
|
(interactive picker when IDs are omitted)
|
||||||
|
--unshare [dev-id] Stop sharing a device
|
||||||
|
--auto-share on|off Toggle automatic sharing of new devices
|
||||||
|
--callback [addr:port] Create a callback connection to a client
|
||||||
|
--close-callback [target|all] Close a client callback
|
||||||
|
--auto-connect on|off [client] Toggle remote auto-connect for a client
|
||||||
|
--disconnect [dev-id|all] Disconnect a device from its clients
|
||||||
|
--nickname [dev-id] [nick] Set a device nickname (empty nick removes it)
|
||||||
|
--timeout [dev-id] [sec] Set device inactivity timeout (0 disables)
|
||||||
|
--port [num] Set the TCP port (restart server to apply)
|
||||||
|
--info Show server info
|
||||||
|
--version Show server version
|
||||||
|
-h, --help Show this help
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
pos usb server --ls
|
||||||
|
pos usb server --share
|
||||||
|
pos usb server --share 0-1 3
|
||||||
|
pos usb server --auto-share on
|
||||||
|
pos usb server --port 32032
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_ls() {
|
||||||
|
echo "==== HOST USB DEVICES ===="
|
||||||
|
usbsrv -list-devices
|
||||||
|
echo
|
||||||
|
echo "==== CONNECTED CLIENTS ===="
|
||||||
|
usbsrv -list-clients
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_ls_shared() {
|
||||||
|
echo "==== SHARED OR IN USE DEVICES ===="
|
||||||
|
usbsrv -list-devices | awk '
|
||||||
|
BEGIN {RS=""; FS="\n"}
|
||||||
|
{
|
||||||
|
for(i=1; i<=NF; i++) {
|
||||||
|
if ($i ~ /Status:.*(shared|in use)/) {
|
||||||
|
print $0 "\n"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' || true
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_share() {
|
||||||
|
local dev="${1:-}" client="${2:-}"
|
||||||
|
if [ -z "$dev" ]; then
|
||||||
|
echo "==== HOST USB DEVICES ===="
|
||||||
|
usbsrv -list-devices
|
||||||
|
echo
|
||||||
|
echo "==== CONNECTED CLIENTS ===="
|
||||||
|
usbsrv -list-clients
|
||||||
|
echo
|
||||||
|
read -rp "Enter device ID to share: " dev
|
||||||
|
read -rp "Enter client ID to connect to: " client
|
||||||
|
fi
|
||||||
|
[ -n "$dev" ] || err "no device ID given"
|
||||||
|
[ -n "$client" ] || err "no client ID given"
|
||||||
|
log "Sharing device ID $dev..."
|
||||||
|
usbsrv -share "$dev"
|
||||||
|
log "Connecting device $dev to client $client..."
|
||||||
|
usbsrv -connect-to "${client}-${dev}"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_unshare() {
|
||||||
|
local dev="${1:-}"
|
||||||
|
if [ -z "$dev" ]; then
|
||||||
|
cmd_ls_shared
|
||||||
|
read -rp "Enter device ID to unshare: " dev
|
||||||
|
fi
|
||||||
|
[ -n "$dev" ] || err "no device ID given"
|
||||||
|
log "Unsharing device ID $dev..."
|
||||||
|
usbsrv -unshare "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_auto_share() {
|
||||||
|
local mode="${1:-}"
|
||||||
|
if [ -z "$mode" ]; then
|
||||||
|
read -rp "Turn auto-share on or off? (on/off): " mode
|
||||||
|
fi
|
||||||
|
case "$mode" in
|
||||||
|
on|off) ;;
|
||||||
|
*) err "Invalid option '$mode' — must be 'on' or 'off'" ;;
|
||||||
|
esac
|
||||||
|
usbsrv -auto-share "$mode"
|
||||||
|
log "Auto-share set to $mode"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_callback() {
|
||||||
|
local addr="${1:-}"
|
||||||
|
if [ -z "$addr" ]; then
|
||||||
|
read -rp "Enter client address:port for callback (e.g. 192.168.1.100:32032): " addr
|
||||||
|
fi
|
||||||
|
[ -n "$addr" ] || err "no address given"
|
||||||
|
usbsrv -create-callback "$addr"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_close_callback() {
|
||||||
|
local target="${1:-}"
|
||||||
|
if [ -z "$target" ]; then
|
||||||
|
usbsrv -list-clients
|
||||||
|
read -rp "Enter client or clientid or 'all' to close callback: " target
|
||||||
|
fi
|
||||||
|
[ -n "$target" ] || err "no target given"
|
||||||
|
usbsrv -close-callback "$target"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_auto_connect() {
|
||||||
|
local mode="${1:-}" client="${2:-}"
|
||||||
|
if [ -z "$mode" ]; then
|
||||||
|
read -rp "Enable or disable remote auto-connect? (on/off): " mode
|
||||||
|
fi
|
||||||
|
case "$mode" in
|
||||||
|
on|off) ;;
|
||||||
|
*) err "Invalid option '$mode' — must be 'on' or 'off'" ;;
|
||||||
|
esac
|
||||||
|
if [ -z "$client" ]; then
|
||||||
|
usbsrv -list-clients
|
||||||
|
read -rp "Enter client or clientid: " client
|
||||||
|
fi
|
||||||
|
[ -n "$client" ] || err "no client given"
|
||||||
|
usbsrv -remote-auto-connect "$mode" "$client"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_disconnect() {
|
||||||
|
local dev="${1:-}"
|
||||||
|
if [ -z "$dev" ]; then
|
||||||
|
cmd_ls_shared
|
||||||
|
read -rp "Enter device ID or 'all' to disconnect from clients: " dev
|
||||||
|
fi
|
||||||
|
[ -n "$dev" ] || err "no device ID given"
|
||||||
|
usbsrv -disconnect-from "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_nickname() {
|
||||||
|
local dev="${1:-}" nick="${2:-}"
|
||||||
|
if [ -z "$dev" ]; then
|
||||||
|
usbsrv -list-devices
|
||||||
|
read -rp "Enter device ID to set nickname (empty to remove): " dev
|
||||||
|
read -rp "Enter nickname (or leave empty to remove): " nick
|
||||||
|
fi
|
||||||
|
[ -n "$dev" ] || err "no device ID given"
|
||||||
|
usbsrv -set-nickname "$nick" "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_timeout() {
|
||||||
|
local dev="${1:-}" sec="${2:-}"
|
||||||
|
if [ -z "$dev" ]; then
|
||||||
|
usbsrv -list-devices
|
||||||
|
read -rp "Enter device ID to set timeout for: " dev
|
||||||
|
read -rp "Enter timeout in seconds (0 to disable): " sec
|
||||||
|
fi
|
||||||
|
[ -n "$dev" ] || err "no device ID given"
|
||||||
|
[[ "$sec" =~ ^[0-9]+$ ]] || err "Invalid timeout '$sec' — must be a number"
|
||||||
|
usbsrv -set-timeout "$sec" "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_port() {
|
||||||
|
local port="${1:-}"
|
||||||
|
if [ -z "$port" ]; then
|
||||||
|
read -rp "Enter new TCP port: " port
|
||||||
|
fi
|
||||||
|
[[ "$port" =~ ^[0-9]+$ ]] || err "Invalid port number '$port'"
|
||||||
|
usbsrv -set-tcp-port "$port"
|
||||||
|
warn "Restart your server for port changes to take effect."
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd="${1:-}"
|
||||||
|
|
||||||
|
case "$cmd" in
|
||||||
|
-h|--help|"") usage ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$cmd" in
|
||||||
|
--ls|--ls-shared|--share|--unshare|--auto-share|--callback|--close-callback|--auto-connect|--disconnect|--nickname|--timeout|--port|--info|--version) ;;
|
||||||
|
*) err "Unknown flag '$cmd'" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
command -v usbsrv &>/dev/null \
|
||||||
|
|| err "usbsrv not found — install the USB Redirector server (https://www.incentivespro.com/usb-server.html)"
|
||||||
|
|
||||||
|
case "$cmd" in
|
||||||
|
--ls) cmd_ls ;;
|
||||||
|
--ls-shared) cmd_ls_shared ;;
|
||||||
|
--share) shift; cmd_share "$@" ;;
|
||||||
|
--unshare) shift; cmd_unshare "$@" ;;
|
||||||
|
--auto-share) shift; cmd_auto_share "$@" ;;
|
||||||
|
--callback) shift; cmd_callback "$@" ;;
|
||||||
|
--close-callback) shift; cmd_close_callback "$@" ;;
|
||||||
|
--auto-connect) shift; cmd_auto_connect "$@" ;;
|
||||||
|
--disconnect) shift; cmd_disconnect "$@" ;;
|
||||||
|
--nickname) shift; cmd_nickname "$@" ;;
|
||||||
|
--timeout) shift; cmd_timeout "$@" ;;
|
||||||
|
--port) shift; cmd_port "$@" ;;
|
||||||
|
--info) usbsrv -info ;;
|
||||||
|
--version) usbsrv -version ;;
|
||||||
|
*) err "Unknown flag '$cmd'"; usage ;;
|
||||||
|
esac
|
||||||
@@ -73,6 +73,10 @@ _pos() {
|
|||||||
COMPREPLY=($(compgen -W "$names" -- "$cur"))
|
COMPREPLY=($(compgen -W "$names" -- "$cur"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_pos_complete_usb_server_flags() {
|
||||||
|
COMPREPLY=($(compgen -W "--ls --ls-shared --share --unshare --auto-share --callback --close-callback --auto-connect --disconnect --nickname --timeout --port --info --version --help" -- "$cur"))
|
||||||
|
}
|
||||||
|
|
||||||
# ── Dispatch ───────────────────────────────────────────────
|
# ── Dispatch ───────────────────────────────────────────────
|
||||||
case "${#words[@]}" in
|
case "${#words[@]}" in
|
||||||
2)
|
2)
|
||||||
@@ -96,6 +100,9 @@ _pos() {
|
|||||||
docker-vbox)
|
docker-vbox)
|
||||||
_pos_complete_docker_vbox_cmds
|
_pos_complete_docker_vbox_cmds
|
||||||
;;
|
;;
|
||||||
|
usb-server)
|
||||||
|
_pos_complete_usb_server_flags
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
5)
|
5)
|
||||||
|
|||||||
Reference in New Issue
Block a user