تسلط بر خط لولهها، ورودی و خروجی استاندارد و پردازش متن
در قسمت اول این مجموعه با فلسفه لینوکس، ساختار فایلسیستم، مفهوم Shell و تعدادی از دستورات پایه آشنا شدیم. اکنون زمان آن رسیده است که از اجرای سادهی دستورات عبور کنیم و یاد بگیریم چگونه چند ابزار کوچک را به یک جریان کاری قدرتمند تبدیل کنیم.
یکی از مهمترین ایدهها در لینوکس این است:
هر ابزار باید یک کار را بهخوبی انجام دهد و امکان ترکیب با ابزارهای دیگر را داشته باشد.
به کمک این نگرش، میتوانیم فایلهای بزرگ، لاگهای سرور، خروجی سرویسها و دادههای متنی را بدون نیاز به نرمافزارهای گرافیکی تحلیل و پردازش کنیم.
در این قسمت با مفاهیم زیر آشنا میشویم:
ورودی استاندارد، خروجی استاندارد و خطای استاندارد
عملگرهای هدایت خروجی
خط لوله یا Pipe
جستوجوی حرفهای با
grepپیدا کردن فایلها با
findشمارش و مرتبسازی دادهها با
sortوuniqپردازش متن با
cut،trوwcویرایش متنی با
sedپردازش ساختاریافته با
awkترکیب این ابزارها در سناریوهای واقعی
۱. سه جریان استاندارد در لینوکس
تقریباً هر برنامهی خط فرمان در لینوکس با سه جریان اصلی کار میکند:
جریان ------------------نام ---------------کاربرد
ورودی استاندارد---------- stdin -----------دریافت ورودی
خروجی استاندارد --------stdout -----------نمایش نتیجه
خطای استاندارد ---------stderr ------------نمایش خطاها
به صورت پیشفرض:
ورودی از صفحهکلید خوانده میشود.
خروجی روی ترمینال نمایش داده میشود.
خطاها نیز روی ترمینال چاپ میشوند.
برای درک بهتر، دستور زیر را اجرا کنید:
cat
اکنون هر متنی که تایپ کنید، دوباره نمایش داده میشود. برای پایان دادن به ورودی، کلیدهای زیر را فشار دهید:
Ctrl + D
در این مثال، cat دادهها را از stdin دریافت و در stdout نمایش میدهد.
۲. هدایت خروجی به فایل
۲.۱. ذخیره خروجی با >
با استفاده از علامت > میتوان خروجی >
با استفاده از علامت > میتوان خروجیHello Linux" > message.txt
``توای فایل را بررسی کنید:
cat
```bash
cat message.txt
اگر فایل وجود داشته باشد، محتوای قبلی آن با محتوای جدید جایگزین میشود:
echo "New content" > message.txt
هشدار مهم
دستور زیر بدون پرسش، محتوای فایل را بازنویسی میکند:
command > file.txt
بنابراین هنگام کار با فایلهای مهم باید با دقت استفاده شود.
۲.۲. افزودن خروجی با >>
اگر بخواهیم خروجی جدید به انتهای فایل اضافه شود، از >> استفاده میکنیم:
echo "Line one" > notes.txt
echo "Line two" >> notes.txt
echo "Line three" >> notes.txt
مشاهده محتوا:
cat notes.txt
خروجی:
Line one
Line two
Line three
تفاوت اصلی:
> # ایجاد یا بازنویسی فایل
>> # ایجاد یا افزودن به انتهای فایل
۳. هدایت خطاها با 2>
برای ذخیره خطاها باید جریان شمارهی ۲ را هدایت کنیم:
ls /this/path/does/not/exist 2> error.log
خروجی خطا در فایل error.log ذخیره میشود.
برای مشاهده آن:
cat error.log
در صورتی که بخواهیم خروجی عادی و خطا را در یک فایل ذخیره کنیم:
command > output.log 2>&1
در Bash جدیدتر میتوان از شکل کوتاهتر زیر نیز استفاده کرد:
command &> output.log
ذخیره خروجی و خطا در فایلهای جداگانه
command \
> output.log \
2> error.log
این روش برای اسکریپتهای مدیریتی و سرویسهای پسزمینه بسیار مفید است.
۴. نادیده گرفتن خروجی با /dev/null
در لینوکس فایلی ویژه به نام /dev/null وجود دارد. هر دادهای که به آن ارسال شود، دور ریخته میشود.
command > /dev/null
برای نادیده گرفتن خروجی و خطا:
command > /dev/null 2>&1
یا:
command &> /dev/null
مثلاً:
ping -c 1 example.com > /dev/null 2>&1
در این حالت، هیچ خروجیای روی صفحه نمایش داده نمیشود.
۵. خط لوله یا Pipe چیست؟
علامت Pipe به شکل زیر نوشته میشود:
|
Pipe خروجی دستور سمت چپ را به ورودی دستور سمت راست منتقل میکند.
ساختار کلی:
command1 | command2
مثال:
ls -l | less
در اینجا خروجی ls -l به برنامهی less ارسال میشود تا بتوانیم آن را صفحهبهصفحه ببینیم.
مثال دیگر:
ps aux | grep nginx
این دستور ابتدا فهرست پردازشها را تولید کرده و سپس فقط خطوط مربوط به nginx را نمایش میدهد.
۶. زنجیرهسازی چند دستور
قدرت اصلی Pipe زمانی مشخص میشود که چند دستور را با یکدیگر ترکیب کنیم:
ps aux | grep nginx | grep -v grep
معنی این دستور:
نمایش پردازشهای در حال اجرا
انتخاب خطوط دارای عبارت
nginxحذف خطی که مربوط به خود دستور
grepاست
برای زنجیرههای طولانی، بهتر است دستورات را در چند خط بنویسیم:
aux \
| grep nginx \
| grep -v grep
علامت \ به Shell میگوید که دستور در خط بعد ادامه دارد.
۷. دستور grep؛ جستوجوی سریع در متن
grep یکی از پرکاربردترین ابزارهای لینوکس برای جستوجوی الگو در فایلها و خروجی دستورات است.
جستوجوی ساده
grep "error" application.log
این دستور تمام خطوطی را نشان میدهد که شامل error هستند.
جستوجوی بدون حساسیت به حروف بزرگ و کوچک
grep -i "error" application.log
در این حالت، موارد زیر هم پیدا میشوند:
error
Error
موارد زیر هم پیدا میشوند:
```text
error
Error
```bash
grep -n "error" application.log
جستوجوی بازگشتی در یک پوشه
grep -R "database" /var/www
برای حذف هشدارهای مربوط به فایلهای باینری:
grep -RIn "database" /var/www
گزینهها:
-R: جستوجوی بازگشتی-I: نادیده گرفتن فایلهای باینری-n: نمایش شماره خط
نمایش تعداد تطابقها
grep -c "ERROR" application.log
نمایش خطوط قبل و بعد از نتیجه
grep -C 2 "ERROR" application.log
دستور بالا دو خط قبل و دو خط بعد از هر نتیجه را نمایش میدهد.
همچنین:
grep -A 3 "ERROR" application.log
grep -B 3 "ERROR" application.log
-A: خطوط بعد از نتیجه
-B: خطوط قبل از نتیجه
-C: خطوط قبل و بعد
۸. عبارتهای منظم در grep
با فعالکردن Extended Regular Expressions میتوان جستوجوهای دقیقتری انجام داد:
grep -E "ERROR|CRITICAL|FATAL" application.log
این دستور خطوطی را نمایش میدهد که حداقل یکی از کلمات زیر را داشته باشند:
ERRORCRITICALFATAL
جستوجوی خطوطی که با عبارت مشخص شروع میشوند:
grep '^2026' application.log
جستوجوی خطوطی که با عبارت مشخص پایان مییابند:
grep 'failed$' application.log
جستوجوی خطوط خالی:
grep '^$' file.txt
حذف خطوط خالی:
grep -v '^$' file.txt
حذف خطوط توضیحی و خالی:
grep -vE '^\s*#|^\s*$' config.conf
۹. دستور wc؛ شمارش خطوط، کلمات و بایتها
دستور wc برای شمارش دادهها استفاده میشود.
wc file.txt
خروجی معمولاً شامل موارد زیر است:
lines words bytes filename
گزینههای مهم:
wc -l file.txt # تعداد خطوط
wc -w file.txt # تعداد کلمات
wc -c file.txt # تعداد بایتها
مثال:
grep -i "error" application.log | wc -l
این دستور تعداد خطوط دارای خطا را محاسبه میکند.
۱۰. مرتبسازی با sort
برای مرتبسازی خطوط از sort استفاده میکنیم:
sort names.txt
مرتبسازی عددی:
sort -n numbers.txt
مرتبسازی معکوس:
sort -r names.txt
مرتبسازی بر اساس ستون:
sort -k2 users.txt
ترکیب مرتبسازی و حذف موارد تکراری:
sort names.txt | uniq
یا به شکل کوتاهتر:
sort -u names.txt
۱۱. حذف موارد تکراری با uniq
دستور uniq خطوط تکراری پشتسرهم را حذف میکند. به همین دلیل معمولاً ابتدا دادهها را مرتب میکنیم:
sort requests.txt | uniq
نمایش تعداد تکرار هر خط:
sort requests.txt | uniq -c
مرتبسازی بر اساس تعداد تکرار:
sort requests.txt \
| uniq -c \
| sort -nr
این الگو برای پیدا کردن پرتکرارترین IPها، خطاها یا مسیرهای درخواستشده بسیار کاربردی است.
۱۲. جداکردن ستونها با cut
فرض کنید فایل users.csv شامل دادههای زیر باشد:
ali,ali@example.com,developer
sara,sara@example.com,designer
reza,reza@example.com,admin
برای نمایش ستون اول:
cut -d',' -f1 users.csv
برای نمایش ستون دوم:
cut -d',' -f2 users.csv
گزینهها:
-d: تعیین جداکننده-f: انتخاب شماره ستون
برای فایلهایی که با Tab جدا شدهاند:
cut -f1 data.tsv
۱۳. تبدیل یا حذف کاراکترها با tr
تبدیل حروف کوچک به بزرگ:
echo "hello linux" | tr 'a-z' 'A-Z'
خروجی:
HELLO LINUX
حذف فاصلهها:
echo "hello linux" | tr -d ' '
جایگزینی چند فاصله با یک فاصله:
echo "hello linux" | tr -s ' '
این دستور در پاکسازی دادههای متنی بسیار مفید است.
۱۴. پردازش متن با sed
sed یک ویرایشگر جریان (Stream Editor) است. این ابزار معمولاً فایل را خطبهخط میخواند، روی آن تغییر اعمال میکند و نتیجه را چاپ میکند.
جستوجو و جایگزینی
sed 's/old/new/' file.txt
این دستور در هر خط، اولین رخداد old را با new جایگزین میکند.
جایگزینی همه رخدادها در هر خط:
sed 's/old/new/g' file.txt
جایگزینی بدون حساسیت به حروف:
sed 's/error/fixed/gi' file.txt
نکته مهم
دستورهای بالا فایل اصلی را تغییر نمیدهند و فقط نتیجه را چاپ میکنند.
برای تغییر مستقیم فایل:
sed -i 's/old/new/g' file.txt
پیشنهاد ایمنتر:
sed -i.bak 's/old/new/g' file.txt
در این حالت، قبل از تغییر، نسخهای با نام file.txt.bak ساخته میشود.
حذف خطوط با sed
حذف خط سوم:
sed '3d' file.txt
حذف بازهای از خطوط:
sed '3,7d' file.txt
حذف خطوط خالی:
sed '/^$/d' file.txt
حذف خطوط توضیحی:
sed '/^[[:space:]]*#/d' config.conf
نمایش فقط خطوط ۵ تا ۱۰:
sed -n '5,10p' file.txt
۱۵. پردازش حرفهای دادهها با awk
awk برای کار با دادههای ستونی و ساخت گزارشهای متنی بسیار قدرتمند است.
فرض کنید فایل زیر را داریم:
ali 85 backend
sara 92 frontend
reza 78 devops
نمایش ستون اول:
awk '{print $1}' students.txt
نمایش ستون اول و سوم:
awk '{print $1, $3}' students.txt
محاسبه میانگین نمرهها:
awk '
{
total += $2
count++
}
END {
print total / count
}
' students.txt
در awk:
$1: ستون اول$2: ستون دوم$0: کل خطNF: تعداد ستونهای خطNR: شماره خط فعلیBEGIN: قبل از خواندن دادهها اجرا میشودEND: پس از پایان خواندن اجرا میشود
استفاده از جداکننده CSV
awk -F',' '{print $1, $.csv
فیلترکردن بر اساس شرط
awk '$2 >= 80 {print $1, $2}' students.txt
خروجی فقط دانشجویانی را نشان میدهد که نمره آنها حداقل ۸۰ است.
نمایش شماره خطوط
awk '{print NR ": " $0}' file.txt
۱۶. تفاوت grep، sed و awk
ابزار | کاربرد اصلی |
|---|---|
| تغییر، حذف یا استخراج خطوط |
| پردازش ستونی، شرطها و گزارشسازی |
مثال عملی:
grep "200" access.log | awk '{print $1}' | sort | uniq -c | sort -nr
این زنجیره میتواند IPهای موجود در خطوط دارای وضعیت 200 را استخراج و بر اساس تعداد تکرار مرتب کند؛ البته شماره ستون به قالب دقیق لاگ بستگی دارد.
۱۷. پیدا کردن فایلها با find
دستور find برای جستوجوی فایلها و پوشهها در سیستم استفاده میشود.
جستوجو بر اساس نام
find . -name "*.log"
جستوجوی بدون حساسیت به حروف:
find . -iname "*.log"
جستوجو فقط در فایلها
find /var/log -type f -name "*.log"
جستوجو فقط در پوشهها
find /var/www -type d -name "cache"
جستوجو بر اساس اندازه
فایلهای بزرگتر از ۱۰۰ مگابایت:
find /var -type f -size +100M
جستوجو بر اساس زمان تغییر
فایلهایی که در ۲۴ ساعت اخیر تغییر کردهاند:
find . -type f -mtime -1
اجرای دستور روی نتایج
find . -type f -name "*.tmp" -exec rm -f {} \;
ساختار {} با مسیر هر فایل جایگزین میشود.
روش سریعتر با xargs
find . -type f -name "*.log" -print0 \
| xargs -0 grep -n "ERROR"
استفاده از -print0 و -0 باعث میشود نام فایلهایی که فاصله یا کاراکترهای خاص دارند نیز بهدرستی پردازش شوند.
۱۸. سناریوی عملی اول: پیدا کردن خطاهای پرتکرار
فرض کنید فایل لاگ برنامه در مسیر زیر قرار دارد:
/var/log/app/application.log
برای پیدا کردن خطاها:
grep -i "error" /var/log/app/application.log
برای شمارش خطاها:
grep -i "error" /var/log/app/application.log | wc -l
برای استخراج متن خطا، مرتبسازی و نمایش موارد پرتکرار:
grep -i "error" /var/log/app/application.log \
| sort \
| uniq -c \
| sort -nr \
| head
اگر لاگ چند فایل دارد:
find /var/log/app -type f -name "*.log" -print0 \
| xargs -0 grep -i "error"
۱۹. سناریوی عملی دوم: پیدا کردن IPهای پرتکرار
در بسیاری از لاگهای وب، IP کاربر در ستون اول قرار دارد:
awk '{print $1}' access.log \
| sort \
| uniq -c \
| sort -nr \
| head -n 10
این دستور:
IPها را استخراج میکند.
آنها را مرتب میکند.
تعداد تکرار هر IP را میشمارد.
بر اساس تعداد، مرتبسازی معکوس انجام میدهد.
ده مورد اول را نمایش میدهد.
برای تحلیل لاگ واقعی، همیشه ابتدا قالب فایل را بررسی کنید:
head -n 3 access.log
نباید بدون شناخت ساختار لاگ، شماره ستونها را قطعی فرض کرد.
۲۰. سناریوی عملی سوم: پیدا کردن فایلهای حجیم
برای مشاهده فایلهای بزرگ در یک مسیر:
find /var -type f -printf '%s %p\n' \
| sort -nr \
| head -n 20
خروجی حجم را به بایت نمایش میدهد. برای تبدیل بهتر به واحدهای خوانا میتوان از ابزارهایی مانند numfmt استفاده کرد:
find /var -type f -printf '%s %p\n' \
| sort -nr \
| head -n 20 \
| numfmt --field=1 --to=iec
پیش از حذف هر فایلی، مسیر، مالکیت و کاربرد آن را بررسی کنید:
ls -lh /path/to/file
file /path/to/file
هرگز فایلهای سیستمی یا لاگهای فعال را بدون شناخت سرویس مربوطه حذف نکنید.
۲۱. نکات مهم هنگام استفاده از Pipe
۲۱.۱. خروجی خطا همیشه وارد Pipe نمیشود
در دستور زیر:
command | grep "text"
به صورت پیشفرض فقط stdout وارد Pipe میشود و stderr همچنان روی ترمینال باقی میماند.
برای وارد کردن خطا به Pipe:
command 2>&1 | grep "text"
یا در Bash:
command |& grep "text"
۲۱.۲. از tee برای مشاهده و ذخیره همزمان استفاده کنید
دستور tee خروجی را هم روی صفحه نمایش میدهد و هم در فایل ذخیره میکند:
command | tee output.log
افزودن به فایل:
command | tee -a output.log
مثال:
systemctl status nginx | tee nginx-status.txt
این روش در گزارشگیری و عیبیابی بسیار کاربردی است.
۲۲. پروژه تمرینی این قسمت
یک فایل به نام server.log بسازید:
cat > server.log <<'EOF'
INFO user=ali action=login status=success
ERROR user=sara action=upload status=failed
INFO user=reza actionlogin status=success
ERROR user user=sara action=upload status=failed
WARNING user=ali action=download status=slow
ERROR user=ali action=login status=failed
EOF
اکنون تمرینهای زیر را انجام دهید:
تمرین اول: نمایش خطاها
grep "ERROR" server.log
تمرین دوم: شمارش خطاها
grep "ERROR" server.log | wc -l
تمرین سوم: استخراج نام کاربران دارای خطا
grep "ERROR" server.log | awk -F'user=' '{print $2}' | awk '{print $1}'
تمرین چهارم: شمارش خطا بر اساس کاربر
grep "ERROR" server.log \
| sed 's/.*user=//' \
| awk '{print $1}' \
| sort \
| uniq -c \
| sort -nr
تمرین پنجم: ذخیره گزارش
grep "ERROR" server.log \
| tee error-report.txt
۲۳. نکات امنیتی و حرفهای
هنگام کار با دستورات پردازش فایلها، نکات زیر را رعایت کنید:
پیش از استفاده از
sed -iنسخه پشتیبان بگیرید.قبل از اجرای
rmنتیجهfindرا بررسی کنید.از اجرای مستقیم دستورات خطرناک روی مسیرهای سیستمی خودداری کنید.
مسیرها را تا حد امکان بهصورت کامل و دقیق بنویسید.
هنگام کار با فایلهایی که نام آنها فاصله دارد، از کوتیشن استفاده کنید:
cat "my log file.txt"
برای نام فایلهای نامطمئن، از
find -print0وxargs -0استفاده کنید.
خروجی دستورات مدیریتی را در فایل گزارش ذخیره کنید.
روی سرور واقعی، ابتدا دستورات را در محیط آزمایشی اجرا کنید.
جمعبندی قسمت دوم
در این قسمت یاد گرفتیم که خط فرمان لینوکس فقط مجموعهای از دستورات جداگانه نیست؛ بلکه یک سیستم ترکیبی قدرتمند است. با اتصال ابزارهای کوچک به وسیلهی Pipe میتوانیم عملیات پیچیدهای مانند تحلیل لاگ، استخراج داده، شناسایی خطاها و تهیه گزارش را تنها با چند دستور انجام دهیم.
مهمترین مفاهیمی که آموختیم:
stdin،stdoutوstderrهدایت خروجی با
>و>>هدایت خطا با
2>استفاده از
/dev/nullترکیب دستورات با
|جستوجو با
grepمرتبسازی با
sortحذف تکرارها با
uniqشمارش با
wcپردازش ستونها با
cutوawkویرایش جریان متنی با
sedجستوجوی فایلها با
find
قسمت بعدی
در قسمت سوم وارد دنیای واقعی Bash Scripting میشویم و یاد میگیریم:
یک اسکریپت Bash چگونه ساخته میشود؟
Shebang چیست؟
متغیرها چگونه تعریف میشوند؟
آرگومانهای خط فرمان چه کاربردی دارند؟
شرطها و حلقهها چگونه نوشته میشوند؟
چگونه اولین ابزار اتوماسیون خود را بسازیم؟
