در قلب فلسفهی یونیکس، مفهوم جریانهای داده (Data Streams) قرار دارد. تقریباً همهی دستورات خط فرمان، ورودی خود را از یک منبع میخوانند، پردازش میکنند و خروجی خود را به یک مقصد میفرستند. Pipes و Redirections به شما این قدرت را میدهند که این جریانهای داده را به هر شکلی که میخواهید، هدایت کنید و دستورات را به هم متصل کنید تا کارهای پیچیدهای با ترکیب ابزارهای ساده انجام دهید.
Standard Input, Standard Output, Standard Error
هر برنامهای در محیط یونیکس، سه جریان داده (Data Stream) استاندارد دارد که توسط سیستمعامل برای آن باز میشوند. این جریانها، راههای اصلی ارتباط برنامه با محیط اطراف خود هستند.
| جریان | نام | شمارهی فایل (File Descriptor) | توضیح |
|---|---|---|---|
| Standard Input | stdin | 0 | ورودی استاندارد. جایی که برنامه دادههای ورودی را از آن میخواند. بهطور پیشفرض، این صفحهکلید است. |
| Standard Output | stdout | 1 | خروجی استاندارد. جایی که برنامه نتایج عادی خود را مینویسد. بهطور پیشفرض، این صفحهنمایش است. |
| Standard Error | stderr | 2 | خطای استاندارد. جایی که برنامه پیامهای خطا را مینویسد. بهطور پیشفرض، این نیز صفحهنمایش است. |
نکتهی کلیدی: تفاوت
stdoutوstderrدر این است کهstdoutبرای خروجی دادهی اصلی برنامه است، در حالی کهstderrبرای پیامهای خطا و هشدار طراحی شده است. این تفاوت به شما اجازه میدهد که خروجی عادی را به یک فایل بفرستید و خطاها را جداگانه مدیریت کنید (مثلاً آنها را در ترمینال ببینید یا به فایل خطا بفرستید).
برای درک بهتر، این دستور را در نظر بگیرید:
ls /exists /not-exists
-
stdout: لیست فایلهای موجود در/existsرا نمایش میدهد. -
stderr: پیام خطایcannot access '/not-exists': No such file or directoryرا نمایش میدهد.
Pipe (|)
Pipe یا لوله یکی از قدرتمندترین مفاهیم در محیط خط فرمان است. نماد آن | (خط عمودی) است. وظیفهی Pipe این است که خروجی استاندارد (stdout) یک دستور را بگیرد و آن را بهعنوان ورودی استاندارد (stdin) دستور بعدی متصل کند.
به عبارت دیگر، Pipe به شما اجازه میدهد که خروجی یک برنامه را بدون ذخیرهسازی در فایل، مستقیماً به برنامهی بعدی بدهید.
ساختار کلی:
command1 | command2
مثالها
-
فیلتر کردن خروجی
lsباgrep:ls -la | grep ".txt"
خروجی
ls -la(لیست تمام فایلها) را بهgrepمیدهیم تا فقط خطوطی که شامل.txtهستند را فیلتر کند. -
شمارش تعداد فایلهای یک دایرکتوری:
ls -1 | wc -l
ls -1هر فایل را در یک خط جداگانه لیست میکند وwc -lتعداد خطوط (یعنی تعداد فایلها) را شمارش میکند. -
نمایش ۵ دستور پرکاربرد اخیر از تاریخچه:
history | tail -5
-
چندین Pipe پشت سر هم (زنجیرهای):
ps aux | grep "nginx" | grep -v "grep" | wc -l
-
ps aux: لیست تمام فرآیندها. -
grep "nginx": فقط فرآیندهای مربوط به Nginx را نگه میدارد. -
grep -v "grep": خود دستورgrepرا از لیست حذف میکند. -
wc -l: تعداد فرآیندهای باقیمانده را شمارش میکند.
-
-
مرتبسازی و مشاهدهی صفحهبهصفحه:
cat bigfile.txt | sort | uniq | less
-
cat bigfile.txt: محتوای فایل را میخواند. -
sort: خطوط را مرتب میکند. -
uniq: خطوط تکراری را حذف میکند. -
less: خروجی را صفحهبهصفحه نمایش میدهد.
-
نکته: Pipe فقط
stdoutرا به دستور بعدی میفرستد. اگر میخواهیدstderrرا نیز به لوله بفرستید، باید آن را بهstdoutهدایت کنید (در بخش2>&1توضیح داده شده است).
Output Redirection (>)
نماد > (بیشتر از) برای هدایت خروجی استاندارد (stdout) به یک فایل استفاده میشود. این عمل بهعنوان Redirection یا «بازنویسی مسیر» شناخته میشود. اگر فایل مقصد از قبل وجود داشته باشد، محتوای آن کاملاً بازنویسی (Overwrite) میشود.
ساختار کلی:
command > output.txt
مثالها
-
ذخیرهی خروجی
lsدر یک فایل:ls -la > filelist.txt
محتوای
filelist.txtبا خروجیls -laجایگزین میشود. -
ذخیرهی پیام
echoدر یک فایل:echo "Hello World" > message.txt
-
ذخیرهی فقط
stdout(و نهstderr):ls /exists /not-exists > output.txt
فقط خروجی عادی (لیست
/exists) درoutput.txtذخیره میشود و پیام خطا همچنان روی صفحهنمایش دیده میشود.
هشدار: استفاده از
>باعث میشود که محتوای قبلی فایل از بین برود. اگر به فایل موجود اهمیت میدهید، از>>استفاده کنید.
Append Redirection (>>)
نماد >> (بیشتر از دو بار) برای افزودن (Append) خروجی استاندارد به انتهای یک فایل استفاده میشود. اگر فایل وجود نداشته باشد، مانند > عمل میکند و آن را ایجاد میکند.
ساختار کلی:
command >> output.txt
مثالها
-
افزودن یک خط به انتهای فایل:
echo "New line" >> log.txt
-
افزودن خروجی چند دستور به یک فایل:
date >> log.txt echo "Backup completed" >> log.txt ls -la >> log.txt
هر سه خروجی پشت سر هم به
log.txtاضافه میشوند.
Input Redirection (<)
نماد < (کمتر از) برای هدایت محتوای یک فایل بهعنوان ورودی استاندارد (stdin) یک دستور استفاده میشود. به عبارت دیگر، به جای اینکه کاربر از صفحهکلید تایپ کند، دستور محتوای فایل را میخواند.
ساختار کلی:
command < input.txt
مثالها
-
ارسال محتوای یک فایل به
grep:grep "error" < log.txt
معادل
grep "error" log.txtاست. -
شمارش خطوط یک فایل با
wc:wc -l < myfile.txt
فقط تعداد خطوط را نمایش میدهد (برخلاف
wc -l myfile.txtکه نام فایل را هم چاپ میکند). -
استفاده از
sortبا ورودی از فایل:sort < unsorted.txt
-
استفاده در اسکریپتنویسی برای خواندن فایل:
while read line; do echo "Line: $line" done < data.txt
یک حلقهی
whileکه هر خط ازdata.txtرا میخواند و پردازش میکند.
Error Redirection (2>)
برای هدایت خطای استاندارد (stderr) به یک فایل، از نماد 2> استفاده میشود. عدد 2 شمارهی فایل (File Descriptor) مربوط به stderr است.
ساختار کلی:
command 2> error.log
مثالها
-
ذخیرهی خطاها در یک فایل (و نمایش خروجی عادی روی صفحه):
ls /exists /not-exists 2> errors.txt
-
خروجی عادی (لیست
/exists) روی صفحهنمایش دیده میشود. -
پیام خطا (
cannot access '/not-exists') در فایلerrors.txtذخیره میشود.
-
-
ذخیرهی خطاها و نادیده گرفتن آنها (ارسال به
/dev/null):find / -name "myfile" 2> /dev/null
تمام پیامهای خطا (مثل
Permission denied) به/dev/nullفرستاده میشوند و نادیده گرفته میشوند. خروجی عادی (یعنی مسیر فایلهای پیدا شده) روی صفحه نمایش داده میشود. -
افزودن خطاها به انتهای یک فایل (با
2>>):command 2>> error.log
Redirecting stdout and stderr
گاهی نیاز دارید که هم stdout و هم stderr را به یک فایل بفرستید یا هر دو را به یک لوله (Pipe) بدهید. برای این کار از ترکیب شمارههای فایل استفاده میشود.
۱. ارسال stdout و stderr به دو فایل جداگانه
command > output.txt 2> error.txt
۲. ارسال هر دو (stdout و stderr) به یک فایل
-
روش اول (با
2>&1):command > output.txt 2>&1
این دستور میگوید: «
stdoutرا بهoutput.txtبفرست (با>). بعدstderr(شماره ۲) را به همان جایی بفرست کهstdout(شماره ۱) در حال رفتن است (با2>&1).» چونstdoutبهoutput.txtهدایت شده،stderrنیز بهoutput.txtمیرود. -
روش دوم (با
&>که مختصرتر است):command &> output.txt
این روش کوتاهتر و معادل روش اول است.
-
روش سوم (افزودن به فایل با
&>>):command &>> output.txt
۳. ارسال هر دو (stdout و stderr) به یک Pipe
برای اینکه stderr نیز در یک لوله (Pipe) قرار گیرد، ابتدا باید آن را به stdout هدایت کنید:
command 2>&1 | grep "error"
مثالهای عملی
-
اجرای یک اسکریپت و ذخیرهی همهی خروجیها در یک فایل:
./myscript.sh > script.log 2>&1
-
اجرای یک دستور و دیدن خطاها همراه با خروجی عادی در یک
less:make 2>&1 | less
-
اجرای دستور و ارسال خروجی عادی به یک فایل و خطاها به فایل دیگر:
find / -name "*.conf" > found.txt 2> errors.txt
tee
دستور tee یکی از ابزارهای ظریف و بسیار کاربردی است. نام آن از شکل یک لولهی T شکل گرفته شده است. وظیفهی tee این است که ورودی استاندارد (stdin) خود را هم به خروجی استاندارد (stdout) بفرستد و هم در یک یا چند فایل بنویسد.
به عبارت دیگر، tee به شما اجازه میدهد که خروجی یک دستور را همزمان هم روی صفحه ببینید و هم در یک فایل ذخیره کنید.
ساختار کلی:
command | tee [option] [file...]
مثالها
-
نمایش خروجی
lsروی صفحه و ذخیرهی آن در فایل:ls -la | tee filelist.txt
خروجی
ls -laهم روی صفحه نمایش داده میشود و هم درfilelist.txtذخیره میشود. -
افزودن به یک فایل (با گزینه
-aبرای Append):echo "New log entry" | tee -a log.txt
با
-a، خروجی به انتهای فایل اضافه میشود و محتوای قبلی از بین نمیرود. -
نوشتن در چند فایل بهطور همزمان:
ls -la | tee file1.txt file2.txt file3.txt
خروجی هم روی صفحه نمایش داده میشود و هم در هر سه فایل ذخیره میشود.
-
استفاده با
sudoبرای نوشتن در فایلهای محافظتشده:echo "new config" | sudo tee /etc/myapp/config.conf
چون
teeیک دستور مستقل است، میتواند باsudoاجرا شود و در فایلهایی که فقط root مجوز نوشتن دارد، بنویسد. این یک روش استاندارد و امنتر ازsudo echo >است. -
ذخیرهی خروجی و خطاها با استفاده از
tee:command 2>&1 | tee output.log
-
ذخیرهی خروجی در یک فایل و ارسال به دستور بعدی (Pipeline):
dmesg | tee kernel.log | grep "error"
خروجی
dmesgهم درkernel.logذخیره میشود، هم بهgrepفرستاده میشود تا خطاها را فیلتر کند و نمایش دهد.
خلاصه و جدول مقایسهی Redirection ها
| عملگر | نام | کاربرد | مثال |
|---|---|---|---|
| | Pipe | ارسال stdout دستور قبلی به stdin دستور بعدی | ls | grep txt |
> | Output Redirection | ذخیرهی stdout در یک فایل (بازنویسی) | ls > list.txt |
>> | Append Redirection | افزودن stdout به انتهای یک فایل | ls >> list.txt |
< | Input Redirection | خواندن stdin از یک فایل | grep error < log.txt |
2> | Error Redirection | ذخیرهی stderr در یک فایل (بازنویسی) | cmd 2> err.log |
2>> | Append Error Redirection | افزودن stderr به انتهای یک فایل | cmd 2>> err.log |
2>&1 | Merge stderr to stdout | ارسال stderr به همان جایی که stdout میرود | cmd > out 2>&1 |
&> | All Redirection | ارسال هر دو (stdout و stderr) به یک فایل | cmd &> all.log |
&>> | Append All Redirection | افزودن هر دو به انتهای یک فایل | cmd &>> all.log |
tee | Tee | نمایش روی صفحه و ذخیره در فایل (بهطور همزمان) | ls | tee list.txt |
ترتیب اهمیت و اولویت
هنگام ترکیب چند عملگر، ترتیب آنها مهم است. برای مثال:
command > output.txt 2>&1
این دستور stdout را به output.txt میفرستد و سپس stderr را به همان جایی که stdout میرود (یعنی output.txt) هدایت میکند.
اگر ترتیب را عوض کنید:
command 2>&1 > output.txt
stderr ابتدا به stdout (که هنوز به صفحهنمایش متصل است) هدایت میشود و سپس stdout به output.txt میرود. در نتیجه، خطاها روی صفحه نمایش داده میشوند و فقط خروجی عادی در فایل ذخیره میشود.