
ltm هو مصحح أخطاء تاريخ الآلة لنظام لينكس. يسجل بيانات تعريف العمليات والملفات والشبكة والذاكرة والإدخال/الإخراج عبر الكتل عبر eBPF، ثم يتيح لك الاستعلام عن الجدول الزمني.
مصحح تاريخ الآلة لنظام لينكس. يسجل العمليات، الملفات، الشبكة، الذاكرة، وإدخال/إخراج الكتل عبر eBPF، ويخزن البيانات الوصفية في SQLite، ويجيب عن أسئلة حول ما حدث على الجهاز بصيغة خط زمني / فرق / إنجليزية بسيطة / SQL.
⚠️ التقاط يعتمد على نقاط التتبع فقط حاليًا — يستخدم التسجيل حاليًا برامج نقاط التتبع. لا يستخدم بعد خطافات kprobes أو uprobes أو XDP أو TC، لذا فهو يفضل البيانات الوصفية المستقرة لاستدعاءات النظام/الكتلة/العملية على العمق الداخلي للنواة، أو تتبع دوال مساحة المستخدم، أو فحص مسار الحزمة.
go build -o bin/ltm ./cmd/ltm
sudo ./bin/ltm start # تسجيل (eBPF؛ صلاحية الجذر، لينكس/x86_64)
./bin/ltm timeline --since 5m
./bin/ltm watch # تتبع حي؛ Ctrl-C للإيقاف
./bin/ltm diff --from 10m --to now
./bin/ltm query "who modified /etc/some.conf?"
sudo ./bin/ltm stop
التسجيل يحتاج صلاحية الجذر (أو CAP_BPF + CAP_PERFMON). الاستعلام لا يحتاج.
بدون مسجل لينكس فعلي: ltm benchmark --count 1000 يزرع أحداثًا اصطناعية في قاعدة بيانات يمكنك فحصها باستخدام timeline و diff و query.
العلامات العامة توضع قبل الأمر الفرعي (ltm --db /tmp/ltm.db status).
الإعدادات الافتراضية: قاعدة بيانات ~/.local/share/ltm/ltm.db، معرف العملية ~/.local/run/ltm.pid.
أضف --json لأي أمر قراءة للحصول على مخرجات قابلة للقراءة آليًا.
قاعدة بيانات SQLite واحدة، كاتب WAL محتفظ به من قبل الخفي. كل مسار قراءة يفتح للقراءة فقط (PRAGMA query_only=ON) — الاستعلامات لا تتنافس أبدًا مع الكاتب ولا تغير السجل. بيانات وصفية فقط؛ لا محتويات ملفات.
export LTM_AGENT=claude # أو codex، cursor، gemini، auto، أو أمر مخصص
ltm query "which process wrote to files the most today?"
"
يتم طباعة SQL الوكيل، ثم تشغيله على اتصال القراءة فقط، ويتم رفضه ما لم يكن عبارة `SELECT` واحدة. لا وكيل (أو فشل الوكيل) → قوالب مدمجة.
## ما يتم تسجيله
حوالي 60 نقطة تتبع: **عملية** (exec، exit، fork، clone، kill)، **ملف**
(open/close، read/write، rename، unlink، link، symlink، mkdir، rmdir، chmod،
chown، stat، access، truncate، dup، pipe، …)، **ذاكرة** (mmap، munmap،
mprotect)، **شبكة** (socket، connect، bind، listen، accept، send/recv،
shutdown)، **كتلة** (`block_rq_issue`).
BPF يتجاوز `/proc`، `/sys`، `/dev` ومعرف العملية الخاص بالخفي. قائمة نقاط التتبع اليدوية موجودة في `internal/abi/abi.yaml`؛ جدول وقت التشغيل المضمن يتم إنشاؤه في `internal/abi/tracepoints_gen.go`. بعد تعديل `collector.bpf.c`، أعد البناء باستخدام `make ebpf`. بعد تعديل بيانات ABI الوصفية في `internal/abi/abi.yaml`، قم بتشغيل `make generate` ثم `make ebpf` إذا تغير تخطيط أحداث النواة أو جدول نقاط التتبع.
### القيود
- **تسجيل x86_64 فقط** — BPF مبني بـ `-D__TARGET_ARCH_x86`
([#2](https://github.com/Agent-Hellboy/ltm/issues/2)). الاستعلام والبيانات التجريبية المولدة بواسطة `benchmark` لا تتطلب دعم تسجيل لينكس.
- **عناوين IPv4 فقط** — يتم تخزين اتصالات/ربطات IPv6 بدون عنوان مفكوك.
- **عدادات البايت** هي الحجم *المطلوب* لاستدعاء النظام (مسبار الدخول)؛ الإدخال/الإخراج القصير/الفاشل يتم عدّه بشكل زائد؛ `readv`/`writev`/`sendmsg`/`recvmsg` يبلغون `0`.
- **fd→path** يغطي واصفات الملفات ≤ 1024 وقد يسند بشكل خاطئ بعد إعادة استخدام كثيفة لمعرفات العمليات؛ يتم تسجيل واصفات الملفات الأعلى بدون مسار.
## التطوير
```bash
go test ./... # اختبارات محلية/وحدوية
make generate # إعادة توليد مخرجات ABI/المخطط من abi.yaml
make ebpf # إعادة توليد كائن/ارتباطات BPF المضمنة (لينكس)
make integration # تسجيل eBPF حقيقي؛ لينكس + صلاحية الجذر
التخطيط: cmd/ltm نقطة الدخول؛ كل شيء آخر تحت internal/
(abi، cli، daemon، collector، ebpf، storage، agent، diff، query).
مولد ABI/المخطط يبقي تعريفات الأحداث، DDL التخزين، بيانات نقاط التتبع الوصفية، وهياكل النواة مربوطة بمصدر واحد للحقيقة:
internal/abi/abi.yaml. هو متعمد مشابه في روحه لسير عمل Argument Clinic
لمشروع CPython (المصدر):
عند إضافة حدث/وحدة سطح جديدة يتم التقاطها، قم بتحديث القائمة وأعد توليد المخرجات المضمنة بدلاً من تحرير ملفات Go أو C المشتقة يدويًا.
الوثائق: docs/ (ABI، CLI، الملفات المولدة، الاستعلام، التسجيل،
الهندسة، الأمان).
قواعد المساهمين: AGENTS.md.
| الأمر | ما يفعله |
|---|
start / stop / status | التحكم في المسجل |
timeline | التصفية حسب --pid --uid --comm --category --action --path --exe --since --until --limit (قابل للتكرار؛ --path/--exe هما LIKE في SQL) |
watch | تتبع حي (--interval --since --category --comm --pid) |
diff --from --to | تغييرات حالة الآلة بين وقتين |
query "<question>" | إنجليزية بسيطة (قوالب، أو وكيل → SQL) |
query sql ["<SELECT>"] | SQL للقراءة فقط؛ بدون وسيط يطبع المخطط (ltm sql يعمل أيضًا) |
prune --older-than 720h [--vacuum] | حذف الصفوف القديمة، مع إمكانية استعادة مساحة القرص |
benchmark --count N | كتابة N حدث اصطناعي (بدون eBPF) |
version | إصدار البناء، الالتزام، المنصة |