CH-J Server Managerمدیریت سرور از طریق SSH
منو

ذخیره در ویرایشگر راه‌دور و پایش تأخیر

دانلود فایل

این ترجمه در حال بازبینی زبانی است. اگر بخشی روشن نیست، آن را با متن اصلی انگلیسی مقایسه کنید.

علت‌های ریشه‌ای

ویرایشگر پیشین فایل کاری خود را در پوشهٔ والد مقصد بارگذاری می‌کرد؛ پوشه‌ای که حساب SSH اغلب در /etc یا /var اجازهٔ نوشتن در آن را ندارد. تغییر نام از طریق SFTP هیچ مسیر مجاز sudo، بررسی تعارض در برابر وضعیت پایه، راستی‌آزمایی فرادادهٔ امنیتی یا معنای قابل اعتماد بازنویسی فراهم نمی‌کرد. کنترل‌کنندهٔ خطای آن نسخهٔ موقت را حذف می‌کرد و حتی وقتی از پایان کار اطمینانی نبود، مادهٔ بازیابی را از بین می‌برد.

وضعیت نشست پیش‌تر فقط حالت اتصال را نشان می‌داد. هیچ اندازه‌گیری ICMP یا پاسخ احراز هویت‌شدهٔ SSH نشانگر ترمینال را تغذیه نمی‌کرد.

پروتکل ذخیره

  1. یک برنامهٔ کمکی ثابت SSH فایلی معمولی با یک پیوند را با عملیات نسبی به توصیفگر و O_NOFOLLOW برای هر جزء مسیر باز می‌کند. این برنامه محتوا، هش 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 و مهلت کانال/بارگذاری شصت ثانیه‌ای بارگذاری می‌کند. دفترچه شامل مقصد، وضعیت پایهٔ اصلی و هش مورد انتظار فایل کاری است؛ اطلاعات احراز هویت در آن نیست.
  4. یک اجرای SSH کل مرحلهٔ نهایی‌سازی را انجام می‌دهد، به‌صورت اختیاری از طریق مجری sudo موجود. برنامهٔ کمکی نسخهٔ کاری خصوصی را به‌طور امن باز و هش می‌کند و آن را روی دیسک تخلیه (flush) می‌کند. inode اصلی را قفل می‌کند، وضعیت پایهٔ آن را بررسی می‌کند، فایل مقصدی انحصاری کنار مقصد می‌سازد، کل محتوا را می‌نویسد، فراداده را اعمال و راستی‌آزمایی می‌کند، فایل اصلی را دوباره بررسی می‌کند و فایل جایگزین را روی دیسک تخلیه می‌کند.
  5. os.replace در همان پوشه مقصد را به‌صورت اتمی جایگزین می‌کند. پوشهٔ والد روی دیسک تخلیه می‌شود و مسیر نهایی، هش، inode و فراداده راستی‌آزمایی می‌شوند. مسیر اصلی تا زمان جایگزینی در دسترس می‌ماند. فایل کاری هرگز میان سیستم‌های فایل جابه‌جا نمی‌شود و هرگز توسط نهایی‌سازی حذف نمی‌شود.
  6. پس از آنکه Core موفقیت راستی‌آزمایی‌شده را دریافت کرد، یک پاک‌سازی جداگانه محتوای نهایی و فرادادهٔ امنیتی را پیش از حذف فایل کاری و دفترچه دوباره بررسی می‌کند. شکست پاک‌سازی همچنان ذخیرهٔ تأییدشده را با recoveryAvailable: true گزارش می‌کند.

بارگذاری ناموفق، sudo ناموفق، تعارض، خطای فراداده یا جایگزینی ناموفق، فایل اصلی و هر مادهٔ آماده‌شده را حفظ می‌کند. بارگذاری‌های ناقص به همین عنوان شناسایی می‌شوند و نمی‌توان آن‌ها را به‌عنوان سند ویرایش‌شدهٔ کامل بازیابی کرد. قطع ارتباط SSH، نبود وضعیت خروج، پایان مهلت‌ها و نتایج غیرمنتظرهٔ نهایی‌سازی به‌عنوان نامعلوم گزارش می‌شوند، هرگز به‌عنوان ذخیره‌شده. Core ذخیرهٔ دیگری را روی سندی با نتیجهٔ نامطمئن مسدود می‌کند؛ تلاش دوبارهٔ خودکار برای جایگزینی وجود ندارد.

فراداده، امتیازها و مرزهای ایمنی

برنامهٔ کمکی UID، GID و همهٔ بیت‌های مجوز POSIX، از جمله بیت‌های اجرایی، setuid، setgid و sticky را حفظ و راستی‌آزمایی می‌کند. ویژگی‌های گستردهٔ Linux را بایت به بایت بازتولید می‌کند، از جمله POSIX ACL، capabilities و برچسب‌های SELinux. مالکیت و محتوای فایل پیش از ویژگی‌های امنیتی تنظیم می‌شوند، زیرا نوشتن/chown می‌تواند capabilities یا بیت‌های مجوز ویژه را پاک کند. ویژگی‌های به‌ارث‌رسیده در مقصد که در فایل اصلی نیستند حذف می‌شوند. زمان اصلاح، نوشتن جدید را بازتاب می‌دهد و از فایل اصلی کپی نمی‌شود.

ویژگی ناخوانا یا غیرقابل نمایش عملیات را متوقف می‌کند؛ فراداده بی‌صدا کنار گذاشته نمی‌شود. امضاهای IMA/EVM به‌صراحت رد می‌شوند، زیرا کپی کردن امضاهای یکپارچگی وابسته به محتوا/inode آن‌ها را باطل می‌کند. پیوندهای نمادین در مسیر مقصد یا پوشهٔ خانگی، فایل‌های دارای پیوند سخت و فایل‌های غیرمعمول رد می‌شوند. هیچ بازگشتی به بازنویسی درجا یا بازنویسی ضعیف‌تر SFTP به کار نمی‌رود.

ذخیره‌های معمولی که مجوز نوشتن دارند با حساب SSH اجرا می‌شوند. ذخیره‌های محافظت‌شده به { sudo: true } صریح نیاز دارند؛ گذرواژهٔ sudo برای sudo بدون گذرواژه اختیاری است. گذرواژه‌ها اعتبارسنجی می‌شوند و فقط از طریق stdin کانال ارسال می‌شوند، هرگز درون فرمان، دفترچه، فایل کاری، ثبت‌کننده یا خطای راه‌دور. نشست‌های SSH با root از مجری مستقیم root موجود استفاده می‌کنند. شکست مجوزدهی فایل اصلی و نسخهٔ کاری را دست‌نخورده باقی می‌گذارد. همهٔ ذخیره‌هایی که با root اجرا می‌شوند (SSH مستقیم root یا sudo) همچنین پوشه‌های مقصد/نیاکانی را که متعلق به حساب‌های دیگر یا قابل نوشتن توسط آن‌ها هستند یا ACL دسترسی دارند رد می‌کنند، به‌جای اعتماد به مسیری دارای امتیاز ویژه که حساب دیگری آن را کنترل می‌کند.

برنامهٔ کمکی ثابت با python3 -I -B اجرا می‌شود: مسیرهای Python کاربر، پوشهٔ کاری و site packages کاربر را نادیده می‌گیرد و bytecode نمی‌نویسد. مسیرها و آرگومان‌های JSON در Core برای پوسته نقل‌قول می‌شوند. افزونه‌ها هرگز اجرای دلخواه SSH یا دستگیره‌های SFTP دریافت نمی‌کنند. sandbox، CSP، مجوزهای manifest، راستی‌آزمایی کلید میزبان و راستی‌آزمایی به‌روزرسانی موجود همچنان به کار می‌روند.

Plugin API و یکپارچه‌سازی باقی‌ماندهٔ Monaco

رابط کاربری Monaco/File Manager که جداگانه توزیع می‌شود در این checkout وجود ندارد. یکپارچه‌سازی رابط آن، پیام sudo، مدیریت بافر ذخیره‌نشده و ترجمه‌های آن در اینجا قابل پیاده‌سازی یا آزمایش نبودند. منبع افزونهٔ همراه، افزونهٔ Hash & Checksum است. هیچ منبع جایگزینی برای File Manager ساخته نشده است.

روش‌های موجود در دسترس می‌مانند. روش‌ها/گزینه‌های افزوده توسط preload در sandbox و محیط اجرای دارای بررسی مجوز در اختیار گذاشته می‌شوند:

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، فضای کاری کاربر احراز هویت‌شده را حفظ می‌کنند. دفترچه‌ها پس از راه‌اندازی دوبارهٔ برنامه و اتصال دوبارهٔ SSH باقی می‌مانند؛ بازیابی هرگز نهایی‌سازی را به‌طور خودکار تکرار نمی‌کند. پیش از ذخیرهٔ صریح بافر بازیابی‌شده، آن را با مقصدی که تازه باز شده مقایسه کنید.

files.read خواندن، بررسی و آزادسازی دستگیره‌ها را محافظت می‌کند. files.write ذخیره‌ها و پاک‌سازی بازیابی را محافظت می‌کند. writeText برای افزونه‌های موجود همچنان هنگام شکست رد (reject) می‌شود؛ saveText پوشش ساخت‌یافتهٔ { ok, value/error } را برمی‌گرداند، زیرا Electron ویژگی‌های سفارشی اشیای Error ردشده را حذف می‌کند. writeText قدیمی با سه آرگومان می‌تواند از وضعیت پایهٔ تنها سند باز استفاده کند. چند سند زنده برای یک مسیر به editId نیاز دارند؛ فراخوانی‌های قدیمی مبهم به‌جای انتخاب وضعیت پایهٔ سند دیگر، به‌طور امن شکست می‌خورند. افزونه‌ها باید دستگیره‌های بلااستفاده را آزاد کنند.

رابط کاربری خارجی باید وضعیت ذخیره را فوراً نشان دهد، هنگام شکست بافرها را ذخیره‌نشده نگه دارد، sudo را فقط پس از شکست مجوز/احراز هویت پیشنهاد دهد، تعارض‌ها را بدون بازنویسی نشان دهد و پس از قطع اتصال یا نتیجهٔ نامعلوم، بازیابی را پیشنهاد دهد. این رابط باید این وضعیت‌ها را به زبان‌های چکی، آلمانی و انگلیسی ترجمه کند. متن پیشنهادی وضعیت‌ها:

وضعیت چکی آلمانی انگلیسی
در حال ذخیره 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 مدت یکنواخت performance.now() یک درخواست ثابت اجرای 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، حفظ شوند؛ هیچ تغییر شاخه یا پاک‌سازی نامرتبطی انجام نشد.

فایل‌های تغییریافته برای این کار