CH-J Server Managerการจัดการเซิร์ฟเวอร์ผ่าน SSH
เมนู

การบันทึกในตัวแก้ไขระยะไกลและการตรวจสอบเวลาแฝง

ดาวน์โหลดไฟล์

คำแปลนี้อยู่ระหว่างการตรวจทานด้านภาษา หากส่วนใดไม่ชัดเจน โปรดเทียบกับต้นฉบับภาษาอังกฤษ

สาเหตุที่แท้จริง

ตัวแก้ไขเดิมอัปโหลดไฟล์ทำงานไปยังไดเรกทอรีหลักของไฟล์เป้าหมาย ซึ่งบัญชี SSH มักไม่มีสิทธิ์เขียนภายใต้ /etc หรือ /var การเปลี่ยนชื่อผ่าน SFTP ไม่มีเส้นทาง sudo ที่ได้รับอนุญาต การตรวจสอบข้อขัดแย้งเทียบกับสถานะตั้งต้น การตรวจสอบเมทาดาทาด้านความปลอดภัย หรือความหมายของการเขียนทับที่เชื่อถือได้ ตัวจัดการข้อผิดพลาดของตัวแก้ไขเดิมลบสำเนาชั่วคราว ทำให้ข้อมูลสำหรับกู้คืนหายไปแม้ในกรณีที่ไม่แน่ใจว่าการบันทึกเสร็จสมบูรณ์หรือไม่

สถานะเซสชันก่อนหน้านี้แสดงเพียงสถานะการเชื่อมต่อ ไม่มีการวัด ICMP หรือการตอบกลับ SSH ที่ยืนยันตัวตนแล้วซึ่งส่งข้อมูลให้ตัวบ่งชี้ของเทอร์มินัล

โปรโตคอลการบันทึก

  1. Helper SSH แบบคงที่จะเปิดไฟล์ปกติที่มีลิงก์เดียวโดยใช้การดำเนินการแบบอ้างอิงตาม descriptor และ O_NOFOLLOW สำหรับทุกส่วนของพาธ Helper จะเก็บเนื้อหา แฮช SHA-256 อุปกรณ์/inode, UID, GID บิตสิทธิ์ทั้งหมด เวลาแก้ไข/เปลี่ยนแปลงระดับนาโนวินาที และแอตทริบิวต์ขยายทั้งหมดที่อ่านได้ Core จะตรวจสอบแฮชและถอดรหัส UTF-8 อย่างเข้มงวด โดยคง BOM ไว้ เอกสารแต่ละฉบับจะได้รับ editId แบบทึบ ซึ่งจำกัดขอบเขตไว้ที่ปลั๊กอิน เซสชันเทอร์มินัล และตัวตนของเซิร์ฟเวอร์
  2. การดำเนินการเตรียมการที่ไม่มีสิทธิ์พิเศษจะหาโฮมของบัญชีที่ยืนยันตัวตนแล้วผ่าน pwd.getpwuid(os.getuid()) สร้าง $HOME/ch-j-sm/ ด้วยโหมด 0700 และสร้างบันทึกการกู้คืน (journal) ส่วนตัวแบบเอกสิทธิ์ โฮมที่ไม่ปลอดภัย พื้นที่ทำงานที่เป็นลิงก์สัญลักษณ์ หรือพื้นที่ทำงานที่เป็นของบัญชีอื่นจะถูกปฏิเสธ
  3. Core อัปโหลดไฟล์ทำงาน .tmp ที่ซ่อนอยู่และมีชื่อสุ่ม 128 บิตผ่าน SFTP ด้วยการสร้างแบบเอกสิทธิ์ (wx) โหมด 0600 และการหมดเวลาของช่องสัญญาณ/การอัปโหลดหกสิบวินาที Journal มีไฟล์เป้าหมาย สถานะตั้งต้นดั้งเดิม และแฮชที่คาดไว้ของไฟล์ทำงาน โดยไม่มีข้อมูลรับรอง
  4. การเรียกใช้ SSH ครั้งเดียวจะทำขั้นตอนสรุปผลทั้งหมด โดยอาจผ่านตัวดำเนินการ sudo ที่มีอยู่ Helper จะเปิดและคำนวณแฮชของสำเนาทำงานส่วนตัวอย่างปลอดภัย แล้วเขียนลงดิสก์ (flush) จากนั้นล็อก inode ดั้งเดิม ตรวจสอบสถานะตั้งต้น สร้างไฟล์ปลายทางแบบเอกสิทธิ์ข้างไฟล์เป้าหมาย เขียนเนื้อหาทั้งหมด ใช้และตรวจสอบเมทาดาทา ตรวจสอบไฟล์ดั้งเดิมอีกครั้ง และเขียนไฟล์ทดแทนลงดิสก์
  5. os.replace ในไดเรกทอรีเดียวกันจะแทนที่ไฟล์เป้าหมายแบบอะตอมมิก ไดเรกทอรีหลักจะถูกเขียนลงดิสก์ แล้วจึงตรวจสอบพาธสุดท้าย แฮช inode และเมทาดาทา พาธดั้งเดิมยังคงใช้ได้จนกว่าจะแทนที่ ไฟล์ทำงานจะไม่ถูกย้ายข้ามระบบไฟล์ และจะไม่ถูกลบโดยขั้นตอนสรุปผล
  6. หลังจาก Core ได้รับผลสำเร็จที่ตรวจสอบแล้ว ขั้นตอนล้างข้อมูลที่แยกต่างหากจะตรวจสอบเนื้อหาสุดท้ายและเมทาดาทาด้านความปลอดภัยอีกครั้งก่อนลบไฟล์ทำงานและ journal หากการล้างข้อมูลล้มเหลว ยังคงรายงานว่าการบันทึกได้รับการยืนยันพร้อม recoveryAvailable: true

การอัปโหลดที่ล้มเหลว sudo ที่ล้มเหลว ข้อขัดแย้ง ข้อผิดพลาดของเมทาดาทา หรือการแทนที่ที่ล้มเหลว จะคงไฟล์ดั้งเดิมและข้อมูลที่เตรียมไว้ทั้งหมด การอัปโหลดที่ไม่สมบูรณ์จะถูกระบุเช่นนั้นและไม่สามารถกู้คืนเป็นเอกสารที่แก้ไขฉบับสมบูรณ์ได้ การสื่อสาร SSH ที่ขาดหาย สถานะการออกที่หายไป การหมดเวลา และผลลัพธ์การสรุปผลที่ไม่คาดคิดจะถูกรายงานเป็น ไม่ทราบ ไม่ใช่บันทึกแล้ว Core จะบล็อกการบันทึกครั้งต่อไปสำหรับเอกสารที่ผลลัพธ์ไม่แน่นอน และไม่มีการลองแทนที่ซ้ำโดยอัตโนมัติ

เมทาดาทา สิทธิ์พิเศษ และขอบเขตด้านความปลอดภัย

Helper จะคงไว้และตรวจสอบ UID, GID และบิตสิทธิ์ POSIX ทั้งหมด รวมถึงบิต executable, setuid, setgid และ sticky และจะจำลองแอตทริบิวต์ขยายของ Linux ทีละไบต์ รวมถึง POSIX ACL, capabilities และป้ายกำกับ SELinux ความเป็นเจ้าของและเนื้อหาไฟล์จะถูกตั้งค่าก่อนแอตทริบิวต์ด้านความปลอดภัย เนื่องจากการเขียน/chown อาจล้าง capabilities หรือบิตสิทธิ์พิเศษ แอตทริบิวต์ที่สืบทอดมาที่ปลายทางแต่ไม่มีในไฟล์ดั้งเดิมจะถูกลบ เวลาแก้ไขสะท้อนการเขียนครั้งใหม่และไม่ได้คัดลอกมาจากไฟล์ดั้งเดิม

แอตทริบิวต์ที่อ่านไม่ได้หรือแสดงแทนไม่ได้จะทำให้การดำเนินการถูกยกเลิก เมทาดาทาจะไม่ถูกทิ้งไปอย่างเงียบ ๆ ลายเซ็น IMA/EVM จะถูกปฏิเสธอย่างชัดแจ้ง เพราะการคัดลอกลายเซ็นความสมบูรณ์ที่ผูกกับเนื้อหา/inode จะทำให้ลายเซ็นใช้ไม่ได้ ลิงก์สัญลักษณ์ในพาธเป้าหมายหรือโฮม ไฟล์ที่มีฮาร์ดลิงก์ และไฟล์ที่ไม่ใช่ไฟล์ปกติจะถูกปฏิเสธ ไม่มีการถอยกลับไปใช้การเขียนทับในที่เดิมหรือการเขียนทับ SFTP ที่ปลอดภัยน้อยกว่า

การบันทึกปกติที่มีสิทธิ์เขียนจะทำงานในนามบัญชี SSH การบันทึกที่ได้รับการป้องกันต้องระบุ { sudo: true } อย่างชัดแจ้ง รหัสผ่าน sudo ไม่บังคับสำหรับ sudo แบบไม่ใช้รหัสผ่าน รหัสผ่านจะได้รับการตรวจสอบและส่งผ่าน stdin ของช่องสัญญาณเท่านั้น ไม่เคยอยู่ในคำสั่ง journal ไฟล์ทำงาน ตัวบันทึก (logger) หรือข้อผิดพลาดระยะไกล เซสชัน SSH ของ root ใช้ตัวดำเนินการ root โดยตรงที่มีอยู่ การอนุญาตที่ล้มเหลวจะคงไฟล์ดั้งเดิมและสำเนาทำงานไว้ครบถ้วน การบันทึกทั้งหมดที่ทำงานในนาม root (SSH ของ root โดยตรงหรือ sudo) จะปฏิเสธไดเรกทอรีเป้าหมาย/ไดเรกทอรีบรรพบุรุษที่เป็นของหรือเขียนได้โดยบัญชีอื่น หรือมี ACL การเข้าถึงด้วย แทนที่จะเชื่อถือชื่อพาธที่มีสิทธิ์พิเศษซึ่งบัญชีอื่นควบคุมได้

Helper แบบคงที่ทำงานด้วย python3 -I -B ซึ่งจะไม่สนใจพาธ Python ของผู้ใช้ ไดเรกทอรีทำงาน และ site packages ของผู้ใช้ และไม่เขียน bytecode พาธและอาร์กิวเมนต์ JSON จะถูกใส่เครื่องหมายคำพูดสำหรับเชลล์ใน Core ปลั๊กอินไม่เคยได้รับการเรียกใช้ SSH แบบอิสระหรือ handle ของ SFTP แซนด์บ็อกซ์ CSP สิทธิ์ในแมนิเฟสต์ การตรวจสอบคีย์โฮสต์ และการตรวจสอบการอัปเดตที่มีอยู่ยังคงใช้งานอยู่

Plugin API และการผสานรวม Monaco ที่เหลืออยู่

UI ของ Monaco/File Manager ที่เผยแพร่แยกต่างหากไม่มีอยู่ใน checkout นี้ การผสานรวม UI ข้อความแจ้ง sudo การจัดการบัฟเฟอร์ที่ยังไม่บันทึก และคำแปลของ UI ดังกล่าวจึงไม่สามารถนำไปใช้หรือทดสอบได้ที่นี่ ซอร์สปลั๊กอินที่รวมมาคือปลั๊กอิน Hash & Checksum ไม่มีการสร้างซอร์ส File Manager ทดแทนขึ้นมาเอง

เมธอดที่มีอยู่ยังคงใช้ได้ เมธอด/ตัวเลือกเพิ่มเติมเปิดให้ใช้ผ่าน preload ในแซนด์บ็อกซ์และรันไทม์ที่ตรวจสอบสิทธิ์:

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.

เมธอดการกู้คืนรับอาร์กิวเมนต์สุดท้ายแบบไม่บังคับ { sudo: true, sudoPassword } เมื่อการตรวจสอบไฟล์เป้าหมายต้องใช้สิทธิ์ที่สูงขึ้น เมธอดเหล่านี้ยังคงใช้พื้นที่ทำงานของผู้ใช้ที่ยืนยันตัวตนแล้วแม้จะทำงานผ่าน sudo Journal ยังคงอยู่หลังการรีสตาร์ตแอปและการเชื่อมต่อ SSH ใหม่ การกู้คืนจะไม่ทำขั้นตอนสรุปผลซ้ำโดยอัตโนมัติ ให้ตรวจทานบัฟเฟอร์ที่กู้คืนเทียบกับไฟล์เป้าหมายที่เพิ่งเปิดใหม่ก่อนบันทึกอย่างชัดแจ้ง

files.read ควบคุมการอ่าน การตรวจสอบ และการปล่อย handle ส่วน files.write ควบคุมการบันทึกและการล้างข้อมูลการกู้คืน writeText ยังคงปฏิเสธ (reject) เมื่อล้มเหลวสำหรับปลั๊กอินที่มีอยู่ ส่วน saveText ส่งคืนซองข้อมูลที่มีโครงสร้าง { ok, value/error } เนื่องจาก Electron ทิ้งพร็อพเพอร์ตี้ที่กำหนดเองบนอ็อบเจ็กต์ Error ที่ถูกปฏิเสธ writeText แบบเดิมที่มีสามอาร์กิวเมนต์สามารถใช้สถานะตั้งต้นของเอกสารที่เปิดอยู่เพียงฉบับเดียวได้ เอกสารที่เปิดอยู่หลายฉบับสำหรับพาธเดียวกันต้องใช้ editId การเรียกแบบเดิมที่กำกวมจะล้มเหลวอย่างปลอดภัยแทนที่จะเลือกสถานะตั้งต้นของเอกสารอื่น ปลั๊กอินควรปล่อย handle ที่ไม่ได้ใช้

UI ภายนอกต้องแสดงสถานะการบันทึกทันที คงบัฟเฟอร์ไว้เป็นสถานะยังไม่บันทึกเมื่อล้มเหลว เสนอ sudo หลังจากความล้มเหลวด้านสิทธิ์/การยืนยันตัวตนเท่านั้น แสดงข้อขัดแย้งโดยไม่เขียนทับ และเสนอการกู้คืนหลังการเชื่อมต่อขาดหายหรือผลลัพธ์ที่ไม่ทราบ UI ต้องแปลสถานะเหล่านี้เป็นภาษาเช็ก เยอรมัน และอังกฤษ ข้อความสถานะที่แนะนำ:

สถานะ ภาษาเช็ก ภาษาเยอรมัน ภาษาอังกฤษ
กำลังบันทึก Ukládání… Wird gespeichert… Saving…
ยืนยันแล้ว Uloženo Gespeichert Saved
ล้มเหลว Uložení selhalo Speichern fehlgeschlagen Save failed
ต้องใช้ sudo Vyžadováno oprávnění sudo sudo-Autorisierung erforderlich Sudo authorization required
ข้อขัดแย้ง Původní soubor byl změněn Originaldatei wurde geändert Original file changed
ขาดการเชื่อมต่อ Spojení bylo přerušeno Verbindung unterbrochen Connection lost
ไม่ทราบ Výsledek uložení není znám Speicherergebnis unbekannt Save result unknown
การกู้คืน Obnova je dostupná Wiederherstellung verfügbar Recovery available

นิยามของเวลาแฝงและวงจรชีวิต

Ping คือเวลาแฝงที่รายงานโดยการตอบกลับ ICMP echo จริงฝั่งไคลเอนต์ไปยัง IP ที่แปลงชื่อแล้วซึ่ง SSH ใช้ Core เรียกไฟล์ปฏิบัติการ ping ของแพลตฟอร์มแบบอะซิงโครนัสด้วยอาร์เรย์อาร์กิวเมนต์คงที่ โดยไม่ใช้เชลล์และไม่ต้องเริ่มด้วยสิทธิ์ผู้ดูแลระบบ อาร์กิวเมนต์สำหรับ Linux, macOS (รวมถึง ping6) และ Windows ถูกเลือกแยกกัน ICMP ที่ถูกบล็อก ไฟล์ปฏิบัติการที่ไม่มี การหมดเวลา เอาต์พุตที่ไม่ถูกต้อง หรือการตอบกลับของ Windows ที่มีเพียงขอบเขตบน เช่น <1ms จะให้ค่าที่ไม่พร้อมใช้งาน ไม่ใช่ตัวเลขที่แต่งขึ้น

SSH RTT คือระยะเวลาแบบ monotonic ของ performance.now() สำหรับคำขอ exec true แบบคงที่ผ่านไคลเอนต์ SSH ที่ยืนยันตัวตนแล้วซึ่งมีอยู่ ค่านี้รวมการตั้งค่าช่องสัญญาณ การประมวลผลของเซิร์ฟเวอร์ และการส่งการตอบกลับ ไม่ใช่ RTT ของเครือข่ายล้วน ๆ หรือระยะเวลาเข้าสู่ระบบ SSH คำอธิบายเครื่องมือ (tooltip) ที่แปลแล้วของตัวบ่งชี้จะอธิบายความแตกต่างนี้

การตรวจสอบจะเริ่มทันทีที่เทอร์มินัลเชื่อมต่อ การตรวจวัดทำงานพร้อมกันแบบอะซิงโครนัส โดยมีการหมดเวลาของคำขอ/กระบวนการห้าวินาที ตัวอย่างถัดไปจะถูกกำหนดเวลาสิบสองวินาทีหลังจากตัวอย่างก่อนหน้าเสร็จสิ้น เพื่อป้องกันการทับซ้อน การตัดการเชื่อมต่อจะยกเลิก ICMP ล้างตัวจับเวลา ยกเลิกงาน SSH ที่ค้างอยู่ และล้างค่า การตรวจสอบตัวตนของระเบียนจะป้องกันไม่ให้การเชื่อมต่อก่อนหน้าเผยแพร่ค่าหลังจากเชื่อมต่อใหม่ ความล้มเหลวของ ICMP ไม่เคยเปลี่ยนสถานะการเชื่อมต่อ SSH

เวลาแฝงถูกส่งภายในเพย์โหลด IPC ของเหตุการณ์ state / ssh:state ที่มีอยู่:

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

ตัวเลขที่ไม่พร้อมใช้งานมีค่าเป็น null ตัวบ่งชี้เทอร์มินัลแบบกะทัดรัดใช้หน่วยมิลลิวินาที ข้อความไม่พร้อมใช้งานที่แปลแล้ว และป้ายกำกับภาษาเช็ก/เยอรมัน/อังกฤษ และจะซ่อนเมื่อตัดการเชื่อมต่อ ไม่จำเป็นต้องมีความสามารถในการเรียกใช้ของ renderer หรือคำขอ IPC เพิ่มเติม

การตรวจสอบและข้อจำกัดในการดำเนินงาน

ผู้ใช้ขอให้เก็บการเปลี่ยนแปลงไว้ใน working tree ที่มีอยู่ ซึ่งขณะนี้คือ feature/hash-checksum-plugin ไม่มีการสลับแบรนช์หรือการล้างข้อมูลที่ไม่เกี่ยวข้อง

ไฟล์ที่เปลี่ยนแปลงสำหรับงานนี้