نحوه مشاهده و بهروزرسانی متغیر محیطی PATH در لینوکس

مقدمه
متغیر محیطی PATH در لینوکس، فهرستی از دایرکتوریها—جدا شده با دونقطه—است که شل هنگام اجرای دستور جستجو میکند. هر بار که نام دستوری مانند python3، grep یا myapp را وارد میکنید، شل دایرکتوریهای PATH را از چپ به راست چک کرده و اولین مورد اجراییِ مطابقتیافته را اجرا میکند.
در این آموزش، PATH را مشاهده کرده؛ بهصورت موقت و دائم (در bash و zsh) تغییر میدهید؛ تغییرات را تأیید، Entryها را حذف و خرابیهای رایج را عیبیابی میکنید.
مثالهای این راهنما روی اوبونتو 24.04، دبیان ۱۲ و راکی لینوکس ۹ اعتبارسنجی شدهاند. دستورات با خروجی مورد انتظار نشان داده شدهاند تا نتایجتان را مقایسه و از اعمال هر تغییر مطمئن شوید.
نکات کلیدی
- PATH، فهرستی از دایرکتوریها—جدا شده با دونقطه—است که شل هنگام Resolve کردن دستور، از چپ به راست جستجو میکند.
- هر دوی
echo $PATHوprintenv PATHمقدار فعلی را نمایش میدهند. export PATH=$PATH:/new/dirمقدار PATH را فقط برای نشست فعلی تغییر میدهد.- تغییرات دائم به
~/.bashrc(برای شلهای تعاملی bash)،~/.zshrc(برای zsh) و/etc/environment(برای مقادیر در-سطح-سیستم) میروند. which،type -aوcommand -vتأیید میکنند دستوری به کدام باینری Resolve میشود.- اعمال تغییرات، یا
source ~/.bashrcیا نشست Shell جدیدی لازم دارد. - ترتیب مهم است: دایرکتوریهای زودتر فهرستشده در PATH بر دیرترها اولویت دارند.
پیشنیازها
- سیستم لینوکسی اجراکننده bash یا zsh. دستورات روی اوبونتو 24.04، دبیان ۱۲ و راکی لینوکس ۹ اعتبارسنجی شدهاند.
- کاربر غیر root با دسترسی sudo. در صورت نیاز راهنمای راهاندازی اولیه سرور با اوبونتو در پارمین کلود را ببینید.
- آشنایی با متغیرهای محیطی. راهنمای «نحوه خواندن و تنظیم متغیرهای محیطی و شل در لینوکس» را در پارمین کلود ببینید.
درک نحوه کار متغیر PATH در لینوکس
PATH چه چیزی شامل و شل چگونه از آن استفاده میکند
PATH، مسیرهای مطلق دایرکتوریها—جدا شده با دونقطه—را ذخیره میکند. وقتی دستوری را بدون مسیر کامل اجرا میکنید، شل هر دایرکتوری را بهترتیب بازرسی کرده و اولین فایل مطابقتیافته با مجوز اجرا را اجرا میکند.
برای بازرسی PATH بهصورت یک-دایرکتوری-در-هر-خط، این را اجرا کنید:
tr ':' '\n' <<< "$PATH"
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/local/games
/usr/games
اگر نام اجراییِ یکسانی در بیش از یک دایرکتوری وجود داشته باشد، اولین دایرکتوریِ این فهرست برنده میشود.
PATH چگونه توسط پروسهها و Subshellها به ارث میرسد
پروسههای فرزند، متغیرهای محیطیِ Export-شده را از پروسه والد به ارث میبرند. متغیر Shell فقط در شل فعلی موجود است—تا وقتی با export علامتگذاریش کنید:
MYVAR="hello"
bash -c 'echo $MYVAR' # چیزی چاپ نمیکند
export MYVAR="hello"
bash -c 'echo $MYVAR' # چاپ میکند: hello
PATH هم از همین قاعده پیروی میکند.
گام ۱ — مشاهده متغیر PATH فعلی
استفاده از echo برای نمایش PATH
echo $PATH سریعترین راه دیدن اینکه شلتان هنگام اجرای دستور کدام دایرکتوریها را جستجو میکند، است:
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
خروجی، رشته منفردی است که هر دایرکتوری با : جدا شده.
استفاده از printenv برای نمایش PATH
printenv PATH مستقیماً از محیط پروسه میخواند—not از طریق بسط Shell؛ که آن را در اسکریپتها و زمینههای غیر-تعاملی قابل-اعتمادتر میسازد:
printenv PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
چون printenv فقط متغیرهای Export-شده را چاپ میکند، بهشکل تمیزی محیطِ به-ارث-رسیده را از متغیرهای محلیِ شل تفکیک میکند.
خواندن PATH در زمینه اسکریپت
اسکریپتهایی که با bash script.sh فراخوانی میشوند، PATHای متفاوت از شل تعاملیتان میبینند—چون ~/.bashrc یا ~/.bash_profile را Source نمیکنند. این اسکریپت PATHای را که پروسه bashِ غیر-تعاملی واقعاً دریافت میکند چاپ میکند:
#!/usr/bin/env bash
echo "Script PATH: $PATH"
برای قابل-اعتماد کردن PATH اسکریپت—فارغ از نحوه فراخوانی—PATH را در بالای اسکریپت، قبل از هر دستوری که به او وابسته است، صریح تعریف کنید:
#!/usr/bin/env bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
echo "Script PATH: $PATH"
بهعنوان جایگزین، از مسیر مطلق کامل برای هر دستور استفاده کنید—مثلاً /usr/bin/python3 بهجای python3—تا اسکریپت اصلاً به PATH وابسته نباشد.
گام ۲ — افزودن دایرکتوری به PATH برای نشست فعلی
استفاده از export برای تنظیم تغییر موقت PATH
دستور export، متغیری را برای به-ارث-رسیدن به پروسههای فرزند علامتگذاری کرده و فوراً در شل فعلی بهروزرسانیاش میکند. برای افزودن دایرکتوریای به PATH در نشست فعلی، برای اولویت بالاتر جلوی آن ببندید یا برای اولویت پایینتر، در انتهایش Append کنید:
# جلو ببندید: /opt/myapp/bin قبل از همه دایرکتوریهای موجود چک میشود
export PATH="/opt/myapp/bin:$PATH"
# Append کنید: /opt/myapp/bin بعد از همه دایرکتوریهای موجود چک میشود
export PATH="$PATH:/opt/myapp/bin"
جلوبندن به دایرکتوری جدید، اولویتِ بالاتری از دایرکتوریهای سیستمی میدهد—which وقتی نسخه جدیدتری از ابزاری را در کنار نسخه سیستمی نصب میکنید مفید است. Append کردن برای استفاده عمومی امنتر است.
تأیید اعمال شدن تغییر
دو دستور تغییر را تأیید میکنند: echo $PATH مقدار خام را نشان میدهد؛ و which نشان میدهد شل واقعاً کدام باینری را اجرا خواهد کرد:
echo $PATH
which myapp
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games:/opt/myapp/bin
/opt/myapp/bin/myapp
این تغییر فقط به نشست شل فعلی اعمال میشود. وقتی Terminal را ببندید یا نشست جدیدی شروع کنید، PATH به مقدار پیشفرضش Reset میشود.
گام ۳ — افزودن دایرکتوری به PATH بهصورت دائم
انتخاب فایل پیکربندی درست
فایل راهاندازی درست به شل شما و اینکه نشست Login است یا تعاملیِ غیر-Login بستگی دارد. فایلی را انتخاب کنید که با نحوه راهاندازی شلتان مطابقت دارد.
| فایل | محدوده | کِی Source میشود | شلها |
|---|---|---|---|
~/.bashrc | خاص-کاربر | هر شل bashِ تعاملیِ غیر-Login | bash |
~/.bash_profile | خاص-کاربر | شلهای Loginِ bash (معمولاً ~/.bashrc را Source میکند) | bash |
~/.profile | خاص-کاربر | شلهای Login وقتی ~/.bash_profile وجود ندارد | bash، sh، dash |
~/.zshrc | خاص-کاربر | هر شل تعاملی zsh | zsh |
~/.zprofile | خاص-کاربر | شلهای Loginِ zsh (معادل ~/.bash_profile برای zsh) | zsh |
/etc/environment | در-سطح-سیستم | توسط PAM هنگام Login خوانده میشود؛ اسکریپت شل نیست | همه |
/etc/profile | در-سطح-سیستم | شلهای Login | bash، sh |
/etc/profile.d/*.sh | در-سطح-سیستم | توسط /etc/profile Source میشوند | bash، sh |
برای بیشتر استفادههای تعاملی روی دسکتاپ یا سروری که تنها کاربرش هستید، ~/.bashrc (یعنی bash) یا ~/.zshrc (یعنی zsh) فایل درست است.
ویرایش bashrc. برای کاربران Bash
Append کردن خط exportای به ~/.bashrc، تغییر PATH را در هر نشست bashِ تعاملی جدیدی در دسترس میسازد. فایل را باز کنید:
nano ~/.bashrc
به پایین اسکرول کرده و این را Append کنید:
export PATH="$PATH:/opt/myapp/bin"
تغییر را بدون Logout خارج شدن بارگذاری کنید:
source ~/.bashrc
تأیید کنید:
echo $PATH
اگر /opt/myapp/bin در خروجی ظاهر شد، بهروزرسانی برای دستورات جدید در Terminal فعلی فعال است.
ویرایش zshrc. برای کاربران Zsh
برای zsh، فایل معادل ~/.zshrc است. بازش کنید:
nano ~/.zshrc
خط export را Append کنید:
export PATH="$PATH:/opt/myapp/bin"
پیکربندی را Reload کنید:
source ~/.zshrc
تأیید کنید:
echo $PATH
اگر سیستمتان شلهای Loginِ zsh باز میکند—not تعاملیِ غیر-Login—toجایش از ~/.zprofile استفاده کنید.
ویرایش /etc/environment برای تغییرات در-سطح-سیستم
/etc/environment توسط PAM هنگام Login پارس میشود و اسکریپت شل نیست؛ پس سینتکس شل—including بسط متغیر $PATH—در آن کار نمیکند. قبل از ویرایش، مقدار فعلی را بخوانید:
grep PATH /etc/environment
فایل را ویرایش کنید:
sudo nano /etc/environment
مقدار Literal کامل را—شامل دایرکتوریهای موجود و مورد جدید—تنظیم کنید:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/myapp/bin"
هشدار: از
$PATHداخل/etc/environmentاستفاده نکنید. بسط متغیر در این فایل پشتیبانی نمیشود. همیشه فهرست کامل دایرکتوریها را بهصورت رشته Literal بنویسید.
تغییرات /etc/environment بعد از Login بعدی اثر میکنند—not بعد از Source کردن در شل فعلی.
Reload کردن پیکربندی شل بدون Logout
خط export جدیدِ نوشتهشده به ~/.bashrc تا وقتی فایل Source نشود فعال نیست. سه روش بدون نیاز به Logout پیکربندی را Reload میکنند:
# Source مستقیم فایل
source ~/.bashrc
# میانبر معادل
~/.bashrc .
# جایگزینی پروسه شل فعلی (bashrc~/. را Source میکند ولی نه ~/.bash_profile را)
exec bash
exec bash شل تعاملیِ غیر-Login جدیدی شروع میکند؛ پس ~/.bashrc را Source میکند—but نه ~/.bash_profile را. اگر خط export شما فقط در ~/.bash_profile است، source ~/.bash_profile را اجرا کنید یا نشست Login جدیدی باز کنید.
گام ۴ — تأیید کار کردن تغییرات PATH
استفاده از which برای چک Resolve شدن باینری
which اولین مورد اجراییِ منطبق با نام دستور را در سراسر دایرکتوریهای PATH برمیگرداند. بعد از تغییر PATH، اجرایش کنید تا تأیید کنید شل دستور را به باینری مورد انتظار Resolve میکند:
which python3
/usr/bin/python3
مسیر برگرداندهشده همان چیزی است که شل دفعه بعد که دستور را اجرا میکنید اجرا خواهد کرد—with فرض اینکه چیزی در کش Hash مربوط به bash یا جدول Alias، Overrideاش نکند.
استفاده از type و command -v برای تأیید
type -a فراتر از which میرود. هر مورد منطبق در سراسر PATH—toهمراه هر Alias یا تابع شلیِ همنام—را گزارش میکند. وقتی استفادهاش کنید که لازم است تأیید کنید نسخه درست اول در ترتیب Resolution است:
type -a python3
python3 is /usr/bin/python3
python3 is /usr/local/bin/python3
برای چک تک-مسیرِ سازگار با POSIX، command -v را اجرا کنید:
command -v python3
/usr/bin/python3
type یک Builtin شل است که Aliasها، توابع و همه موارد PATH را گزارش میکند؛ در حالی که which فقط دایرکتوریهای PATH را چک کرده و اولین مورد را برمیگرداند. از type -a وقتی استفاده کنید که لازم است همه کاندیدها را برای تشخیص تعارض نسخه ببینید.
باز کردن نشست Shell جدید برای تأیید ماندگاری
اجرای echo $PATH در همان نشستی که export را اعمال کرد، ماندگاری را تأیید نمیکند—فقط وضعیت نشست فعلی را تأیید میکند. پروسه Shell تازهای شروع کنید تا تأیید کنید مقدار از فایل راهاندازی میآید:
exec bash
echo $PATH
اگر دایرکتوری جدید در خروجی ظاهر شد، فایل راهاندازی درست پیکربندی شده. اگر نه، خط export مفقود، در فایل اشتباه، یا زیر Guardِ Return زودهنگام نشسته.
گام ۵ — حذف یا یکتاسازی Entryها از PATH
حذف دستی دایرکتوری مشخص
برای حذف /opt/myapp/bin از نشست فعلی:
PATH=$(echo "$PATH" | sed -e 's|/opt/myapp/bin:||g' -e 's|:/opt/myapp/bin||g')
export PATH
الگوی دونقطه-انتهایی، دایرکتوری را وقتی بهدنبالش دونقطه آمده حذف میکند—which موقعیتهای شروع و وسط را پوشش میدهد. الگوی دونقطه-ابتدایی هم وقتی قبلش دونقطه آمده حذفش میکند—which موقعیتهای وسط و انتها را پوشش میدهد. اجرای هر دو با هم، همه موقعیتها را پوشش میدهد. بعد از آن echo $PATH را برای تأیید حذف اجرا کنید.
جلوگیری از Entryهای تکراری هنگام Source کردن فایلهای کانفیگ
Source کردن ~/.bashrc چند بار در نشستی—مثلاً بعد از ویرایش—میتواند هر بار همان دایرکتوری را Append کند. از این الگوی Guardای استفاده کنید تا مسیر فقط یکبار اضافه شود:
case ":$PATH:" in
*":/opt/myapp/bin:"*) ;;
*) export PATH="$PATH:/opt/myapp/bin" ;;
esac
پیچاندن دونقطه دور هر دو $PATH و دایرکتوری هدف، باعث میشود الگو با Entry کامل مطابقت یابد—not زیررشتهای از مسیر طولانیتر.
عیبیابی مسائل رایج PATH
تغییر PATH بعد از Logout ماندگار نمیشود
دستور export، PATH را فقط در پروسه شل فعلی بهروزرسانی میکند. وقتی آن پروسه خارج شود، تغییر از بین میرود. برای تأیید همین اتفاق، Terminal جدیدی باز کرده و اجرا کنید:
echo $PATH
اگر دایرکتوریِ افزودهشدهتان غایب است، تغییر هرگز به فایل راهاندازی نوشته نشده. برای ردیابی دقیق اینکه bash هنگام Login کدام فایلها را به چه ترتیبی Source میکند، این را اجرا کنید:
bash -lxv 2>&1 | head -50
فلگ -l شل Loginای را اجباری میکند، -x خروجی Trace را فعال کرده و -v هر خط را وقتی خوانده میشود چاپ میکند. به دنبال خطوطی بگردید که ~/.profile، ~/.bash_profile یا /etc/profile را Source میکنند تا تأیید کنید کدام فایل PATHِ Login شما را کنترل میکند. سپس خط export را به فایل درست Append کرده و Source کنید:
echo 'export PATH="$PATH:/opt/myapp/bin"' >> ~/.bashrc
source ~/.bashrc
Command Not Found بعد از افزودن به PATH
علت: PATH در Subshell یا اسکریپتی که خارج شده بهروزرسانی شده، فایل راهاندازی اشتباه ویرایش شده، یا نشست فعلی هنوز تغییر را بارگذاری نکرده. تشخیص:
echo $PATH
grep -n PATH ~/.bashrc ~/.profile ~/.bash_profile 2>/dev/null
تأیید کنید که خط export در فایل درست موجود و source اجرا شده یا نشست جدیدی باز شده.
نسخه اشتباه باینری Resolve میشود
علت: دایرکتوری حاوی نسخه قدیمیترِ باینری، زودتر از دایرکتوری حاوی نسخه جدیدتر در PATH ظاهر میشود. تشخیص:
type -a python3
رفع: دایرکتوری حاوی نسخه موردنظر را با export PATH="/opt/myapp/bin:$PATH" جلو ببندید؛ یا دایرکتوری حاوی نسخه ناخواسته را با الگوی sed از گام ۵ حذف کنید.
تغییرات PATH روی اپلیکیشنهای GUI اعمال نمیشود
علت: بیشتر محیطهای دسکتاپ هنگام Login یعنی ~/.profile و /etc/environment را Source میکنند—not ~/.bashrc را. تغییری در ~/.bashrc فقط بر شبیهسازهای Terminal—which شلهای تعاملیِ غیر-Login تولید میکنند—اثر میگذارد. رفع: خط export را به ~/.profile منتقل کنید؛ یا دایرکتوری را به /etc/environment اضافه کرده؛ سپس Logout و دوباره Login کنید.
مدیریت PATH در محیطهای غیر-استاندارد
PATH در اسکریپتهای شل و Cron Jobها
Cron با PATH پیشفرضِ مینیمالی (معمولاً /usr/bin:/bin) اجرا میشود. دستوراتی که در شل تعاملیتان موجودند ممکن است پیدا نشوند. PATH را در بالای فایل crontab—قبل از هر تعریف Jobای—تنظیم کنید. Crontab را با crontab -e باز کرده و تخصیص PATH را اول اضافه کنید:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# اجرای myapp هر ساعت
0 * * * * /opt/myapp/bin/myapp >> /var/log/myapp.log 2>&1
خط PATH به هر Jobی که زیرش در همان فایل crontab تعریف شده اعمال میشود. اگر اسکریپتی که توسط cron صدا زده میشود هم به دستورات وابسته-به-PATH تکیه دارد، همان تخصیص PATH را در بالای آن اسکریپت اضافه کنید.
PATH در کانتینرهای داکر و Dockerfileها
از دستورالعمل ENV در Dockerfile برای گسترش PATHِ Image استفاده کنید:
ENV PATH="/opt/myapp/bin:${PATH}"
ENV در سراسر لایههای بعدی و درون کانتینرِ در-حال-اجرا ماندگار است؛ پس هر دستورالعمل RUN، CMD و ENTRYPOINT مقدار به-روزشده را میبیند.
استفاده از direnv برای مدیریت PATH خاص-پروژه
direnv متغیرهای محیطی را هنگام ورود یا خروج از دایرکتوری خودکار بارگذاری و Unload میکند. نصبش کنید و Hook شل را به فایل راهاندازیتان اضافه کنید:
sudo apt install direnv
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc
source ~/.bashrc
روی راکی لینوکس، فدورا یا RHEL، خط نصب را با sudo dnf install direnv جایگزین کنید. برای کاربران zsh روی هر توزیعی، در دستور Hook بهجای bash از zsh استفاده کنید. Hook الزامی است. بدون آن، direnv هنگام تغییر دایرکتوری فعال نمیشود.
فایل .envrc را در ریشه پروژهتان بسازید:
PATH_add ./bin
یکبار اجازهاش بدهید:
direnv allow
PATH وقتی cd از پروژه خارج میشوید به مقدار قبلی برمیگردد.
دامهای رایج PATH در پروداکشن
سناریوهای زیر رایجترین دلایلیاند که PATHِ درست-پیکربندیشده همچنان در دیپلویهای واقعی طبق انتظار کار نمیکند.
sudo یعنی PATH شما را نادیده میگیرد
اجرای دستوری با sudo اغلب—even وقتی دستور بدون sudo کار میکند—with خطای «command not found» شکست میخورد. علت، secure_path در /etc/sudoers است—which هنگام فراخوانی sudo، PATH را کاملاً جایگزین میکند.
مقدار secure_path فعلی را چک کنید:
sudo grep secure_path /etc/sudoers
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
اگر /opt/myapp/bin فهرست نشده، sudo myapp فارغ از PATH کاربری شما شکست خواهد خورد. برای رفع بدون غیرفعال کردن secure_path، از مسیر کامل استفاده کنید:
sudo /opt/myapp/bin/myapp
یا دایرکتوری را با ویرایش /etc/sudoers با visudo به secure_path اضافه کنید:
sudo visudo
خط secure_path را تغییر بدهید تا دایرکتوریتان شامل شود:
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/myapp/bin"
هشدار: همیشه از visudo برای ویرایش
/etc/sudoersاستفاده کنید. ویرایش مستقیم فایل با ویرایشگر متنی و معرفی خطای سینتکسی، شما را از sudo روی آن سیستم بیرون میکِشد.
شلهای غیر-تعاملی SSH یعنی bashrc. را Source نمیکنند
اجرای دستوری روی SSH با ssh user@host 'mycommand' شل غیر-تعاملیِ غیر-Loginای میسازد. این شل نه ~/.bashrc و نه ~/.bash_profile را Source میکند؛ پس تغییرات PATH در آن فایلها برایش نامرئیاند.
برای تأیید اینکه شل غیر-تعاملی SSH چه PATHای میبیند:
ssh user@host 'echo $PATH'
/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
خروجی، PATH سیستمیِ مینیمالی است که sshd تنظیم کرده—بدون هیچکدام از دایرکتوریهای فایلهای راهاندازی شل تعاملی شما. برای در دسترس کردن PATH در این زمینه، در ~/.bashrc تنظیمش کنید و بلاک را Guard کنید تا حتی در شلهای غیر-تعاملی اجرا شود:
export PATH="$PATH:/opt/myapp/bin"
چک کنید آیا Guardای مثل [ -z "$PS1" ] && return نزدیک بالای ~/.bashrc شما وجود دارد. این خط باعث میشود bash برای شلهای غیر-تعاملی زودهنگام خارج شود—و همه چیزهای زیرش را رد کند. اگر Guard موجود است، خط export PATH را بالای آن منتقل کنید. اگر Guard غایب است، خط export میتواند در پایین فایل بماند. بهعنوان جایگزین، PATH را در ~/.profile تعریف و مطمئن شوید ~/.bashrc آن را Source میکند.
bash مکان باینریها را Cache میکند
بعد از بهروزرسانی PATH، bash ممکن است همچنان باینری قدیمی را اجرا کند—چون مکان دستوراتِ از-پیش-اجرا-شده را در جدول Hash کش میکند. Entry کششده، Lookup مربوط به PATH را برای آن نام دستور Override میکند.
بعد از تغییر PATH، کش را پاک کنید:
hash -r
برای چک اینکه آیا دستور خاصی Cache شده و به کجا اشاره میکند:
hash python3
hits command
3 /usr/bin/python3
اگر مسیر کششده کهنه است، hash -r همه Entryها را پاک کرده و Lookupِ تازه PATH را در فراخوانی بعدی اجباری میکند.
تقدم Resolve شدن دستور
PATH اولین جایی نیست که bash هنگام اجرای دستور نگاه میکند. ترتیب Resolution این است:
۱. Aliasها (تعریفشده با alias)
۲. توابع شل
۳. Builtinهای شل (cd، echo، type و غیره)
۴. مکانهای Hash-شده (کش باینری که بالا توصیف شد)
۵. اسکن دایرکتوریهای PATH
این دلیل اینکه type -a برای تشخیص رفتار غیرمنتظره مفیدتر از which است. اگر type python3 مقدار python3 is aliased to python برگرداند، Alias بر هر Entry مربوط به PATH تقدم دارد. برای رسیدن به باینری، Alias را حذف یا تغییر نام بدهید.
ترکیب PATH در macOS با لینوکس متفاوت است
روی macOS، سیستم هنگام Login یعنی /usr/libexec/path_helper را اجرا میکند تا PATH را از دو منبع بسازد: /etc/paths (یک دایرکتوری در هر خط) و فایلهای داخل /etc/paths.d/. این قبل از فایلهای راهاندازی شل اجرا میشود؛ پس دایرکتوریهای فهرستشده آنجا قبل از هر چیزی در ~/.zshrc یا ~/.bash_profile در PATH ظاهر میشوند.
برای افزودن دایرکتوریای در-سطح-سیستم روی macOS، در /etc/paths.d/ فایلی بسازید:
sudo sh -c 'echo /opt/myapp/bin > /etc/paths.d/myapp'
فایل بعد از Login بعدی اثر میکند. برای تأیید:
cat /etc/paths
ls /etc/paths.d/
نکته: این بخش فقط به macOS اعمال میشود. روی سیستمهای لینوکسیِ پوششدادهشده در این tutorial،
/etc/pathsو path_helper وجود ندارند.
PATH در یونیتهای سرویس systemd
هنگام اجرای اپلیکیشنها بهعنوان سرویسهای systemd، PATH از محیط کاربری شما به ارث نمیرسد. systemd سرویسها را با محیط مینیمالی شروع میکند. دستورات نصبشده در /opt/myapp/bin یا مکانهای مشابه پیدا نخواهند شد—مگر اینکه PATH صریحاً در فایل Unit تنظیم شود.
PATH را در بلاک [Service] فایل Unit تنظیم کنید:
[Service]
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/myapp/bin"
ExecStart=/opt/myapp/bin/myapp
برای چند متغیر محیطی، از EnvironmentFile استفاده کنید:
[Service]
EnvironmentFile=/etc/myapp/environment
ExecStart=/opt/myapp/bin/myapp
که /etc/myapp/environment شامل:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/myapp/bin
MYAPP_ENV=production
بعد از ویرایش فایل Unit، دیمن را Reload و سرویس را ریاستارت کنید:
sudo systemctl daemon-reload
sudo systemctl restart myapp
سوالات متداول
متغیر محیطی PATH در لینوکس چیست؟
PATH، فهرستی از مسیرهای دایرکتوری—جدا شده با دونقطه—است که شل هنگام تایپ دستور، از چپ به راست جستجو میکند. وقتی python3 را اجرا میکنید، شل هر دایرکتوری در PATH را چک میکند تا اجراییِ بهنام python3 پیدا کند؛ سپس اجرایش میکند. بدون PATH، هر دستور لازم داشت مسیر مطلق کاملش تایپ شود.
چطور PATH فعلیام را در لینوکس ببینم؟
echo $PATH یا printenv PATH را در هر Terminalای اجرا کنید تا مقدار فعلی نمایش یابد. هر دو دستور همان فهرست دایرکتوریهای جداشده-با-دونقطه را چاپ میکنند. برای دیدن یک-دایرکتوری-در-هر-خط، tr ':' '\n' <<< "$PATH" را اجرا کنید.
تفاوت تغییر موقت و دائم PATH در لینوکس چیست؟
اجرای export PATH="$PATH:/new/dir" در Terminal، تغییر را فقط به شل فعلی اعمال میکند. وقتی نشست تمام شود، PATH به مقدارِ تنظیمشده توسط فایلهای راهاندازی برمیگردد. برای ماندگاری، خط export را به ~/.bashrc (یعنی bash) یا ~/.zshrc (یعنی zsh) بنویسید و فایل را Source کنید.
کدام فایل را برای افزودن دائم دایرکتوری به PATH در لینوکس ویرایش کنم؟
برای نشستهای bashِ تعاملی روی سرور یا دسکتاپی که بهعنوان کاربر منفردی Login میکنید، ~/.bashrc را ویرایش کنید. برای نشستهای شل Login از ~/.profile یا ~/.bash_profile استفاده کنید؛ و وقتی تغییر باید به همه کاربران سیستم اعمال شود از /etc/environment. جدول گام ۳، محدوده و رفتار Sourcing هر فایل را فهرست میکند.
چرا PATH بعد از اجرای export در Terminal بهروز نمیشود؟
export در اسکریپت، شل والد را متأثر نمیکند—چون اسکریپت در Subshell اجرا میشود. تغییرات باید Source شوند (. script.sh یا source script.sh) تا به شل فعلی اعمال؛ یا به فایل راهاندازی نوشته و در نشست جدیدی بارگذاری شوند. echo $PATH را بلافاصله بعد از export اجرا کنید تا تأیید کنید تغییر در نشست فعلی قابل مشاهده است.
چطور دایرکتوریای به PATH در zsh اضافه کنم؟
~/.zshrc را در ویرایشگر متنی باز کنید، export PATH="$PATH:/opt/myapp/bin" را در پایین اضافه، فایل را ذخیره و source ~/.zshrc را اجرا کنید. برای شلهای Loginِ zsh، بهجای ~/.zshrc از ~/.zprofile استفاده کنید.
چطور بعد از بهروزرسانی PATH چک کنم دستوری به کدام باینری Resolve میشود؟
which python3 را اجرا کنید تا اولین مورد در PATH را ببینید. type -a python3 را اجرا کنید تا هر مورد در سراسر دایرکتوریهای PATH فهرست شود—which وقتی چند نسخه نصب است مفید است. command -v python3 را برای جایگزینِ قابل-انتقال-به-POSIX یعنی which اجرا کنید.
چطور دایرکتوریای را از PATH در لینوکس حذف کنم؟
برای حذف /opt/myapp/bin از نشست فعلی این را اجرا کنید:
PATH=$(echo "$PATH" | sed -e 's|/opt/myapp/bin:||g' -e 's|:/opt/myapp/bin||g')
export PATH
برای دائمی کردن حذف، خط exportای که دایرکتوری را از ~/.bashrc، ~/.zshrc یا هر فایل راهاندازیِ حاویاش اضافه کرده بود حذف یا کامنت کنید؛ سپس فایل را Source کنید.
نتیجهگیری
این tutorial، چرخه کامل مدیریت PATH در لینوکس را مرور کرد: خواندن مقدار فعلی، تغییرات موقت و دائم در bash و zsh، انتخاب فایل راهاندازی درست برای نوع نشست، تأیید Resolve شدن باینری درست، حذف و یکتاسازی Entryها؛ و تشخیص خرابیهایی که در محیطهای پروداکشن—including پاک شدن PATH توسط sudo، شلهای غیر-تعاملی SSH، کشهای کهنه باینری و ایزوله شدن سرویس systemd—رخ میدهند.
حالا میتوانید PATH را برای هر ابزارِ نصبشده-توسط-کاربر پیکربندی، فایل راهاندازی درست را برای شل و حالت Login خودتان انتخاب؛ و تشخیص بدهید چرا دستوری پیدا نمیشود یا به باینری اشتباه Resolve میشود.




