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

103.4 استفاده از جریان‌ها، لوله‌ها و تغییر مسیرها

اهداف

پس از مطالعه این فصل باید بتوانید:

  • ورودی، خروجی و خطای استاندارد را تغییر مسیر دهید.
  • خروجی یک دستور را به ورودی دستور دیگری لوله کنید.
  • خروجی یک دستور را به عنوان آرگومان به دستور دیگری ارسال کنید.
  • خروجی را هم به stdout و هم به یک فایل ارسال کنید.

کلیدواژه‌ها

tee, xargs


مقدمه

وزن: 4

کاندیداها باید بتوانند جریان‌ها را تغییر مسیر دهند و به طور کارآمد داده‌های متنی را پردازش کنند. وظایف شامل تغییر مسیر ورودی استاندارد، خروجی استاندارد و خطای استاندارد، لوله کردن خروجی یک دستور به ورودی دستور دیگر، استفاده از خروجی یک دستور به عنوان آرگومان برای دستور دیگر و ارسال خروجی به stdout و یک فایل است.

ویژگی‌های ذکر شده به ما کمک می‌کنند تا ورودی/خروجی دستورات را کنترل کنیم و کارهایی مانند ذخیره خروجی یک دستور در فایل، گرفتن ورودی یک دستور از دستور دیگر یا جدا کردن خروجی نرمال از خطاها انجام دهیم. ما قبلاً از آنها در بخش‌های قبلی استفاده کرده‌ایم اما بیایید درک عمیق‌تری از آنها داشته باشیم.

تغییر مسیر ورودی/خروجی استاندارد

در یک سیستم لینوکس، اکثر shellها از جریان‌ها برای ورودی و خروجی استفاده می‌کنند. این جریان‌ها می‌توانند از (و به سمت) چیزهای مختلفی مانند صفحه کلید، دستگاه‌های بلوکی (هارد، USB، ...)، فایل‌ها و ... باشند.

ما سه جریان استاندارد مختلف داریم:

  • STDIN: جریان ورودی استاندارد که ورودی را به یک دستور ارائه می‌دهد.
  • STDOUT: جریان خروجی استاندارد که خروجی یک دستور را شامل می‌شود.
  • STDERR: جریان خطای استاندارد که خروجی خطای یک دستور را شامل می‌شود.

شماره‌گذاری 0، 1 و 2 به ترتیب به STDIN، STDOUT و STDERR اشاره دارد. به عنوان مثال، اگر بخواهید خطا را تغییر مسیر دهید، می‌توانید از 2> استفاده کنید و STDERR تغییر مسیر داده می‌شود.

اینها تغییر مسیرهای دیگری هستند که می‌توانید استفاده کنید:

عملگر کاربرد
> خروجی STDOUT را به یک فایل تغییر مسیر می‌دهد؛ اگر وجود دارد، بازنویسی می‌کند
>> خروجی STDOUT را به یک فایل تغییر مسیر می‌دهد؛ اگر وجود دارد، اضافه می‌کند
2> STDERR را به یک فایل تغییر مسیر می‌دهد؛ اگر وجود دارد، بازنویسی می‌کند
2>> STDERR را به یک فایل تغییر مسیر می‌دهد؛ اگر وجود دارد، اضافه می‌کند
&> هم STDOUT و هم STDERR را تغییر مسیر می‌دهد؛ اگر وجود دارد، بازنویسی می‌کند
&>> هم STDOUT و هم STDERR را تغییر مسیر می‌دهد؛ اگر وجود دارد، اضافه می‌کند
< STDIN را از یک فایل تغییر مسیر می‌دهد
<> STDIN را از فایل تغییر مسیر می‌دهد و STDOUT را به آن ارسال می‌کند

مثال‌ها

$ ls
bob
jack
jadi
linus
sara
who_uses_what.txt

$ ls x*
ls: x*: No such file or directory

$ ls j*
jack
jadi

$ ls j* x* > output 2> errors

$ cat output
jack
jadi

$ cat errors
ls: x*: No such file or directory

همچنین می‌توان از &1 و &2 و &0 برای اشاره به هدف STDOUT، STDERR و STDIN استفاده کرد. در این حالت ls > file1 2>&1 به معنای تغییر مسیر خروجی به file1 و ارسال stderr به همان جایی که stdout است (file1) است.

توجه داشته باشید! ls 2>&1 > file1 به معنای ارسال stderr به مکان فعلی stdout (ترمینال) و سپس تغییر stdout به file1 است.

ارسال به null

در لینوکس دستگاه /dev/null مانند یک چاه کار می‌کند. می‌توانید هر چیزی را به آن ارسال کنید و بدون هیچ بار اضافی روی سیستم شما ناپدید می‌شود. بنابراین معمول است که بگوییم:

$ ls j* x* > file1
ls: x*: No such file or directory

$ ls j* x* > file1 2>/dev/null

$ cat file1
jack
jadi

Here-documents

بسیاری از shellها here-documents (همچنین here-docs نامیده می‌شود) را به عنوان راهی برای ورودی دارند. از << و یک WORD استفاده می‌کنید و سپس هر چیزی که وارد می‌کنید تا زمانی که WORD را به تنهایی در یک خط وارد کنید، به عنوان stdin در نظر گرفته می‌شود.

$ tr ' ' '.' << END_OF_DATA
> this is a line
> and then this
>
> we'll still type
> and,
> done!
> END_OF_DATA
this.is.a.line
and.then.this
we.'ll.still.type
and,
done!

Here-Documents بسیار مفید هستند اگر اسکریپت‌ها و وظایف خودکار می‌نویسید.

لوله‌ها

با لوله (|) می‌توانید STDOUT، STDIN و STDERR را بین چندین دستور در یک خط فرمان لوله کنید. وقتی command1 | command2 انجام می‌دهید؛ command1 اجرا می‌شود اما STDOUT آن به عنوان STDIN به COMMAND2 تغییر مسیر داده می‌شود.

$ cat who_uses_what.txt
jadi,fedora
linux,fedora
bob,ubuntu
jack,arch
sara,fedora

$ cut -f2 -d, who_uses_what.txt | sed -e 's/ //g' | sort | uniq -c | sort -nr
      3 fedora
      1 ubuntu
      1 arch

اگر نیاز به شروع pipeline خود با محتویات یک فایل دارید، از cat filename | ... شروع کنید یا از < stdin redirect استفاده کنید.

لوله‌ها یکی از ویژگی‌های فوق‌العاده و شگفت‌انگیز در دنیای UNIX هستند. آنها به شما اجازه می‌دهند ابزارهای جدیدی با ترکیب ابزارهایی که کارهای اتمی انجام می‌دهند، ایجاد کنید. به عنوان مثال، این را بررسی کنید:

xargs

ابزار xargs رشته‌های جدا شده با space، tab، newline و end-of-file را از ورودی استاندارد می‌خواند و ابزار ارائه شده را با رشته‌ها به عنوان آرگومان‌های آن اجرا می‌کند.

$ ls
bob
file1
jadi
output
who_uses_what.txt
errors
jack
linus
sara

$ ls | xargs echo these are files:
these are files: bob errors file1 jack jadi linus output sara who_uses_what.txt

اگر دستور مشخص نکنید، echo به طور پیش‌فرض استفاده می‌شود.

یک سوئیچ رایج -I است. این مفید است اگر نیاز به عبور دادن آرگومان‌های stdin در وسط (یا حتی شروع) دستورات خود دارید. از آن به این صورت استفاده کنید: xargs -I SOMETHING echo here is SOMETHING end

$ cat who_uses_what.txt
jadi,fedora
linus,fedora
bob,ubuntu
jack,arch
sara,fedora

$ cat who_uses_what.txt | xargs -I DATA echo name is DATA is the choice.
name is jadi,fedora is the choice.
name is linus,fedora is the choice.
name is bob,ubuntu is the choice.
name is jack,arch is the choice.
name is sara,fedora is the choice.

دو سوئیچ مفید دیگر:

  1. -L 1 بر اساس newlineها تقسیم می‌کند
  2. -n 1 به xargs می‌گوید پس از دریافت 1 آرگومان، ابزار ارائه شده را فراخوانی کند.

tee

مشکل تغییر مسیر این است که نمی‌توانید پیشرفت دستورات خود را در همان ترمینال ببینید. ابزار tee این مشکل را حل می‌کند. اگر نیاز به دیدن خروجی روی صفحه و همچنین ذخیره آن در فایل دارید، tee دوست شماست. یک یا چند نام فایل بدهید و کار را انجام می‌دهد.

$ ls -1 | tee allfiles myfiles
bob
errors
file1
jack
jadi
linus
output
sara
who_uses_what.txt

$ cat allfiles myfiles
bob
errors
file1
jack
jadi
linus
output
sara
who_uses_what.txt
bob
errors
file1
jack
jadi
linus
output
sara
who_uses_what.txt

سوئیچ -a به فایل‌ها اضافه می‌کند اگر وجود داشته باشند.

اگر نیاز به ذخیره stderr نیز دارید، ابتدا آن را به stdout تغییر مسیر دهید.

نکات

  • همیشه از فضای کافی در اطراف عملگرها استفاده کنید.
  • برای ترکیب دستورات، از && و || استفاده کنید.
  • xargs برای پردازش لیست‌ها مفید است.
  • tee برای نظارت و ذخیره همزمان خروجی استفاده می‌شود.

تمرین‌ها

  1. خروجی دستور ls را به یک فایل تغییر مسیر دهید و خطاها را به فایل دیگری ارسال کنید.
  2. از لوله برای شمارش تعداد فایل‌ها در دایرکتوری استفاده کنید.
  3. از xargs برای اجرای یک دستور روی هر فایل در یک لیست استفاده کنید.
  4. از tee برای ذخیره خروجی یک دستور طولانی در فایل و نمایش آن روی صفحه استفاده کنید.
  5. یک here-document برای ارسال ورودی چند خطی به یک دستور ایجاد کنید.

خلاصه

در این فصل، یاد گرفتیم چگونه جریان‌های ورودی و خروجی را در لینوکس کنترل کنیم. تغییر مسیرها، لوله‌ها، xargs و tee ابزارهای قدرتمندی برای پردازش داده‌های متنی هستند. با تمرین این مفاهیم، می‌توانید وظایف پیچیده را به طور کارآمد انجام دهید.

نکات کلیدی برای آزمون

  • تغییر مسیر STDOUT، STDERR و STDIN (>, >>, 2>, &>, <، <>) و ترتیب آنها (مثلاً 2>&1)
  • استفاده از /dev/null برای دور ریختن خروجی‌ها
  • لوله‌کردن دستورات با | و ترکیب ابزارها برای پردازش داده‌ها
  • استفاده از xargs برای تبدیل STDIN به آرگومان‌ها و tee برای ذخیره و نمایش همزمان خروجی
  • here-documents (<<) برای ارسال ورودی چند خطی به دستورات