رفتن به محتوا
LoopX

نصب برنامه با apt

توی این درس یاد می‌گیری در Debian و Ubuntu برنامه‌ها با apt نصب می‌شوند: از مخزن‌ها (repositories) که فهرست بسته‌ها را دارند، با حل خودکار وابستگی‌ها. فرق apt update (به‌روزکردن فهرست بسته‌ها) و apt upgrade (به‌روزکردن برنامه‌های نصب‌شده) را می‌فهمی؛ با apt search، apt install، apt remove و purge کار می‌کنی؛ ابزار پایه‌ی dpkg (dpkg -l، -L، -S، -i) را می‌شناسی؛ و می‌بینی چطور یک میرور داخلی را آزمایش و منبع دانلود را عوض کنی. تمرین: htop را نصب می‌کنی و منبع apt را به یک میرور داخلی تغییر می‌دهی.

مسئله: برنامه را از کجا و چطور بگیریم؟

Section titled “مسئله: برنامه را از کجا و چطور بگیریم؟”

در ویندوز معمولاً فایل نصب را از سایت هر برنامه می‌گیری و اجرا می‌کنی. در لینوکس مدیر بسته (package manager) این کار را برایت می‌کند: برنامه را از یک مخزن مورد اعتماد (با امضای دیجیتال) می‌گیرد، وابستگی‌ها (کتابخانه‌هایی که برنامه لازم دارد) را خودش پیدا و نصب می‌کند، همه‌چیز را ثبت می‌کند تا بشود به‌روز کرد یا کامل حذف کرد.

تشبیه: مدیر انبار و کارگر قفسه‌چین

Section titled “تشبیه: مدیر انبار و کارگر قفسه‌چین”

apt مثل مدیر انبار است: فهرست کالاها را می‌خواند (update)، سفارش را بررسی می‌کند (install)، می‌داند هر کالا چه قطعاتی لازم دارد (وابستگی‌ها)، و از انبار مرکزی (مخزن یا میرور) می‌آورد. dpkg کارگر قفسه‌چین است: فقط یک بسته‌ی آماده (.deb) را می‌گیرد و روی قفسه‌ها (/usr/bin، /etc…) می‌گذارد، بدون اینکه بداند از کجا آمده یا قطعاتش کجاست.

apt فهرست و وابستگی‌ها را از مخزن (یا میرور) می‌گیرد، فایل‌های .deb را دانلود می‌کند و نصب واقعی را به dpkg می‌سپارد.

همه‌ی این درس روی Ubuntu 24.04 واقعی اجرا شده است (در ماشین آزمایشی من که یک ARM است؛ فقط یک نکته‌ی معماری در مثال ۱ و ۷ هست). دستورهای نصب و حذف root می‌خواهند، پس با sudo.

مثال ۱: مخزن‌ها، apt بسته‌ها را از کجا می‌آورد؟

Section titled “مثال ۱: مخزن‌ها، apt بسته‌ها را از کجا می‌آورد؟”

فایل منبع‌ها در Ubuntu 24.04 این است (فرمت جدید deb822؛ نسخه‌های قدیمی‌تر به‌جایش فایل /etc/apt/sources.list دارند):

Terminal window
. /etc/os-release; echo "سیستم: $PRETTY_NAME"
echo "معماری: $(dpkg --print-architecture)"
echo "--- /etc/apt/sources.list.d/ubuntu.sources (بدون توضیح):"
grep -v '^#' /etc/apt/sources.list.d/ubuntu.sources | grep -v '^$'
خروجی
سیستم: Ubuntu 24.04.5 LTS
معماری: arm64
--- /etc/apt/sources.list.d/ubuntu.sources (بدون توضیح):
Types: deb
URIs: http://ports.ubuntu.com/ubuntu-ports/
Suites: noble noble-updates noble-backports
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
Types: deb
URIs: http://ports.ubuntu.com/ubuntu-ports/
Suites: noble-security
Components: main universe restricted multiverse
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg

هر بلوک یک مخزن است:

کلید معنی
URIs آدرس مخزن (همان جایی که می‌شود عوضش کرد؛ مثال ۷)
Suites شاخه‌ها: noble (نسخه‌ی اصلی ۲۴٫۰۴)، noble-updates (اصلاحات بعدی)، noble-backports (نسخه‌های جدیدتر)، noble-security (وصله‌های امنیتی)
Components بخش‌ها: main (رسمی و پشتیبانی‌شده)، universe (جامعه)، restricted و multiverse (مالکیتی یا با محدودیت)
Signed-By کلید عمومی که امضای مخزن را بررسی می‌کند (امنیت)

یک نکته: آدرس این ماشین ports.ubuntu.com/ubuntu-ports است چون معماری ARM (arm64) است. روی سرور و WSL معمولی (x86) آدرس archive.ubuntu.com/ubuntu و برای وصله‌های امنیتی security.ubuntu.com/ubuntu است؛ بقیه‌ی ساختار یکی است.

مثال ۲: apt update در برابر apt upgrade

Section titled “مثال ۲: apt update در برابر apt upgrade”

apt یک نسخه‌ی محلی از فهرست بسته‌ها نگه می‌دارد (در /var/lib/apt/lists). apt update فقط آن فهرست را از مخزن‌ها تازه می‌کند و هیچ برنامه‌ای را عوض نمی‌کند. در ماشین‌های داکری فهرست عمداً خالی است (تا image کوچک بماند)؛ ببین بدون update چه می‌شود:

Terminal window
sudo rm -rf /var/lib/apt/lists/*
sudo apt install -y figlet
خروجی
Reading package lists...
Building dependency tree...
Reading state information...
E: Unable to locate package figlet

Unable to locate package: apt هیچ فهرستی ندارد که بداند figlet چیست. روی یک سرور تازه هم اگر مدتی از آخرین update گذشته باشد، همین خطا یا نسخه‌های قدیمی می‌بینی. پس اول:

Terminal window
sudo apt update
خروجی (بخشی از آن)
Get:17 http://ports.ubuntu.com/ubuntu-ports noble-security/universe arm64 Packages [1624 kB]
Get:18 http://ports.ubuntu.com/ubuntu-ports noble-security/restricted arm64 Packages [2886 kB]
Get:19 http://ports.ubuntu.com/ubuntu-ports noble-security/multiverse arm64 Packages [89.7 kB]
Fetched 35.1 MB in 46s (755 kB/s)
Reading package lists...
Building dependency tree...
Reading state information...
2 packages can be upgraded. Run 'apt list --upgradable' to see them.

خط‌های Get: یعنی فهرست یک بخش از یک مخزن دانلود شد (Hit: یعنی تغییری نکرده). آخرش می‌گوید چند بسته نسخه‌ی جدیدتر دارند. ببینیمشان، و بدون هیچ تغییری شبیه‌سازی کنیم upgrade چه می‌کرد (--dry-run):

Terminal window
echo "--- بسته‌های قابل‌به‌روزرسانی:"
apt list --upgradable 2>/dev/null
echo "--- شبیه‌سازی upgrade (--dry-run؛ چیزی نصب نمی‌شود):"
sudo apt upgrade --dry-run | grep -E '^(Inst|[0-9]+ upgraded)'
خروجی
--- بسته‌های قابل‌به‌روزرسانی:
Listing...
libaudit-common/noble-updates 1:3.1.2-2.1ubuntu0.1 all [upgradable from: 1:3.1.2-2.1build1.1]
libaudit1/noble-updates 1:3.1.2-2.1ubuntu0.1 arm64 [upgradable from: 1:3.1.2-2.1build1.1]
--- شبیه‌سازی upgrade (--dry-run؛ چیزی نصب نمی‌شود):
2 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Inst libaudit-common [1:3.1.2-2.1build1.1] (1:3.1.2-2.1ubuntu0.1 Ubuntu:24.04/noble-updates [all])
Inst libaudit1 [1:3.1.2-2.1build1.1] (1:3.1.2-2.1ubuntu0.1 Ubuntu:24.04/noble-updates [arm64])
  • apt update: فهرست را تازه کن (کاتالوگ).
  • apt upgrade: نسخه‌ی جدیدتر برنامه‌هایی که نصب‌اند را نصب کن، بدون حذف یا نصب بسته‌ی دیگر. apt full-upgrade اگر لازم باشد بسته‌ها را حذف/اضافه هم می‌کند. هیچ‌کدام سیستم را به نسخه‌ی بعدی Ubuntu نمی‌برند.

ترتیب همیشگی: sudo apt update && sudo apt upgrade. (apt upgrade را من فقط شبیه‌سازی کردم تا ماشین آزمایشی تغییر نکند؛ روی سرور خودت با -y تأیید خودکار هم می‌گیری.)

مثال ۳: جستجو و اطلاعات بسته

Section titled “مثال ۳: جستجو و اطلاعات بسته”
Terminal window
echo "--- apt search (جستجو در نام و توضیح):"
apt search figlet 2>/dev/null | head -6
echo "--- apt show (جزئیات؛ ۱۲ خط اول):"
apt show figlet 2>/dev/null | head -12
echo "--- apt-cache policy (کدام نسخه و از کدام مخزن؟):"
apt-cache policy figlet
خروجی
--- apt search (جستجو در نام و توضیح):
Sorting...
Full Text Search...
figlet/noble 2.2.5-3 arm64
Make large character ASCII banners out of ordinary text
php-text-figlet/noble 1.0.2-5 all
--- apt show (جزئیات؛ ۱۲ خط اول):
Package: figlet
Version: 2.2.5-3
Priority: optional
Section: universe/text
Origin: Ubuntu
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Original-Maintainer: Carlos Laviola <claviola@debian.org>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 745 kB
Depends: libc6 (>= 2.17)
Homepage: http://www.figlet.org/
Download-Size: 130 kB
--- apt-cache policy (کدام نسخه و از کدام مخزن؟):
figlet:
Installed: (none)
Candidate: 2.2.5-3
Version table:
2.2.5-3 500
500 http://ports.ubuntu.com/ubuntu-ports noble/universe arm64 Packages

Candidate نسخه‌ای است که نصب می‌شود، Installed: (none) یعنی هنوز نصب نیست، و آخر خط، مخزنی که این نسخه را دارد. Depends در apt show وابستگی‌هاست.

Terminal window
sudo apt install -y figlet
خروجی
Reading package lists...
Building dependency tree...
Reading state information...
The following NEW packages will be installed:
figlet
0 upgraded, 1 newly installed, 0 to remove and 2 not upgraded.
Need to get 130 kB of archives.
After this operation, 745 kB of additional disk space will be used.
Get:1 http://ports.ubuntu.com/ubuntu-ports noble/universe arm64 figlet arm64 2.2.5-3 [130 kB]
Fetched 130 kB in 1s (104 kB/s)
Selecting previously unselected package figlet.
(Reading database ... 23924 files and directories currently installed.)
Preparing to unpack .../figlet_2.2.5-3_arm64.deb ...
Unpacking figlet (2.2.5-3) ...
Setting up figlet (2.2.5-3) ...
update-alternatives: using /usr/bin/figlet-figlet to provide /usr/bin/figlet (figlet) in auto mode
Processing triggers for man-db (2.12.0-4build2) ...

مراحل خروجی: فهرست و وابستگی‌ها محاسبه شد؛ «NEW packages will be installed» یعنی چه چیزهایی تازه می‌آیند (اینجا فقط یک بسته)؛ Get: دانلود از مخزن؛ و بعد Unpacking/Setting up، یعنی dpkg فایل‌ها را باز و تنظیم کرد. -y به همه‌ی پرسش‌های «ادامه بدهم؟» جواب «بله» می‌دهد (برای اسکریپت‌ها)؛ بدون آن apt قبل از نصب می‌پرسد [Y/n]. حالا برنامه کار می‌کند، و ببین بسته چه چیزی روی سیستم گذاشته:

Terminal window
figlet LoopX
echo "--- کجاست؟"
which figlet
echo "--- فایل ls مال کدام بسته است؟ (dpkg -S)"
dpkg -S /usr/bin/ls
echo "--- فایل‌هایی که بسته‌ی figlet نصب کرده (dpkg -L؛ چند تای اول):"
dpkg -L figlet | head -8
خروجی
_ __ __
| | ___ ___ _ __\ \/ /
| | / _ \ / _ \| '_ \\ /
| |__| (_) | (_) | |_) / \
|_____\___/ \___/| .__/_/\_\
|_|
--- کجاست؟
/usr/bin/figlet
--- فایل ls مال کدام بسته است؟ (dpkg -S)
coreutils: /usr/bin/ls
--- فایل‌هایی که بسته‌ی figlet نصب کرده (dpkg -L؛ چند تای اول):
/.
/etc
/etc/emacs
/etc/emacs/site-start.d
/etc/emacs/site-start.d/50figlet.el
/usr
/usr/bin
/usr/bin/chkfont

dpkg -S فایل می‌گوید یک فایل مال کدام بسته است (ls مال بسته‌ی coreutils است) و dpkg -L بسته همه‌ی فایل‌های نصب‌شده‌ی یک بسته را می‌دهد. (چون figlet با سازوکار update-alternatives یک لینک نمادین /usr/bin/figlet می‌سازد، خود آن مسیر در فهرست بسته نیست و برای آن dpkg -S جوابی نمی‌دهد؛ برای فایل‌های معمولی مثل ls همیشه جواب می‌دهد.)

⚡ بررسی سریع

کدام دستور می‌گوید فایل /usr/bin/ls از کدام بسته آمده؟

مثال ۵: apt remove، purge و autoremove

Section titled “مثال ۵: apt remove، purge و autoremove”

remove برنامه را حذف می‌کند ولی فایل‌های تنظیمات (در /etc) را نگه می‌دارد، تا اگر دوباره نصب کردی تنظیماتت سر جایش باشد. purge همه‌چیز را پاک می‌کند. با یک فایل تنظیمات واقعی همین بسته ببینیمش:

Terminal window
CONF=/etc/emacs/site-start.d/50figlet.el
echo "; تنظیم شخصی من" | sudo tee -a $CONF > /dev/null
echo "--- بعد از apt remove:"
sudo apt remove -y figlet
ls -l $CONF
dpkg -l figlet | tail -1
echo "--- بعد از apt purge:"
sudo apt purge -y figlet
ls $CONF
dpkg -l figlet | tail -1
خروجی
--- بعد از apt remove:
Reading package lists...
Building dependency tree...
Reading state information...
The following packages will be REMOVED:
figlet
0 upgraded, 0 newly installed, 1 to remove and 2 not upgraded.
After this operation, 745 kB disk space will be freed.
(Reading database ... 24003 files and directories currently installed.)
Removing figlet (2.2.5-3) ...
Processing triggers for man-db (2.12.0-4build2) ...
-rw-r--r-- 1 root root 317 Oct 3 21:42 /etc/emacs/site-start.d/50figlet.el
rc figlet 2.2.5-3 arm64 Make large character ASCII banners out of ordinary text
--- بعد از apt purge:
Reading package lists...
Building dependency tree...
Reading state information...
The following packages will be REMOVED:
figlet*
0 upgraded, 0 newly installed, 1 to remove and 2 not upgraded.
After this operation, 0 B of additional disk space will be used.
(Reading database ... 23927 files and directories currently installed.)
Purging configuration files for figlet (2.2.5-3) ...
ls: cannot access '/etc/emacs/site-start.d/50figlet.el': No such file or directory
dpkg-query: no packages found matching figlet

ستون اول dpkg -l وضعیت بسته است: ii نصب‌شده، rc حذف‌شده ولی تنظیماتش مانده (removed, config files)، و un (unknown/not installed) یعنی هیچ ردی نیست. بعد از remove فایل مانده بود (rc) و بعد از purge رفت (un). و وابستگی‌هایی که فقط به خاطر یک بسته نصب شده بودند را با sudo apt autoremove پاک می‌کنی:

Terminal window
sudo apt autoremove -y
خروجی
Reading package lists...
Building dependency tree...
Reading state information...
0 upgraded, 0 newly installed, 0 to remove and 2 not upgraded.

مثال ۶: dpkg و نصب دستی یک فایل .deb

Section titled “مثال ۶: dpkg و نصب دستی یک فایل .deb”

گاهی یک فایل .deb داری (از سایت یک برنامه یا apt download). dpkg -i آن را نصب می‌کند، ولی وابستگی‌ها را حل نمی‌کند. با apt download یک .deb بدون وابستگی‌هایش بگیریم تا این را ببینیم (mc، یک فایل‌منیجر ترمینالی):

Terminal window
apt download mc 2>&1 | tail -1
ls -1 mc_*.deb
sudo dpkg -i mc_*.deb
خروجی
Fetched 562 kB in 1s (441 kB/s)
mc_3%3a4.8.30-1ubuntu0.1_arm64.deb
Selecting previously unselected package mc.
(Reading database ... 23924 files and directories currently installed.)
Preparing to unpack mc_3%3a4.8.30-1ubuntu0.1_arm64.deb ...
Unpacking mc (3:4.8.30-1ubuntu0.1) ...
dpkg: dependency problems prevent configuration of mc:
mc depends on libslang2 (>= 2.2.4); however:
Package libslang2 is not installed.
mc depends on libssh2-1t64 (>= 1.2.8); however:
Package libssh2-1t64 is not installed.
mc depends on mc-data (= 3:4.8.30-1ubuntu0.1); however:
Package mc-data is not installed.
dpkg: error processing package mc (--install):
dependency problems - leaving unconfigured
Errors were encountered while processing:
mc

dpkg نصب را نیمه‌کاره گذاشت: mc به کتابخانه‌هایی (libslang2 و بقیه) نیاز دارد که نصب نیستند، و فقط apt می‌داند آن‌ها را از کجا بیاورد. راه‌حل apt install -f (fix broken) است که وابستگی‌های ناقص را کامل می‌کند:

Terminal window
sudo apt install -f -y 2>&1 | tail -6
dpkg -l mc | tail -1
echo "--- پاک‌سازی:"
sudo apt purge -y mc > /dev/null
sudo apt autoremove -y > /dev/null
rm -f mc_*.deb
dpkg -l | grep -c '^ii'
خروجی
Setting up libslang2:arm64 (2.3.3-3build2) ...
Setting up mc-data (3:4.8.30-1ubuntu0.1) ...
Setting up libssh2-1t64:arm64 (1.11.0-4.1ubuntu0.24.04.4) ...
Setting up mc (3:4.8.30-1ubuntu0.1) ...
Processing triggers for man-db (2.12.0-4build2) ...
Processing triggers for libc-bin (2.39-0ubuntu8.9) ...
ii mc 3:4.8.30-1ubuntu0.1 arm64 Midnight Commander - a powerful file manager
--- پاک‌سازی:
303

پس dpkg -l فهرست همه‌ی بسته‌های نصب‌شده است (عدد آخر: بسته‌های ii). برای نصب یک .deb محلی، بهتر است مستقیم sudo apt install ./فایل.deb بزنی (apt وابستگی‌ها را خودش می‌آورد). قاعده: از apt استفاده کن؛ dpkg فقط برای پرس‌وجو (-l، -L، -S).

مثال ۷: میرور، منبع دانلود را عوض کن

Section titled “مثال ۷: میرور، منبع دانلود را عوض کن”

میرور یک کپی کامل از مخزن روی یک سرور دیگر است. سه چیز برای انتخاب یک میرور مهم است: در دسترس بودن، سرعت و مهم‌تر تازه‌بودن: میرور بی‌به‌روز یعنی وصله‌های امنیتی دیر می‌رسند. هر سه را با یک حلقه‌ی curl از همین ماشین بررسی می‌کنم. برای هر آدرس، فایل InRelease شاخه‌ی امنیتی (noble-security) را می‌گیرم و کد پاسخ، زمان، و مهم‌تر تاریخ Date: آن را چاپ می‌کنم (تاریخی که مخزن آخرین بار تازه شده):

Terminal window
for m in http://archive.ubuntu.com/ubuntu https://mirror.arvancloud.ir/ubuntu https://repo.iut.ac.ir/ubuntu https://ubuntu.pishgaman.net/ubuntu https://mirror.iranserver.com/ubuntu; do
code=$(curl -sL -m 20 -o /tmp/inrelease -w '%{http_code} %{time_total}s' "$m/dists/noble-security/InRelease")
echo "$code | $(grep -m1 '^Date:' /tmp/inrelease) | $m"
done
rm -f /tmp/inrelease
echo "--- ساعت همین سیستم: $(date -u '+%a, %d %b %Y %H:%M UTC')"
خروجی
200 0.853118s | Date: Sat, 03 Oct 2026 8:51:07 UTC | http://archive.ubuntu.com/ubuntu
200 0.370186s | Date: Fri, 02 Oct 2026 3:27:10 UTC | https://mirror.arvancloud.ir/ubuntu
200 0.635259s | Date: Thu, 01 Oct 2026 17:53:35 UTC | https://repo.iut.ac.ir/ubuntu
200 0.322770s | Date: Sat, 03 Oct 2026 8:51:07 UTC | https://ubuntu.pishgaman.net/ubuntu
200 0.572752s | Date: Fri, 02 Oct 2026 6:20:59 UTC | https://mirror.iranserver.com/ubuntu
--- ساعت همین سیستم: Sat, 03 Oct 2026 21:42 UTC

(این‌ها چند میرور عمومی Ubuntu هستند که آدرسشان را آزمایش کرده‌ام؛ توصیه‌ی رسمی نیستند و کیفیتشان با زمان و شبکه‌ی تو تغییر می‌کند. نتیجه‌ی بالا مال همین لحظه است و باید خودت تست کنی.) هر خط: کد 200 یعنی در دسترس، زمان پاسخ، و Date: آخرین تازه‌شدن. میرور خوب 200 با تاریخ نزدیک به الآن دارد. اگر تاریخ یک میرور هفته‌ها عقب باشد از آن استفاده نکن.

حالا خود تغییر منبع. چون ماشین آزمایشی من ARM است و میرورهای ایرانیِ Ubuntu که آزمایش کردم فقط نسخه‌ی x86 (/ubuntu) را دارند (نه ubuntu-ports)، همین کار را روی یک Debian انجام می‌دهم: Debian با Ubuntu همان apt را دارد و میرور مورد نظر نسخه‌ی ARM آن را هم دارد. یک کانتینر Debian دورریختنی (lx-deb) می‌سازم (-e DEBIAN_FRONTEND=noninteractive یعنی apt پرسش تعاملی نپرسد) و منبع پیش‌فرضش را نشان می‌دهم (از اینجا deb یعنی «در آن کانتینر اجرا کن»):

Terminal window
docker rm -f lx-deb > /dev/null 2>&1
docker run -d -e DEBIAN_FRONTEND=noninteractive --name lx-deb debian:stable-slim sleep 900 > /dev/null
deb() { docker exec lx-deb "$@"; }
echo "--- منبع پیش‌فرض Debian:"
deb grep -E '^(URIs|Suites)' /etc/apt/sources.list.d/debian.sources
خروجی
--- منبع پیش‌فرض Debian:
URIs: http://deb.debian.org/debian
Suites: stable stable-updates
URIs: http://deb.debian.org/debian-security
Suites: stable-security

آدرس مخزن اصلی (http://deb.debian.org/debian) همان خط URIs اول است؛ دومی مخزن امنیتی. اگر URIs را به یک میرور HTTPS عوض کنیم، با یک تله روبه‌رو می‌شویم که روی image های کم‌حجم (و گاهی سرورهای تازه) رایج است:

Terminal window
deb() { docker exec lx-deb "$@"; }
deb sed -i 's|http://deb.debian.org/debian$|https://mirror.iranserver.com/debian|' /etc/apt/sources.list.d/debian.sources
deb grep -E '^URIs' /etc/apt/sources.list.d/debian.sources
echo "--- apt-get update:"
deb apt-get update 2>&1 | grep -E '^W:' | head -2
خروجی
URIs: https://mirror.iranserver.com/debian
URIs: http://deb.debian.org/debian-security
--- apt-get update:
W: Failed to fetch https://mirror.iranserver.com/debian/dists/stable/InRelease SSL connection failed: error:0A000086:SSL routines::certificate verify failed / Success [IP: 185.255.89.114 443]
W: Failed to fetch https://mirror.iranserver.com/debian/dists/stable-updates/InRelease SSL connection failed: error:0A000086:SSL routines::certificate verify failed / Success [IP: 185.255.89.114 443]

SSL ... certificate verify failed: برای اعتبارسنجی HTTPS به بسته‌ی ca-certificates (فهرست گواهی‌های معتبر) نیاز است که در این image نیست. راه‌حل (مشکل مرغ و تخم‌مرغ): برای نصب ca-certificates به منبع قدیمی (HTTP) برگرد، نصبش کن، بعد منبع را عوض کن:

Terminal window
deb() { docker exec lx-deb "$@"; }
deb sed -i 's|https://mirror.iranserver.com/debian$|http://deb.debian.org/debian|' /etc/apt/sources.list.d/debian.sources
deb apt-get update -qq
deb apt-get install -y -qq ca-certificates > /dev/null
deb sed -i 's|http://deb.debian.org/debian$|https://mirror.iranserver.com/debian|' /etc/apt/sources.list.d/debian.sources
echo "--- apt-get update با میرور:"
deb apt-get update 2>&1 | tail -7
echo "--- از کدام مخزن نصب می‌شود؟"
deb apt-cache policy htop | head -6
خروجی
--- apt-get update با میرور:
Get:1 https://mirror.iranserver.com/debian stable InRelease [140 kB]
Hit:2 http://deb.debian.org/debian-security stable-security InRelease
Get:3 https://mirror.iranserver.com/debian stable-updates InRelease [47.3 kB]
Get:4 https://mirror.iranserver.com/debian stable/main arm64 Packages [9614 kB]
Get:5 https://mirror.iranserver.com/debian stable-updates/main arm64 Packages [4424 B]
Fetched 9806 kB in 8s (1296 kB/s)
Reading package lists...
--- از کدام مخزن نصب می‌شود؟
htop:
Installed: (none)
Candidate: 3.4.1-5
Version table:
3.4.1-5 500
500 https://mirror.iranserver.com/debian stable/main arm64 Packages

حالا Get: ها از آدرس میرور می‌آیند (خط stable و stable-updates). دقت کن مخزن امنیتی (debian-security) را عمداً دست نزدم و از منبع رسمی ماند. اگر آن را هم به این میرور ببریم:

Terminal window
deb() { docker exec lx-deb "$@"; }
deb sed -i 's|http://deb.debian.org/debian-security|https://mirror.iranserver.com/debian-security|' /etc/apt/sources.list.d/debian.sources
deb apt-get update 2>&1 | grep -E '^E:'
خروجی
E: Release file for https://mirror.iranserver.com/debian-security/dists/stable-security/InRelease is expired (invalid since 12d 9h 10min 59s). Updates for this repository will not be applied.

و تاریخ آخرین تازه‌شدن همان مخزن، در برابر منبع رسمی (همان تکنیک InRelease بالا):

Terminal window
for m in https://mirror.iranserver.com/debian-security http://deb.debian.org/debian-security; do
echo "$(curl -sL -m 20 "$m/dists/stable-security/InRelease" | grep -m1 '^Date:') ← $m"
done
خروجی
Date: Mon, 14 Sep 2026 12:32:40 UTC ← https://mirror.iranserver.com/debian-security
Date: Sat, 03 Oct 2026 21:12:44 UTC ← http://deb.debian.org/debian-security

Release file ... is expired: در لحظه‌ی آزمایش، تاریخ مخزن امنیتی این میرور حدود دو هفته عقب‌تر از منبع رسمی بود، و apt (به‌درستی) نمی‌گذارد از فهرست منقضی‌شده استفاده شود. (این برای همان لحظه است؛ میرورها گاهی عقب می‌افتند و بعداً به‌روز می‌شوند. به همین دلیل میرور را قبل از استفاده تست کن.) قاعده: به‌روزرسانی‌های امنیتی را از منبع رسمی بگیر مگر میرور را تازه‌بودنش را مرتب بسنجی. حالا به حالت سالم برمی‌گردانیم و htop را از میرور نصب می‌کنیم:

Terminal window
deb() { docker exec lx-deb "$@"; }
deb sed -i 's|https://mirror.iranserver.com/debian-security|http://deb.debian.org/debian-security|' /etc/apt/sources.list.d/debian.sources
deb apt-get update -qq
echo "--- نصب htop (از میرور):"
deb apt-get install -y htop 2>&1 | grep -E '^(Get|Setting up htop)'
deb htop --version
docker rm -f lx-deb > /dev/null
خروجی
--- نصب htop (از میرور):
Get:1 https://mirror.iranserver.com/debian stable/main arm64 libncursesw6 arm64 6.5+20250216-2 [124 kB]
Get:2 https://mirror.iranserver.com/debian stable/main arm64 htop arm64 3.4.1-5 [164 kB]
Get:3 https://mirror.iranserver.com/debian stable/main arm64 libgpm2 arm64 1.20.7-11+b2 [14.7 kB]
Setting up htop (3.4.1-5) ...
htop 3.4.1

htop از https://mirror.iranserver.com/debian دانلود شد: همان تغییر منبع، با همان دستورهای apt. روی Ubuntu 24.04 (x86) فقط فایل و آدرس‌ها فرق دارند. دستورهای زیر را روی ماشین x86 اجرا نکرده‌ام (نمونه)، ولی ساختار همان است که بالا نشان دادم:

نمونه (روی Ubuntu x86 اجرا نشده)
# مخزن اصلی را به میرور ببر، مخزن امنیتی را رسمی بگذار
sudo sed -i 's|http://archive.ubuntu.com/ubuntu|https://mirror.arvancloud.ir/ubuntu|' /etc/apt/sources.list.d/ubuntu.sources
sudo apt update

برای Ubuntu 22.04 و قدیمی‌تر فایل /etc/apt/sources.list است (همان sed روی آن). و بعد از هر تغییر یادت نرود apt update.

پشت پرده: apt و dpkg چطور کار می‌کنند؟

Section titled “پشت پرده: apt و dpkg چطور کار می‌کنند؟”

dpkg بسته‌ها را روی دیسک می‌نشاند و در یک پایگاه داده‌ی ساده‌ی متنی (/var/lib/dpkg/status) ثبت می‌کند که چه چیزی نصب است. apt لایه‌ی بالاتر است: فهرست‌های مخزن‌ها را در /var/lib/apt/lists نگه می‌دارد، گراف وابستگی را حل می‌کند و بعد dpkg را صدا می‌زند. هر بسته یک فایل .deb است که یک آرشیو ساده است:

Terminal window
echo "--- بسته‌ی دانلود‌شده را بدون نصب باز می‌کنیم (dpkg-deb):"
apt download figlet 2>&1 | tail -1
f=$(ls figlet_*.deb)
dpkg-deb -I "$f" | grep -E '^ (Package|Version|Architecture|Depends|Description):' | head -5
echo "--- فایل‌های داخلش (۶ تای اول):"
dpkg-deb -c "$f" | awk 'NR <= 6 {print $1, $6}'
rm -f "$f"
echo "--- پایگاه‌داده‌ی dpkg و فهرست‌های apt:"
ls /var/lib/dpkg/status
ls /var/lib/apt/lists | head -3
خروجی
--- بسته‌ی دانلود‌شده را بدون نصب باز می‌کنیم (dpkg-deb):
Fetched 130 kB in 1s (137 kB/s)
Package: figlet
Version: 2.2.5-3
Architecture: arm64
Depends: libc6 (>= 2.17)
Description: Make large character ASCII banners out of ordinary text
--- فایل‌های داخلش (۶ تای اول):
drwxr-xr-x ./
drwxr-xr-x ./etc/
drwxr-xr-x ./etc/emacs/
drwxr-xr-x ./etc/emacs/site-start.d/
-rw-r--r-- ./etc/emacs/site-start.d/50figlet.el
drwxr-xr-x ./usr/
--- پایگاه‌داده‌ی dpkg و فهرست‌های apt:
/var/lib/dpkg/status
auxfiles
lock
partial

dpkg-deb -I (info) متادیتا و dpkg-deb -c (contents) فهرست فایل‌ها را بدون نصب نشان می‌دهند. و هنگام نصب هر .deb این اتفاق می‌افتد: بررسی امضا (apt)، باز کردن در مسیرها، اجرای اسکریپت‌های postinst (تنظیمات)، ثبت در /var/lib/dpkg/status.

دستور کار
sudo apt update تازه‌کردن فهرست بسته‌ها
sudo apt upgrade به‌روزکردن برنامه‌های نصب‌شده
apt list --upgradable بسته‌های قابل‌به‌روزرسانی
apt search عبارت جستجو
apt show بسته / apt-cache policy بسته جزئیات / نسخه و مخزن
sudo apt install بسته نصب (-y تأیید خودکار)
sudo apt install ./فایل.deb نصب یک .deb محلی با حل وابستگی
sudo apt remove بسته حذف (تنظیمات می‌ماند)
sudo apt purge بسته حذف کامل با تنظیمات
sudo apt autoremove پاک‌کردن وابستگی‌های بی‌صاحب
sudo apt install -f رفع وابستگی‌های ناقص
apt download بسته دانلود .deb بدون نصب
dpkg -l [الگو] فهرست بسته‌های نصب‌شده
dpkg -L بسته / dpkg -S فایل فایل‌های بسته / بسته‌ی یک فایل
dpkg -i فایل.deb نصب دستی (بدون حل وابستگی)
وضعیت در dpkg -l معنی
ii نصب‌شده
rc حذف‌شده ولی فایل‌های تنظیمات مانده
un نصب‌نشده و بدون ردپا

مثال ۲: E: Unable to locate package. راه‌حل: sudo apt update اول. (روی سرورهای زنده هم قبل از نصب update کن تا نسخه‌ی قدیمی یا خطا نگیری.)

Terminal window
apt install -y figlet
خروجی
E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), are you root?

Permission denied و «are you root?»: نصب بسته روی کل سیستم اثر می‌گذارد و فقط root اجازه دارد. (پیام Unable to acquire the dpkg frontend lock هم برای همین است.) راه‌حل: sudo apt install ....

Terminal window
( sudo apt-get install -y --reinstall figlet > /dev/null 2>&1 & )
sleep 1
sudo apt install -y figlet 2>&1 | head -2
sleep 4
خروجی
Waiting for cache lock: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 3857 (apt-get)...
Waiting for cache lock: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 3857 (apt-get)...

هر زمان فقط یک apt/dpkg می‌تواند اجرا شود؛ دومی با این پیام منتظر می‌ماند (همیشه یک قفل در /var/lib/dpkg/lock-frontend می‌گیرند). پیام می‌گوید قفل دست چه پروسه‌ای است. راه‌حل: صبر کن تا اولی تمام شود (معمولاً به‌روزرسانی خودکار پس‌زمینه است)؛ و هرگز فایل‌های lock را دستی پاک نکن، چون ممکن است پایگاه‌داده‌ی بسته‌ها خراب شود.

۴) dpkg -i برای نصب یک .deb با وابستگی

Section titled “۴) dpkg -i برای نصب یک .deb با وابستگی”

مثال ۶: نصب نیمه‌کاره و «dependency problems». راه‌حل: sudo apt install ./فایل.deb یا بعد از dpkg -i، sudo apt install -f.

۵) میرور HTTPS بدون ca-certificates، یا میرور بی‌به‌روز

Section titled “۵) میرور HTTPS بدون ca-certificates، یا میرور بی‌به‌روز”

مثال ۷: certificate verify failed و Release file ... is expired. راه‌حل: اول ca-certificates را نصب کن (یا موقتاً HTTP)، و تاریخ InRelease میرور را با منبع رسمی بسنج؛ امنیتی را از رسمی بگیر.

بعد از remove، فایل‌های تنظیمات می‌مانند (rc) و نصب مجدد با تنظیمات قدیمی بالا می‌آید که گاهی همان مشکلی است که می‌خواستی از شرش خلاص شوی. راه‌حل: برای شروع تمیز purge.

✎ تمرینآسان

تعداد بسته‌های نصب‌شده روی سیستم را بشمار (فقط خط‌هایی که وضعیتشان ii است) و بررسی کن tmux نصب است یا نه.

دیدن جواب
Terminal window
echo "تعداد بسته‌های نصب‌شده: $(dpkg -l | grep -c '^ii')"
dpkg -l tmux | tail -1
خروجی
تعداد بسته‌های نصب‌شده: 304
ii tmux 3.4-1ubuntu0.1 arm64 terminal multiplexer
✎ تمرینمتوسط

تمرین اصلی: htop را نصب کن و منبع apt را به یک میرور داخلی تغییر بده. روی ماشین آزمایشی (ARM) میرور Ubuntu قابل‌استفاده نیست، پس این را در یک کانتینر Debian دورریختنی انجام می‌دهم: میرور را بگذار، ca-certificates را فراموش نکن، htop را نصب کن و apt-cache policy htop را ببین تا مخزن را نشان دهد. (روی Ubuntu x86 فقط فایل ubuntu.sources و آدرس فرق دارند.)

دیدن جواب
Terminal window
docker rm -f lx-deb2 > /dev/null 2>&1
docker run -d -e DEBIAN_FRONTEND=noninteractive --name lx-deb2 debian:stable-slim sleep 600 > /dev/null
d() { docker exec lx-deb2 "$@"; }
d apt-get update -qq
d apt-get install -y -qq ca-certificates > /dev/null
d sed -i 's|http://deb.debian.org/debian$|https://mirror.iranserver.com/debian|' /etc/apt/sources.list.d/debian.sources
d apt-get update -qq
d apt-get install -y -qq htop > /dev/null
echo "--- مخزن htop:"
d apt-cache policy htop | sed -n '1,3p;5,6p'
d dpkg -l htop | tail -1
docker rm -f lx-deb2 > /dev/null
خروجی
--- مخزن htop:
htop:
Installed: 3.4.1-5
Candidate: 3.4.1-5
*** 3.4.1-5 500
500 https://mirror.iranserver.com/debian stable/main arm64 Packages
ii htop 3.4.1-5 arm64 interactive processes viewer
✎ تمرینسخت

یک بسته را کامل «بررسی» کن: figlet را نصب کن، با dpkg -L تعداد فایل‌هایش را بشمار، با dpkg -S ثابت کن فایل /etc/emacs/site-start.d/50figlet.el مال همین بسته است، با purge پاکش کن و ثابت کن هیچ ردی نمانده (which و dpkg -l).

دیدن جواب
Terminal window
sudo apt install -y figlet > /dev/null
echo "تعداد فایل‌های بسته: $(dpkg -L figlet | wc -l)"
dpkg -S /etc/emacs/site-start.d/50figlet.el
sudo apt purge -y figlet > /dev/null
sudo apt autoremove -y > /dev/null
which figlet || echo "figlet پیدا نشد"
dpkg -l figlet | tail -1
خروجی
تعداد فایل‌های بسته: 87
figlet: /etc/emacs/site-start.d/50figlet.el
figlet پیدا نشد
dpkg-query: no packages found matching figlet
؟ آزمونک
  1. تفاوت apt update و apt upgrade؟

  2. روی ماشینی تازه apt install foo می‌گوید Unable to locate package. اول چه می‌زنی؟

  3. تفاوت apt remove و apt purge؟

  4. کدام دستور می‌گوید /usr/bin/ls مال کدام بسته است؟

  5. چرا dpkg -i فایل.deb گاهی نصب را ناقص می‌گذارد و چه می‌کنی؟

  6. هنگام انتخاب میرور، چه چیزی مهم‌تر از سرعت است؟

  • apt بسته‌ها را از مخزن‌ها (/etc/apt/sources.list.d/ubuntu.sources؛ URIs، Suites، Components) می‌گیرد و وابستگی‌ها را خودش حل می‌کند؛ نصب واقعی کار dpkg است.
  • همیشه sudo apt update (فهرست)، بعد sudo apt upgrade (برنامه‌ها). --dry-run برای شبیه‌سازی.
  • apt search، apt show، apt-cache policy برای شناخت؛ sudo apt install، remove (تنظیمات می‌ماند)، purge (همه‌چیز)، autoremove (وابستگی‌های بی‌صاحب).
  • dpkg -l (فهرست، وضعیت ii/rc/un)، dpkg -L (فایل‌های بسته)، dpkg -S (بسته‌ی یک فایل)؛ نصب .deb با apt install ./فایل.deb.
  • میرور: آدرس URIs را عوض کن؛ قبلش با curl در دسترس بودن، سرعت و تاریخ InRelease را بسنج؛ برای HTTPS به ca-certificates نیاز است؛ امنیتی را از منبع رسمی بگیر.
  • هر زمان فقط یک apt اجرا می‌شود (Waiting for cache lock)؛ قفل را دستی پاک نکن.
برگه‌ی تقلب این درس
دستورکاری که می‌کند
sudo apt updateتازه‌کردن فهرست بسته‌ها
sudo apt upgrade / sudo apt upgrade --dry-runبه‌روزرسانی / شبیه‌سازی
apt list --upgradableبسته‌های قابل‌به‌روزرسانی
apt search عبارت / apt show بستهجستجو و جزئیات
apt-cache policy بستهنسخه و مخزن
sudo apt install -y بستهنصب
sudo apt remove بسته / sudo apt purge بستهحذف / حذف با تنظیمات
sudo apt autoremoveوابستگی‌های بی‌صاحب
sudo apt install ./فایل.debنصب فایل .deb با وابستگی
dpkg -l | grep بستهنصب‌بودن و وضعیت
dpkg -L بسته / dpkg -S /مسیر/فایلفایل‌های بسته / بسته‌ی فایل
curl -sL آدرس/dists/noble-security/InRelease | grep ^Date:تازه‌بودن یک میرور