کتابخانه‌ی استاندارد · سیستم و ابزار

پوسته os/shell

اجرای فرمان و گرفتن کد خروج، خروجی و خطا با هم.

واردسازی سیستم عامل.پوسته

بسته‌ی پوسته فرمانی را اجرا می‌کند، منتظر پایانش می‌ماند و همه‌ی نتیجه را یک‌جا در یک نتیجه فرمان برمی‌گرداند: کد خروج، خروجی استاندارد و خروجی خطا. لایه‌ای نازک روی فرآیند است (شروع با ضبط، انتظار، خواندن، پاکسازی) برای حالت رایجی که هر سه را می‌خواهید و لازم نیست چیزی را هم‌زمان اجرا کنید. در مقایسه با اجرا با خروجی در بسته‌ی سیستم عامل، خروجی خطا را هم می‌گیرد و با اجرا آرگومان‌ها را بدون پوسته می‌رساند.

تفاوت سه تابع در این است که چه کسی فرمان را می‌خواند:

تابعپوستهآرگومان‌هانتیجه
اجرا(برنامه، آرگومان‌ها)نداردیک وکتور، دقیقاً همان‌طور که هستنتیجه فرمان؛ اگر برنامه اجرا نشود کد -۱
اجرا با متن فرمان(فرمان)نداردمتن، شکسته با تک‌فاصلهنتیجه فرمان
اجرای پوسته(فرمان)/bin/sh -c، یا cmd در ویندوزپوسته تجزیه‌شان می‌کندفقط کد خروج؛ خروجی روی صفحه می‌رود

اجرا با متن فرمان فرمان را فقط با فاصله می‌شکند و پوسته‌ای در کار نیست: لوله (|)، هدایت (>)، نقل‌قول و تب کار نمی‌کنند. برای این‌ها sh -c را با اجرا صدا بزنید، مثل نخستین نمونه.

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

لوله و هدایت خروجی با sh

برای یک لوله (pipeline)، کل اسکریپت را به sh -c بدهید. اگر این کار را در تابع کوچکی بپیچید، فراخوانی‌ها کوتاه می‌مانند و نتیجه هنوز هر سه بخش را دارد: کد آخرین فرمان، خروجی و خروجی خطا.

os-shell-guide-pipe.salam
واردسازی سیستم عامل.پوسته

تابع اسکریپت(متن: رشته): پوسته.نتیجه فرمان:
    ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
    دیرکن آرگ.آزادکن()
    آرگ.بیفزا("-c")
    آرگ.بیفزا(متن)
    برگشت پوسته.اجرا("sh"، آرگ)
پایان

تابع ریشه:
    ن := اسکریپت("printf 'سرخ\\nآبی\\nسرخ\\nسبز\\nسرخ\\n' | sort | uniq -c | sort -rn | head -n 1")
    اگر ن.کد != ۰:
        سرچاپ "لوله شکست خورد:"، ن.خروجی خطا
        برگشت ۰
    پایان
    سرچاپ "پرتکرارترین:"، ن.خروجی.پیراست()
    ن۲ := اسکریپت("echo ذخیره شد > یادداشت.txt && cat یادداشت.txt && rm یادداشت.txt")
    سرچاپ ن۲.کد، ن۲.خروجی.پیراست()
پایان
خروجیپرتکرارترین: 3 سرخ 0 ذخیره شد

فقط متنی را که خودتان نوشته‌اید در چنین اسکریپتی بگذارید. مقدارهایی که از کاربر می‌آیند باید آرگومان‌های جدای اجرا باشند، جایی که هیچ پوسته‌ای آن‌ها را نمی‌خواند.

کار با خروجی، سطر به سطر

بیشتر ابزارها هر چیز را در یک سطر چاپ می‌کنند. خروجی را بپیرایید، با خط تازه بشکنید و هر سطر را جدا بررسی کنید. برنامه‌ی زیر پوشه‌ی جاری را با ls فهرست می‌کند و پرونده‌های CSV را جدا می‌کند.

os-shell-guide-lines.salam
واردسازی سیستم عامل
واردسازی سیستم عامل.پوسته

تابع ریشه:
    سیستم عامل.نوشتن پرونده("خرید.csv"، "1,2\n")
    سیستم عامل.نوشتن پرونده("فروش.csv"، "3,4\n")
    سیستم عامل.نوشتن پرونده("یادداشت.txt"، "سلام\n")
    ن := پوسته.اجرا با متن فرمان("ls")
    ناپایا شمار := ۰
    هر نام در ن.خروجی.پیراست().بشکاف("\n"):
        اگر نام.ختم با(".csv"):
            سرچاپ "پیدا شد:"، نام
            شمار += ۱
        پایان
    پایان
    سرچاپ شمار، "پرونده‌ی csv"
    سیستم عامل.حذف("خرید.csv")
    سیستم عامل.حذف("فروش.csv")
    سیستم عامل.حذف("یادداشت.txt")
پایان
خروجیپیدا شد: خرید.csv پیدا شد: فروش.csv 2 پرونده‌ی csv

برای فهرست کردن پرونده‌ها در یک برنامه‌ی واقعی، پوشه یا سیستم عامل بهترند: به برنامه‌ی بیرونی نیاز ندارند و روی ویندوز هم یکسان کار می‌کنند. اجرای یک ابزار وقتی درست است که کار اصلی را خود آن ابزار انجام دهد، مثل git یا ffmpeg.

بررسی این‌که فرمان کار کرد یا نه

فرمانی که شکست می‌خورد کدی غیر صفر برمی‌گرداند و معمولاً علتش را در خروجی خطا می‌گوید. اول code را بررسی کنید؛ err برای پیامی است که نشان می‌دهید یا ثبت می‌کنید. برنامه‌ای که اصلاً پیدا نشود با کد -۱ برمی‌گردد و برنامه‌ی شما را متوقف نمی‌کند، و دلیلش در خطا ثبت می‌شود.

os-shell-guide-check.salam
واردسازی سیستم عامل.پوسته

تابع آزمودن(فرمان: رشته):
    ن := پوسته.اجرا با متن فرمان(فرمان)
    اگر ن.کد == ۰:
        سرچاپ "موفق:"، فرمان
        برگشت
    پایان
    سرچاپ "ناموفق:"، فرمان، "با کد"، ن.کد
    سرچاپ "  پیام خطا دارد:"، ن.خروجی خطا.طول() > ۰
پایان

تابع ریشه:
    آزمودن("ls .")
    آزمودن("ls no-such-folder")
    سرچاپ "کد خروج false:"، پوسته.اجرای پوسته("false")
پایان
خروجیموفق: ls . ناموفق: ls no-such-folder با کد 2 پیام خطا دارد: true کد خروج false: 1

کدها و پیام‌های دقیق مال هر ابزارند و از سیستمی به سیستم دیگر فرق می‌کنند: ls برای پوشه‌ی ناموجود روی لینوکس ۲ و روی مک ۱ برمی‌گرداند. جز وقتی که ابزار کدهایش را مستند کرده، فقط صفر یا غیر صفر بودن را بسنجید.

اجرا با متن فرمان نقل‌قول را نمی‌فهمد

اجرا با متن فرمان فقط با فاصله می‌شکند، پس نقل‌قول‌ها در متن می‌مانند و عبارت نقل‌قول‌شده باز هم دو آرگومان می‌شود. وقتی آرگومانی فاصله دارد، اجرا را با آرگومان‌ها در یک وکتور به کار ببرید یا بگذارید sh -c نقل‌قول‌ها را بخواند.

os-shell-guide-quote.salam
واردسازی سیستم عامل.پوسته

تابع ریشه:
    ن := پوسته.اجرا با متن فرمان("echo 'دو واژه'")
    سرچاپ "اجرا با متن فرمان:"، ن.خروجی.پیراست()
    ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
    دیرکن آرگ.آزادکن()
    آرگ.بیفزا("دو واژه")
    ن۲ := پوسته.اجرا("echo"، آرگ)
    سرچاپ "اجرا:"، ن۲.خروجی.پیراست()
    ناپایا اسکریپت := وکتور {} برگردان وکتور<رشته>
    دیرکن اسکریپت.آزادکن()
    اسکریپت.بیفزا("-c")
    اسکریپت.بیفزا("echo 'دو واژه'")
    ن۳ := پوسته.اجرا("sh"، اسکریپت)
    سرچاپ "sh -c:"، ن۳.خروجی.پیراست()
پایان
خروجیاجرا با متن فرمان: 'دو واژه' اجرا: دو واژه sh -c: دو واژه
نیازچه به کار ببرید
فرمانی ساده بدون نقل‌قول یا نویسه‌ی خاصاجرا با متن فرمان
آرگومان‌های فاصله‌دار یا متن کاربراجرا با یک وکتور
لوله، هدایت خروجی، &&اجرا("sh"، ...) با -c
فقط کد خروج، با خروجی مستقیم روی صفحهاجرای پوسته
شروع بدون انتظار، یا متوقف کردن برنامهفرآیند

گونه‌ها

نتیجه فرمان CmdResult

ساختار نتیجه فرمان
نتیجه‌ی یک فرمان.
نامانگلیسیگونهتوضیح
کدcodeصحیح = 0کد خروج؛ صفر یعنی موفق، ۱۲۸ به‌علاوه‌ی شماره‌ی علامت اگر علامتی آن را تمام کرده باشد، و -۱ اگر برنامه اجرا نشده باشد.
خروجیoutرشته = ""خروجی استاندارد، همراه با خط‌های تازه؛ در نخستین بایت صفر تمام می‌شود.
خروجی خطاerrرشته = ""خروجی خطا.
os-shell-Run.salam
واردسازی سیستم عامل.پوسته

تابع ریشه:
    ناپایا آرگ := وکتور {} برگردان وکتور<رشته>
    دیرکن آرگ.آزادکن()
    آرگ.بیفزا("-n")
    آرگ.بیفزا("سلام")
    ن := پوسته.اجرا("echo"، آرگ)
    سرچاپ ن.کد، "[" + ن.خروجی + "]"
    ن۲ := پوسته.اجرا با متن فرمان("echo یک دو سه")
    سرچاپ ن۲.کد، "[" + ن۲.خروجی + "]"
    ناپایا آرگ۲ := وکتور {} برگردان وکتور<رشته>
    دیرکن آرگ۲.آزادکن()
    آرگ۲.بیفزا("-c")
    آرگ۲.بیفزا("echo خطا >&2; exit 3")
    ن۳ := پوسته.اجرا("sh"، آرگ۲)
    سرچاپ ن۳.کد، "[" + ن۳.خروجی خطا + "]"
    سرچاپ پوسته.اجرای پوسته("true")، پوسته.اجرای پوسته("false") != ۰
پایان
خروجی0 [سلام] 0 [یک دو سه ] 3 [خطا ] 0 true

تابع‌ها

اجرا Run

تابع اجرا(command: رشته، args: وکتور<رشته>): نتیجه فرمان
برنامه را با آرگومان‌های جدا اجرا می‌کند (بدون پوسته، با جستجوی نام در PATH)، منتظر می‌ماند تا تمام شود و کد، خروجی و خروجی خطا را برمی‌گرداند. اگر اجرا نشود کد -۱.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-shell-Run.salam

اجرا با متن فرمان Exec

تابع اجرا با متن فرمان(command: رشته): نتیجه فرمان
متن فرمان را با تک‌فاصله به برنامه و آرگومان‌ها می‌شکند و با اجرا اجرا می‌کند؛ بدون پوسته. نقل‌قول‌ها نویسه‌ی معمولی می‌مانند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-shell-Run.salam

اجرای پوسته System

تابع اجرای پوسته(command: رشته): صحیح
فرمان را در پوسته‌ی واقعی (/bin/sh -c، یا cmd در ویندوز) اجرا می‌کند و فقط کد خروج را برمی‌گرداند؛ خروجی مستقیم چاپ می‌شود. اگر پوسته راه نیفتد ۱۲۷.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: os-shell-Run.salam