CH-J Toolsspráva serverů přes SSH
Menu

Ukládání ve vzdáleném editoru a sledování latence

Stáhnout soubor

Jazyková revize tohoto překladu probíhá. Při nejasnostech porovnejte anglický originál.

Hlavní příčiny

Předchozí editor nahrával svůj pracovní soubor do nadřazeného adresáře cíle, do kterého účet SSH pod /etc nebo /var často nemůže zapisovat. Přejmenování přes SFTP neposkytovalo autorizovanou cestu přes sudo, kontrolu konfliktu vůči výchozímu stavu, ověření bezpečnostních metadat ani spolehlivou sémantiku přepsání. Obsluha chyb mazala dočasnou kopii, a tím odstraňovala materiál pro obnovu i tehdy, když dokončení nebylo jisté.

Stav relace dříve ukazoval pouze stav spojení. Indikátor terminálu nedostával žádné měření ICMP ani měření odezvy autentizovaného SSH.

Protokol ukládání

  1. Pevný pomocný program SSH otevře běžný soubor s jediným pevným odkazem pomocí operací relativních k deskriptoru a O_NOFOLLOW pro každou složku cesty. Zaznamená obsah, hash SHA-256, zařízení/inode, UID, GID, všechny bity oprávnění, nanosekundové časy změny obsahu a stavu a všechny čitelné rozšířené atributy. Core ověří hash a dekóduje striktní UTF-8 se zachováním BOM. Každý dokument dostane neprůhledné editId omezené na svůj plugin, relaci terminálu a identitu serveru.
  2. Neprivilegovaná přípravná operace zjistí domovský adresář autentizovaného účtu přes pwd.getpwuid(os.getuid()), vytvoří $HOME/ch-j-sm/ s režimem 0700 a vytvoří soukromý výhradní deník obnovy. Nebezpečný domovský adresář, pracovní prostor jako symbolický odkaz nebo pracovní prostor vlastněný jiným účtem je odmítnut.
  3. Core nahraje přes SFTP skrytý náhodný 128bitový pracovní soubor .tmp s výhradním vytvořením (wx), režimem 0600 a šedesátisekundovým limitem kanálu/nahrávání. Deník obsahuje cíl, původní výchozí stav a očekávaný hash pracovní kopie; neobsahuje žádné přihlašovací údaje.
  4. Celé dokončení provede jediné spuštění přes SSH exec, volitelně přes stávající vykonavatel sudo. Pomocný program bezpečně otevře soukromou pracovní kopii, spočítá její hash a zapíše ji na disk. Uzamkne původní inode, zkontroluje výchozí stav, vytvoří výhradní cílový soubor vedle cíle, zapíše celý obsah, nastaví a ověří metadata, znovu zkontroluje originál a zapíše náhradu na disk.
  5. os.replace ve stejném adresáři atomicky nahradí cíl. Nadřazený adresář se zapíše na disk a ověří se konečná cesta, hash, inode a metadata. Původní cesta zůstává dostupná až do nahrazení. Pracovní soubor se nikdy nepřesouvá mezi souborovými systémy a dokončení jej nikdy neodstraňuje.
  6. Jakmile Core obdrží ověřený úspěch, samostatný úklid znovu zkontroluje konečný obsah a bezpečnostní metadata a teprve poté odstraní pracovní soubor a deník. Selhání úklidu stále hlásí potvrzené uložení s recoveryAvailable: true.

Neúspěšné nahrání, neúspěšné sudo, konflikt, chyba metadat nebo neúspěšné nahrazení zachová originál i veškerý připravený materiál. Neúplná nahrání se jako taková označí a nelze je obnovit jako úplný upravený dokument. Ztracená komunikace SSH, chybějící návratový stav, vypršení časových limitů a neočekávané výsledky dokončení se hlásí jako neznámé, nikdy jako uložené. Core u nejistého dokumentu blokuje další uložení; automatické opakování nahrazení neexistuje.

Metadata, oprávnění a bezpečnostní hranice

Pomocný program zachovává a ověřuje UID, GID a všechny bity oprávnění POSIX, včetně bitů spustitelnosti, setuid, setgid a sticky. Rozšířené atributy Linux reprodukuje bajt po bajtu, včetně POSIX ACL, capabilities a značek SELinux. Vlastnictví a obsah souboru se nastavují před bezpečnostními atributy, protože zápis/chown může vymazat capabilities nebo speciální bity oprávnění. Zděděné atributy cíle, které originál nemá, se odstraní. Čas změny odpovídá novému zápisu a nekopíruje se z originálu.

Nečitelný nebo nepřenositelný atribut operaci přeruší; metadata se nikdy tiše nezahazují. Podpisy IMA/EVM jsou výslovně odmítnuty, protože kopírování podpisů integrity vázaných na obsah/inode by je zneplatnilo. Symbolické odkazy v cílové nebo domovské cestě, soubory s více pevnými odkazy a jiné než běžné soubory jsou odmítnuty. Nepoužívá se žádné přepsání na místě ani slabší náhradní přepsání přes SFTP.

Běžná zapisovatelná uložení běží pod účtem SSH. Chráněná uložení vyžadují výslovné { sudo: true }; heslo pro sudo je u sudo bez hesla volitelné. Hesla se ověřují a předávají pouze přes stdin kanálu, nikdy v příkazu, deníku, pracovním souboru, logu ani ve vzdálené chybě. Relace SSH jako root používají stávající přímý vykonavatel root. Neúspěšná autorizace ponechá originál i pracovní kopii beze změny. Všechna uložení prováděná jako root (přímé SSH jako root nebo sudo) navíc odmítají cílové adresáře/předky vlastněné jinými účty nebo jimi zapisovatelné či opatřené přístupovým ACL, místo aby důvěřovala privilegované cestě ovládané jiným účtem.

Pevný pomocný program běží s python3 -I -B: ignoruje uživatelské cesty Pythonu, pracovní adresář a uživatelské site packages a nezapisuje bytecode. Cesty a argumenty JSON se v Core uvozují pro shell. Pluginy nikdy nedostávají libovolný SSH exec ani handly SFTP. Stávající sandbox, CSP, oprávnění manifestu, ověřování klíče hostitele a ověřování aktualizací zůstávají v platnosti.

Plugin API a zbývající integrace Monaco

Samostatně distribuované UI Monaco/File Manager v tomto checkoutu chybí. Jeho integraci do UI, výzvu sudo, práci s neuloženým bufferem a překlady zde nebylo možné implementovat ani otestovat. Přibaleným zdrojem pluginu je plugin Hash & Checksum. Žádný náhradní zdroj File Manageru nebyl vymyšlen.

Stávající metody zůstávají dostupné. Doplňkové metody/volby zpřístupňuje preload v sandboxu a běhové prostředí s kontrolou oprávnění:

const opened = await chjPlugin.files.readText(sessionId, path);
// For a protected read, explicitly pass { sudo: true, sudoPassword }.

const result = await chjPlugin.files.saveText(sessionId, path, editor.getValue(), {
  editId: opened.editId,
  sudo: true,           // Include only after the user authorizes elevation.
  sudoPassword         // Omit for passwordless sudo; never persist this value.
});

if (result.ok && result.value.status === "saved") {
  // Mark this exact submitted editor version as saved. Later edits stay dirty.
} else {
  // Keep the Monaco model dirty. Translate result.error.code/status.
  // result.error.recoveryId/recoveryPath identify retained working material.
}

await chjPlugin.files.closeText(opened.editId);
const recovery = await chjPlugin.files.listRecovery(sessionId);
const copy = await chjPlugin.files.readRecovery(sessionId, recoveryId);
// Review copy.status and copy.text; open a fresh document before another save.
await chjPlugin.files.cleanupRecovery(sessionId, recoveryId);
// Cleanup rejects anything whose target is not currently confirmed.

Metody obnovy přijímají volitelný poslední argument { sudo: true, sudoPassword }, pokud kontrola cíle vyžaduje zvýšení oprávnění. Ponechávají pracovní prostor autentizovaného uživatele i při spuštění přes sudo. Deníky přežijí restart aplikace i nové připojení SSH; obnova nikdy automaticky neopakuje dokončení. Obnovený buffer před výslovným uložením porovnejte s nově otevřeným cílem.

files.read chrání čtení, kontrolu a uvolnění handlů. files.write chrání uložení a úklid obnovy. writeText u stávajících pluginů při selhání nadále odmítá; saveText vrací strukturovanou obálku { ok, value/error }, protože Electron u odmítnutých objektů Error zahazuje vlastní vlastnosti. Starší tříargumentové volání writeText může použít výchozí stav jediného otevřeného dokumentu. Více živých dokumentů pro stejnou cestu vyžaduje editId; nejednoznačná starší volání bezpečně selžou, místo aby použila výchozí stav jiného dokumentu. Pluginy by měly nepoužívané handly uvolňovat.

Externí UI musí ukládání zobrazit okamžitě, při selhání ponechat buffery jako neuložené, nabízet sudo až po selhání oprávnění/autentizace, zobrazit konflikty bez přepsání a po ztrátě spojení nebo neznámém výsledku nabídnout obnovu. Tyto stavy musí překládat do češtiny, němčiny a angličtiny. Navržené texty stavů:

Stav Čeština Němčina Angličtina
Ukládání Ukládání… Wird gespeichert… Saving…
Potvrzeno Uloženo Gespeichert Saved
Selhání Uložení selhalo Speichern fehlgeschlagen Save failed
Vyžadováno sudo Vyžadováno oprávnění sudo sudo-Autorisierung erforderlich Sudo authorization required
Konflikt Původní soubor byl změněn Originaldatei wurde geändert Original file changed
Odpojeno Spojení bylo přerušeno Verbindung unterbrochen Connection lost
Neznámé Výsledek uložení není znám Speicherergebnis unbekannt Save result unknown
Obnova Obnova je dostupná Wiederherstellung verfügbar Recovery available

Definice latence a životní cyklus

Ping je latence hlášená skutečnou odpovědí ICMP echo na straně klienta na přeloženou IP adresu, kterou používá SSH. Core spouští systémový program ping asynchronně s pevným polem argumentů, bez shellu a bez nutnosti spouštět aplikaci jako správce. Argumenty pro Linux, macOS (včetně ping6) a Windows se volí zvlášť. Blokované ICMP, chybějící program, vypršení času, neplatný výstup nebo odpověď Windows udávající jen horní mez, například <1ms, vedou k nedostupné hodnotě, nikoli k vymyšlenému číslu.

SSH RTT je monotónní doba performance.now() pevného požadavku exec true přes stávajícího autentizovaného klienta SSH. Zahrnuje vytvoření kanálu, zpracování na serveru a doručení odpovědi; nejde o čisté síťové RTT ani o dobu přihlášení SSH. Přeložená nápověda indikátoru tento rozdíl vysvětluje.

Sledování začíná, jakmile se terminál připojí. Sondy běží souběžně a asynchronně s pětisekundovým limitem požadavku/procesu. Další vzorek se plánuje dvanáct sekund po dokončení předchozího, takže se nepřekrývají. Odpojení přeruší ICMP, vymaže časovače, zruší probíhající práci SSH a vymaže hodnoty. Kontroly identity záznamu brání tomu, aby předchozí spojení publikovalo hodnoty po novém připojení. Selhání ICMP nikdy nemění stav spojení SSH.

Latence se přenáší uvnitř stávající události state / datové části IPC ssh:state:

latency: { pingMs: 24.1, sshRttMs: 31.25, measuredAt: "…" }

Nedostupná čísla jsou null. Kompaktní indikátor terminálu používá milisekundy, lokalizovaný text pro nedostupnost a popisky v češtině/němčině/angličtině. Po odpojení se skryje. Nebyla potřeba žádná další schopnost spouštění v rendereru ani požadavek IPC.

Ověření a provozní omezení

Uživatel požadoval zachovat změny ve stávajícím pracovním stromu, nyní feature/hash-checksum-plugin; nedošlo k přepnutí větve ani k nesouvisejícímu úklidu.

Soubory změněné v tomto úkolu