
تتبع كل متغير بيئة في الصدفة إلى ملفه وسطر مصدره بدقة. دقق في إعدادات الصدفة بحثًا عن إدخالات ميتة، ومكررات، وملفات يتيمة عبر zsh وbash على macOS وLinux وFreeBSD.
لكل متغير في الصدفة الحالية لديك، ابحث عن الملف والسطر الذي قام بتعيينه، أو أي نظام فرعي (direnv، launchd، terminal، SSH، system) قام بحقنه. بالإضافة إلى بعض أوامر الملفات الثابتة للحظة التي تنتشر فيها إعدادات الصدفة عبر N من الملفات والنسخ الاحتياطية وتفقد السيطرة.
بنيت هذا لأنني كنت أفقد نفس الساعة كل بضعة أشهر في تتبع سبب إشارة بعض JAVA_HOME أو PATH إلى مكان لم أتوقعه. which يعرف الأوامر، direnv status يعرف direnv، launchctl getenv يعرف launchd. لا أحد منهم يخبرك أن ~/.zshrc:42 هو الكاتب الفعلي.
يعمل مع zsh و bash على macOS و Linux و FreeBSD. المخرجات النموذجية أدناه تستخدم ~/ للإيجاز؛ الأداة تطبع المسارات المطلقة في كل مكان باستثناء report.
grep -r JAVA_HOME ~ يُظهر كل ملف يذكر المتغير. لكنه لا يخبرك أي إسناد فاز في الصدفة التي تجلس فيها:
$ envocabulary explain --chain JAVA_HOME
JAVA_HOME
origin shell-file
primary ~/helpers.sh:3
chain ~/.zshrc → ~/helpers.sh
writers
~/.zshenv:8
~/helpers.sh:3 (winner)
value [hidden, use --values]
المتغيرات المعينة عبر eval "$(brew shellenv)" و eval "$(pyenv init -)" وما شابه تشير إلى سطر eval. الكود المُولَّد ليس له سطر خاص به؛ eval هو ما يمكنك فتحه في محرر.
curl -fsSL https://raw.githubusercontent.com/sreckoskocilic/envocabulary/main/install.sh | sh
يكتشف السكربت نظام التشغيل والمعمارية، ويحمّل أرشيف الإصدار، ويتحقق من مجموع التحقق sha256 الخاص به، ويتحقق من توقيع cosign عند تثبيت cosign. يثبّت في /usr/local/bin إذا كان قابلاً للكتابة، وإلا في ~/.local/bin، ويحذّر إذا لم يكن ذلك الدليل على $PATH الخاص بك. على macOS يقوم أيضاً بمسح علامة الحجر الصحي الخاصة بـ Gatekeeper.
الخيارات: sh -s -- --version v1.0.4 لتثبيت إصدار معين، --bin-dir DIR لاختيار الوجهة.
أو go install github.com/sreckoskocilic/envocabulary/cmd/envocabulary@latest. لاحظ أن بناء go install يُبلّغ عن dev لـ --version؛ فقط ثنائيات الإصدار تحمل الإصدار والالتزام وتاريخ البناء.
الثنائيات الجاهزة وحزم Linux (.deb / .rpm / .apk / .pkg.tar.zst) موجودة على صفحة الإصدارات.
البيئة الحية (تقرأ الصدفة قيد التشغيل):
scan (افتراضي) — يطبع جميع المتغيرات في البيئة الحالية مجمّعة حسب الأصلexplain NAME — الإسناد الكامل لمتغير واحدpath [VARNAME...] — إسناد لكل مدخل لمتغيرات المسار المفصولة بنقطتين؛ --check يجد المدخلات الميتةالملفات الثابتة:
inventory — يسرد ملفات إعدادات الصدفة في $HOME (الملفات الأساسية بالإضافة إلى النسخ الاحتياطية مثل .zshrc.bak) ويحصي التعريفات حسب النوعcatalog — يطبع تلك الملفات مدمجة بالترتيب الذي تقرأها به الصدفةdedup — تقرير التكرارات لـ exports و assigns و aliases و functions، داخل الملفات وعبرهاdangling — يسرد مدخلات الإعدادات التي لم يعد هدفها موجوداً؛ يخرج بـ 1 عند العثور على أي منهاlost — يسرد التعريفات الموجودة فقط في الملفات اليتيمة/الاحتياطيةreport — تدقيق مدمج: آمن للحذف، مراجعة (التكرارات التي تختلف قيمتها، بالإضافة إلى جميع الدوال المكررة)، dangling، الملفات اليتيمة؛ --html يكتب ملف .html بطابع زمني في الدليل الحاليclean [--full] FILE — يسرد أسطر التعليقات التي سيتم إزالتها؛ مع --full، يطبع المحتوى المنظّفأخرى:
-V، --version — طباعة الإصدار والالتزام وتاريخ البناءenvocabulary <cmd> -h للأعلام.
رموز الخروج: 0 عند النجاح، 1 عند خطأ وقت التشغيل أو عندما يجد dangling / path --check شيئاً، 2 عند خطأ في الاستخدام.
dangling يسرد مدخلات الإعدادات التي لم تعد تشير إلى أي شيء، من نوع JAVA_HOME=/opt/jdk-i-uninstalled و source ~/dotfiles/work-old.zsh المتبقية:
$ envocabulary dangling
## ~/.zshrc
~/.zshrc:14 source → ~/dotfiles/work-old.zsh (source target missing)
~/.zshrc:42 export JAVA_HOME → /opt/jdk-11 (path does not exist)
path يُظهر أين تم إدخال كل مدخل في PATH (أو MANPATH، FPATH، إلخ):
$ envocabulary path PATH
## PATH
/opt/homebrew/bin ~/.zprofile:6
/opt/homebrew/sbin ~/.zprofile:6
/usr/local/bin /etc/zprofile:11
/usr/bin inherited
/bin inherited
~/.cargo/bin ~/.zshrc:22
المدخلات غير المطابقة لأي إسناد بدء تشغيل الصدفة تظهر كـ inherited. يشمل ذلك دائماً /usr/bin و /bin و /usr/sbin و /sbin: فهي البذرة التي يبدأ منها المتتبع، وليست شيئاً أضافه ملف.
--check يرشّح إلى المدخلات التي لم يعد دليلها موجوداً ويعيد تحليل المصدر مقابل ملفات dotfiles و /etc/paths.d، بحيث يشير إلى السطر الذي يجب تعديله:
$ envocabulary path --check PATH
## PATH
/opt/homebrew/Cellar/go/1.25.1/libexec/bin ~/.zshrc:17 (does not exist)
/opt/pkg/env/active/bin /etc/paths.d/10-pmk-global:1 (does not exist)
/Applications/VMware /etc/paths.d/com.vmware.fusion.public:1 (does not exist)
يخرج بـ 1 عند العثور على مدخلات ميتة، مما يجعله قابلاً للاستخدام في السكربتات.
export EDITOR=vim VISUAL=vim يسجّل EDITOR فقط.$HOME (.zshenv، .zprofile، .zshrc، .zlogin، .zlogout، .bashrc، .bash_profile، .profile) ومتغيراتها من نوع .bak/.old. لا تتبع $ZDOTDIR أو ~/.config/zsh أو /etc أو الملفات التي تقوم بـ source لها.dangling يتخطى القيم الشبيهة بـ PATH وأي شيء يحتوي على توسيع (export GOPATH=$HOME/go)؛ لا يمكنه تحليل تلك بشكل ثابت.path يعتمد على فروقات xtrace. أول إسناد يتضمن مدخلاً يطالب به، حتى لو تم نقله عبر توسيع $PATH بدلاً من إضافته صراحة.eval يُبلّغ عن سطر eval بالإضافة إلى إزاحة؛ bash ليس لديه علامة لأجسام eval كما هو الحال في zsh.لن يقوم envocabulary أبداً بـ unset أو rm أو تعديل إعدادات الصدفة الخاصة بك. أداة الطوارئ لا ينبغي أن تكون الشيء الذي يزيد الطوارئ سوءاً. إذا أردت تنظيف الأمور، انسخ مؤشرات file:line وقم بالتعديلات بنفسك. clean يُخرج إلى stdout؛ أنت تقوم بإعادة التوجيه.