remote.DokumentationStartseite

Linux-, FreeBSD-, NetBSD-, Windows-, macOS- und Android-Geräte

Linux (glibc / musl), FreeBSD, NetBSD, Windows, macOS und Android verwenden gemeinsam remote-agent, Exchange, remote-cli und den mobilen Administrationsclient. Geräteprogramm und CLI verwenden allgemeine Namen; Umgebungsvariablen heißen einheitlich REMOTE_*.

Installation mit einem Befehl (Windows / Linux / macOS / FreeBSD / NetBSD)

Das Skript der offiziellen Website lädt das passende geprüfte Paket herunter und legt die Programme unter ~/.local/bin ab. Der Agent registriert mit remote-agent install den automatischen Start bei Anmeldung:

Wählen Sie den passenden Befehl und kopieren Sie jeden Befehl einzeln.

Agent auf dem verwalteten Gerät installieren

curl -fsSL https://remote.ivjn.us/install.sh | bash -s -- agent

CLI auf dem Bediengerät installieren

curl -fsSL https://remote.ivjn.us/install.sh | bash -s -- cli

Unter Windows in Git Bash ausführen. Die Zugangsdaten müssen hinter der Pipe stehen: bash -s -- agent --device-id NAME --token TOKEN (oder vorhandene config.json / REMOTE_CONFIG verwenden). Vor curl gesetzte Umgebungsvariablen erreichen bash nicht. Für systemweites systemd unter Linux --system ergänzen. Das Skript unterscheidet automatisch glibc und musl (etwa Alpine), auch Linux arm64 (aarch64) wird unterstützt. REMOTE_LIBC=musl erzwingt das musl-Paket. FreeBSD / NetBSD: Benutzerinstallationen bleiben in ~/.local/bin; sudo remote-agent install --system --config CONFIG registriert rc.d. Desktopsteuerung benötigt eine X11-Sitzung mit python3 und xdotool. Android und OpenWrt verwenden eigene Pakete.

Befehle und Dienste

Die Geräte- und CLI-Befehle heißen remote-agent und remote-cli. remote-cli schreibt standardmäßig nach remote-cli/config.toml; ein explizites REMOTE_CLI_CONFIG hat Vorrang.

OpenWrt-Paket, UCI-Datei und init-Dienst heißen remote-agent. Die Statusdatei ist /var/run/remote-agent.state, die Konfigurationsdatei /etc/config/remote-agent. Das LuCI-Plugin luci-app-remote benötigt dieses Paket. REMOTE_AGENT_SRC legt den Quellpfad für den Build fest.

Gerät Befehlsausführung Interaktives Terminal Dauerbetrieb ubus
Linux /bin/sh -c Unix PTY systemd oder Vordergrundprozess Nur OpenWrt
Linux musl (Alpine 3.x usw.), x64 / arm64 /bin/sh -c Unix PTY Vordergrundprozess oder eigener OpenRC-Dienst (kein systemd) Nicht unterstützt
FreeBSD 14+, amd64 / arm64 /bin/sh -c Unix PTY rc.d (root/System); Vordergrund (Benutzer) Nicht unterstützt
NetBSD 10+, amd64 /bin/sh -c Unix PTY rc.d (root/System); Vordergrund (Benutzer) Nicht unterstützt
Windows 10 1809+/11, Server 2019+ Windows PowerShell 5.1 ConPTY + PowerShell Anmeldeaufgabe oder Vordergrundprozess Nicht unterstützt
macOS 11+, Apple Silicon / Intel /bin/sh -c Unix PTY launchd LaunchAgent oder Vordergrundprozess Nicht unterstützt
Android 8.0+, arm64 / x86_64 /system/bin/sh -c Unix PTY Vordergrunddienst der eigenständigen APK Nicht unterstützt

Allgemeine Konfiguration

Zuerst mit remote-cli device add <id> das Gerät registrieren und das Gerätetoken beziehen. Unter Linux/Windows eine nur für das ausführende Konto lesbare config.json erstellen:

{
  "server": "wss://mgmt.example.com",
  "device_id": "my-device",
  "token": "REPLACE_WITH_DEVICE_TOKEN"
}
remote-agent --config /path/to/config.json

Vorrang haben Kommandozeile bzw. REMOTE_SERVER, REMOTE_DEVICE_ID, REMOTE_TOKEN, danach JSON und zuletzt ausschließlich unter OpenWrt UCI. JSON unterstützt state_file; --state-file / REMOTE_STATE_FILE überschreiben dies. Ohne explizite Statusdatei verwendet OpenWrt /var/run/remote-agent.state; andere Plattformen remote-agent/agent.state unter dem ersten verfügbaren Verzeichnis aus LOCALAPPDATA, XDG_STATE_HOME, $HOME/.local/state, ohne Benutzerverzeichnis ersatzweise das temporäre Verzeichnis. Mehrere Instanzen benötigen getrennte Statuspfade.

Für produktive Verbindungen wss:// verwenden. ws://127.0.0.1 in Beispielen dient nur lokalen Prüfungen.

Benachrichtigungen zur Agent-Verbindung

JSON unterstützt "notify_urls": ["https://example.invalid/notify"], alternativ remote-agent --notify-url https://example.invalid/notify (wiederholbar). REMOTE_NOTIFY_URL akzeptiert kommagetrennte Adressen. Nicht leere Kommandozeilen-/Umgebungslisten ersetzen JSON; andernfalls gilt JSON und zuletzt, nur unter OpenWrt, der kommagetrennte UCI-Wert remote-agent.main.notify_url. Sind alle Quellen leer oder ausgelassen, ist POST deaktiviert.

Nach erfolgreicher Registrierung wird agent.connected gesendet, beim Ende einer bestehenden Sitzung einmal agent.disconnected, bei ausdrücklicher Ablehnung nur agent.rejected. Netzwerkfehler vor Registrierung lösen keine Benachrichtigung aus. POST verwendet dasselbe JSON-Objekt wie Exchange Web Push (title, body, url, event, device_id, occurred_at), beschreibt aber die Agent-Verbindung statt des Geräte-Onlinestatus: Präfix agent. statt device. in event, url ist "" (kein Web-Push-Konsolenpfad), kein tag. Trennungs-/Ablehnungstexte enthalten eine kurze sichere Begründung ohne Gerätetoken; Zeitangaben sind RFC3339 UTC.

Benachrichtigungen laufen im Hintergrund; bei Fehlern wird nur der Ereignisname protokolliert, keine Zieladresse, und die Wiederverbindung nicht blockiert. Wie bei Exchange Web Push höchstens 5 Versuche, Wiederholungen bei Netzwerkfehlern und HTTP 408/429/5xx, Verwerfen bei 404/410 und anderen nicht wiederholbaren 4xx. Ganzzahlige Sekunden aus Retry-After haben Vorrang, sonst exponentielles Backoff ab 5 Sekunden, begrenzt auf 1–900 Sekunden. Nur HTTP/HTTPS, keine Weiterleitungen. Keine Benutzernamen, Passwörter oder sonstigen Zugangsdaten in URLs; Adressen mit Benutzername/Passwort werden abgelehnt.

Ausgehende Proxys und Verbindungserhaltung

Headless und --ui verbinden über dasselbe client::run mit Exchange. WebSocket liest geerbte Proxyvariablen des Agent-Prozesses: erster nicht leerer Wert aus HTTPS_PROXY / https_proxy, ALL_PROXY / all_proxy, HTTP_PROXY / http_proxy. Hosts passend zu NO_PROXY / no_proxy umgehen den Proxy. remote-cli verwendet dieselben Regeln (#36/#37, #39). Anmeldestart und Hintergrunddienste benötigen diese Variablen in ihrer Laufzeitumgebung; Setzen in einem anderen Terminal erreicht gestartete Prozesse nicht.

WSS über Proxy baut zuerst einen HTTP CONNECT-Tunnel und verbindet dann das Ziel mit rustls. ALPN im TLS ClientHello meldet wie die CLI nur http/1.1. Aushandeln von h2 beschädigt den aktuellen HTTP/1.1-WebSocket-Upgrade-Pfad. Bei hängendem Verbindungsaufbau mit Proxys wie Clash CONNECT-Unterstützung prüfen und Builds mit #39/#42 verwenden. Geräte- und CLI-WebSocket unterstützen kein SOCKS; HTTP-CONNECT-Proxy verwenden (etwa HTTPS_PROXY=http://127.0.0.1:7890).

Nach direktem Aufbau oder CONNECT aktiviert der Agent TCP_NODELAY und TCP-Keepalive nach 30 Sekunden Leerlauf. Jeder JSON-Heartbeat sendet auch WebSocket-Ping; auf Ping wird das automatisch eingereihte Pong ausdrücklich geflusht. Verbindungsaufbau und Registrierungsantwort haben jeweils 45 Sekunden Zeitlimit, Senden und Pong-Flush nach Registrierung 30 Sekunden. Siehe Verbindungserhaltung und Zeitlimits (#42).

Windows-Builds mit desktop-ui verwenden auch headless eine mehrthreadige Tokio-Laufzeit, die axum, das lokale Tray und den Geräte-WebSocket parallel ausführt. Auf anderen Plattformen mit diesem Feature nutzt die lokale UI (explizites --ui oder Start ohne Argumente) ebenfalls mehrere Threads. Builds ohne das Feature und Headless-Aufrufe mit expliziter Konfiguration auf anderen Plattformen verwenden das für kleine Geräte geeignete current_thread.

Konfigurationsoberfläche für Linux / Windows / macOS

Builds aktivieren desktop-ui standardmäßig. Desktop-Veröffentlichungen müssen die lokale Konfigurationsoberfläche enthalten. Verwenden Sie --no-default-features nur für Server ohne Oberfläche oder eingebettete Systeme. Bei bestehender Verbindung sind die Eingaben für Verwaltungsserver, Geräte-ID und Token ausgeblendet. Nach dem Stoppen des Fernzugriffs erscheinen sie wieder. Verbindungsstatus, LAN-Einstellungen und Autostart bleiben sichtbar.

cargo build --locked -p agent --release
# Linux / macOS
./target/release/remote-agent --ui
# Windows
.\target\release\remote-agent.exe --ui

Bei Start ohne Verbindungsparameter unter Linux / Windows / macOS (etwa Doppelklick auf remote-agent.exe) mit desktop-ui wird bei fehlender nutzbarer Konfiguration eine Standard-config.json geschrieben (nur Standard-Exchange vorbelegt, device_id/token leer) und die Browserkonfiguration geöffnet. Bei vorhandener Konfiguration verwendet Windows das Tray ohne erzwungenes Browseröffnen; Linux/macOS geben die lokale URL aus (macOS hat zusätzlich ein Symbol in der Menüleiste). Interaktiver parameterloser Start ohne desktop-ui erstellt die Standardkonfiguration, gibt ihren Pfad aus und beendet sich, statt nur Missing device_id anzuzeigen. OpenWrt / systemd / geplante Aufgaben verwenden weiterhin --config, UCI oder REMOTE_*.

Ein Start ohne Argumente und explizites --ui verwenden dieselbe Regel: Der Standardbrowser öffnet sich nur, wenn die gespeicherte Konfiguration keinen nichtleeren device_id/token-Wert enthält. Konfigurierte Agenten verbinden sich im Hintergrund, ohne bei der Anmeldung erneut den Browser zu öffnen. Windows behält den Tray-Eintrag zum manuellen Öffnen; Linux/macOS verwenden die lokale URL im Terminal. --ui --no-open verhindert das automatische Öffnen auch bei der Ersteinrichtung. --ui-port 8765 setzt einen festen Port; sonst wird ein freier Port zufällig gewählt. Die UI lauscht ausschließlich auf 127.0.0.1. Alle Ressourcen sind eingebettet, ohne externe Schriftarten oder CDNs.

Das Windows-Tray und die macOS-Menüleiste bieten Einträge für die Konfiguration, den Bildschirmschoner, die Aufgabenverwaltung und Zwischenablageaktionen. Die Aufgabenverwaltung öffnet direkt das lokale Aufgabenpanel. Linux verwendet die Konfigurationsseite im Browser.

Mit remote-cli device add <id> Geräte-ID und Token beziehen, dann Server, Geräte-ID und Token unter Connection settings eintragen:

  • Save only: Speichern ohne Serververbindung.
  • Save and connect: Speichern und verbinden; Änderungen im Betrieb trennen die alte und starten eine neue Verbindung.
  • Stop remote access: Trennen und aktuelle Fernausführungen und Terminalsitzungen abbrechen; Konfiguration bleibt erhalten.
  • Die Statusleiste zeigt nach Registrierung Connected, sonst Verbindungsaufbau, Wiederverbindung oder gestoppt sowie den letzten Verbindungsfehler.

Die UI schreibt beim Verbindungsbeginn zuerst Connecting in ihre Statusdatei und startet danach client::run, damit die Seite nicht beim Standardwert einer fehlenden Statusdatei stehen bleibt (#42).

Gespeicherte Token werden nicht an die Webseite zurückgesendet; leer bedeutet bisherigen Token behalten. Die Konfiguration wird über eine temporäre Datei atomar ersetzt, unter Linux mit 0600, unter Windows mit ACL nur für den aktuellen Benutzer. Beschädigtes oder unlesbares JSON führt zur Reparaturaufforderung ohne Überschreiben der Originaldatei. Nur ein UI-Prozess kann dieselbe Konfiguration öffnen.

Standardpfad unter Linux/macOS ist $XDG_CONFIG_HOME/remote-agent/config.json (sonst ~/.config/remote-agent/config.json), unter Windows %LOCALAPPDATA%\remote-agent\config.json. --ui --config <path> oder REMOTE_CONFIG wählen vorhandenes JSON. Die UI akzeptiert keine Überschreibungen per --server, --device-id, --token, --state-file und entsprechenden Umgebungsvariablen, damit gespeicherte Werte und Verbindung übereinstimmen. JSON state_file gilt auch für die UI; ohne Angabe wird derselbe dauerhafte Standardpfad wie bei headless verwendet, damit versiegelte Identität und Vertrauen erhalten bleiben.

Die Seite bietet Start at login / Start bei Anmeldung (autostart: { supported, enabled, detail } in GET /api/status; POST /api/autostart erhält { "enabled": true|false }). Keine Rechteerhöhung nötig:

  • macOS: Installiert/entfernt ~/Library/LaunchAgents/us.ivjn.remote-agent.plist (Vorlage wie install/macos/install.sh), mit launchctl bootstrap / bootout. Programm bevorzugt nach ~/.local/bin/remote-agent, Konfiguration standardmäßig ~/.config/remote-agent/config.json (vorhandene bleibt erhalten).
  • Windows: Registriert/entfernt Benutzeraufgabe RemoteAgent (AtLogOn), entsprechend install/windows/install.ps1, Installationsverzeichnis %LOCALAPPDATA%\remote-agent.
  • Linux: Installiert/entfernt systemd-Benutzereinheit (install/linux/remote-agent.service), systemctl --user enable --now / disable.

Beim Aktivieren wird das aktuelle Programm bei Bedarf zum vereinbarten Installationspfad kopiert, vorhandene config.json bleibt erhalten. Antworten und Logs geben keine Token aus. Die UI verwaltet den aktuellen Prozess; nach Autostartaktivierung und Verlassen der UI startet LaunchAgent / Aufgabenplanung / systemd den Hintergrundagenten bei nächster Anmeldung.

Das Schließen des Browsertabs stoppt den Agenten nicht; das Beenden des Agent-Prozesses trennt die Verbindung. Eine konfigurierte UI verbindet sich beim Start automatisch; die Ersteinrichtung benötigt Save and connect. Die UI verwaltet den aktuellen Prozess und kann den Anmeldestart ein- oder ausschalten. Vor einer weiteren UI-Instanz für dasselbe Gerät den vorhandenen Hintergrunddienst stoppen. Nach Konfiguration und Autostartaktivierung kann der Tab geschlossen werden. Fernaktionen verwenden die Rechte des Agent-Kontos.

Die lokale URL enthält einen zufälligen Zugriffsschlüssel dieser UI-Sitzung, nicht teilen. Die API prüft auch Host und Origin und lehnt externe Webseitenaufrufe ab. Das Gerätetoken liegt unverschlüsselt in der Konfiguration; aktueller lokaler Benutzer und Administratoren können es lesen. Schlanke Builds ohne desktop-ui behalten das bisherige Kommandozeilenverhalten; OpenWrt und Android verwenden ihre eigenen Oberflächen.

FreeBSD

Die Website bietet remote-freebsd-x64.tar.gz und remote-freebsd-arm64.tar.gz (unter Linux mit cargo zigbuild crosskompiliert, gegen FreeBSD 14 libc gelinkt). Nach dem Entpacken:

mkdir -p ~/.local/bin
cp remote-agent remote-cli ~/.local/bin/
sudo remote-agent install --system --device-id NAME --token TOKEN

Der aktuelle Quellcode unterstützt rc.d-Systeminstallation, sysctl-Metriken, Schnittstellenzähler mit netstat -ibn, FreeBSD-Temperatur/Lüfter und NetBSD envstat. X11-Steuerung wird bei vorhandenem DISPLAY, python3 und xdotool gemeldet; Screenshots benötigen zusätzlich Pillow. Medien und Systemeinstellungen bleiben nicht verfügbar. Selbstaktualisierung erkennt BSD-x64/arm64-Archive, wenn ein geprüftes Paket im Veröffentlichungsmanifest vorhanden ist. Neue Pakete und native BSD-Laufzeittests sind erforderlich.

NetBSD

Die Website bietet remote-netbsd-x64.tar.gz (amd64, unter Linux mit zig gegen NetBSD 10 libc crosskompiliert; dynamische Abhängigkeiten nur libc / libpthread / libutil). Verwendung wie FreeBSD:

mkdir -p ~/.local/bin
cp remote-agent remote-cli ~/.local/bin/
sudo remote-agent install --system --device-id NAME --token TOKEN

Fähigkeiten: Exchange-Verbindung, exec / PTY / Dateiübertragung; Metriken über sysctl (kern.cp_time, hw.physmem64, vm.uvmexp2); Desktop-GUI-Steuerung nur als Platzhalter, nicht gemeldet. Plattformmeldung netbsd. Selbstupdate und rc.d-Neustart funktionieren wie unter FreeBSD (remote-netbsd-x64.tar.gz / remote-netbsd-arm64.tar.gz), sofern das Manifest das Archiv enthält.

Offizielle OpenWrt-25.12-Pakete

Die Website bietet remote-agent, paketiert mit dem offiziellen OpenWrt 25.12.5 SDK (apk-tools, Paketversion 0.1.29-r1, enthält Agent 0.1.29):

target Paketarchitektur Datei
ipq40xx/generic arm_cortex-a7_neon-vfpv4 remote-agent-openwrt-ipq40xx-official.apk
x86/64 x86_64 remote-agent-openwrt-x86_64-official.apk
armsr/armv8 aarch64_generic remote-agent-openwrt-armsr-armv8-official.apk
mediatek/filogic aarch64_cortex-a53 remote-agent-openwrt-mediatek-filogic-official.apk
bcm27xx/bcm2711 aarch64_cortex-a72 remote-agent-openwrt-bcm27xx-bcm2711-official.apk
ramips/mt7621 mipsel_24kc remote-agent-openwrt-ramips-mt7621-official.apk
ath79/generic mips_24kc remote-agent-openwrt-ath79-official.apk

Universelle LuCI-Oberfläche: luci-app-remote-openwrt-official.apk. Mit apk --print-arch Architektur prüfen, dann apk add --allow-untrusted ./文件.apk. MIPS benötigt zusätzlich libgcc1 (in offiziellen Images enthalten).

Linux musl (Alpine) und arm64

  • remote-linux-arm64.tar.gz: aarch64, glibc 2.28+ (Debian 10+/Ubuntu 18.04+/RHEL 8+, Raspberry Pi mit 64-Bit-System usw.), unterstützt systemd-Registrierung per remote-agent install und Selbstaktualisierung.
  • remote-linux-musl-x64.tar.gz / remote-linux-musl-arm64.tar.gz: statisch gegen musl gelinkt für Distributionen ohne glibc wie Alpine. Alpine hat standardmäßig kein systemd; mit remote-agent install --no-start konfigurieren und einen eigenen OpenRC-Dienst (/etc/init.d/remote-agent) schreiben oder im Vordergrund starten. musl-Builds unterstützen update self und Desktop-Auto-Updates und installieren nur das musl-Archiv; nach einem einmaligen Update versuchen sie systemd, dann OpenRC (rc-service remote-agent restart), dann einen Prozessneustart. Ein musl-Archiv auf einem OpenWrt-Host wird weiter über opkg/apk aktualisiert.

Linux

Empfohlen ist der integrierte Unterbefehl (kopiert das aktuelle Programm, schreibt private Konfiguration und registriert systemd, ohne install/-Dateien aus dem Repository):

cargo build --locked -p agent --no-default-features --profile release-small
# 用户级(默认,非 root)
./target/release-small/remote-agent install \
  --config /path/to/config.json
# 或直接传凭证(无需先有文件;安装过程不访问网络)
./target/release-small/remote-agent install \
  --device-id NAME --token TOKEN

# 系统级(root 或 --system):/usr/local/bin + /etc/remote-agent + multi-user.target
sudo ./target/release-small/remote-agent install --system \
  --device-id NAME --token TOKEN

remote-agent status                    # 安装布局、服务、进程、连接(不打印令牌)
systemctl --user status remote-agent   # 用户级
# systemctl status remote-agent        # 系统级
remote-agent uninstall                 # 卸服务;加 --force 同时删二进制与配置

Gleichwertige manuelle Schritte (weiterhin möglich):

install -Dm755 target/release-small/remote-agent ~/.local/bin/remote-agent
install -Dm600 /path/to/config.json ~/.config/remote-agent/config.json
install -Dm644 install/linux/remote-agent.service ~/.config/systemd/user/remote-agent.service
systemctl --user daemon-reload
systemctl --user enable --now remote-agent

Benutzerdienste laufen standardmäßig mit der Anmeldesitzung. Für Dauerbetrieb ab Boot lässt ein Administrator loginctl enable-linger <user> ausführen oder verwendet die obige --system-Einheit (RuntimeDirectory=remote-agent, WantedBy=multi-user.target). Fernbefehle verwenden Dienstkontorechte. Stoppen beendet alle Prozesse im Dienst. install/linux/install.sh ist ein dünner Wrapper um remote-agent install --force.

Windows

Nach Installation der Rust-MSVC-Toolchain und Visual Studio C++ Build Tools:

cargo build --locked -p agent --release
.\target\release\remote-agent.exe --config C:\path\config.json

# 推荐:为当前登录用户安装常驻计划任务
.\target\release\remote-agent.exe install --config C:\path\config.json
# 已存在任务/文件时加 --force;仅注册不启动加 --no-start
Get-ScheduledTaskInfo -TaskName RemoteAgent
remote-agent status
remote-agent uninstall
remote-agent uninstall --force   # 同时删除 %LOCALAPPDATA%\remote-agent 下的文件

install kopiert Programme und Konfiguration nach %LOCALAPPDATA%\remote-agent, beschränkt Konfigurations-ACL und registriert die Anmeldeaufgabe RemoteAgent. Vorhandene Aufgabe oder Zieldateien verursachen standardmäßig Fehler; --force stoppt und entfernt zuerst die alte Aufgabe und überschreibt dann. Dieser Modus benötigt Benutzeranmeldung und ist kein Windows-SCM-Systemdienst. install/windows/install.ps1 ist ein dünner Wrapper um remote-agent install (optional -Force).

Wurde die Konfiguration über die UI erstellt, kann --config auf einen separaten Pfad zeigen (etwa die Datei aus --ui --config .\device-config.json).

Windows-Befehle verwenden PowerShell-Syntax wie Get-Process, Ausgabe als UTF-8. Jede Ausführungssitzung und jedes Terminal hat ein eigenes Job Object; Timeout, Abbruch, Trennung und Agent-Ende bereinigen den jeweiligen Kindprozessbaum.

macOS

Benötigt wird die Rust-Toolchain (rustup, mit Standardtarget aarch64-apple-darwin oder x86_64-apple-darwin). Metriken kommen aus sysctl, getloadavg(3) und mach host_statistics; statische Informationen (Modell, Kernel, Systemversion) aus sysctl und sw_vers. Plattformmeldung macos.

Sensoren werden auf Abruf (nicht im Heartbeat) bestmöglich ohne sudo und zusätzliche SMC-Abhängigkeit gelesen: Batterie per pmset -g batt (Notebooks), CPU_Speed_Limit / Scheduler / Available CPUs und thermischer Druck per pmset -g therm, AppleSmartBattery-Temperature und Lüfter-RPM per ioreg (falls Firmware sie bereitstellt). Desktops wie Mac mini haben oft keine Batterie; Apple Silicon möglicherweise keinen numerischen CPU_Speed_Limit. CPU-die-/proximity-Temperaturen benötigen private IOKit/SMC und werden derzeit nicht ausgelesen. Sobald thermischer Druck, Drosselung oder Lüfterwerte vorliegen, gilt thermal nicht als unavailable. Mit desktop-ui kann remote-agent --ui konfigurieren und Anmeldestart (LaunchAgent) umschalten.

cargo build --locked -p agent --release

# 推荐:安装为随登录会话运行的 LaunchAgent(无需 sudo)
./target/release/remote-agent install --config ~/.config/remote-agent/config.json
# 或:install/macos/install.sh ~/.config/remote-agent/config.json
remote-agent status
launchctl print gui/$(id -u)/us.ivjn.remote-agent | grep state

remote-agent install kopiert das aktuelle Programm nach ~/.local/bin/remote-agent, schreibt ~/.config/remote-agent/config.json (Rechte 600), erzeugt ~/Library/LaunchAgents/us.ivjn.remote-agent.plist, führt codesign -s - --force aus (macOS beendet unsignierte direkt ersetzte Programme) und dann launchctl bootstrap / kickstart. RunAtLoad + KeepAlive starten bei Anmeldung und lassen launchd nach Absturz oder Trennung neu starten. Logs: ~/Library/Logs/remote-agent.log. install/macos/install.sh ist ein dünner Wrapper. Ohne explizite Statusdatei gilt $HOME/.local/state/remote-agent/agent.state. Fernbefehle laufen mit Rechten des angemeldeten Benutzers.

Stoppen/deinstallieren:

remote-agent uninstall
# 或手动:
# launchctl bootout gui/$(id -u)/us.ivjn.remote-agent
# rm ~/Library/LaunchAgents/us.ivjn.remote-agent.plist

Für Dauerbetrieb ab Boot ohne Anmeldung einen LaunchDaemon unter /Library/LaunchDaemons als root laden. Fernbefehle laufen dann mit root-Rechten; Risiko entsprechend bewerten.

Eigenständige Android-APK

Geräteprojekt: android-agent/. mobile/ bleibt Administrationsclient; beide sind getrennt installierbar, ohne Expo Go, Termux oder root.

Standardadresse aller Agenten ist wss://exchange.ivjn.us. Unter Android Connect with a six-digit code wählen; nach Freigabe des sechsstelligen Codes durch die Administrator-CLI erhält das Gerät automatisch seine Identität. Native Agenten (lokale Windows/macOS-Seite, OpenWrt LuCI „Gerät hinzufügen“, remote-agent pair / remote-agent join <邀请>) können sechsstelligen Code und QR-Code zur Freigabe durch Console-Scan anzeigen oder über eine eingefügte einmalige Einladung beitreten. Siehe Initialisierung und Kopplung.

Erste Verbindung und Startseite

  1. Öffnen Sie Remote Agent auf dem Android-Gerät, das verwaltet werden soll. Wählen Sie zuerst Mit einem sechsstelligen Code verbinden oder Verbindungs-QR-Code scannen und lassen Sie den Zugriff durch einen Administrator genehmigen. Die Abläufe für Konten, QR-Codes und sechsstellige Codes stehen unter Initialisierung und Kopplung.
  2. Wenn Geräte-ID und Gerätetoken vorliegen, öffnen Sie Einstellungen → Verbindungseinstellungen, tragen Server und Zugangsdaten ein und wählen Speichern und verbinden. Bei aktivierter Verbindung sind die Eingabefelder ausgeblendet. Trennen Sie die Verbindung auf der Startseite, bevor Sie die Geräteidentität ändern.
  3. Die Startseite zeigt Verbindungsstatus, Bildschirmfreigabe und Verwalterliste. Bei gespeicherter Konfiguration und deaktivierter Verbindung wählen Sie Gerät verbinden. Beim erneuten Öffnen der App wird eine aktivierte Verbindung wiederhergestellt.

Android 12 und neuer verwenden den Systemstartbildschirm; Android 8–11 zeigen einen Start-Hintergrund mit denselben Markenfarben. Sobald das erste Bild bereitsteht, öffnet sich die Startseite, ohne auf die Netzwerkverbindung zu warten oder eine Mindestanzeigedauer einzufügen. Bei deaktivierten Systemanimationen entfallen die Übergänge. Einstellungen werden bei Bedarf geladen. Das Öffnen der Startseite erteilt keine Berechtigung für Bedienungshilfen oder Bildschirmfreigabe. Dies beschreibt den aktuellen Quellcode; prüfen Sie bei öffentlichen Downloads die installierte Version.

Hintergrundbetrieb, Benachrichtigungen und Beenden

Der Wechsel in den Hintergrund oder das Schließen der Oberfläche beendet den Vordergrunddienst nicht. Nach einem Netzwerkausfall verbindet sich der Agent erneut. Bei aktivierter Verbindung versucht er, den Dienst nach Geräteneustart und Entsperren oder nach einem App-Update wiederherzustellen. Nach erzwungenem Beenden muss die App manuell geöffnet werden. Energiesparregeln des Herstellers können eine zusätzliche Freigabe für den Hintergrundbetrieb verlangen.

Bei erlaubten Benachrichtigungen führt Verbindung verwalten zurück zur App. Während einer Freigabe beendet Freigabe beenden in der Benachrichtigung nur die Bildschirmfreigabe. Um den Fernzugriff zu trennen und die automatische Wiederherstellung zu deaktivieren, wählen Sie auf der Startseite Trennen und bestätigen. Die Konfiguration bleibt für eine spätere Verbindung über Gerät verbinden erhalten. Auch Bildschirmfreigabe beenden auf der Startseite beendet nur die Freigabe, nicht den Fernzugriff.

Das Gerätetoken wird mit Android Keystore AES-GCM verschlüsselt gespeichert. Die Konfiguration ist von Sicherungen ausgeschlossen; exportierte Activities oder Services geben keine Token weiter. Fernbefehle laufen unter der Anwendungs-UID der APK und unterliegen Android-Sandbox und SELinux. Sie gewähren weder Zugriff auf Daten anderer Apps noch Root-Rechte. Systemeinstellungen, Bedienungshilfen und Bildschirmfreigabe benötigen jeweils eigene Berechtigungen.

Bei aktiviertem Fernzugriff hält der Vordergrunddienst CPU- und Bildschirm-Wake-Locks. Der Bildschirm bleibt dadurch auch im Hintergrund und bei erneuter Verbindung an, was mehr Strom benötigt. Beim Trennen oder Beenden des Dienstes werden die Sperren freigegeben und die normale Bildschirmabschaltung wiederhergestellt. Die Ein-/Aus-Taste sperrt das Gerät weiterhin regulär und umgeht keine Anmeldung. Benachrichtigungen zeigen Verbindungs- oder Freigabestatus; die Startseite bietet die Trennfunktion.

Aus dem Quellcode bauen

Beginnen Sie jedes folgende Debug- oder Release-Beispiel im Repository-Stamm. Prüfen Sie vor der Installation die Geräteliste und ersetzen Sie DEVICE_SERIAL durch die Seriennummer des Zielgeräts. Paketbau, Unit-Tests und vollständiges Lint sind getrennte Prüfungen. Bei Lint-Fehlern den Bericht prüfen und die Ursache beheben oder dokumentieren. Überspringen gilt nicht als Bestehen.

Buildvoraussetzungen: JDK 17+, Android SDK Platform 36, NDK 28.2.13676358, Python 3 und Rust. ANDROID_HOME (oder ANDROID_SDK_ROOT) setzen; eigenen NDK-Pfad mit ANDROID_NDK_HOME. Vollbild-.Aran benötigt Metafile Android SDK: Repository Metafile neben remote-control ablegen (Gradle referenziert :aran über ../../Metafile/android-sdk/aran).

rustup target add aarch64-linux-android x86_64-linux-android
cd android-agent
./gradlew :app:assembleDebug :app:testDebugUnitTest
# Windows: .\gradlew.bat :app:assembleDebug :app:testDebugUnitTest
./gradlew :app:lintDebug
# Windows: .\gradlew.bat :app:lintDebug
adb devices -l
adb -s DEVICE_SERIAL install -r app/build/outputs/apk/debug/remote-agent-debug.apk

Gradle ruft automatisch scripts/build-android-agent.py auf und packt die Rust-Programme beider ABIs ins native Bibliotheksverzeichnis der APK. Nach Installation starten sie aus diesem schreibgeschützten Verzeichnis und erfüllen Androids Ausführungsverbot im App-Datenverzeichnis. debug-APK dient Entwicklungsprüfungen; zur Veröffentlichung release mit organisations eigener Signaturkonfiguration bauen und Schlüssel für spätere Upgrades aufbewahren.

Release-Builds lesen android-agent/keystore.properties (Git-ignoriert) oder externe Konfiguration aus REMOTE_AGENT_SIGNING_PROPERTIES. Felder siehe android-agent/keystore.properties.example, Schlüssel außerhalb des Repositorys aufbewahren. Ohne Signaturkonfiguration scheitert Release, ohne Rückfall auf Debug-Signatur.

cd android-agent
$env:REMOTE_AGENT_SIGNING_PROPERTIES = "$env:USERPROFILE/.remote-control/signing/remote-agent.properties"
.\gradlew.bat :app:assembleRelease :app:lintRelease :app:testReleaseUnitTest --no-daemon
# Output: app/build/outputs/apk/release/remote-agent-release.apk

Veröffentlichungsschlüssel und Passwort sicher sichern; Upgrades müssen denselben Schlüssel verwenden. Debug und Release sind verschieden signiert, vorhandene Debug-Installationen nicht direkt überschreibbar. Deinstallation löscht lokale Konfiguration und Gerätezugangsdaten; erneute Kopplung einplanen. scripts/build-site-downloads.py verwendet die signierte Release-APK als Agent-Download. Release-Signierung garantiert keine Aufhebung einer Play-Protect-Sperre.

Android-Verbindung per QR-Code

Scan connection QR code auf der Remote-Agent-Startseite erkennt Verbindungscodes offline per Kamera, ohne Google Play-Dienste. Beim ersten Mal Kamera erlauben; Abbrechen ändert nichts. Nach Scan erscheinen Server und Geräte-ID, Token bleibt verborgen. Erst Connect speichert verschlüsselt und startet die Verbindung. Bestehende Verbindung vor Konfigurationsimport stoppen. Scannen aktiviert weder Bildschirmsteuerung noch Bedienungshilfen automatisch.

Separates Gerät in Exchange registrieren und dessen Gerätetoken beziehen, dann QR-Code lokal am Computer erzeugen (kein Operator-Kontotoken oder fremder Online-QR-Dienst):

python -m pip install qrcode==8.2
python scripts/connection-qr.py --server wss://exchange.example.com --device-id android-phone --output "$env:TEMP\android-phone-connection.svg"
# 按提示输入设备令牌,输入不会显示。也可用 --token-stdin 从标准输入读取。

Erzeugtes SVG am Computer öffnen und mit Remote Agent scannen. Es enthält das Gerätetoken, muss vertraulich behandelt und anschließend gelöscht werden; nicht in Git einchecken. Bestehende Dateien werden nicht überschrieben.

QR-Inhalt ist UTF-8-JSON mit höchstens 2048 Byte Gesamtlänge:

{"type":"remote-agent","version":1,"server":"wss://exchange.example.com","device_id":"android-phone","token":"DEVICE_TOKEN"}

Scannen akzeptiert nur wss://, optional /ws/device, ohne URL-Benutzerinformationen, Queryparameter oder Fragment. server, device_id, token müssen nicht leere Strings mit höchstens 512, 128, 512 Zeichen ohne Steuerzeichen oder führende/nachgestellte Leerzeichen sein. Manuelle Konfiguration unterstützt lokale ws://-Tests.

Android-Bedienungshilfen, Screenshots und Texteingabe

Die folgenden Befehle verwenden remote-cli. Das Gerät meldet android_control über die APK-Brücke; Berechtigungen zeigt status.

  1. Verbinden Sie das Gerät, öffnen Sie Einstellungen → Bildschirm und Interaktion und aktivieren Sie Bildschirmfernsteuerung erlauben (standardmäßig aus).
  2. Wählen Sie Einstellungen zur Bedienungshilfe und aktivieren Sie Remote Agent in den Android-Einstellungen. Dies erlaubt das Lesen zugänglicher UI-Bäume, Tippen, Wischen, Systemnavigation und Ersetzen des Textes im fokussierten Eingabefeld.
  3. Android 11+ kann über aktivierte Bedienungshilfen Screenshots aufnehmen. Unter Android 8–10 oder für reine Bildschirmaufnahme wählen Sie Bildschirm freigeben auf der Startseite oder Standard-Bildschirmfreigabe in den Einstellungen und bestätigen den Systemdialog. Nach Ende der Freigabe oder Prozessneustart ist eine neue Bestätigung nötig.
remote-cli ui my-device status
remote-cli ui my-device tree
remote-cli ui my-device xml > screen.xml
remote-cli ui my-device click --view-id com.example:id/search
remote-cli ui my-device click --text "Search" --description "Open search"
remote-cli ui my-device screenshot --output screen.jpg
remote-cli ui my-device tap 300 500
remote-cli ui my-device swipe 500 1500 500 500 --duration-ms 400
# 多段滑动(折线,2-64 个点)
remote-cli ui my-device swipe-path 300,1500 300,800 900,800 --duration-ms 800
remote-cli ui my-device key back
remote-cli ui my-device text "Hello"
remote-cli ui my-device text --stdin < message.txt
remote-cli ui my-device type --stdin < message.txt

text ersetzt den gesamten Text des fokussierten Eingabefeldes mit Android ACTION_SET_TEXT, unterstützt Chinesisch, Emoji und mehrere Zeilen, höchstens 8192 UTF-8-Byte ohne NUL. Zuerst editierbares Feld antippen; ohne Fokus, Editierbarkeit oder Aktionsunterstützung wird ein Fehler gemeldet. --stdin liest UTF-8 mit Zeilenumbrüchen und vermeidet Texte im Kommandoverlauf. key unterstützt back, home, recents, notifications, quick-settings.

xml liefert verschachtelten <hierarchy><node ...>-Baum mit resource-id, text, content-desc, bounds und Elementzustand; höchstens 200 Knoten, 50 Ebenen, 256 Zeichen pro Attribut. Antwort und Wurzel melden Kürzung. click verwendet exakte vollständige Attributwerte (kein XPath): --view-id entspricht resource-id, --description entspricht content-desc; mehrere Bedingungen sind UND-verknüpft. Nur sichtbare aktivierte Elemente, kein oder mehrere Treffer sind Fehler. Bei Traversierungslimit kein Klick. Textlabels suchen anklickbare Eltern; sonst tap X Y. Nach Änderungen XML neu abrufen, lange Attribute durch Ressourcen-ID ersetzen.

Für die Eingabemethode öffnen Sie Einstellungen → Remote Input. Aktivieren Sie Remote Input in Android über Remote Input aktivieren und wählen Sie es anschließend über Eingabemethode auswählen aus. Nach Fokus im Zielfeld fügt type über InputConnection.commitText Text am Cursor/in Auswahl ein, unterstützt Chinesisch, Emoji und mehrere Zeilen mit gleichem 8192-UTF-8-Byte-Limit wie text. Kein automatisches Senden oder Formularabsenden, keine Änderung eigener Agent-Konfiguration. Switch keyboard stellt Alltagstastatur wieder her. status liefert ime_enabled, ime_selected und ime_connected. Vor Lesen, Klicken und Eingeben Bildschirm einschalten und lokal entsperren.

Remote Consoles Gerätebildschirm bietet Koordinatentippen, XML-Abruf und Attributklicks, Remote-Input-Texteingabe. Fehlende Berechtigungen oder Bildschirmzustände deaktivieren Schaltflächen. Erfolgreiche Eingabe leert Text; Hintergrundwechsel löscht Screenshots, XML und ausstehende Eingaben.

Systemfähigkeiten

Systemeinstellungen verwenden vom Gerät gemeldete Anbieter; Namensräume sind Strings statt fester Enumerationen. Android verwendet android_settings mit system, secure, global. Linux ohne OpenWrt und macOS verwenden system_settings: gsettings des aktuellen Linux-Benutzers bzw. /usr/bin/defaults des macOS-Benutzers. Browsererweiterungen verwenden browser_settings, lesen/schreiben privacy.network, privacy.services, privacy.websites verschlüsselt. Windows/OpenWrt bieten diese Einstellungen nicht. Neue Schlüssel/Wert-Einstellungen benötigen nur Anbieterregistrierung im Agenten/Erweiterung; der Client rendert die Liste.

Androids drei Namensräume sind unabhängig von Bildschirmschalter, Display und Sperrzustand, Zugriff über ContentResolver statt Shellzusammensetzung. Normale APKs benötigen zum Schreiben von system die Freigabe über Ändern von Systemeinstellungen erlauben im Agenten; secure/global benötigt zusätzlich WRITE_SECURE_SETTINGS. Status liefert Berechtigungen und providers; Android-/Herstellerrichtlinien können einzelne Zugriffe weiter ablehnen.

settings list --prefix filtert unter Android Einstellungsnamen. Linux/macOS liefern ohne prefix nur Schema-/Domainnamen, mit prefix deren oberste String-, Integer- und Booleanwerte. settings clear akzeptieren derzeit nur Browserdatenschutzeinstellungen; andere Anbieter melden ausdrücklichen Fehler. Audit erfasst Namensraum, Name, Zeichenzahl, keine Werte.

remote-cli ui realmev5 settings
remote-cli ui realmev5 settings list --namespace system --limit 100
remote-cli ui realmev5 settings get screen_off_timeout
remote-cli ui realmev5 settings set screen_off_timeout 600000
remote-cli ui realmev5 screen-timeout 600
remote-cli ui realmev5 settings get device_name --namespace global
remote-cli ui realmev5 settings set vendor.custom_setting --stdin

settings set verwendet Strings; --stdin erhält Zeilenumbrüche, Werte werden nicht auditiert. Höchstens 8192 UTF-8-Byte ohne NUL; Namen höchstens 256 ASCII-Zeichen (Buchstaben, Ziffern, Unterstrich, Punkt, Doppelpunkt, Bindestrich). Listen höchstens 500 Einträge/512 KiB, sonst truncated; Einzelwerte höchstens 64 KiB. Fehlende Einstellung liefert value: null. Eingeschränkte Einstellungen werden nicht stillschweigend erzwungen; jeder Schreibvorgang wird erneut gelesen und Fehler ausdrücklich gemeldet. Änderungen bleiben bestehen, Trennen stellt alte Werte nicht wieder her. screen-timeout verwendet Sekunden (15–86400), screen_off_timeout Millisekunden. Ausschaltzeit und anschließende Sperrverzögerung sind verschieden.

Medienwiedergabe (media)

Sprache, Audio, Bilder samt Vollbildtext, Video und Webseiten verwenden media, von Android- und Windows/Linux/macOS-Agenten gemeldet, nicht OpenWrt. Drei Protokollaktionen: media_play (mit media-Objekt), media_stop, media_status; alle liefern denselben media-Status.

media.type Felder Kanal
speech text, optional language (BCP-47, etwa zh-CN) Ton
audio Genau eines aus url oder path, optional loop Ton
image Genau eines aus url, path, text, optional p2p (nicht mit text) Bild
video Genau eines aus url oder path, optional p2p Bild
web url (nur https) Bild

Zwei unabhängige Kanäle: Ton (Sprache, Audio) und Bild (Bilder, Text, Video, Webseiten). Neuer Inhalt ersetzt nur laufenden Inhalt desselben Kanals, sodass Hintergrundmusik und Bildfolge gleichzeitig möglich sind. channel bei media_stop: sound, screen, all (Standard).

remote-cli ui realmev5 media speak "Remote 连接正常" --language zh-CN
remote-cli ui realmev5 media speak --stdin --language zh-CN
remote-cli ui realmev5 media audio --path /sdcard/Music/doorbell.mp3
remote-cli ui realmev5 media audio --url https://cdn.example.com/notice.mp3 --loop
remote-cli ui realmev5 media image --text "值班中"
remote-cli ui realmev5 media image --url https://example.com/poster.jpg
remote-cli ui realmev5 media video --path /sdcard/loop.mp4
remote-cli ui realmev5 media video --url https://files.example.org/library/clip.Aran --p2p-group library --p2p-discovery https://p2p.ivjn.us --p2p-token secret --p2p-peer 192.0.2.10:7300
remote-cli ui realmev5 media web https://status.example.com/board
remote-cli ui realmev5 media status
remote-cli ui realmev5 media stop sound      # 或 screen;不写则两个通道都停
remote-cli ui laptop media audio --path 'C:\Users\me\Music\alert.wav'
remote-cli ui laptop media image --text "Kiosk"

media status liefert:

{"kind":"media",
 "sound":{"type":"audio","id":"…","state":"playing","language":null,"loop":true},
 "screen":{"type":"web","keep_awake":true},
 "speech_available":true,"media_volume":7,"media_volume_max":15}

sound ist der letzte Toneintrag (bleibt nach Ende zur Ergebnisprüfung), Zustand queued / speaking / loading / playing / completed / stopped / error, ohne bisherige Wiedergabe null. screen erscheint nur bei aktiver Anzeige, sonst null. speech_available=false bedeutet keine Sprachengine. Medienlautstärke hat nur unter Android Werte, am Desktop 0.

Validierung und Audit: Text (Sprache/Bildtext) höchstens 4000 UTF-8-Byte ohne NUL; URL nur https, höchstens 2048 Byte ohne Leer-/Steuerzeichen; Pfade höchstens 4096 Byte ohne Steuerzeichen. Audit erfasst Typ, Quellenart (url / path / text), Zeichenzahl, Schleife und P2P, niemals URL, Pfad oder Text (URLs können Signaturtoken enthalten). readonly darf keine Medienaktionen ausführen.

Ton: Sprachausgabe und Audio

  • Sprache: Android verwendet System-TTS, Windows System.Speech, macOS say, Linux spd-say / espeak-ng / espeak (ohne diese speech_available=false und ausdrücklicher Fehler). Desktop versucht Sprachkennungen lokalen Stimmen zuzuordnen. Android antwortet erst nach Tonbeginn; Engineinitialisierung oder fehlende Sprachdaten liefern Fehler. Agent-Stopp gibt TTS frei.
  • Audio: Absoluter Gerätepfad oder https-URL. Fehlende Dateien vorher mit remote-cli files upload übertragen und per Pfad abspielen. loop wiederholt bis zum Stopp.
    • Android verwendet MediaPlayer mit Medienlautstärke, streamt URL direkt, antwortet nach Tonbeginn und meldet Fehler, falls kein Start innerhalb 10 Sekunden.
    • Desktop lädt URL ins temporäre Statusverzeichnis des aktuellen Benutzers (höchstens 50 MB, Weiterleitungen nur https), löscht nach Ende, Stopp oder Fehler. Antwort nach Start des Wiedergabeprozesses; Download-/Dekodierfehler erscheinen als sound.state=error in media status. Windows verwendet MediaPlayer (mp3, wav, m4a, aac, wma, flac), macOS afplay, Linux sucht mpv, ffplay, paplay, pw-play, aplay; fehlen alle, Fehler (paplay / aplay ohne mp3).
    • Pfad muss vorhandene lesbare reguläre Datei sein; Windows lehnt Netzwerkpfade wie \\server\share ab, um keine Zugangsdaten an SMB-Server zu senden.
  • Gerätelautstärke null kann unhörbare Wiedergabe bewirken.

Bild: Bilder, Text, Video und Webseiten

  • image: Lokaler path, https-URL oder text (großer UTF-8-Text auf dunklem Hintergrund, als statisches Bild). Android entschlüsselt .Aran mit Metafile Android SDK vor Anzeige.
  • video: Lokaler path oder https-URL, Schleife. Android behandelt .Aran nicht als normalen HTTPS-Medienstream: Ohne Cache blockweise Entschlüsselung während Download/Wiedergabe, Klartext lokal für spätere direkte Wiedergabe gespeichert. HTTP-Blöcke unter /meta/<SHA1> an der Origin-Wurzel; lokale Dateien lesen meta/ neben Manifest. Standardmäßig eingebetteter Manifestschlüssel oder SDK-Standard. Optional P2P: Quellenfolge lokales meta/, UDP P2P (LOOKUP_ONLY, keine metastore-Registrierung), HTTP-Rückfall. Discovery und statische Peers aus media.p2p, etwa --p2p-group library --p2p-discovery https://p2p.ivjn.us; fehlgeschlagener P2P-Start nutzt HTTP/lokal ohne Wiedergabeabbruch.
  • web: Vollbild-https-Seite. Android verwendet WebView in Vollbild-Activity (JavaScript/DOM storage an, Navigation nur https; Renderabsturz beendet Anzeige ohne Agent-Auswirkung). Desktop startet separaten Kioskbrowser mit temporärem Profil, beim Stopp mitsamt Browser beendet: Windows sucht Edge, Chrome, Firefox; macOS Chrome, Edge, Chromium, Firefox (Safari ohne Kiosk); Linux Chromium, Chrome, Edge, Firefox. Ohne Browser ausdrücklicher Fehler.

Android verwendet für .Aran-Manifeste/-Blöcke von https://cdn.ivjn.cn und https://cdn.ivjn.us automatisch die andere Domain als Ersatzquelle; Manifestpfad bleibt, Blöcke weiter aus /meta/<SHA1> jeder Quelle. Keine automatische Abbildung anderer Domains. Bei temporären Fehlern (auch HTTP 554), Timeout oder fehlgeschlagener Blockprüfung zuerst Ersatzquelle, dann 250/500 ms Backoff, höchstens 3 Runden; erfolgreiche Quelle danach bevorzugt. Verbindungstimeout 5 Sekunden, Lesen 30 Sekunden; permanente 403/404 usw. führen im selben Lesen nicht zu erneuter Anfrage derselben Quelle. Blockgröße und SHA-1 bleiben geprüft, keine Weiterleitungen oder gelockerte HTTPS-Prüfung. Benötigt Metafile ab2b92f oder neueres Android SDK mit MirroredHttpSource.

Der Bildkanal zeigt einen Inhalt, neuer ersetzt vorherigen. Bildschirm bleibt an (Android: FLAG_KEEP_SCREEN_ON + turnScreenOn / showWhenLocked; Windows: SetThreadExecutionState; macOS: caffeinate -d; Linux: systemd-inhibit oder xdg-screensaver inhibit). Statische Bilder/Texte verschieben sich langsam pixelweise gegen Einbrennen; Videos laufen in Schleife, Webseiten ohne Verschiebung. Kein statischer heller Rahmen. Android nutzt separate Vollbild-Activity ohne Bedienungshilfe. Linux benötigt entsperrte X11-Sitzung, Video lokal mpv oder ffplay; macOS bevorzugt mpv, sonst open.

Steuerung: Fortschritt und Webseiten

media_control steuert laufenden Kanalinhalt und liefert denselben media-Status. channel muss sound oder screen sein; op aus folgender Tabelle:

op.type Parameter Anwendbar auf
pause / resume — Audio (sound), Video (screen)
seek position_ms (absolute Position, höchstens 7 Tage) Audio, Video
navigate url (https) Webseiten
reload / back / forward — Webseiten
scroll dx, dy (Pixel, ungleich null, jeweils höchstens 100000) Webseiten
eval script (höchstens 16 KiB) Webseiten, liefert script_result (JSON-kodiertes Ergebnis, höchstens 64 KiB)
remote-cli ui realmev5 media pause sound
remote-cli ui realmev5 media seek 1:30 screen      # 也接受 90、1:02:03.5
remote-cli ui realmev5 media resume screen
remote-cli ui realmev5 media web go https://status.example.com/next
remote-cli ui realmev5 media web back
remote-cli ui realmev5 media web scroll 0 800
remote-cli ui realmev5 media web eval "document.title"

Status ergänzt position_ms, duration_ms, paused unter sound / screen (Audio/Video, soweit Player meldet), bei Webseiten url, title unter screen. Sprache, Bilder, Text sind nicht steuerbar; unpassender Kanalinhalt liefert ausdrücklichen Fehler. Audit erfasst Kanal, Aktionstyp, Skriptzeichenzahl, keine URLs/Skriptinhalte.

  • Android: Audio/Video steuern MediaPlayer / VideoView, Webseiten WebView der Vollbild-Activity.
  • Windows: Audio über mitgelieferten MediaPlayer-Worker, Video mit mpv über IPC-Pipe, auch WPF-Ersatzplayer steuerbar, ffplay nicht.
  • Linux / macOS: Audio/Video nur mit mpv steuerbar (JSON IPC), sonst „Install mpv to pause or seek desktop media“. macOS verwendet bei vorhandenem mpv auch für Audio mpv.
  • Desktop-Webseiten: Chrome / Edge / Chromium starten Kiosk mit --remote-debugging-port=0 (nur 127.0.0.1, zufälliger Port, temporäres Profil), Steuerung über DevTools. Firefox unterstützt nur navigate (Kiosk mit neuer Adresse neu öffnen).

Die mobile Remote Console bietet unter Systemfähigkeiten in Gerätedetails „Systemeinstellungen“ und „Medien“. Medien liest beide Kanäle, stoppt Ton/Bild getrennt, spielt Sprache, Audio-URL, Text, Bilder, Video und Webseiten und steuert Audio-/Videofortschritt sowie Webseiten (Navigation, vor/zurück, neu laden, scrollen, JS). Hintergrundwechsel leert Einstellungsergebnisse, ausstehende Werte, Sprachtext und Anzeigeeingaben. Webkonsole bietet dieselben Einstellungsformulare; Browsereinstellungen verwenden bestehende verschlüsselte Sitzung. Keine separate Web-Medienseite.

Android-Textsuche und XML

remote-cli ui realmev5 xml
remote-cli ui realmev5 find-text "设置"
remote-cli ui realmev5 find-text "Settings" --exact --ignore-case

Textsuche vergleicht Text/Beschreibung sichtbarer Knoten, standardmäßig Teilzeichenfolge, optional exakt oder ohne Groß-/Kleinschreibung. Jeder Treffer liefert bounds, center (ursprüngliche Bildschirmpixel, nutzbar mit tap X Y), Ressourcen-ID, Text und Aktivierungszustand. Mittelpunkt aus Schnittfläche mit Bildschirm vermeidet externe Koordinaten. Höchstens 200 Knoten, Kürzung gemeldet. Passwortknoten und eigener Agent-Konfigurationsunterbaum ausgeschlossen. Selbst gezeichneter Text eventuell nicht für Android-Bedienungshilfen lesbar; kein OCR. Nach Änderungen erneut suchen.

Screenshots sind JPEG, längste Seite höchstens 1600 Pixel; CLI überschreibt keine Dateien. CLI zeigt Bild- und Originalbildschirmmaße. Tippen, Wischen, bounds verwenden Originalpixel. Vorschaukoordinaten umrechnen mit 屏幕坐标 = 图像坐标 × screen_width / width (vertikal Höhenverhältnis). Nach Drehung Maße neu lesen. Baum höchstens 200 Knoten, Strings höchstens 256 UTF-16-Einheiten, truncated zeigt Knotenlimit. Selbst gezeichnete Apps eventuell ohne zugängliche Knoten.

Text/Beschreibungen von Passwortknoten und eigener Konfigurationsunterbaum werden nicht geliefert; Ferneingabe ändert eigene Konfiguration nicht. Android-FLAG_SECURE-Fenster erscheinen schwarz oder liefern Systemfehler; Android 15 schwärzt beim Teilen möglicherweise Apps mit Passwortfeldern oder sensiblen Inhalten. Bildschirmsteuerung verwendet vorhandene Operatorauthentifizierung, readonly darf sie nicht starten. Audit erfasst Aktionen, Koordinaten, Eingabezeichenzahl, keine Texte, Bäume oder Screenshots.

Stop screen sharing beendet MediaProjection; aktivierte Android-11+-Bedienungshilfen können weiter Screenshots liefern. Allow remote screen controls ausschalten blockiert alle weiteren Bildschirmaktionen und beendet Freigabe; Stop remote access trennt auch den Agenten. Ausgeführte Eingaben sind nicht rückgängig zu machen. Android verwaltet Bedienungshilfeberechtigungen separat; sie bleiben bei Schalter-Aus oder Dienststopp erhalten, ohne Annahme von Fernaktionen.

Die lokale Brücke verwendet zufälligen Unix-Socketnamen und prüft gleiche UID von Aufrufer und APK. Das schützt gegenüber anderen gewöhnlichen Apps. Autorisierte Fernshell teilt App-UID; der Schalter ist keine Berechtigungsisolation gegenüber dieser Shell oder Geräteadministratoren.

Systeminformationen und Metriken

DeviceInfo.platform: linux, freebsd, netbsd, windows, android, macos, openwrt; os_version ist allgemeine Systemversion, capabilities beschreibt exec, pty, ubus, android_control. OpenWrt meldet openwrt_version.

Linux/OpenWrt lesen /proc; Android behält bei SELinux-Einschränkungen andere lesbare Metriken, Betriebszeit über CLOCK_BOOTTIME. Windows liest Speicher, CPU, Betriebszeit und Netzwerkkartenzähler über native APIs. Fehlende Metriken stehen in unavailable, CLI/mobile Clients zeigen Lücken. Windows hat keinen Unix load average, load ist immer nicht verfügbar.

Prüfung

cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo test -p agent --features desktop-ui
cargo clippy -p agent --features desktop-ui --all-targets -- -D warnings
cd mobile && npm run typecheck && npm run lint && npm test

scripts/agent-smoke.py ist ein lokales Testrelay mit Python websockets, prüft echte Agent-Registrierung, Metriken, Ausführung, Timeout, Abbruch, PTY, resize und nicht unterstütztes ubus. Kein Ersatz für Exchange-Authentifizierungs-/Datenbanktests. Feste Testzugangsdaten nach Anleitung, keine produktiven Geräte/Dienste verbinden. Windows/Linux führen jeweilige native Tests aus; Android nach Installation zusätzlich Vordergrund, Hintergrund, Stopp, Wiederverbindung real prüfen.

scripts/agent-ui-smoke.py --agent <binary> --platform linux|windows prüft Erstkonfiguration, Authentifizierung/Herkunftsbeschränkungen, private Speicherung, Tokenbeibehaltung, echte Registrierung/Ausführung, Stoppbereinigung, Wiederverbindung, erneutes Öffnen. Benötigt Python 3.11+ und websockets, Agent zuerst mit desktop-ui bauen. Browsertests auch für Speichern, Fehler, Tokensichtbarkeit, Neuladewiederherstellung, schmale Layouts.

scripts/android-control-smoke.py prüft Bildschirmaktionen mit echtem Exchange, CLI und separater Android-Test-App. Nur dedizierten wegwerfbaren Emulator verwenden: Skript löscht Remote-Agent-Daten und ändert Bedienungshilfen. Zuerst :app:assembleDebug und :control-fixture:assembleDebug bauen/installieren, separates Exchange/Datenbank vorbereiten, Gerät registrieren, Token und CLI-Konfiguration speichern. Benötigt Python 3.11+, Pillow, adb.

adb -s emulator-5580 install -r android-agent/app/build/outputs/apk/debug/remote-agent-debug.apk
adb -s emulator-5580 install -r -t android-agent/control-fixture/build/outputs/apk/debug/control-fixture-debug.apk
python scripts/android-control-smoke.py --serial emulator-5580 \
  --cli target/debug/remote-cli --cli-config /private/qa-cli.toml \
  --device-token /private/qa-device-token.txt \
  --device-id android-control-qa --device-server ws://10.0.2.2:18820/ws/device

Windows: CLI-Pfad target/debug/remote-cli.exe. Standardartefakte: target/android-control-qa/screenshots/. fixture nur für Tests, nicht in Geräte-APK.

Android-Logs, Bildschirmstatus und Aufwecken

Remote Console ergänzt Gerätelogs und Gerätebildschirm in Details. Bildschirmseite zeigt Displayvorhandensein, Strom-/Sperrzustand, Maße, Berechtigungen, JPEG-Vorschau auf Abruf und Bildschirm aufwecken. Ohne Display oder Android-Schnittstelle sind Bildschirmaktionen deaktiviert; fehlende Aufnahmeberechtigung separat. Ausgeschaltete Displays lassen sich bei lokal aktivierter Steuerung wecken. Die Tastensperre wird nie aufgehoben.

Android-Agent bietet lokal Bildschirmstatus und Gerätelogs. Bei Fernzugriff sind Verbindungsfelder, QR-Registrierung und Code-Schaltflächen verborgen. Trennen benötigt Bestätigung und behält Zugangsdaten. Autorisierung und aktive Bindung der Bedienungshilfen werden separat gemeldet; bei Autorisierung ohne Bindung nur Remote Agent in System-Bedienungshilfen umschalten.

remote-cli ui realmev5 status
remote-cli ui realmev5 logs --limit 100
remote-cli ui realmev5 wake
remote-cli ui realmev5 screenshot --output screen.jpg

open_android akzeptiert {action:"logs",limit:100} (1–300 Einträge) und {action:"wake"}. Optionaler Status: display_present, screen_on, locked, screen_width, screen_height, accessibility_authorized; accessibility_enabled bedeutet weiterhin verbundener Dienst. Native Android-Bildschirm-APIs benötigen APK; andere Agenten melden diese Schnittstelle nicht.

Logs kommen aus logcat -b all, ohne PID-/Paket-/Tagfilter: System-, App-, Ereignis-, Absturzpuffer von Android logd. Abruf liefert bis 100 UI-Einträge oder 1–300 per CLI mit Zeitstempeln, Stufen, Puffernamen, PID/TID, Tags, Originalnachrichten. Aktuelle logcat-Historie, kein Archiv beliebiger Dateien oder rotierter Logs.

Systemlogberechtigung über autorisierte ADB-Verbindung erteilen:

adb shell pm grant com.remote.agent android.permission.READ_LOGS

Bei Android mit Freigabe je Zugriff Agent-Diagnoseseite öffnen, Systemdialog bestätigen und Fernanfrage wiederholen. Hintergrundzugriff kann verweigert werden, Freigabe nach Android-/OEM-Richtlinie ablaufen. Android liefert nach Ablehnung möglicherweise still nur Aufrufer-UID; daher prüft der Collector UID-Metadaten der letzten 301 logcat-Einträge vor Auswahl des gewünschten Endes. Ohne andere UID (auch leere Logs) meldet er fehlende Bestätigung geräteweiten Zugriffs statt App-only-Aufnahme. Fehlende Berechtigung/logcat-Fehler liefern ausdrücklichen Fehler, kein Rückfall auf Agent-Ereignisring. Erfassung außerhalb UI-Thread, Abbruch bei Stornierung, sechs Sekunden Zeitlimit und begrenzte Ausgabe; Übergröße meldet Kürzung/Fehler. Bestehende authentifizierte Operatorsitzungen, Mandantenrouting und Rollenbeschränkungen gelten. Logs können Inhalte anderer Apps enthalten. Web-/Mobilansichten leeren sich bei Verlassen/Hintergrund und speichern nicht auf Datenträger; Remote Console löscht dann auch Screenshots.

Transparente Vollbildfreigabe: Im Android-Agent Share full screen with transparent overlay wählen, Android-Anzeige-über-Apps und Bildschirmfreigabe erlauben. Agent wechselt in Hintergrund und legt Vollbild-TYPE_APPLICATION_OVERLAY mit Deckkraft null und FLAG_NOT_TOUCHABLE | FLAG_NOT_FOCUSABLE an: Berührungen gehen an darunterliegende App. MediaProjection erfasst ganzes Display (Android 14+ fordert Standarddisplay explizit an). Stopp über Agent-Seite/Benachrichtigung trennt Agent nicht. Overlay wird bei Ende oder Dienststopp entfernt.

Bildschirmvorschau und verbundene Agent-Statusseiten erlauben Aufnahmen. Verbindungseinrichtung, Anmeldetickets und Token-QR-Seiten bleiben geschützt. Sichere Fenster anderer Apps können weiter schwarz erscheinen; transparentes Overlay umgeht deren Schutz nicht.

Vor Aufnahme prüft der Agent Displayzustand und interaktiven PowerManager-Zustand. Nur ausgeschaltetes Display wird geweckt, interaktiver Zustand geprüft, bei Tastensperre Aufnahme verweigert. MediaProjection-Reader leert kontinuierlich Frames und behält ein aktuelles zusammengesetztes Bild statt Surface pro Screenshot neu anzulegen. Bei ganz schwarzen Frames wartet er auf brauchbaren Frame und liefert bei Timeout handlungsorientierten Fehler statt erfolgreiches schwarzes JPEG.

Vergleich der Agent-Modi

Startmodus und Geräteplattform sind getrennte Aspekte. Nativer headless-Betrieb, lokale UI und Systemdienste teilen den Verbindungskern; desktop-ui ergänzt nur die lokale Konfiguration und erteilt keine Fernzugriffsrechte.

Modus/Plattform Funktionen Voraussetzungen und Grenzen
headless / lokale UI Gleiches natives Protokoll, Befehle, Terminal, Dateien, Metriken, Benachrichtigungen, optionales LAN UI nur auf Linux/Windows/macOS; Windows mit Tray; Desktop-Aktionen benötigen eine nutzbare grafische Benutzersitzung
Systemdienst / Anmeldestart Derselbe native Agent Übernimmt Dienstkonto und Umgebung; Startparameter werden nicht in andere Dienste kopiert
OpenWrt Nativer Kern, ubus Meldet ubus nur bei Verfügbarkeit; procd überwacht; keine Desktop-Steuerung gemeldet
Linux / Windows / macOS Nativer Kern, Desktop-Steuerung, Systemprotokolle, Medien OS-Rechte/Werkzeuge erforderlich; Systemeinstellungen nur auf Linux/macOS gemeldet
FreeBSD / NetBSD Nativer Kern, Terminal, Dateien, Netzwerk, Metriken, optionales LAN Keine Batterie; X11-Abhängigkeiten; keine Medien/Systemeinstellungen
Android APK Rust-Kern + Java-Brücke, Bildschirm, Einstellungen, Medien, OTA App-UID und OS-Berechtigungen; eigenständiges Rust-Programm ohne APK-Steuerbrücke
Chromium-Erweiterung URL, Cookies, Webseiten, Browsereinstellungen, CDP, Metriken Keine OS-Befehle/PTY/beliebigen Hostdateien/LAN-Listener; vollständiges CDP benötigt lokale Erlaubnis

UI und headless nutzen dieselbe Auflösung der Laufzeitkonfiguration: CLI/Umgebung haben für LAN, watchdog, TLS und Benachrichtigungen Vorrang vor JSON; automatische Updates bleiben bei CLI > JSON > REMOTE_AUTO_UPDATE > standardmäßig aktiviert. REMOTE_WATCHDOG=1 sowie 0, true/false, yes/no und on/off werden akzeptiert. Die UI lehnt Startüberschreibungen für Verbindungsdaten und Zustandspfade weiterhin ab. Laufzeitüberschreibungen werden nicht in JSON gespeichert; Autostart-Prozesse müssen separat konfiguriert werden. Der LAN-Status zeigt wirksame Werte; Speichern entfernt keine Startüberschreibungen.

UI und headless nutzen JSON state_file, sonst denselben dauerhaften Systemstandardpfad; separate Geräteinstanzen benötigen separate Pfade. Beim Verbinden wird connecting, beim Stoppen stopped angezeigt. Stoppen bricht das Auto-Update-Future dieser Verbindung ab und gibt den watchdog-Zustand frei; Hintergrundprüfer enden bei der nächsten Prüfung. Abgeschlossene Vorgänge lassen sich nicht rückgängig machen. Jede neue Verbindung lädt Geräteidentität und Vertrauensrichtlinie erneut; schlägt das Laden fehl, wird die vorherige Identität gelöscht, statt die alte Geräteautorisierung beizubehalten.

Alle Geräteoperationen erfordern versiegelte Sitzungen und eine Autorisierung durch den Workspace-Stammschlüssel. Die Einzelbestätigung/unbeaufsichtigte Freigabe für vollständiges Browser-CDP wird nicht durch typisierte Cookie-Bereiche isoliert und kann Chrome-Richtlinien nicht umgehen. Nach Schließen oder Verbindungsabbruch ist ein neuer Handshake nötig. Desktop-Updatearchive sind Windows x64, Linux glibc x64/arm64 und macOS arm64 zugeordnet; andere native Plattformen verwenden Installer/Paketmanager, Android APK OTA und Browser Erweiterungspakete. Eine gemeldete Fähigkeit garantiert keine verfügbare Hardware, Berechtigung oder Veröffentlichung.

Automatischer Bildschirmschoner

Die Einstellungen des lokalen Agents und der Browsererweiterung bieten Leerlauf (Standard: 300 Sekunden), Steuerungsbeginn/-ende und Sofortstart. Inhalte: Text, HTTPS-Bilder/-Videos oder isoliertes statisches HTML. Videos laufen stumm in Schleife; Text und Bilder können sich weiträumig bewegen. Desktop und Android bieten ein Beenden-Passwort. Das Browser-Vollbild hat kein Passwort und endet per Taste, Mausbewegung oder Fensterschließen. Nur der aktive Bildschirm wird abgedeckt; keine Betriebssystemsperre. Linux benötigt X11 und xprintidle. OpenWrt ohne Desktop, Wayland und BSD unterstützen derzeit keine Bildschirmanzeige.

Einfarbiger Modus ohne Text oder Medien: Hintergrundfarbe #RRGGBB und Helligkeit 0–100% (0% ist schwarz). Android dimmt auch die Fensterbeleuchtung und stellt bei Eingabe die Systemhelligkeit wieder her. Andere Plattformen dimmen nur das Bild; LCD-Einsparungen hängen von der Beleuchtung ab. Der Beenden-Dialog bleibt lesbar.

Ab 0.1.34 bewegen sich nur Text und Bilder über einen großen Bereich des Hintergrunds. Große Inhalte werden bei Bedarf auf höchstens 44% der verfügbaren Breite und Höhe verkleinert, damit gegenüberliegende Eckpositionen nicht überlappen. HTML, Video und Vollfarben bleiben still; reduzierte Bewegung pausiert die Animation. Alle Modi verbergen den Mauszeiger ab dem ersten Bild, zeigen ihn im Beenden-Dialog und verbergen ihn nach Abbrechen erneut. Windows aktualisiert den Zeiger im Schonerfenster alle 100 ms, ohne den Systemcursor zu ändern. Zuerst verfügbar in Windows und Browser Agent 0.1.34; andere Plattformversionen stehen im Download-Manifest.