پرش به محتویات

۲. فایل‌ها و دایرکتوری‌ها

اشتباه در این فصل معمولاً بی‌برگشت است: فایلی که با rm پاک شود سطل زباله ندارد. پس قاعدهٔ کلی: اول ببین (ls، find ... -print)، بعد عمل کن.

راهنمای سریع

فرمان کاربرد ریسک
ls -lah / ls -lt / ls -lhS فهرست، جدیدترین‌ها، بزرگ‌ترین‌ها بدون تغییر
stat / file / readlink -f مشخصات فایل، نوع، مسیر واقعی بدون تغییر
find / grep -R / locate جست‌وجو بدون تغییر (با -delete/-exec: مخرب)
cp / mv / ln -s / mkdir -p کپی، جابه‌جایی، پیوند تغییر (بازنویسی بی‌صدا ممکن است)
chmod / chown مجوز و مالکیت تغییر (-R روی /: فاجعه)
rm -r / rm -rf حذف مخرب
chattr +i غیرقابل‌تغییر کردن فایل تغییر

فهرست و جابه‌جایی

pwd
ls
ls -lah
ls -lt /var/log | head          # جدیدترین‌ها
ls -lhS /var/log | head         # بزرگ‌ترین‌ها
ls -ld /etc /etc/ssh            # خود پوشه (نه محتوایش)
cd /etc
mkdir -p /opt/myapp/{config,logs,data}
touch notes.txt
cp -i source.txt backup.txt     # -i: قبل از بازنویسی بپرسد
cp -a /etc/myapp /backup/myapp
mv -i old-name.conf new-name.conf
  • ls -lah: نمایش فایل‌های مخفی، اندازه خوانا و جزئیات.
  • mkdir -p: ساخت مسیرهای تو در تو بدون خطا در صورت وجود.
  • cp -a: حفظ ویژگی‌ها، مالکیت، زمان و پیوندها تا حد امکان (ACL/xattr برای -a تضمین نیست؛ برای بکاپ از rsync -aHAX یا tar --acls --xattrs استفاده کنید).
  • mv و cp بی‌صدا بازنویسی می‌کنند؛ در دست‌وپا از -i یا -n (بازنویسی نکن) استفاده کنید.
  • برای کپی دایرکتوری با حفظ ساختار و زمان‌ها از rsync -a هم می‌توان استفاده کرد (SSH و rsync).

مشاهده محتوا

cat /etc/os-release
less /var/log/syslog
head -n 30 file.txt
tail -n 100 file.txt
tail -F /var/log/syslog          # -F: بعد از logrotate هم دنبال می‌کند
wc -l file.txt
file archive.bin
stat /etc/hosts
stat -c '%a %U:%G %n' /etc/ssh/sshd_config   # مجوز عددی، مالک، نام
diff -u old.conf new.conf        # تفاوت دو فایل (قبل و بعد از ویرایش)

less برای فایل بزرگ مناسب‌تر از cat است. در less با /عبارت جست‌وجو، n برای مورد بعدی، G برای انتها، F برای دنبال‌کردن زنده (مثل tail -f) و q برای خروج.

tail -f یا tail -F؟

tail -f فایل را با شمارهٔ inode دنبال می‌کند؛ بعد از چرخش لاگ (logrotate) روی فایل قدیمی می‌ماند و ساکت می‌شود. tail -F نام فایل را دنبال می‌کند و بعد از چرخش به فایل جدید می‌پرد.

جست‌وجو

find /var/log -type f -name '*.log'
find /opt -type f -mtime -7                 # در ۷ روز اخیر تغییر کرده
find /tmp -type f -size +100M
find /srv -type f -name '*.bak' -print
find /var -xdev -type f -size +500M -exec ls -lh {} +   # بزرگ‌ها فقط روی همین filesystem
find /home -xdev \( -nouser -o -nogroup \)              # فایل‌های یتیم (مالک حذف‌شده)
find / -xdev -type f -newermt '2026-01-01' ! -newermt '2026-01-02'   # تغییر در یک روز مشخص
grep -Rni 'error' /var/log/myapp/
grep -Rnw --include='*.conf' 'listen' /etc/nginx
locate sshd_config
sudo updatedb                                # تازه‌کردن پایگاه locate
  • find: جست‌وجوی زنده بر اساس نام، نوع، زمان، اندازه، مالک و مجوز.
  • -mtime -7 یعنی «کمتر از ۷ روز پیش»؛ -mtime +7 یعنی «بیش از ۷ روز پیش». برای دقت بیشتر -mmin یا -newermt استفاده کنید.
  • -xdev از ورود به filesystem دیگر (NFS، /proc، mount ها) جلوگیری می‌کند؛ روی / تقریباً همیشه لازم است.
  • locate: سریع است اما به پایگاه داده‌ای وابسته است که ممکن است به‌روز نباشد (فایل تازه را نمی‌بیند، فایل حذف‌شده را نشان می‌دهد).
  • grep -Rni: جست‌وجوی بازگشتی، بدون حساسیت به بزرگی حروف، همراه شماره خط. -w فقط کلمهٔ کامل.

find با عمل مخرب: قاعدهٔ «اول print، بعد delete»

# مرحلهٔ ۱: ببینید دقیقاً چه چیزی انتخاب می‌شود
find /var/tmp/cache -type f -mtime +30 -print

# مرحلهٔ ۲: همان شرط‌ها، با -delete در انتها
find /var/tmp/cache -type f -mtime +30 -delete

ترتیب آرگومان‌های find مهم است

-delete باید آخر بیاید. اگر قبل از شرط‌هایی مثل -type f یا -name بیاید، همه‌چیز حذف می‌شود (find . -delete -name '*.tmp' همه را پاک می‌کند). -delete روی مسیر اشتباه (مثلاً متغیر خالی) هم فاجعه است.

حذف و احتیاط

rm -i file.txt
rmdir empty-dir

rm -r پوشه و محتویاتش را حذف می‌کند؛ rm -rf می‌تواند بسیار مخرب باشد. پیش از حذف، مسیر را با pwd و فهرست را با ls بررسی کنید. برای کارهای زمان‌بندی‌شده، مسیرهای متغیر را بدون اعتبارسنجی به rm ندهید.

الگوی ایمن در اسکریپت:

# اگر BUILD_DIR خالی/تنظیم‌نشده باشد، اسکریپت متوقف می‌شود (به‌جای rm -rf /*)
rm -rf -- "${BUILD_DIR:?BUILD_DIR تنظیم نشده}"/*

# هرگز: rm -rf $DIR/*        (بدون نقل‌قول و بدون :?)
# هرگز: rm -rf /path /        (فاصلهٔ اشتباه = ریشه)
  • -- یعنی بعد از این آرگومان‌ها گزینه نیستند (فایل‌هایی مثل -rf را امن می‌کند).
  • shred روی SSD، فایل‌سیستم‌های journaling/CoW (btrfs، zfs) و دیسک‌های ابری حذف مطمئن تضمین نمی‌کند. برای داده‌های حساس از رمزگذاری دیسک (LUKS) و حذف کلید استفاده کنید.
  • فایل حذف‌شده‌ای که هنوز توسط پردازشی باز است، فضا را آزاد نمی‌کند: sudo lsof +L1 (رخدادها).

پیوندها

ln -s /opt/myapp/current /var/www/myapp      # پیوند نمادین
ln /data/a.txt /data/b.txt                   # پیوند سخت (فقط روی همان filesystem)
readlink -f /var/www/myapp
realpath /var/www/myapp
ls -l /var/www/                              # پیوند شکسته با رنگ قرمز دیده می‌شود
find /var/www -xtype l                       # پیوندهای شکسته
  • پیوند نمادین (symbolic link) به مسیر دیگری اشاره می‌کند؛ اگر هدف حذف شود «شکسته» می‌شود.
  • پیوند سخت نام دوم برای همان inode است؛ حذف یک نام، داده را پاک نمی‌کند تا آخرین نام حذف شود.
  • الگوی استقرار امن: ln -sfn /opt/app/releases/2026-10-30 /opt/app/current (جابه‌جایی نسخه با یک عمل تقریباً اتمیک و برگشت آسان).

مجوز و مالکیت فایل

chmod 640 app.conf
chmod -R u=rwX,g=rX,o= /opt/myapp
chown appuser:appgroup app.log
chown -R appuser:appgroup /opt/myapp

از chmod -R 777 به‌عنوان راه‌حل عمومی استفاده نکنید؛ معمولاً مشکل مجوز را پنهان و سطح دسترسی را بیش از حد باز می‌کند. جزئیات (setuid/setgid/sticky، umask، ACL): کاربران و مجوزها.

  • X (بزرگ) فقط به پوشه‌ها و فایل‌های از قبل اجرایی x می‌دهد؛ برای -R امن‌تر از x است.
  • chown -R و chmod -R را روی مسیرهایی که پیوند نمادین به بیرون دارند با دقت اجرا کنید؛ اگر لازم بود chown -R -h (خود پیوند، نه هدف).

خصوصیات ویژه و فایل‌های موقت

lsattr /etc/resolv.conf
sudo chattr +i /etc/important.conf     # حتی root هم نمی‌تواند تغییر/حذف کند (تا chattr -i)
sudo chattr -i /etc/important.conf
tmp=$(mktemp)                          # فایل موقت امن (نام غیرقابل‌حدس، مجوز 600)
tmpdir=$(mktemp -d)

chattr +i را مستند کنید

فایل immutable بعداً مدیر بعدی را گیج می‌کند («چرا نمی‌توانم این فایل را ویرایش کنم؟» حتی با root). هر chattr +i را در runbook یادداشت کنید.

ویرایشگر متن

روی سرور حداقل یک ویرایشگر را کامل بلد باشید. nano ساده‌تر است؛ vim همه‌جا هست.

کار vim nano
ورود به حالت ویرایش i (همیشه فعال)
ذخیره Esc سپس :w Ctrl+O
خروج :q (بدون ذخیره: :q!) Ctrl+X
ذخیره و خروج :wq Ctrl+O سپس Ctrl+X
جست‌وجو /عبارت سپس n Ctrl+W
حذف خط dd Ctrl+K
بازگردانی u Alt+U

فایل‌های سیستمی حساس (sudoers، fstab) را با ابزار اعتبارسنج ویرایش کنید: sudo visudo، sudoedit /etc/fstab سپس findmnt --verify.

خطاهای رایج

نشانه علت احتمالی روش بررسی
Permission denied روی فایلی که مجوزش درست است مجوز x پوشهٔ والد، ACL، SELinux/AppArmor namei -l /path/to/file ، getfacl ، ls -Z
No space left on device با df آزاد تمام شدن inode df -ih
Argument list too long glob بیش از حد (rm *) find . -name '*.x' -delete یا xargs
فایل حذف شد ولی فضا آزاد نشد پردازش هنوز فایل را باز نگه داشته sudo lsof +L1
Too many levels of symbolic links حلقه در پیوندها namei -l PATH
Text file busy تلاش برای تغییر باینری در حال اجرا سرویس را متوقف یا فایل جدید را mv کنید
mv ناگهان کند شد جابه‌جایی بین دو filesystem (کپی + حذف) df PATH1 PATH2

نکات امنیتی و عملیاتی

  • قبل از هر rm -r / find -delete: pwd، ls، سپس همان فرمان با -print یا ls.
  • فایل پیکربندی را قبل از ویرایش کپی کنید: sudo cp -a file file.bak.$(date +%F)؛ بعد از ویرایش diff -u file.bak.* file.
  • در /tmp با نام قابل‌حدس فایل نسازید (mktemp را استفاده کنید)؛ مسیرهای /tmp و /var/tmp برای همه قابل‌نوشتن هستند.
  • فایل‌های حاوی رمز/کلید: مجوز 600 یا 640 با گروه مناسب؛ هرگز 644.

خلاصهٔ اجرایی

  1. اول ببین، بعد حذف کن: -print قبل از -delete.
  2. در اسکریپت، متغیر مسیر را با ${VAR:?} محافظت و آرگومان‌ها را نقل‌قول کنید.
  3. tail -F برای لاگ‌ها؛ mktemp برای فایل موقت.
  4. chmod 777 و chmod -R بی‌فکر ممنوع.