آموزش‌های خط فرمانی

این وبلاگ تلاش می‌کند گامی در حد بضاعت در جهت آموزش خط فرمان و اسکریپت‌نویسی پوسته گنو-لینوکس بردارد.

آموزش‌های خط فرمانی

این وبلاگ تلاش می‌کند گامی در حد بضاعت در جهت آموزش خط فرمان و اسکریپت‌نویسی پوسته گنو-لینوکس بردارد.

کمبودهای Bash


موارد معینی وجود دارد که در آن موارد BASH خیلی مناسب نیست. برخی وظایف هستند که شما نباید در bash انجام بدهید، مگر اینکه واقعاً، به درستی مجبور باشید. اغلب بهتر است برای انجام اکثر آن وظایف زبان دیگری را انتخاب کنید.

  1. سرعت: آیا ما واقعاً باید آن را بگوییم؟ Bash کُند است. اگر سرعت یک وجه‌التزامِ با اهمیت است، آنوقت ممکن است Bash بهترین انتخاب نباشد.

  2. حساب ممیز شناور: Bash فقط حساب اعداد صحیح دارد. از ‎bc(1)‎ یا در صورتیکه به محاسبه ممیز شناور نیاز دارید از AWK استفاده کنید.

  3. ساختمان داده‌ها: Bash نه رکوردهای سَبکِ پاسکال(ساخت‌های C-شکل) دارد، نه اشاره‌گر دارد. هر تلاشی برای ایجاد ساختمان داده‌های پیشرفته(پشته‌ها، صف‌ها، لیست‌های پیوندی، درختهای دو دویی...) باید با ترفندهای فوق‌العاده قدیمی انجام بشود.

  4. مدیریت پردازش برازنده: Bash مورد قابل قیاس با ‎select(2)‎ یا ‎poll(2)‎ ندارد. راهی برای وارد شدن به یک event loop وجود ندارد. اگر به نمونه فعال شونده در نتیجه رویدادها احتیاج دارید از سایر زبانهای برنامه‌نویسی استفاده نمایید. اکثر زبانهای شئ‌گرا برای انجام این وظایف مناسب‌تر هستند.

  5. تجزیه XML و HTML: (یا مشابه). برای انجام آن به طور صحیح، به ابزارها یا کتابخانه‌های خارجی نیاز دارید. از ‏xslt, tidy, xmlstarlet, پرل، یا برخی ابزارهای مناسب دیگر استفاده کنید.

  6. داده‌های باینری: Bash روشی برای ذخیره بایت تهی در یک متغیر ندارد، بنابراین داده‌های باینری یا باید رمزنگاری(و رمزگشایی) گردند، یا در یک فایل نگهداری شوند. همچنین نمی‌توانید بایت تهی را به عنوان یک شناسه به برنامه عبور بدهید، زیرا کرنل از رشته‌های C برای آنها استفاده می‌کند. تجزیه داده‌های باینری از یک فایل نیز مشکل ناچیزی نیست. به جای آن پرل یا C را امتحان کنید.

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

  8. تعیین نوع متغیر: Bash مانند اکثر زبانهای اسکریپت‌نویسی، به راستی از انواع متغیر نیرومند پشتیبانی نمی‌کند. متغیرها به سستی به عنوان ساده یا آرایه(بعلاوه آرایه‌های انجمنی در ‎bash 4‎)، با پشتیبانی جزئی برای عدد صحیح طبقه‌بندی می‌شوند. اما واقعاً، همه چیز یک رشته است.

  9. اعطای مجوزها: مجاز نمودن یک اسکریپت bash برای اجرا شدن به عنوان کاربر ارشد، می‌تواند دشوار باشد. در زبانهایی مانند C، پرل، و پایتون، شما در یک نقطه معین به آسانی می‌توانید امتیازات را اعطا کنید. در bash این یک مورد ترفندگونه است، زیرا در حالیکه می‌توانید su یا sudo را اجرا کنید، اینها برنامه‌های خارجی هستند -- تمام محیط اجرایی‌تان را از دست می‌دهید.

  10. Try/catch: برخی زبانهای برنامه‌نویسی به شما اجازه می‌دهند فرمانی را در یک بلوک ‎try ... catch‎ بسته‌بندی کنید. این امر فرمان را در نوعی "sandbox" تفسیر می‌کند، جایی که در آن خطاهایی که به طور معمول موجب یک انصراف می‌شدند، گرفتار(caught) می‌شوند، و ماشه اجرای کدِ نوعی مدیریت خطا کشیده می‌شود. Bash چیزی قابل قیاس با این مورد ندارد. هر کدِ bash که شما اجرا می‌کنید، کُد واقعی است.

  11. مدیریت استثناء: بسیاری از زبانهای برنامه‌نویسی دارای مفهومی از یک «استثناء» هستند، در اصل یک رویدادی که موقع وقوع انواع معینی از خطاها، محیطِ حینِ اجرا تولید می‌کند. Bash اینها را ندارد. Bash برای مدیریت خطا مدل C را به کار می‌برد: اجرای آن را به عهده شما می‌گذارد. شما نیاز دارید که نتیجه هر فرمان حساس در اسکریپت خود را کنترل نمایید. ( و خیر، ‎set -e‎ نیز پاسخ مناسب نیست.)

  12. توابع: توابع Bash دارای چند موضوع است:

    • برگشت کمیت‌ها: توابع Bash چیزی برگشت نمی‌دهند ، آنها فقط جریانهای خروجی فراهم می‌کنند. هر روش قابل‌قبولِ به چنگ آوردن آن خروجی و یا تخصیص آن به یک متغیر یا عبور دادن آن به عنوان شناسه مستلزم یک پوسته فرعی است، که تمام تخصیص‌ها را برای حوزه بیرونی نقض می‌کند. برای شگردهای بازیابی نتایج یک تابع، پرسش و پاسخ شماره ۸۴ را ببینید، اما توجه نمایید که تمام آنها ترفند هستند و محدودیت‌های گوناگونی دارند.

    • قابلیت استفاده مجدد: شما نمی‌توانید شناسه‌ها را «با ارجاع» عبور بدهید، یا حداقل تا ‎Bash 4.3‎ نمی‌توانستید (و حتی آنجا هم مکانیسم ‎declare -n‎ دارای نواقص امنیتی جدی است). راهی برای گفتن نام متغیری به تابع که می‌خواهید تابع خروجی‌اش را در آن قرار بدهد وجود ندارد. حتی کار با آرایه‌ها بدتر از آن است -- شما نمی‌توانید نام یک آرایه را به یک تابع عبور داده و بگذارید تابع آن را به کار ببرد. بهترین کاری که می‌توانید انجام بدهید، به طور نمونه، عبور دادن هر عضو آرایه به عنوان یک شناسه جداگانه است. این به معنای آن است که کتابخانه‌های مجتمعِ توابعِ قابل استفادهِ مجدد عملی نیست، مگر به واسطه انجام عملیات آکروباتیک eval.

    • حوزه: Bash دارای یک سیستم ساده حوزه محلی است که تقریباً به حوزه پویا شباهت دارد(به عنوان مثال جاوا اسکریپت، elisp). توابع مناطق فراخواننده‌اشان را می‌بینند( مانند کلمه کلیدی "nonlocal" پایتون)، اما نمی‌توانند پارامتر مکانی فراخواننده را دستیابی کنند (مگر از طریق BASH_ARGV در صورتی که extdebug فعال بشود). معاف شدن توابع قابل استفاده مجدد از تداخل‌های namespace نمی‌تواند تضمین شود مگر برای آنکه برخوردها به قدر کفایت غیر محتمل گردند، شما به قواعد نامگذاری عجیب متوسل شوید. این مطلب مخصوصاً در صورتی یک مسئله است که اجرای توابعی مورد انتظار باشد که از قاب n-3 بر روی نام متغیرهایی عمل کند که توسط تابع قابل استفاده مجدد شما در قاب n-2 رونویسی گردیده است. Ksh93 می‌تواند از قواعد حوزه لغوی بیشتر متداول، به وسیله تعریف توابع با ترکیب دستوری ‎"function name { ... }"‎ استفاده نماید (Bash نمی‌تواند، امابه هر حال از این ترکیب پشتیبانی می‌کند).

    • Closureها 2: در Bash، توابع خودشان همیشه سراسری هستند(دارای حوزه فایل)، بنابراین closure نیستند. تعاریف تابع ممکن است تو در تو باشد، اما اینها closure نیستند، هرچند خیلی زیاد مشابه آنها هستند. توابع «گذر پذیر» نیستند(درجه اول)، و هیچ تابع بدون نامی وجود ندارد (lambdas). در حقیقت، چیزی قابل عبور نیست، مخصوصاً آرایه‌ها. Bash معناشناسی سخت‌گیرانه call-by-value را به کار می‌برد .

    • پیچیدگی‌های بسیاری بیشتری را شامل می‌گردد، پوسته‌های فرعی، توابع صادر شده، «function collapsing» (توابعی که خودشان یا سایر توابع را تعریف یا بازتعریف می‌کنند)، traps (و میراث آنها)، و روشی که توابع با ورودی خروجی استاندارد فعل و انفعال می‌کنند. نوآموز را برای عدم درک همه این موارد نیش نزنید. به طور کلی توابع پوسته f***ed(در وضعیت نامناسب) هستند.

  13. مرتب سازی: Bash نمی‌تواند گروههای داده‌ها را مرتب نماید. اگر نیاز دارید یک آرایه را مرتب کنید، یا می‌توانید الگوریتم مرتب‌سازی خودتان را در bash خالص بنویسید، یا می‌توانید مجموعه داده‌ها را مسلسل نموده آن را به sort لوله‌کشی کنید و سپس آنرا تجزیه و برگردانید. هر یک از این روشها آزاردهنده است، مخصوصاً اگر برنامه sort شما گزینه ‎-z‎ نداشته باشد.

برتر از تمام اینها، BASH برای برنامه‌های بزرگ مطلوب نیست. اگر برنامه شما می‌خواهد پاسخگوی وظایف زیادی، بویژه به طور فعل و انفعالی باشد، آنوقت شاید لازم باشد مفسر دیگری را در نظر بگیرید یا به طور کلی به سمت یک زبان قابل ترجمه بروید. اسکریپت‌های بزرگ Bash خیلی به سرعت رنجش‌آور می‌شوند زیرا Bash در بسیاری از مواردی که مفسرهای دیگر در آن سریع هستند، کند است. با کاربرد معدود روشهای غیر از توابع به منظور ایجاد ساختار در کدتان، قطعات بزرگ کدِ Bash به سرعت غیر شفاف می‌گردند. اسکریپت‌های Bash تقریباً غیر قابل تست هستند. حتی آن برنامه‌نویسان bash که بیشترین وسواس را در استعمال صحیح کلمات دارند ( و زیاد هم نیستند ) کدی می‌نویسند که وقتی تمام آن جمع می‌شود، برای نگهداری مشکل می‌گردد. Bash برای ایمنی کدی که اجازه می‌دهد باگهای آب زیر کاه واقعاً به سادگی بدون اطلاع یا هشدار در آن رسوخ کنند، تقریباً راه‌کاری ندارد. و موقعی که امور اشتباه می‌شوند(و امور اشتباه خواهند شد)، به راستی اشکالزدایی اسکریپت‌های بزرگ خیلی دشوار است.

اگر شما طرحی برای نوشتن اسکریپت‌های بزرگ Bash اجرا می‌کنید، تضمین کنید که برای هر قاعده طرز کارِ خوبِ منفرد، حتی, بیش از حد معمول مراقبت به عمل آورید و برای پرهیز از دردسر بسیار زیاد بعدی، از یک شیوه نامتناقض در سرتاسر کد پیروی کنید.


CategoryShell

کمبودهای Bash (آخرین ویرایش ‎2013-06-28 20:51:14‎ توسط GreyCat)


  1. مترجم: tuple یک مورد داده‌‌ای متشکل از دو عنصر یا بیشتر است، مجموعه‌ای از مقادیر مرتبط با هم که در سیستم مدیریت رابطه‌ای در یک سطر ذخیره می‌شود، یا مجموعه‌ای از صفات مشخصه که نشانگر یک موجودیت متناظر با یک سطر از یک جدول هستند (بازگشت)

  2. مترجم: closure یک تکنیک برنامه‌نویسی است که اجازه می‌دهد متغیرهای خارج از حوزه یک تابع دستیابی گردند، در بسیاری از موقعیت‌ها یک closure هنگامی ایجاد می‌شود که تابعی داخل تابع دیگر تعریف می‌گردد، و به تابع داخلی اجازه می‌دهد که به متغیرهای تابع خارجی دسترسی داشته باشد. (بازگشت)


bashism


چگونه اسکریپت‌های bash بسازیم که در dash کار کنند

این صفحه کوششی است برای لیست کردن برخی از رایج‌ترین bashismها، یعنی ویژگی‌هایی که توسط POSIX تعریف نشده‌اند (در dash، یا ‎/bin/sh‎ متداول، کار نخواهند کرد). احتمالاً شامل تمام جزئیات نخواهد بود. همچنین توجه نمایید که ما در باره "bashism" صحبت می‌کنیم، زیرا این ویکی به طور عمده متمرکز بر bash می‌باشد، اما چون اکثر ویژگی‌های اسکریپت‌نویسی Bash از ksh مشتق گردیده است تعدادی(تقریباً همه) از این ملحقات احتمالاً با تفاوت‌هایی در جزئیات، حداقل در برخی پوسته‌های دیگر مانند ksh یا zsh نیز کار می‌کنند. POSIX تعداد بسیار کمتری از آنها را لازم دانسته است.

ادامه مطلب

bashism


چگونه اسکریپت‌های bash بسازیم که در dash کار کنند

این صفحه کوششی است برای لیست کردن برخی از رایج‌ترین bashismها، یعنی ویژگی‌هایی که توسط POSIX تعریف نشده‌اند (در dash، یا ‎/bin/sh‎ متداول، کار نخواهند کرد). احتمالاً شامل تمام جزئیات نخواهد بود. همچنین توجه نمایید که ما در باره "bashism" صحبت می‌کنیم، زیرا این ویکی به طور عمده متمرکز بر bash می‌باشد، اما چون اکثر ویژگی‌های اسکریپت‌نویسی Bash از ksh مشتق گردیده است تعدادی(تقریباً همه) از این ملحقات احتمالاً با تفاوت‌هایی در جزئیات، حداقل در برخی پوسته‌های دیگر مانند ksh یا zsh نیز کار می‌کنند. POSIX تعداد بسیار کمتری از آنها را لازم دانسته است.

ادامه مطلب

CompilingBad


چرا ترجمه کردن (compiling) یک اسکریپت نامناسب است

یا، چرا موقعی که شما در مورد یک مترجم اسکریپت پرسش می‌کنید greycat بر سر شما فریاد می‌کشد

اسکریپت پوسته را ملاحظه کنید. خصوصیات آن چیست؟ توانایی‌ها و ضعف‌هایش کدام هستند؟

نقاط قوت:

  • ساده، به آسانی قابل فهم
  • قابل نوشتن به طور سریع
  • فضای زیادی از دیسک اشغال نمی‌کند
  • اگر بدانید که چکار می‌کنید، بدون نیاز به اصلاح دارای شانس قابل قبولی برای کار کردن روی سیستم‌عامل‌های گوناگون است

ضعف‌ها:

  • اجرای کند (به طور نوعی)
  • عدم دسترسی معقول و قوی به حساب ممیز شناور، ساختارهای داده‌ای پیچیده، پرس و جوی بانک اطلاعاتی، و غیره (وابسته به زبان)
  • سطر ِشبانگ باید برای هر سیستم مقصد ویرایش گردد

البته، من یک اسکریپت پوسته نوشته شده به طور صحیح را در نظر می‌گیرم. بنابراین من مواردی مانند «متمایل به خطاهای دستوری و منطقی نوآموز» را به شمار نمی‌آورم، زیرا این مشخصهِ هر نوع از برنامه‌نویسی است.

دوباره به آن نقطه قوت اول که لیست کردم نگاهی بیاندازید: ساده، به آسانی قابل فهم. کدام مطلب را می‌رساند؟ بیش از هر چیز، بر این دلالت می‌کند که اشخاص می‌توانند به آن نگاه کنند!

اگر یک اسکریپت پوسته را ترجمه کنید، به یکی از این دو دلیل می‌خواهید این کار را انجام بدهید:

  1. می‌خواهید سریع‌تر اجرا شود، یا
  2. می‌خواهید آن را از مردم پنهان کنید.

اکنون، به این صفحه که در حال خواندن آن می‌باشید نگاه کنید. چیست؟ این یک انتقاد است. کجاست؟ در ویکی اشخاص است. ویکی چیست؟ ویکی یک روش آزاد توام با همکاری در ویرایش اطلاعات است. ویکی‌ها کجا زندگی می‌کنند؟ روی ‎WWW (شبکه درهم تنیده گسترده جهانی). WWW چیست؟ سیستمی برای به اشتراک نهادن آزادانه اطلاعات با کل جهان است. (لااقل، تا زمانی که قلمرو صنفی تصمیم گرفت پول در آوردن از آن را امتحان کند، چنین چیزی بود.) WWW کجا زندگی می‌کند؟ روی اینترنت. اینترنت چیست؟ یک فوق شبکه از تمام شبکه‌های کامپیوتری در جهان است که تصمیم گرفته‌اند با یکدیگر صحبت کنند. چرا چنین می‌کنند؟ به علت اینکه اشتراک اطلاعات را دوست دارند!

آگاهی نیازمند آزاد بودن است.

اشتراک گذاشتن اطلاعات همه ما را توانمند می‌سازد. توماس جفرسون1 نوشت:

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

اگر من در حال نوشتن یک سرزنش هستم، روی یک ویکی، روی WWW، روی اینترنت، آیا به راستی تصور کرده‌اید من از آن تیپ‌هایی باشم که با تلاش شما برای پنهان کردن اطلاعات همراهی خواهد کرد؟ تصور نکرده‌اید که ما به اندازه کافی بارها پرسش شما را دیده‌ایم تا بدانیم که آنچه شما سعی در انجام آن دارید کدام است؟

چرا اشخاص می‌خواهند اسکریپت‌های پوسته‌شان را پنهان کنند؟

  • آنان تلاش دارند آنها را به فروش برسانند.

  • آنها از بابت اسکریپت‌هایشان شرمسار هستند.

اگر شما از ما برای کمک به فروش یک محصول می‌پرسید، آنوقت شما یک spammer هستید و ما هیچ کاری با شما نداریم.

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

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


ترجمه زیان‌آور (آخرین ویرایش ‎2013-07-03 16:52:59‎ توسط GreyCat)



  1. مترجم: Thomas Jefferson از مؤثرترین برپاکنندگان ایالات متحده و یکی از قدیمی‌ترین و برجسته‌ترین سیاستمداران و زمامداران امریکایی بود، او یکی از نویسندگان بیانیه استقلال امریکا، و سومین رییس جمهور این کشور بود. (1)