پشت صحنهٔ APT و dpkg؛ از مخزن تا بستهٔ نصبشده
فهرست نوشته
وقتی sudo apt install nginx را اجرا میکنیم، سیستم باید چند پرسش را جواب دهد: کدام نسخه؟ از کدام مخزن؟ همراه کدام وابستگیها؟ با چه تضمینی دربارهٔ اصالت فایل؟ و اگر تنظیم بسته شکست خورد، چه وضعیتی روی دیسک باقی میماند؟
برای فهم این مسیر باید سه چیز را جدا ببینیم: اطلاعات مخزن، فایل بسته و وضعیت نصبشدهٔ سیستم. این نوشته مسیر میان این سه را در دبیان و اوبونتو دنبال میکند؛ از InRelease و Packages تا اسکریپتهای نگهدارنده و پایگاه دادهٔ dpkg.
۱. تقسیم کار میان APT و dpkg#
APT مجموعهای از کتابخانهها و ابزارهای مدیریت بسته است. apt و apt-get رابطهای خط فرمان آن هستند. dpkg لایهای است که بسته را روی سیستم باز میکند، تنظیم میکند و وضعیت نصبش را نگه میدارد.
| ابزار | مسئولیت اصلی |
|---|---|
apt | رابط تعاملی برای جستوجو، نصب و ارتقا |
apt-get | رابط مناسبتر برای اسکریپت و خودکارسازی |
apt-cache | پرسوجو از اطلاعات بستهها و نسخهها |
dpkg | نصب، تنظیم و حذف بسته روی سیستم محلی |
dpkg-deb | بررسی یا استخراج فایل .deb |
dpkg-query | پرسوجو از پایگاه دادهٔ بستههای سیستم |
APT دربارهٔ مجموعهٔ بستههای لازم تصمیم میگیرد و آنها را دریافت میکند؛ سپس اجرای تغییرات را به dpkg میسپارد. dpkg وابستگیها را میشناسد و بررسی میکند، اما خودش برای پیدا کردن و دانلود وابستگی مفقود به مخزن مراجعه نمیکند. مرجع مدیریت بستهٔ دبیان
apt برای استفادهٔ انسانی طراحی شده و خروجی و بعضی پیشفرضهایش ممکن است تغییر کنند؛ برای اسکریپتها از رابطهای مناسب مانند apt-get استفاده کنید. راهنمای apt
۲. داخل فایل deb چه خبر است؟#
یک .deb صرفاً فایل اجرایی نیست. قالب معمول آن یک آرشیو ar با این اجزاست؛ پسوند فشردهسازی میتواند متفاوت باشد:
example.deb
├── debian-binary
├── control.tar.*
└── data.tar.*
debian-binary نسخهٔ قالب را مشخص میکند. آرشیو control شامل شناسنامهٔ بسته و احتمالاً اسکریپتهای نگهدارنده و فهرست conffileهاست. آرشیو data فایلهایی را نگه میدارد که باید در مسیرهایی مانند /usr/bin، /usr/lib و /etc قرار بگیرند. همهٔ بستهها همهٔ اسکریپتها را ندارند. متادیتای بسته در کتاب راهنمای دبیان
برای بررسی بدون نصب، در پوشهای قابلنوشتن اجرا کنید:
mkdir -p ~/apt-lab
cd ~/apt-lab
apt download hello
# اگر چند فایل وجود داشت، نام دقیق فایل موردنظر را جایگزین کنید.
dpkg-deb --info ./hello_*.deb
dpkg-deb --contents ./hello_*.deb
dpkg-deb --field ./hello_*.deb Package Version Architecture Depends
dpkg-deb --control ./hello_*.deb ./hello-control
dpkg-deb --extract ./hello_*.deb ./hello-root
دستورهای بالا بسته را نصب نمیکنند. استخراج، فایلها را در پوشهٔ انتخابی میگذارد؛ اسکریپتهای نصب اجرا نمیشوند و وضعیت dpkg تغییر نمیکند. بنابراین وجود فایل اجرایی در hello-root به معنی نصبشدن بسته نیست. راهنمای dpkg-deb
۳. APT مخزن را از کجا میشناسد؟#
تعریف مخزن در /etc/apt/sources.list و فایلهای .list یا .sources زیر /etc/apt/sources.list.d/ قرار میگیرد. قالب چندخطی .sources را Deb822 مینامند.
این نمونه فقط ساختار یک ورودی دبیان را نشان میدهد؛ تنظیم کامل مخازن نیست و نباید جای تنظیمات اوبونتو قرار بگیرد:
Types: deb
URIs: https://deb.debian.org/debian
Suites: trixie
Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
| فیلد | معنا |
|---|---|
Types | deb برای بستهٔ باینری؛ deb-src برای اطلاعات بستههای سورس |
URIs | نشانی پایهٔ مخزن |
Suites | نام انتشار یا شاخهٔ موردنظر |
Components | بخشهایی از مخزن که باید خوانده شوند |
Signed-By | کلیدهای مجاز برای تأیید همین منبع |
معماری هم در انتخاب فهرستها نقش دارد؛ dpkg --print-architecture معماری اصلی را نشان میدهد. به این ترتیب APT لازم نیست فهرست تمام معماریهای مخزن را دریافت کند. راهنمای sources.list
۴. ساختار مخزن: dists برای فهرستها، pool برای بستهها#
نمای زیر ساختاری آموزشی از یک مخزن متعارف است:
repository/
├── dists/
│ └── trixie/
│ ├── InRelease
│ ├── Release
│ ├── Release.gpg
│ └── main/
│ └── binary-amd64/
│ └── Packages.xz
└── pool/
└── main/
└── h/
└── hello/
└── hello_<version>_amd64.deb
یک بسته میتواند از فهرست چند انتشار ارجاع داده شود؛ لازم نیست برای هر انتشار نسخهای از همان فایل در dists ذخیره شود. فهرستهای Sources مربوط به بستههای سورس هستند و Contents نگاشت مسیر فایلها به بستهها را فراهم میکند. ساختار آرشیو در مرجع دبیان
Release شناسنامهٔ انتشار و اندازه و هش فهرستها را دارد. در فایل واقعی Release دبیان
میتوان فیلدهایی مثل Suite، Codename، Architectures، Components و بخش SHA256 را دید.
هر رکورد Packages اطلاعات یک نسخهٔ بسته را توصیف میکند. مثال زیر ساختگی است و مقادیرش قابلاستفاده برای دانلود یا تأیید نیست:
Package: demo-web
Version: 2.4-1
Architecture: amd64
Depends: libc6 (>= 2.36), demo-common (= 2.4-1)
Filename: pool/main/d/demo-web/demo-web_2.4-1_amd64.deb
Size: 123456
SHA256: <64 hexadecimal characters>
Description: Example package for this article
فیلد Filename مسیر بسته نسبت به ریشهٔ مخزن است. بنابراین APT نشانی دانلود را از متادیتا به دست میآورد؛ نام فایل را بر اساس نام بسته حدس نمیزند. این ساختار را مستندات رسمی ابزار apt-ftparchive
نیز توضیح میدهد.
۵. apt update دقیقاً چه چیزی را بهروز میکند؟#
sudo apt update
این دستور فهرست بستههای موجود در مخزن را تازه میکند؛ برنامههای نصبشده را ارتقا نمیدهد. APT اطلاعات انتشار و فهرستهای لازم را دریافت و بررسی میکند و نسخهٔ محلی آنها را زیر /var/lib/apt/lists/ نگه میدارد. راهنمای apt-get
مسیر دریافت همیشه یک دانلود کامل نیست: مخزن ممکن است فهرست فشرده، تفاوت فهرستها یا PDiff، و دریافت بر اساس هش یا By-Hash ارائه کند. By-Hash کمک میکند هنگام همگامسازی آینه، فهرستی متعلق به نسخهٔ دیگری از متادیتا دریافت نشود. گزینههای دریافت در sources.list
نتیجهٔ عملی: apt install معمولاً بر اساس فهرست محلی تصمیم میگیرد. اگر آن فهرست قدیمی باشد، ممکن است نسخهای را انتخاب کند که فایلش دیگر روی آینه موجود نیست. اجرای update و بررسی خطاهای آن، بخشی از تشخیص چنین وضعیتی است. کار با APT در کتاب راهنمای دبیان
۶. زنجیرهٔ اعتماد: امضا کجاست؟#
در مسیر عادی مخزن، APT امضای جداگانهٔ تکتک فایلهای .deb را بررسی نمیکند. زنجیره چنین است:
Trusted archive key
|
v
InRelease signature OR Release + Release.gpg
|
v
Index checksums in Release
|
v
Package checksum in Packages
|
v
Downloaded .deb
InRelease محتوای Release را همراه امضای درونمتنی حمل میکند؛ Release.gpg امضای جداگانهٔ Release است. پس از تأیید امضا، هش فهرست و سپس هش بسته بررسی میشود. هش بهتنهایی اصالت ایجاد نمیکند؛ باید از متادیتایی بیاید که اعتبارش تأیید شده است.
Signed-By دامنهٔ اعتماد کلید را به منبع مربوط محدود میکند. برای کلیدهای محلی مدیر سیستم معمولاً /etc/apt/keyrings/ و برای کلیدهای مدیریتشده با بسته /usr/share/keyrings/ استفاده میشود.
این سازوکار دستکاری آینه یا مسیر انتقال را آشکار میکند، اما تضمین نمیکند نرمافزار ناشر بیاشکال یا بیخطر است. همچنین نصب یک .deb محلی بهخودیخود آن را وارد زنجیرهٔ اعتماد مخزن نمیکند. مدل اعتماد در apt-secure
۷. انتخاب نسخه و حل وابستگیها#
APT نسخههای موجود را با وضعیت فعلی سیستم و سیاست انتخاب نسخه مقایسه میکند. «بزرگترین شمارهٔ نسخه» همیشه برنده نیست: اولویت مخازن، pinning، انتشار هدف و قواعد downgrade مؤثرند. در اوبونتو، phased updates نیز میتواند عرضهٔ بعضی ارتقاها را برای گروهی از سیستمها عقب بیندازد.
apt-cache policy nginx
apt-cache depends nginx
apt-get -s install nginx
در خروجی policy، مقدار Installed نسخهٔ نصبشده و Candidate نامزد انتخابشده بر اساس سیاست فعلی است. گزینهٔ -s تغییرات پیشنهادی را شبیهسازی میکند؛ این پیشنمایش، موفقیت اسکریپت نصب در اجرای واقعی را تضمین نمیکند. سیاست انتخاب نسخه
، شبیهسازی apt-get
وابستگیها یک نمودار از قیدها هستند:
| رابطه | اثر |
|---|---|
Depends | وابستگی لازم برای تنظیم صحیح بسته |
Pre-Depends | شرط سختگیرانهتر که پیش از بازکردن بسته هم اثر دارد |
Recommends | همراه پیشنهادی قوی |
Suggests | همراه اختیاری |
Conflicts | جلوگیری از همزیستی بستههای ناسازگار |
Breaks | اعلام ناسازگاری با نسخههایی از بستهٔ دیگر |
Replaces | مجازکردن جایگزینی فایلهای متعلق به بستهٔ دیگر در شرایط مشخص |
Provides | ارائهٔ یک قابلیت یا نام بستهٔ مجازی |
مثلاً Depends: mail-transport-agent ممکن است با یکی از چند ارائهدهنده برآورده شود. Replaces بهتنهایی معادل «حذف بستهٔ دیگر» نیست. روابط بستهها در Debian Policy
APT معمولاً Recommends را هم نصب میکند؛ گزینهٔ --no-install-recommends این رفتار را برای درخواست تغییر میدهد. اگر هیچ ترکیب سازگاری پیدا نشود، عملیات با خطای وابستگی متوقف میشود. راهنمای apt-get
۸. دانلود و تحویل به dpkg#
پس از انتخاب مجموعهٔ بستهها، APT فایلهای لازم را دریافت میکند. مسیر معمول آرشیوها /var/cache/apt/archives/ و محل فایلهای در حال دریافت زیرپوشهٔ partial/ است. باقیماندن .deb پس از نصب به ابزار و تنظیمات پاکسازی بستگی دارد؛ خالیبودن این پوشه نشانهٔ نصبنبودن برنامهها نیست. کش بستهها در مرجع دبیان
برای نصب یک فایل محلی همراه با حل وابستگیها:
sudo apt install ./example.deb
این مثال را تنها با نام فایل واقعی و مورداعتماد جایگزین کنید. در مقابل، sudo dpkg -i ./example.deb وابستگی گمشده را دانلود نمیکند و ممکن است بسته را در وضعیت تنظیمنشده باقی بگذارد. نصب بستهٔ محلی در کتاب راهنمای دبیان
۹. چرخهٔ نصب: unpack با configure فرق دارد#
نمای سادهٔ نصب اولیهٔ موفق چنین است:
not-installed -> preinst -> unpacked -> postinst configure -> installed
این نمودار تمام جزئیات ارتقا، خطا و triggerها را نشان نمیدهد. preinst پیش از بازشدن فایلها اجرا میشود. پس از unpack، فایلها وجود دارند، اما بسته هنوز الزاماً قابلاستفاده نیست. در configure، تنظیم conffileها و اجرای postinst انجام میشود. شکست یک اسکریپت میتواند نصب را نیمهتمام بگذارد. راهنمای dpkg
اسکریپتهای نگهدارنده عبارتاند از:
| اسکریپت | کاربرد معمول |
|---|---|
preinst | آمادهسازی پیش از unpack |
postinst | تکمیل تنظیم پس از unpack |
prerm | کارهای پیش از حذف یا برخی مراحل ارتقا |
postrm | پاکسازی پس از حذف و هنگام purge |
هنگام ارتقا، اسکریپتهای نسخهٔ قدیم و جدید با آرگومانهای متفاوت اجرا میشوند؛ ترتیب آن با نصب اولیه یکسان نیست. ساخت کاربر سیستمی یا مدیریت سرویس میتواند بخشی از این اسکریپتها باشد. dpkg فقط فایلها را کپی نمیکند؛ کد نگهدارنده را نیز با دسترسی نصب اجرا میکند. چرخهٔ اسکریپتها در Debian Policy
Triggerها اجازه میدهند کار مشترکی مثل بازسازی یک کش پس از تغییر چند بسته جمعبندی شود. بنابراین دیدن Processing triggers مرحلهای از تکمیل تغییرات است. وضعیتهایی مانند triggers-pending و half-configured نیز نشان میدهند فرایند هنوز کامل نشده است. وضعیتهای dpkg
۱۰. فایل تنظیمات کاربر هنگام ارتقا چه میشود؟#
بعضی فایلهای تنظیمات بهعنوان conffile ثبت میشوند. dpkg برای تشخیص تغییر محلی، اطلاعات نسخهٔ قبلی را نگه میدارد. اگر هم شما فایل را ویرایش کرده باشید و هم نسخهٔ بسته آن را تغییر داده باشد، ممکن است دربارهٔ نگهداشتن نسخهٔ فعلی یا پذیرفتن نسخهٔ جدید سؤال شود.
هر فایل زیر /etc لزوماً conffile نیست؛ بعضی تنظیمات با اسکریپت یا ابزارهایی مانند ucf مدیریت میشوند. در نتیجه نمیتوان از محل فایل بهتنهایی رفتار ارتقای آن را حدس زد. فایلهایی مثل .dpkg-dist یا .dpkg-old نیز میتوانند حاصل تصمیم مربوط به نسخههای تنظیمات باشند. سیاست فایلهای تنظیمات
، رفتار dpkg
۱۱. سیستم از کجا میداند چه چیزی نصب است؟#
| مسیر | نقش |
|---|---|
/var/lib/apt/lists/ | اطلاعات دریافتشده دربارهٔ بستههای موجود در مخازن |
/var/cache/apt/archives/ | فایلهای بستهٔ دانلودشده، اگر نگه داشته شوند |
/var/lib/dpkg/status | وضعیت بستهها در سیستم محلی |
/var/lib/dpkg/info/ | اطلاعات فایلها و اسکریپتهای بستهها |
/var/lib/apt/extended_states | اطلاعات تکمیلی APT مانند نصب خودکار |
سه پرسش متفاوت داریم: «چه بستهای موجود است؟»، «چه فایلی دانلود شده؟» و «چه بستهای نصب شده؟». پاککردن کش دانلود معادل حذف برنامه نیست. پایگاههای دادهٔ مدیریت بسته
برای مشاهدهٔ وضعیت و مالکیت فایلها:
dpkg-query -W -f='${binary:Package}\t${Version}\t${Status}\n' bash
dpkg-query -L bash
dpkg-query -S /usr/bin/apt
dpkg -l nginx
-L فایلهای ثبتشده برای بسته را نشان میدهد؛ لزوماً شامل تمام فایلهایی نیست که برنامه یا اسکریپتهایش بعداً ساختهاند. -S در اطلاعات محلی جستوجو میکند، نه در همهٔ مخازن. در خروجی dpkg -l، حالت رایج ii یعنی بسته برای نصب انتخاب شده و نصب است؛ rc یعنی حذف شده اما تنظیمات باقی ماندهاند. راهنمای dpkg-query
۱۲. ارتقا، حذف و autoremove#
| دستور | رفتار |
|---|---|
apt update | تازهکردن فهرستها |
apt upgrade | ارتقا با امکان افزودن وابستگی جدید، بدون حذف بستهٔ نصبشده |
apt full-upgrade | ارتقا با امکان حذف بسته برای حل تغییر وابستگیها |
apt-get upgrade | در حالت معمول، بدون افزودن یا حذف بسته |
apt remove PACKAGE | حذف بسته با باقیماندن conffileها |
apt purge PACKAGE | حذف بسته و تنظیمات تحت مدیریت فرایند purge |
full-upgrade بهخودیخود انتشار بعدی دبیان یا اوبونتو را انتخاب نمیکند؛ همچنان از منابع پیکربندیشده استفاده میکند. purge نیز پاککنندهٔ عمومی دادههای کاربر در home نیست. راهنمای apt
، راهنمای apt-get
APT میان بستهٔ درخواستی شما و بستهای که خودکار برای وابستگی آمده تفاوت میگذارد. وقتی بستهٔ خودکار دیگر لازم نباشد، میتواند نامزد autoremove شود. برای مشاهده:
apt-mark showmanual
apt-mark showauto
apt-mark showhold
apt-get -s autoremove
اگر بستهای را مستقل لازم دارید، sudo apt-mark manual PACKAGE آن را دستی علامت میزند. hold مفهوم دیگری دارد: درخواست نگهداشتن وضعیت بسته برای جلوگیری از تغییر خودکار آن است. راهنمای apt-mark
۱۳. وقتی نصب نیمهتمام میماند#
نصب چند بسته یک تراکنش اتمیک با rollback کامل نیست. ممکن است تعدادی بسته تغییر کرده باشند و بعد اسکریپتی شکست بخورد. ابتدا محل شکست را پیدا کنید:
dpkg --audit
less /var/log/apt/history.log
less /var/log/apt/term.log
less /var/log/dpkg.log
تاریخچهٔ APT درخواستها و تغییرات را نشان میدهد؛ term.log برای خروجی فرایند نصب و dpkg.log برای تغییر وضعیت بستهها مفید است. عیبیابی مدیریت بسته در مرجع دبیان
پس از رفع علت، مانند کمبود فضا یا خطای تنظیمات، sudo dpkg --configure -a تنظیم بستههای معطل را دوباره امتحان میکند. اگر وابستگیها شکستهاند، ابتدا برنامهٔ اصلاح را با apt-get -s --fix-broken install ببینید و سپس در صورت مناسببودن اجرا کنید:
sudo apt-get --fix-broken install
این دستور ممکن است برای بازگرداندن سازگاری، بسته نصب یا حذف کند؛ درمان هر خطای postinst نیست. بازیابی با dpkg
، گزینهٔ fix-broken
برای خطای قفل، ابتدا بررسی کنید فرایند دیگری مانند بهروزرسان خودکار فعال نباشد؛ حذف فایل قفل راه تشخیص نیست. برای خطای امضا، منبع، کلید و پیام دقیق را بررسی کنید؛ غیرفعالکردن تأیید اصالت علت خطا را برطرف نمیکند.
۱۴. تمرین: مسیر یک بسته را دنبال کنید#
این تمرین را میتوان بدون نصب nginx انجام داد:
# نسخه و سیاست انتخاب
apt-cache policy nginx
# روابط بسته و برنامهٔ نصب
apt-cache depends nginx
apt-get -s install nginx
# متادیتای نسخههای موجود در فهرست محلی
apt-cache show nginx
# دانلود در پوشهٔ آزمایش، بدون نصب
mkdir -p ~/apt-lab/nginx
cd ~/apt-lab/nginx
apt download nginx
dpkg-deb --info ./nginx_*.deb
dpkg-deb --contents ./nginx_*.deb
خروجیها را کنار هم بگذارید: آیا Candidate با نسخهٔ فایل یکی است؟ چه وابستگیهایی از قبل نصب بودهاند؟ کدام فایلها داخل این بستهاند و کدام احتمالاً در بستهای دیگر قرار دارند؟ پاسخ دقیق به انتشار و معماری سیستم شما وابسته است؛ نام nginx بهتنهایی محتوای تمام بستههای مرتبط را مشخص نمیکند.
منابع و ایدهٔ اولیه#
ایدهٔ دنبالکردن مسیر نصب و سپس بررسی ساختار مخزن از این دو نوشته آمده است؛ متن حاضر ترجمهٔ آنها نیست:
جزئیات فنی با مستندات رسمی پیوندشده در هر بخش تطبیق داده شدهاند. بهویژه توضیح امضای مستقل هر .deb در مقالهٔ اول با مدل معمول apt-secure سازگار نیست. مثالهای apt-key در مقالهٔ قدیمی Packagecloud نیز مبنای تنظیم پیشنهادی این نوشته نیستند؛ اینجا کلید هر منبع با Signed-By مشخص شده است.