| EXPECT(1) | General Commands Manual | EXPECT(1) |
نام (NAME)
expect - گفتگوی برنامهریزیشده با برنامههای تعاملی، نسخه ۵
خلاصه دستور (SYNOPSIS)
expect [ -dDinN ] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
مقدمه (INTRODUCTION)
Expect برنامهای است که بر اساس یک اسکریپت با سایر برنامههای تعاملی «گفتگو» میکند. با دنبال کردن اسکریپت، Expect میداند چه انتظاری میتوان از یک برنامه داشت و پاسخ درست چه باید باشد. یک زبان مفسری، ساختارهای کنترلی سطح بالا و انشعاب را برای هدایت گفتگو فراهم میکند. علاوه بر این، کاربر میتواند در صورت تمایل کنترل را به دست بگیرد و مستقیماً تعامل کند، و پس از آن کنترل را دوباره به اسکریپت بازگرداند.
Expectk ترکیبی از Expect و Tk است. رفتاری دقیقاً مشابه Expect و دستور wish مربوط به Tk دارد. همچنین میتوان از Expect مستقیماً در C یا C++ (یعنی بدون Tcl) استفاده کرد. مدخل libexpect(3) را ببینید.
نام «Expect» از ایده توالیهای send/expect گرفته شده که توسط uucp، kermit و سایر برنامههای کنترل مودم محبوبیت یافت. با این حال بر خلاف uucp، ابزار Expect عمومیت یافته است تا بتوان آن را به عنوان یک دستور در سطح کاربر برای هر برنامه و هدفی اجرا کرد. Expect در واقع میتواند همزمان با چندین برنامه گفتگو کند.
به عنوان مثال، در اینجا برخی از کارهایی که Expect میتواند انجام دهد آورده شده است:
- •
- کاری کند که رایانه با شما تماس معکوس برقرار کند، تا بتوانید بدون پرداخت هزینه تماس وارد سیستم شوید.
- •
- یک بازی را آغاز کند (مانند rogue) و اگر پیکربندی بهینه ایجاد نشد، آن را (بارها و بارها) بازراهاندازی کند تا زمانی که ایجاد شود، سپس کنترل را به شما بسپارد.
- •
- دستور fsck را اجرا کند، و در پاسخ به پرسشهای آن، بر اساس معیارهای از پیش تعیینشده پاسخ «yes» یا «no» بدهد یا کنترل را به شما بازگرداند.
- •
- به شبکه یا BBS دیگری (مانند MCI Mail یا CompuServe) متصل شود و نامههای شما را به طور خودکار دریافت کند تا به گونهای به نظر برسد که در اصل به سیستم محلی شما ارسال شده است.
- •
- متغیرهای محیطی، دایرکتوری جاری، یا هر گونه اطلاعاتی را در بسترهایی چون rlogin، telnet، tip، su، chgrp و غیره منتقل کند.
دلایل گوناگونی وجود دارد که چرا شل (shell) نمیتواند این وظایف را انجام دهد. (امتحان کنید، متوجه خواهید شد.) همه اینها با Expect امکانپذیر است.
به طور کلی، Expect برای اجرای هر برنامهای که به تعامل بین برنامه و کاربر نیاز دارد، مفید است. تنها چیزی که نیاز است این است که بتوان این تعامل را به صورت برنامهریزیشده توصیف کرد. همچنین در صورت تمایل، Expect میتواند کنترل را به کاربر بازگرداند (بدون متوقف کردن برنامهای که کنترل میشود). به همین ترتیب، کاربر میتواند در هر زمانی کنترل را دوباره به اسکریپت برگرداند.
نحوه استفاده (USAGE)
Expect فایل cmdfile را برای فهرستی از دستورها جهت اجرا میخواند. همچنین میتوان Expect را در سیستمهایی که از نماد #! پشتیبانی میکنند، با نشانهگذاری اسکریپت به عنوان قابل اجرا و قرار دادن خط زیر به عنوان خط نخست اسکریپت، به صورت ضمنی فراخوانی کرد:
#!/usr/local/bin/expect -f
البته، مسیر باید دقیقاً محل قرارگیری Expect را مشخص کند. /usr/local/bin تنها یک مثال است.
پرچم -c پیشوند دستوری است که باید پیش از هر دستور دیگری در اسکریپت اجرا شود. دستور باید داخل علامت نقلقول قرار گیرد تا از تجزیه شدن آن توسط شل جلوگیری شود. از این گزینه میتوان چندین بار استفاده کرد. با جدا کردن دستورها به وسیله نقطهویرگول، میتوان چندین دستور را با یک پرچم -c واحد اجرا کرد. دستورها به همان ترتیبی که نوشته شدهاند اجرا میشوند. (هنگام استفاده از Expectk، این گزینه با -command مشخص میشود.)
پرچم -d برخی خروجیهای عیبیابی را فعال میکند که عمدتاً فعالیت داخلی دستورهایی مانند expect و interact را گزارش میدهد. این پرچم اثری مشابه «exp_internal 1» در آغاز یک اسکریپت Expect دارد، به علاوه اینکه نسخه Expect نیز چاپ میشود. (دستور strace برای ردگیری دستورها، و دستور trace برای ردگیری انتسابهای متغیرها مفید است.) (هنگام استفاده از Expectk، این گزینه با -diag مشخص میشود.)
پرچم -D یک اشکالزدا (debugger) تعاملی را فعال میکند. یک مقدار عدد صحیح باید پس از آن بیاید. اگر این مقدار غیرصفر باشد، یا اگر ^C فشرده شود (یا به یک نقطه توقف برخورد شود، یا دستور اشکالزدایی مناسب دیگری در اسکریپت پدیدار شود)، اشکالزدا پیش از رویه Tcl بعدی کنترل را به دست میگیرد. برای اطلاعات بیشتر درباره اشکالزدا، فایل README یا بخش «همچنین ببینید» (در ادامه) را ببینید. (هنگام استفاده از Expectk، این گزینه با -Debug مشخص میشود.)
پرچم -f پیشوند فایلی است که دستورها از آن خوانده میشوند. خود پرچم اختیاری است، زیرا تنها زمانی کاربرد دارد که از نماد #! (به بالا مراجعه کنید) استفاده شود، تا بتوان آرگومانهای دیگری را در خط فرمان مشخص کرد. (هنگام استفاده از Expectk، این گزینه با -file مشخص میشود.)
به طور پیشفرض، فایل دستورها به طور کامل در حافظه خوانده شده و یکجا اجرا میشود. گهگاه مطلوب است که فایلها خطبهخط خوانده شوند؛ به عنوان مثال stdin به این شکل خوانده میشود. برای اجبار فایلهای دلخواه به اداره شدن با این روش، از پرچم -b استفاده کنید. (هنگام استفاده از Expectk، این گزینه با -buffer مشخص میشود.) توجه داشته باشید که بافرینگ stdio ممکن است همچنان رخ دهد، با این حال این موضوع نباید هنگام خواندن از یک fifo یا stdin مشکلی ایجاد کند.
اگر رشته «-» به عنوان نام فایل داده شود، به جای آن ورودی استاندارد خوانده میشود. (برای خواندن از فایلی که نام واقعی آن «-» است، از «./-» استفاده کنید.)
پرچم -i باعث میشود که Expect به جای خواندن دستورها از یک فایل، برای دریافت دستورها به صورت تعاملی اعلان (prompt) دهد. فرایند اعلان با دستور exit یا هنگام رسیدن به EOF پایان مییابد. برای اطلاعات بیشتر به interpreter (در ادامه) مراجعه کنید. اگر نه فایل دستور و نه گزینه -c مشخص نشده باشند، پرچم -i به صورت پیشفرض در نظر گرفته میشود. (هنگام استفاده از Expectk، این گزینه با -interactive مشخص میشود.).PP -- میتواند برای مشخص کردن پایان گزینهها به کار رود. این ویژگی زمانی مفید است که بخواهید یک آرگومان شبیه به گزینه را بدون اینکه توسط Expect تفسیر شود، به اسکریپت خود منتقل کنید. این نماد میتواند به شکلی کاربردی در خط #! قرار گیرد تا از هرگونه تفسیر پرچممانند توسط Expect جلوگیری شود. برای مثال، عبارت زیر آرگومانهای اصلی (شامل نام اسکریپت) را در متغیر argv باقی میگذارد.
#!/usr/local/bin/expect --
توجه داشته باشید که هنگام افزودن آرگومانها به خط #! باید قواعد معمول getopt(3) و execve(2) رعایت شوند.
فایل $exp_library/expect.rc در صورت وجود به طور خودکار بارگذاری (source) میشود، مگر آنکه پرچم -N به کار رفته باشد. (هنگام استفاده از Expectk، این گزینه به صورت -NORC مشخص میشود.) بلافاصله پس از آن، فایل ~/.expect.rc به طور خودکار بارگذاری میشود، مگر اینکه پرچم -n به کار رود. اگر متغیر محیطی DOTDIR تعریف شده باشد، به عنوان یک دایرکتوری در نظر گرفته شده و .expect.rc از آنجا خوانده میشود. (هنگام استفاده از Expectk، این گزینه به صورت -norc مشخص میشود.) این بارگذاری تنها پس از اجرای هرگونه پرچم -c رخ میدهد.
-v باعث میشود Expect شماره نسخه خود را چاپ کرده و خارج شود. (پرچم متناظر در Expectk، که از نامهای طولانی برای پرچمها استفاده میکند، -version است.)
آرگومانهای اختیاری args در قالب یک لیست ساختار یافته و در متغیری به نام argv ذخیره میشوند. argc با طول argv مقداردهی اولیه میشود.
متغیر argv0 به عنوان نام اسکریپت (یا باینری در صورتی که اسکریپتی به کار نرفته باشد) تعریف میشود. برای مثال، عبارت زیر نام اسکریپت و سه آرگومان نخست را چاپ میکند:
send_user "$argv0 [lrange $argv 0 2]\n"
دستورها (COMMANDS)
Expect از Tcl (Tool Command Language) استفاده میکند. Tcl ساختارهای کنترل جریان (مانند if، for، break)، ارزیابی عبارات و چندین قابلیت دیگر مانند بازگشت (recursion)، تعریف رویه (procedure) و غیره را فراهم میکند. دستوراتی که در اینجا استفاده شدهاند ولی تعریف نشدهاند (مانند set، if، exec) دستورهای Tcl هستند (به tcl(3) مراجعه کنید). Expect از دستورهای دیگری نیز پشتیبانی میکند که در ادامه شرح داده شدهاند. مگر در مواردی که مشخص شده باشد، دستورها یک رشته خالی برمیگردانند.
دستورها به ترتیب الفبایی فهرست شدهاند تا بتوان به سرعت آنها را پیدا کرد. با این حال، ممکن است برای کاربران جدید آسانتر باشد که مطالعه را با شرح دستورهای spawn، send، expect و interact به همین ترتیب آغاز کنند.
توجه داشته باشید که بهترین مقدمه برای این زبان (هم Expect و هم Tcl) در کتاب «Exploring Expect» ارائه شده است (به بخش «همچنین ببینید (SEE ALSO)» در زیر مراجعه کنید). مثالهایی در این صفحه راهنما گنجانده شدهاند، اما بسیار محدود هستند زیرا این صفحه راهنما اساساً به عنوان یک مرجع در نظر گرفته شده است.
(توجه داشته باشید که در متن این صفحه راهنما، «Expect» با حرف بزرگ «E» به برنامه Expect اشاره دارد، در حالی که «expect» با حرف کوچک «e» به دستور expect درون برنامه Expect اشاره میکند.)
- close [-slave] [-onexec 0|1] [-i spawn_id]
- اتصال به
فرآیند
جاری را
میبندد.
اکثر
برنامههای
تعاملی EOF را
روی ورودی
استاندارد
(stdin) خود تشخیص
داده و خارج
میشوند؛
بنابراین
close معمولاً
برای خاتمه
دادن به
فرآیند نیز
کفایت
میکند.
پرچم -i
فرآیند
مورد نظر
برای بستن
را متناظر
با spawn_id
نامبرده
مشخص
میکند.
هر دو دستور expect و interact خروج فرآیند جاری را تشخیص داده و به طور ضمنی یک close انجام میدهند. اما اگر فرآیند را، به عنوان مثال، با «exec kill $pid» متوقف کنید، باید به صراحت close را فراخوانی نمایید.
پرچم -onexec مشخص میکند که آیا spawn id در هر فرآیند اشتقاقیافته جدیدی (spawned) بسته شود یا خیر، یا اینکه آیا فرآیند جایگزین (overlay) شده است. برای باز گذاشتن یک spawn id از مقدار 0 استفاده کنید. یک مقدار صحیح غیرصفر، بستن فرآیند اشتقاقیافته را در فرآیندهای جدید اجباری میکند (پیشفرض).
پرچم -slave طرف وابسته (slave) مرتبط با spawn id را میبندد. (به «spawn -pty» مراجعه کنید.) هنگامی که اتصال بسته شود، طرف وابسته (slave) نیز در صورت باز بودن به طور خودکار بسته میشود.
صرفنظر از اینکه اتصال به طور ضمنی یا صریح بسته شود، باید wait را فراخوانی کنید تا اسلات فرآیند متناظر در هسته (kernel process slot) پاکسازی شود. دستور close دستور wait را فراخوانی نمیکند، چرا که هیچ تضمینی وجود ندارد که بستن اتصال فرآیند موجب خروج آن شود. برای اطلاعات بیشتر به wait در زیر مراجعه کنید.
- debug [[-now] 0|1]
- یک
اشکالزدای
Tcl را کنترل
میکند که
به شما
امکان
میدهد
دستورها را
گامبهگام
اجرا کنید،
نقاط توقف
(breakpoints) تعیین
نمایید و
غیره.
بدون هیچ آرگومانی، در صورتی که اشکالزدا در حال اجرا نباشد مقدار 1 برگردانده میشود، وگرنه مقدار 0 برگردانده خواهد شد.
با آرگومان 1، اشکالزدا شروع به کار میکند. با آرگومان 0، اشکالزدا متوقف میشود. اگر قبل از آرگومان 1 پرچم -now آمده باشد، اشکالزدا بلافاصله شروع به کار میکند (یعنی در میانه خود دستور debug). در غیر این صورت، اشکالزدا با دستور Tcl بعدی آغاز به کار خواهد کرد.
دستور debug هیچکدام از تلهها (traps) را تغییر نمیدهد. این رفتار را با راهاندازی Expect با پرچم -D مقایسه کنید (بالا را ببینید).
برای اطلاعات بیشتر درباره اشکالزدا، به فایل README یا بخش «همچنین ببینید (SEE ALSO)» (در زیر) مراجعه کنید.
- disconnect
- ارتباط فرآیند منشعبشده (forked) را از ترمینال قطع میکند. این فرآیند به اجرا در پسزمینه ادامه میدهد. به فرآیند گروه فرآیندی (process group) ویژه خودش اختصاص داده میشود (در صورت امکان). ورودی/خروجی استاندارد به /dev/null هدایت میشود.
- قطعهکد
زیر از disconnect
برای ادامه
اجرای
اسکریپت در
پسزمینه
استفاده
میکند.
if {[fork]!=0} exit disconnect . . .اسکریپت زیر یک گذرواژه را میخواند، و سپس هر ساعت برنامهای را اجرا میکند که در هر بار اجرا به گذرواژه نیاز دارد. اسکریپت گذرواژه را فراهم میکند به طوری که شما تنها لازم است یک بار آن را وارد کنید. (دستور stty را ببینید که چگونگی خاموش کردن پژواک گذرواژه را نشان میدهد.)send_user "password?\ " expect_user -re "(.*)\n" for {} 1 {} { if {[fork]!=0} {sleep 3600;continue} disconnect spawn priv_prog expect Password: send "$expect_out(1,string)\r" . . . exit }یک مزیت استفاده از disconnect نسبت به قابلیت فرآیند ناهمگام پوسته (&) این است که Expect میتواند پارامترهای ترمینال را پیش از قطع اتصال ذخیره کند و سپس بعداً آنها را بر روی ptyهای جدید اعمال نماید. در صورت استفاده از &، Expect فرصتی برای خواندن پارامترهای ترمینال نخواهد داشت، چرا که پیش از دریافت کنترل توسط Expect، ارتباط ترمینال از قبل قطع شده است..TP exit [-opts] [status] باعث خروج Expect یا آمادهسازی آن برای این کار میشود.پرچم -onexit باعث میشود آرگومان بعدی بهعنوان یک گردانندهٔ خروج (exit handler) به کار رود. بدون آرگومان، گردانندهٔ خروج فعلی بازگردانده میشود.
پرچم -noexit باعث میشود Expect برای خروج آماده شود، اما دقیقاً پیش از بازگرداندن واقعی کنترل به سیستمعامل متوقف گردد. گردانندهٔ خروج تعریفشده توسط کاربر و همچنین گردانندههای داخلی خود Expect اجرا میشوند. هیچ دستور Expect دیگری نباید اجرا شود. این قابلیت زمانی مفید است که Expect را به همراه سایر افزونههای Tcl اجرا میکنید. مفسر فعلی (و پنجرهٔ اصلی در صورت قرار داشتن در محیط Tk) باقی میمانند تا سایر افزونههای Tcl بتوانند عملیات پاکسازی را انجام دهند. اگر exit مربوط به Expect دوباره فراخوانی شود (به هر ترتیبی که ممکن است رخ دهد)، گردانندهها مجدداً اجرا نخواهند شد.
هنگام خروج، تمام اتصالات به فرایندهای منشعبشده (spawned) بسته میشوند. این بسته شدن توسط فرایندهای منشعبشده بهصورت یک EOF تشخیص داده خواهد شد. دستور exit هیچ اقدام دیگری فراتر از آنچه در روال معمول _exit(2) انجام میشود صورت نمیدهد. بنابراین، فرایندهای منشعبشدهای که EOF را بررسی نمیکنند ممکن است همچنان به اجرای خود ادامه دهند. (شرایط گوناگونی برای تعیین این موضوع حائز اهمیت هستند؛ برای مثال اینکه چه سیگنالهایی به یک فرایند منشعبشده ارسال خواهد شد، اما این شرایط وابسته به سیستم بوده و معمولاً ذیل exit(3) مستند شدهاند.) فرایندهای منشعبشدهای که به اجرای خود ادامه دهند توسط init به ارث برده خواهند شد.
مقدار status (یا 0 در صورت عدم تعیین) بهعنوان وضعیت خروج Expect بازگردانده میشود. در صورت رسیدن به پایان اسکریپت، exit بهطور ضمنی اجرا میگردد.
- exp_continue [-continue_timer]
- دستور exp_continue به خود expect امکان میدهد تا بهجای بازگشت به روال معمول، به اجرای خود ادامه دهد. بهطور پیشفرض، exp_continue تایمر زمانبندی (timeout) را بازنشانی میکند. پرچم -continue_timer از راهاندازی مجدد تایمر جلوگیری مینماید. (برای اطلاعات بیشتر به expect مراجعه کنید.)
- exp_internal [-f file] value
- در صورتی که value عددی غیر صفر باشد، باعث میشود دستورات بعدی اطلاعات عیبیابی داخلیِ Expect را به stderr ارسال کنند. در صورتی که value برابر 0 باشد، این خروجی غیرفعال میشود. اطلاعات عیبیابی شامل تکتک نویسههای دریافتشده و تمامی تلاشهای صورتگرفته برای تطبیق خروجی فعلی با الگوها است.
- اگر
پارامتر
اختیاریِ
file مشخص شده
باشد، تمام
خروجیهای
عادی و
اشکالزدایی
(بدون در
نظر گرفتن
مقدار value) در
آن فایل
نوشته
میشوند.
هرگونه
فایل خروجی
عیبیابی
پیشین بسته
خواهد شد.
پرچم -info باعث میشود exp_internal توصیفی از جدیدترین آرگومانهای دادهشده به جز آرگومانهای مربوط به info را بازگرداند.
- exp_open [args] [-i spawn_id]
- یک شناسهٔ
فایل Tcl
بازمیگرداند
که متناظر
با spawn id اصلی
است. سپس
میتوان از
این شناسهٔ
فایل
بهگونهای
استفاده
کرد که گویی
توسط دستور
open در Tcl باز
شده است.
(شناسهٔ spawn id
دیگر نباید
استفاده
شود. دستور
wait نباید
اجرا شود.)
پرچم -leaveopen شناسهٔ spawn id را برای دسترسی از طریق دستورات Expect باز نگه میدارد. در این حالت باید یک wait روی spawn id اجرا شود.
- exp_pid [-i spawn_id]
- شناسهٔ فرایند (pid) متناظر با فرایند منشعبشدهٔ فعلی را بازمیگرداند. اگر از پرچم -i استفاده شود، pid بازگرداندهشده متناظر با شناسهٔ spawn id مشخصشده خواهد بود.
- exp_send
- نام مستعاری است برای send.
- exp_send_error
- نام مستعاری است برای send_error.
- exp_send_log
- نام مستعاری است برای send_log.
- exp_send_tty
- نام مستعاری است برای send_tty.
- exp_send_user
- نام مستعاری است برای send_user.
- exp_version [[-exit] version]
- برای اطمینان از سازگاری اسکریپت با نسخهٔ فعلی Expect سودمند است.
- بدون آرگومان، نسخهٔ فعلی Expect بازگردانده میشود. سپس میتوان این نسخه را در اسکریپت خود درج کرد. اگر بهطور قطعی میدانید که از قابلیتهای نسخههای اخیر استفاده نمیکنید، میتوانید نسخهٔ قدیمیتری را مشخص نمایید.
- شماره نسخهها از سه عدد تشکیل شدهاند که با نقطه جدا میشوند. اولین عدد، شماره نسخهٔ اصلی (major) است. اسکریپتهایی که برای نسخههایی از Expect با شماره نسخهٔ اصلیِ متفاوت نوشته شده باشند، تقریباً بهطور قطع کار نخواهند کرد. اگر شمارههای نسخهٔ اصلی مطابقت نداشته باشند، exp_version خطا بازمیگرداند.
- دومین عدد، شماره نسخهٔ فرعی (minor) است. اسکریپتهایی که برای نسخهای با شماره فرعی بزرگتر از نسخهٔ فعلی نوشته شدهاند ممکن است به قابلیت جدیدی وابسته باشند و اجرا نشوند. exp_version اگر شمارههای نسخهٔ اصلی یکسان باشند اما شماره نسخهٔ فرعی اسکریپت بزرگتر از نسخهٔ Expect در حال اجرا باشد، خطایی بازمیگرداند.
- سومین عدد نقشی در مقایسه نسخه ندارد. با این حال، هرگاه توزیع نرمافزاری Expect به هر نحوی تغییر کند (مانند افزودن مستندات بیشتر یا بهینهسازی)، این شماره افزایش مییابد. این شماره با انتشار هر نسخهٔ فرعی جدید به 0 بازنشانی میشود.
- با پرچم -exit، اگر نسخه قدیمی باشد، Expect پیام خطایی چاپ کرده و خارج میشود.
- expect [[-opts] pat1 body1] ... [-opts] patn [bodyn]
- منتظر میماند تا یکی از الگوها با خروجی فرایند منشعبشده مطابقت یابد، مدتزمان مشخصی سپری شود، یا به انتهای فایل (end-of-file) برسد. اگر بدنهٔ نهایی خالی باشد، میتوان از آن صرفنظر کرد.
- الگوهای ناشی از جدیدترین دستور expect_before بهطور ضمنی پیش از هر الگوی دیگری استفاده میشوند. الگوهای ناشی از جدیدترین دستور expect_after بهطور ضمنی پس از هر الگوی دیگری استفاده میشوند.
- اگر آرگومانهای کل عبارت expect به بیش از یک خط نیاز داشته باشند، میتوان تمام آرگومانها را درون یک آکولاد قرار داد تا از پایان دادن به هر خط با نویسهٔ بکاسلش (backslash) جلوگیری شود. تنها در این حالت خاص، جایگزینیهای معمول Tcl با وجود آکولادها رخ خواهند داد.
- اگر یک الگو کلمهٔ کلیدی eof باشد، بدنهٔ متناظر هنگام رسیدن به انتهای فایل اجرا میشود. اگر یک الگو کلمهٔ کلیدی timeout باشد، بدنهٔ متناظر هنگام اتمام مهلت زمانی (timeout) اجرا میگردد. اگر از کلمهٔ کلیدی timeout استفاده نشود، در زمان پایان مهلت یک کنشِ تهی (null action) ضمنی اجرا میشود. دورهٔ مهلت پیشفرض ۱۰ ثانیه است اما میتواند برای نمونه با دستور "set timeout 30" روی ۳۰ ثانیه تنظیم شود. مهلت نامحدود را میتوان با مقدار -1 تعیین کرد. اگر الگویی کلمهٔ کلیدی default باشد، بدنهٔ متناظر با آن در صورت رخداد مهلت زمانی یا رسیدن به انتهای فایل اجرا میشود.
- اگر الگویی مطابقت پیدا کند، بدنهٔ متناظر با آن اجرا میشود. expect نتیجهٔ بدنه را بازمیگرداند (یا اگر هیچ الگویی مطابقت پیدا نکرد، یک رشتهٔ خالی برمیگرداند). در صورتی که چندین الگو مطابقت یابند، الگویی که در ابتدا آمده باشد برای انتخاب بدنه استفاده خواهد شد.
- هر بار که خروجی جدیدی برسد، به ترتیبی که در فهرست ذکر شدهاند با هر یک از الگوها مقایسه میشود. بدین ترتیب، میتوانید با قرار دادن آخرین الگو بهصورت چیزی که تضمین شده است نمایش داده میشود (مانند یک اعلان ورودی یا prompt)، عدم وجود تطابق را بررسی کنید. در مواردی که اعلان ورودی وجود ندارد، باید از timeout استفاده نمایید (دقیقاً همانگونه که در تعامل دستی عمل میکردید)..IP الگوها به سه روش مشخص میشوند. به طور پیشفرض، الگوها همانند دستور string match در Tcl مشخص میگردند. (چنین الگوهایی همچنین مشابه عبارات منظم C-shell هستند که معمولاً با نام الگوهای «glob» شناخته میشوند). پرچم -gl میتواند برای محافظت از الگوهایی به کار رود که ممکن است در غیر این صورت با پرچمهای expect تطبیق یابند. هر الگویی که با «-» شروع میشود باید به این شکل محافظت شود. (تمام رشتههایی که با «-» آغاز میشوند برای گزینههای آینده رزرو شدهاند.)
- برای مثال،
قطعه کد زیر
به دنبال یک
ورود (login)
موفقیتآمیز
میگردد.
(توجه داشته
باشید که
فرض شده است
abort رویهای
است که در
جای دیگری
از اسکریپت
تعریف شده
است.)
expect { busy {puts busy\n ; exp_continue} failed abort "invalid password" abort timeout abort connected }استفاده از نقلقول برای الگوی چهارم ضروری است زیرا شامل یک فاصله است، که در غیر این صورت الگو را از کنش جدا میکرد. الگوهایی با کنش یکسان (مانند سومی و چهارمی) نیازمند ذکر مجدد کنشها هستند. با استفاده از الگوهای سبک regexp میتوان از این کار اجتناب کرد (زیر را ببینید). اطلاعات بیشتر درباره تشکیل الگوهای سبک glob را میتوان در کتابچه راهنمای Tcl یافت. - الگوهای
سبک regexp از
ساختار
نحوی
تعریفشده
توسط دستور
regexp در Tcl
(کوتاهشدهی
«regular expression»)
پیروی
میکنند.
الگوهای regexp
با پرچم -re
معرفی
میشوند.
مثال قبلی
را میتوان
با استفاده
از یک regexp به
صورت زیر
بازنویسی
کرد:
expect { busy {puts busy\n ; exp_continue} -re "failed|invalid password" abort timeout abort connected }هر دو نوع الگو «مهارنشده» (unanchored) هستند. این بدان معناست که الگوها مجبور نیستند با کل رشته مطابقت داشته باشند، بلکه میتوانند تطابق را در هر نقطهای از رشته آغاز کرده و پایان دهند (تا زمانی که همه چیزهای دیگر مطابقت داشته باشند). از ^ برای تطابق با ابتدای رشته، و از $ برای تطابق با انتهای آن استفاده کنید. توجه داشته باشید که اگر منتظر انتهای رشته نمانید، پاسخهای شما میتوانند به آسانی در میانه رشته و به هنگام بازتاب (echo) از فرآیند ایجادشده (spawned) قرار گیرند. با وجود اینکه نتایج همچنان صحیح تولید میشوند، اما خروجی ممکن است غیرطبیعی به نظر برسد. بنابراین، در صورتی که میتوانید نویسههای انتهای رشته را دقیقاً توصیف کنید، استفاده از $ توصیه میشود.توجه داشته باشید که در بسیاری از ویرایشگرها، ^ و $ به ترتیب با ابتدا و انتهای خطوط تطابق دارند. با این حال، از آنجا که expect خطمحور نیست، این نویسهها با ابتدا و انتهای دادههای فعلی در بافر تطابق expect (در مقایسه با خطوط) مطابقت مییابند. (همچنین یادداشت زیر را درباره «system indigestion» ببینید.)
پرچم -ex باعث میشود الگو به عنوان یک رشته «دقیق» (exact) تطبیق داده شود. هیچ تفسیری از *، ^، و غیره صورت نمیگیرد (اگرچه قراردادهای معمول Tcl همچنان باید رعایت شوند). الگوهای دقیق همیشه مهارنشده هستند.
- پرچم -nocase باعث میشود نویسههای بزرگ خروجی طوری مقایسه شوند که گویی نویسههای کوچک هستند. الگو تحت تأثیر قرار نمیگیرد.
- هنگام
خواندن
خروجی، بیش
از ۲۰۰۰
بایت
میتواند
باعث شود که
بایتهای
اولیه
«فراموش»
شوند. این
مقدار ممکن
است با تابع
match_max تغییر
یابد. (توجه
داشته
باشید که
مقادیر بیش
از حد بزرگ
میتوانند
سرعت
تطابقدهنده
الگو را
کاهش دهند.)
اگر patlist
برابر با
full_buffer باشد،
در صورتی که
match_max بایت
دریافت شده
باشد و هیچ
الگوی
دیگری
مطابقت
نیافته
باشد، بدنه
متناظر
اجرا
میشود.
صرفنظر از
اینکه کلمه
کلیدی full_buffer
استفاده
شده باشد یا
خیر،
نویسههای
فراموششده
در expect_out(buffer)
نوشته
میشوند.
اگر patlist کلمه کلیدی null باشد، و مقادیر null مجاز باشند (از طریق دستور remove_nulls)، در صورتی که یک بایت ASCII 0 تطابق یابد، بدنه متناظر اجرا میشود. تطابق بایتهای ۰ از طریق الگوهای glob یا regexp امکانپذیر نیست.
پس از تطابق یک الگو (یا eof یا full_buffer)، هر خروجی تطابقیافته و خروجیهای تطابقنیافته پیشین در متغیر expect_out(buffer) ذخیره میشوند. تا ۹ زیررشته تطابقیافته با regexp در متغیرهای expect_out(1,string) تا expect_out(9,string) ذخیره میشوند. اگر پرچم -indices قبل از یک الگو استفاده شود، نمایههای شروع و پایان (در قالبی مناسب برای lrange) ۱۰ رشته در متغیرهای expect_out(X,start) و expect_out(X,end) ذخیره میشوند که در آن X یک رقم متناظر با موقعیت زیررشته در بافر است. رقم ۰ به رشتههایی اشاره دارد که با کل الگو تطابق یافتهاند و هم برای الگوهای glob و هم الگوهای regexp تولید میشود. برای مثال، اگر فرآیندی خروجی "abcdefgh\n" را تولید کرده باشد، نتیجه:
expect "cd"
به گونهای است که گویی عبارتهای زیر اجرا شدهاند:set expect_out(0,string) cd set expect_out(buffer) abcd
و "efgh\n" در بافر خروجی باقی میماند. اگر فرآیندی خروجی "abbbcabkkkka\n" را تولید کرده باشد، نتیجه:expect -indices -re "b(b*).*(k+)"
به گونهای است که گویی عبارتهای زیر اجرا شدهاند:set expect_out(0,start) 1 set expect_out(0,end) 10 set expect_out(0,string) bbbcabkkkk set expect_out(1,start) 2 set expect_out(1,end) 3 set expect_out(1,string) bb set expect_out(2,start) 10 set expect_out(2,end) 10 set expect_out(2,string) k set expect_out(buffer) abbbcabkkkk
و "a\n" در بافر خروجی باقی میماند. الگوی "*" (و -re ".*") بافر خروجی را بدون خواندن هیچ خروجی بیشتری از فرآیند، خالی (flush) میکند. - به طور
معمول،
خروجی
تطابقیافته
از بافرهای
داخلی Expect دور
ریخته
میشود. با
قرار دادن
پرچم -notransfer
قبل از یک
الگو
میتوان از
این امر
جلوگیری
کرد. این
پرچم
بهویژه در
هنگام
آزمایش
سودمند است
(و میتواند
برای راحتی
در هنگام
آزمایش به
"-not" خلاصه
شود).
شناسه spawn id مرتبط با خروجی تطابقیافته (یا eof یا full_buffer) در expect_out(spawn_id) ذخیره میشود.
پرچم -timeout باعث میشود دستور expect فعلی به جای استفاده از مقدار متغیر timeout، از مقدار پس از خود به عنوان زمان انتظار (timeout) استفاده کند.
به طور پیشفرض، الگوها در برابر خروجی فرآیند فعلی تطابق داده میشوند، اما پرچم -i اعلام میکند که خروجی فهرست spawn_id نامبردهشده با هر یک از الگوهای بعدی (تا -i بعدی) تطبیق داده شود. فهرست spawn_id یا باید فهرستی از spawn_idها جداشده با فاصله خالی باشد یا متغیری که به چنین فهرستی از spawn_idها اشاره دارد.
برای مثال، نمونه زیر منتظر دریافت "connected" از فرآیند فعلی، یا "busy"، "failed" یا "invalid password" از spawn_id نامبردهشده توسط proc2$ میماند.
expect { -i $proc2 busy {puts busy\n ; exp_continue} -re "failed|invalid password" abort timeout abort connected }مقدار متغیر سراسری any_spawn_id میتواند برای تطبیق الگوها با هر spawn_id که با تمام پرچمهای -i دیگر در دستور expect فعلی مشخص شدهاند، استفاده شود. شناسه spawn_id مربوط به یک پرچم -i بدون الگوی متناظر (یعنی بلافاصله پس از آن یک -i دیگر آمده باشد) برای تمام الگوهای دیگر در همان دستور expect که به any_spawn_id مرتبط هستند، در دسترس قرار میگیرد.پرچم -i همچنین میتواند نام یک متغیر سراسری باشد که در این صورت متغیر برای دریافت فهرستی از spawn idها خوانده میشود. متغیر هر زمان که تغییر کند، مجدداً خوانده میشود. این کار روشی را برای تغییر مبدأ ورودی/خروجی (I/O) در زمان اجرای دستور فراهم میسازد. شناسههای spawn id ارائهشده از این طریق، spawn idهای «غیرمستقیم» (indirect) نامیده میشوند.
کنشهایی مانند break و continue باعث میشوند ساختارهای کنترلی (یعنی for، proc) به شیوه معمول رفتار کنند. دستور exp_continue به خودِ expect اجازه میدهد تا به جای بازگشت به روال معمول، به اجرای خود ادامه دهد..IP این قابلیت برای جلوگیری از حلقههای صریح یا عبارتهای تکراری expect مفید است. مثال زیر بخشی از یک قطعهکد برای خودکارسازی rlogin است. دستور exp_continue در صورتی که rlogin درخواست گذرواژه کند، از نیاز به نوشتن یک عبارت دوم expect (برای جستجوی دوبارهٔ اعلان) جلوگیری میکند.
expect { Password: { stty -echo send_user "password (for $user) on $host: " expect_user -re "(.*)\n" send_user "\n" send "$expect_out(1,string)\r" stty echo exp_continue } incorrect { send_user "invalid password or account\n" exit } timeout { send_user "connection to $host timed out\n" exit } eof { send_user \ "connection to host failed: $expect_out(buffer)" exit } -re $prompt }برای نمونه، قطعهکد زیر میتواند به کاربر در هدایت تعاملی که پیشتر کاملاً خودکار شده است کمک کند. در این مورد، ترمینال در حالت raw قرار میگیرد. اگر کاربر «+» را فشار دهد، یک متغیر افزایش مییابد. اگر «p» فشرده شود، چندین نویسه بازگشت (return) به فرایند ارسال میشود، شاید برای تلنگر زدن به آن به نحوی؛ و «i» به کاربر اجازه میدهد با فرایند تعامل داشته باشد و عملاً واپایش را از اسکریپت پس بگیرد. در هر حالت، exp_continue به expect فعلی اجازه میدهد پس از اجرای کنش فعلی، به تطبیق الگو ادامه دهد.stty raw -echo expect_after { -i $user_spawn_id "p" {send "\r\r\r"; exp_continue} "+" {incr foo; exp_continue} "i" {interact; exp_continue} "quit" exit } - بهطور پیشفرض، exp_continue شمارشگر زمانبندی (timeout timer) را بازنشانی میکند. اگر exp_continue با پرچم -continue_timer فراخوانی شود، این شمارشگر مجدداً راهاندازی نمیشود.
- expect_after [expect_args]
- دقیقاً مانند expect_before عمل میکند، با این تفاوت که اگر الگوهای هر دو دستور expect و expect_after بتوانند مطابقت یابند، از الگوی expect استفاده میشود. برای اطلاعات بیشتر دستور expect_before را ببینید.
- expect_background [expect_args]
- همان
آرگومانهای
expect را
میپذیرد،
اما
بلافاصله
بازمیگردد.
الگوها هر
زمان که
ورودی
جدیدی برسد
آزمایش
میشوند.
الگوهای timeout
و default برای
expect_background
بیمعنی
هستند و
بدون هیچ
پیامی
نادیده
گرفته
میشوند. در
غیر این
صورت،
دستور expect_background
دقیقاً
مانند expect از
الگوهای
expect_before و expect_after
استفاده
میکند.
هنگامی که کنشهای expect_background در حال ارزیابی هستند، پردازش پسزمینه برای همان spawn id مسدود میشود. پردازش پسزمینه با تکمیل کنش از حالت مسدود خارج میشود. در حالی که پردازش پسزمینه مسدود است، امکان انجام یک expect (پیشزمینه) روی همان spawn id وجود دارد.
امکان اجرای یک expect در حالی که یک expect_background از حالت مسدود خارج است، وجود ندارد. دستور expect_background برای یک spawn id مشخص با اعلان یک expect_background جدید با همان spawn id حذف میشود. اعلان expect_background بدون هیچ الگویی، توانایی تطبیق الگو در پسزمینه را از spawn id دادهشده سلب میکند.
- expect_before [expect_args]
- همان
آرگومانهای
expect را
میپذیرد،
اما
بلافاصله
بازمیگردد.
جفتهای
الگو-کنش از
جدیدترین
expect_before با همان
spawn id بهطور
ضمنی به
تمامی
دستورهای
بعدی expect
افزوده
میشوند.
اگر الگویی
مطابقت
یابد، به
گونهای با
آن برخورد
میشود که
گویی در خود
دستور expect
مشخص شده
بوده است، و
بدنهٔ
مرتبط در
زمینهٔ (context)
دستور expect
اجرا
میشود. اگر
الگوهای هر
دو دستور
expect_before و expect
بتوانند
مطابقت
یابند، از
الگوی expect_before
استفاده
میشود.
اگر هیچ الگویی مشخص نشود، spawn id برای هیچ الگویی بررسی نمیشود.
مگر در صورتی که با پرچم -i لغو شود، الگوهای expect_before با spawn id تعریفشده در زمان اجرای دستور expect_before (نه زمانی که الگوی آن تطبیق داده میشود) مطابقت داده میشوند.
پرچم -info باعث میشود expect_before مشخصات فعلی الگوهایی را که تطبیق خواهد داد بازگرداند. بهطور پیشفرض، این پرچم گزارش spawn id فعلی را میدهد. برای دریافت اطلاعات درباره یک spawn id خاص، میتوان مشخصهٔ آن را بهصورت اختیاری ارائه داد. برای مثال:
expect_before -info -i $proc
حداکثر یک مشخصهٔ spawn id میتوان ارائه داد. پرچم -indirect شناسههای مستقیم spawn id را که صرفاً از مشخصات غیرمستقیم ناشی میشوند سرکوب میکند.به جای مشخصهٔ spawn id، پرچم «-all» باعث میشود «-info» دربارهٔ همهٔ spawn idها گزارش دهد.
خروجی پرچم -info را میتوان مجدداً به عنوان آرگومان expect_before استفاده کرد.
- expect_tty [expect_args]
- مانند expect است اما نویسهها را از /dev/tty (یعنی کلیدهای فشردهشده توسط کاربر) میخواند. بهطور پیشفرض، خواندن در حالت cooked (پخته) انجام میشود. بنابراین، خطوط باید با یک بازگشت (return) پایان یابند تا expect بتواند آنها را ببیند. این رفتار را میتوان از طریق stty تغییر داد (دستور stty در ادامه را ببینید).
- expect_user [expect_args]
- مانند expect است اما نویسهها را از stdin (یعنی کلیدهای فشردهشده توسط کاربر) میخواند. بهطور پیشفرض، خواندن در حالت cooked (پخته) انجام میشود. بنابراین، خطوط باید با یک بازگشت (return) پایان یابند تا expect بتواند آنها را ببیند. این رفتار را میتوان از طریق stty تغییر داد (دستور stty در ادامه را ببینید).
- fork
- یک فرایند جدید ایجاد میکند. فرایند جدید رونوشتی دقیق از فرایند فعلی Expect است. در صورت موفقیت، fork مقدار 0 را به فرایند جدید (فرزند) بازمیگرداند و شناسه فرایند (process ID) فرزند را به فرایند والد میدهد. در صورت شکست (که همواره به دلیل کمبود منابع، مانند فضای swap یا حافظه رخ میدهد)، fork مقدار -1 را به فرایند والد بازمیگرداند و هیچ فرایند فرزندی ایجاد نمیشود..IP فرایندهای مشتقشده (forked) درست مانند فرایند اصلی از طریق دستور exit خارج میشوند. فرایندهای مشتقشده مجازند در فایلهای گزارش (log) بنویسند. اگر اشکالزدایی یا ثبت وقایع را در بیشتر فرایندها غیرفعال نکنید، نتیجه میتواند گیجکننده باشد.
- برخی از پیادهسازیهای pty ممکن است حتی به طور موقت با چندین خواننده و نویسنده دچار اختلال و تداخل شوند. بنابراین، امنترین کار این است که پیش از آغاز فرایندها (spawning)، عمل fork انجام شود.
- interact [string1 body1] ... [stringn [bodyn]]
- کنترل فرایند جاری را به کاربر واگذار میکند، به طوری که کلیدهای فشردهشده به فرایند جاری ارسال میشوند، و stdout و stderr فرایند جاری بازگردانده میشوند.
- جفتهای رشته-بدنه (string-body) میتوانند به عنوان آرگومان مشخص شوند، که در این حالت با وارد شدن رشتهٔ مربوطه، بدنه اجرا میشود. (به طور پیشفرض، رشته به فرایند جاری ارسال نمیشود.) در صورتی که بدنهٔ پایانی وجود نداشته باشد، دستور interpreter فرض میشود.
- اگر آرگومانهای کل عبارت interact به بیش از یک خط نیاز داشته باشند، میتوان تمام آرگومانها را درون آکولاد قرار داد تا از پایان دادن به هر خط با یک backslash اجتناب شود. در این یک مورد، با وجود آکولادها، جایگزینیهای معمول Tcl رخ خواهند داد.
- برای مثال،
دستور زیر interact
را با
جفتهای
رشته-بدنهٔ
تعریفشدهٔ
زیر اجرا
میکند:
هنگامی که ^Z
فشرده شود،
Expect معلق
میشود.
(پرچم -reset
حالتهای
ترمینال را
بازمیگرداند.)
هنگامی که ^A
فشرده شود،
کاربر پیام
"you typed a control-A" را
میبیند و
یک ^A به
فرایند
ارسال
میشود.
هنگامی که $
فشرده شود،
کاربر
تاریخ را
میبیند.
هنگامی که ^C
فشرده شود،
Expect خارج
میشود. اگر
"foo" وارد
شود، کاربر
"bar" را
میبیند.
هنگامی که ~~
فشرده شود،
مفسر Expect به
صورت
تعاملی
اجرا
میشود.
set CTRLZ \032 interact { -reset $CTRLZ {exec kill -STOP [pid]} \001 {send_user "you typed a control-A\n"; send "\001" } $ {send_user "The date is [clock format [clock seconds]]."} \003 exit foo {send_user "bar"} ~~ } - در جفتهای رشته-بدنه، رشتهها به ترتیبی که به عنوان آرگومان فهرست شدهاند تطبیق داده میشوند. رشتههایی که تطابق جزئی دارند، به امید رسیدن بقیهٔ نویسهها به فرایند جاری ارسال نمیشوند. اگر سپس نویسههایی وارد شوند به گونهای که دیگر امکان هیچ تطابقی وجود نداشته باشد، تنها بخشی از رشته به فرایند ارسال خواهد شد که به هیچ وجه نمیتواند آغازگر تطابق دیگری باشد. بنابراین، رشتههایی که زیررشتهای از تطابقهای جزئی هستند، در صورتی که رشتههای اصلی که برای تطابق تلاش میکردند در نهایت ناموفق شوند، میتوانند بعداً تطبیق داده شوند.
- به طور
پیشفرض،
تطبیق
رشتهها
دقیق و بدون
نویسههای
عام (wildcard) است.
(در مقابل،
دستور expect به
طور
پیشفرض از
الگوهای
سبک glob
استفاده
میکند.)
پرچم -ex
میتواند
برای
محافظت از
الگوهایی
استفاده
شود که ممکن
است در غیر
این صورت با
پرچمهای
interact اشتباه
گرفته شوند.
هر الگویی
که با "-"
آغاز
میشود
باید به این
روش محافظت
شود. (تمام
رشتههایی
که با "-"
شروع
میشوند
برای
گزینههای
آینده رزرو
شدهاند.)
پرچم -re رشته را وادار میکند تا به عنوان الگویی به سبک عبارت باقاعده (regexp) تفسیر شود. در این حالت، زیررشتههای منطبق در متغیر interact_out ذخیره میشوند؛ مشابه روشی که expect خروجی خود را در متغیر expect_out ذخیره میکند. پرچم -indices نیز به طور مشابه پشتیبانی میشود.
الگوی eof کنشی را معرفی میکند که هنگام پایان فایل (end-of-file) اجرا میشود. یک الگوی مجزای eof همچنین میتواند پس از پرچم -output بیاید که در این صورت اگر هنگام نوشتن خروجی یک eof تشخیص داده شود، تطبیق مییابد. کنش پیشفرض eof مقدار "return" است، به طوری که interact به سادگی با دریافت هرگونه EOF بازمیگردد.
الگوی timeout یک مهلت زمانی (به ثانیه) و کنشی را معرفی میکند که پس از خوانده نشدن هیچ نویسهای برای یک مدت مشخص اجرا میشود. الگوی timeout به فرایندی اعمال میشود که اخیراً مشخص شده است. هیچ مهلت زمانی پیشفرضی وجود ندارد. متغیر ویژهٔ "timeout" (استفادهشده توسط دستور expect) هیچ تاثیری بر این مهلت زمانی ندارد.
برای مثال، عبارت زیر میتواند برای خروج خودکار (autologout) کاربرانی استفاده شود که به مدت یک ساعت چیزی تایپ نکردهاند اما همچنان پیامهای مکرر سیستمی دریافت میکنند:
interact -input $user_spawn_id timeout 3600 return -output \ $spawn_idاگر الگو کلیدواژهٔ null باشد و مقادیر null مجاز باشند (از طریق دستور remove_nulls)، در صورتی که یک بایت 0 در ASCII تطبیق یابد، بدنهٔ مربوطه اجرا میشود. تطبیق بایتهای ۰ از طریق الگوهای glob یا regexp امکانپذیر نیست.
قرار دادن پرچم -iwrite پیش از یک الگو باعث میشود که متغیر interact_out(spawn_id) روی spawn_idای تنظیم شود که با الگو (یا eof) تطبیق یافته است.
کنشهایی مانند break و continue باعث میشوند ساختارهای کنترلی (یعنی for، proc) به شیوهٔ معمول عمل کنند. با این حال، return باعث میشود interact به فراخوانندهٔ خود بازگردد، در حالی که inter_return باعث میشود interact موجب بازگشت در فراخوانندهٔ خود شود. برای مثال، اگر "proc foo" دستور interact را فراخوانی کند و سپس کنش inter_return اجرا شود، proc foo بازمیگردد. (این بدان معناست که اگر interact دستور interpreter را فراخوانی کند، وارد کردن تعاملی return باعث ادامه یافتن interact خواهد شد، در حالی که inter_return باعث بازگشت interact به فراخوانندهاش میشود.)
- در طول interact، حالت raw استفاده میشود تا تمامی نویسهها بتوانند به فرایند جاری منتقل شوند. اگر فرایند جاری سیگنالهای کنترل کار (job control) را مدیریت نکند، در صورت ارسال سیگنال توقف (به طور پیشفرض ^Z) متوقف خواهد شد. برای راهاندازی مجدد آن، یک سیگنال ادامه ارسال کنید (مانند دستور "kill -CONT <pid>"). اگر واقعاً میخواهید یک SIGSTOP به چنین فرایندی ارسال کنید (با ^Z)، اجرای csh در ابتدا و سپس اجرای برنامهٔ خود را در نظر بگیرید. از سوی دیگر، اگر میخواهید یک SIGSTOP به خود Expect ارسال کنید، ابتدا interpreter را فراخوانی کنید (شاید با استفاده از یک نویسهٔ گریز)، و سپس ^Z را فشار دهید.
- جفتهای رشته-بدنه میتوانند به عنوان میانبری برای اجتناب از ورود به مفسر و اجرای تعاملی دستورها استفاده شوند. حالت قبلی ترمینال در زمان اجرای بدنهٔ یک جفت رشته-بدنه استفاده میشود.
- برای سرعت بیشتر، کنشها به طور پیشفرض در حالت raw اجرا میشوند. پرچم -reset ترمینال را به حالتی که پیش از اجرای interact داشت بازمیگرداند (همواره، حالت cooked). توجه داشته باشید نویسههایی که در هنگام تغییر حالت وارد میشوند ممکن است از دست بروند (یک ویژگی نامطلوب در درایور ترمینالِ برخی از سیستمها). تنها دلیل برای استفاده از -reset این است که کنش شما وابسته به اجرا در حالت cooked باشد..IP پرچم -echo نویسههایی را که با الگوی پس از آن مطابقت دارند، همزمان با خوانده شدن هر نویسه، به فرایندی که آنها را تولید کرده است بازمیگرداند. این ویژگی ممکن است زمانی مفید باشد که کاربر نیاز دارد بازخورد الگوهای نیمهتایپشده را مشاهده کند.
- اگر بازتاب
(echo) یک الگو در
حال انجام
باشد اما در
نهایت
تطابق
برقرار
نشود،
نویسهها
به فرایند
ایجادشده
ارسال
میشوند.
اگر فرایند
ایجادشده
نیز آنها
را بازتاب
دهد، کاربر
نویسهها
را دو بار
خواهد دید.
-echo
احتمالاً
تنها در
شرایطی
مناسب است
که بعید
باشد کاربر
الگو را
ناتمام
بگذارد.
برای مثال،
بخش زیر از rftp
(اسکریپت ftp
بازگشتی)
گرفته شده
است؛ جایی
که از کاربر
خواسته
میشود
برای
دریافت (get)،
ارسال (put) یا
فهرستگیری
(list) بازگشتی
دایرکتوری
جاری، ~g، ~p یا ~l
را وارد
کند. اینها
با
دستورهای
عادی ftp چنان
فاصلهای
دارند که
بعید است
کاربر پس از
~ چیز دیگری
را تایپ
کند، مگر به
اشتباه، که
در آن صورت
نیز
احتمالاً
نتیجه را به
سادگی
نادیده
خواهد گرفت.
interact { -echo ~g {getcurdirectory 1} -echo ~l {getcurdirectory 0} -echo ~p {putcurdirectory} }پرچم -nobuffer نویسههایی را که با الگوی پس از آن مطابقت دارند، همزمان با خوانده شدن نویسهها، به فرایند خروجی ارسال میکند.این ویژگی زمانی مفید است که بخواهید اجازه دهید یک برنامه الگو را بازتاب دهد. برای مثال، مورد زیر ممکن است برای نظارت بر شمارهای که فردی شمارهگیری میکند (یک مودم با سبک Hayes) استفاده شود. با هر بار مشاهده "atd"، اسکریپت ادامه خط را ثبت میکند.
proc lognumber {} { interact -nobuffer -re "(.*)\r" return puts $log "[clock format [clock seconds]]: dialed $interact_out(1,string)" } interact -nobuffer "atd" lognumber - در طول interact، استفاده قبلی از log_user نادیده گرفته میشود. بهویژه، interact خروجی خود را مجبور میکند که ثبت (به خروجی استاندارد ارسال) شود، چرا که فرض بر این است که کاربر مایل نیست تعاملی کورکورانه داشته باشد.
- پرچم -o باعث میشود که هر جفت کلید-بدنه (key-body) پس از آن، بر خروجی فرایند جاری اعمال شود. این ویژگی برای مثال هنگام تعامل با میزبانهایی که در طول یک نشست telnet نویسههای ناخواسته ارسال میکنند مفید است.
- بهطور پیشفرض، interact انتظار دارد که کاربر روی stdin بنویسد و stdout خود فرایند Expect را بخواند. پرچم -u (برگرفته از "user") باعث میشود interact کاربر را فرایندی در نظر بگیرد که با آرگومان آن نامگذاری شده است (که باید یک شناسه ایجادشده یا spawned id باشد).
- این امر به دو فرایند نامرتبط اجازه میدهد تا بدون استفاده از یک حلقه صریح، به یکدیگر متصل شوند. برای کمک به اشکالزدایی، پیامهای تشخیصی Expect همیشه به stderr فرستاده میشوند (یا برای برخی اطلاعات ثبت وقایع و اشکالزدایی، به stdout). به همین دلیل، دستور interpreter به صورت تعاملی از stdin خواهد خواند.
- برای مثال،
قطعهکد
زیر یک
فرایند login
ایجاد
میکند. سپس
با کاربر
شمارهگیری
میکند
(نشان داده
نشده)، و در
نهایت آن دو
را به
یکدیگر
متصل
میسازد.
البته، هر
فرایندی را
میتوان
جایگزین login
کرد. برای
نمونه، یک
پوسته به
کاربر
اجازه
میدهد تا
بدون نیاز
به ارائه
حساب
کاربری و
گذرواژه
کار کند.
spawn login set login $spawn_id spawn tip modem # dial back out to user # connect user to login interact -u $login
برای ارسال خروجی به چندین فرایند، هر فهرست spawn id را با پیشوند پرچم -output مشخص کنید. ورودی یک گروه از spawn idهای خروجی میتواند توسط فهرستی از spawn idها با پیشوند پرچم -input تعیین شود. (هر دو پرچم -input و -output میتوانند فهرستها را به همان قالبی دریافت کنند که پرچم -i در دستور expect دریافت میکند، با این تفاوت که any_spawn_id در interact معنایی ندارد.) تمام پرچمها و رشتهها (یا الگوها)ی بعدی تا زمانی که پرچم -input دیگری ظاهر شود، به این ورودی اعمال میشوند. اگر هیچ -input ظاهر نشود، -output به معنای "-input $user_spawn_id -output" تلقی خواهد شد. (مشابهاً برای الگوهایی که -input ندارند.) اگر یک -input مشخص شود، جایگزین $user_spawn_id میشود. اگر دومین -input مشخص شود، جایگزین $spawn_id خواهد شد. پرچمهای -input بیشتری را نیز میتوان مشخص کرد.دو فرایند ورودی ضمنی بهطور پیشفرض خروجیهای خود را به صورت $spawn_id و $user_spawn_id (به طور معکوس) دارند. اگر یک پرچم -input بدون پرچم -output ظاهر شود، نویسههای آن فرایند دور ریخته میشوند.
پرچم -i زمانی که هیچ پرچم -input یا -output دیگری استفاده نشده باشد، جایگزینی برای spawn_id جاری معرفی میکند. یک پرچم -i متضمن پرچم -o نیز هست.
تغییر فرایندهایی که با آنها تعامل میشود با استفاده از spawn idهای غیرمستقیم امکانپذیر است. (شناسههای غیرمستقیم spawn id در بخش دستور expect شرح داده شدهاند.) شناسههای غیرمستقیم spawn id را میتوان با پرچمهای -i، -u، -input یا -output تعیین کرد.
- interpreter [args]
- باعث میشود که از کاربر به صورت تعاملی برای دریافت دستورهای Expect و Tcl درخواست شود. نتیجه هر دستور چاپ خواهد شد.
- کنشهایی مانند break و continue باعث میشوند ساختارهای کنترلی (مانند for و proc) به روش معمول رفتار کنند. اما return باعث میشود interpreter به فراخواننده خود بازگردد، در حالی که inter_return باعث میشود interpreter موجب بازگشت در فراخواننده خود شود. برای مثال، اگر "proc foo" دستور interpreter را فراخوانی کند و سپس کنش inter_return اجرا شود، proc foo بازمیگردد. هر دستور دیگری باعث میشود interpreter به درخواست دستورهای جدید ادامه دهد.
- بهطور پیشفرض، اعلان (prompt) شامل دو عدد صحیح است. عدد اول عمق پشته ارزیابی را مشخص میکند (یعنی چند بار Tcl_Eval فراخوانی شده است). عدد دوم شناسه تاریخچه در Tcl است. اعلان را میتوان با تعریف رویهای به نام "prompt1" تنظیم کرد که مقدار بازگشتی آن به عنوان اعلان بعدی استفاده میشود. اگر یک عبارت دارای علامت نقلقول، پرانتز، آکوالاد یا قلاب باز باشد، با رفتن به سطر جدید یک اعلان ثانویه (بهطور پیشفرض "+> ") صادر میشود. اعلان ثانویه را میتوان با تعریف رویهای به نام "prompt2" تعیین کرد.
- در طول اجرای interpreter، از حالت پخته (cooked mode) استفاده میشود، حتی اگر فراخواننده آن از حالت خام (raw mode) استفاده کرده باشد.
- اگر stdin بسته
شود، interpreter
بازمیگردد
مگر اینکه
پرچم -eof
استفاده
شده باشد؛
که در آن
صورت،
آرگومان
بعدی
فراخوانی
میشود..TP log_file
[args] [[-a] file] اگر نام
فایلی
ارائه شود،
log_file رونوشتی
از نشست را
(با شروع از
آن نقطه) در
فایل ثبت
خواهد کرد.
اگر هیچ
آرگومانی
داده نشود،
log_file ضبط را
متوقف
میکند. هر
فایل لاگ
قبلی بسته
میشود.
به جای نام فایل، میتوان با استفاده از پرچمهای -open یا -leaveopen یک شناسهٔ فایل Tcl ارائه داد. این عملکرد مشابه دستور spawn است. (برای اطلاعات بیشتر به spawn مراجعه کنید.)
پرچم -a باعث میشود خروجیهایی که توسط دستور log_user نادیده گرفته شده بودند نیز در لاگ ثبت شوند.
بهطور پیشفرض، دستور log_file به جای کوتاهکردن فایلهای قدیمی، به انتهای آنها ضمیمه میکند تا امکان فعال و غیرفعال کردن مکرر گزارشگیری در طول یک نشست فراهم باشد. برای خالیکردن فایلها، از پرچم -noappend استفاده کنید.
پرچم -info باعث میشود log_file توصیفی از جدیدترین آرگومانهای غیر-info دادهشده را برگرداند.
- log_user -info|0|1
- بهطور
پیشفرض،
گفتگوی send/expect
در stdout (و در
صورت باز
بودن، در یک
فایل لاگ)
ثبت میشود.
ثبت در stdout با
دستور “log_user 0”
غیرفعال و
با “log_user 1”
مجدداً
فعال
میشود. ثبت
در فایل لاگ
بدون تغییر
میماند.
پرچم -info باعث میشود log_user توصیفی از جدیدترین آرگومانهای غیر-info دادهشده را برگرداند.
- match_max [-d] [-i spawn_id] [size]
- اندازهٔ بافر (به بایت) را که به صورت داخلی توسط expect استفاده میشود تعیین میکند. بدون آرگومان size، اندازهٔ فعلی بازگردانده میشود.
- با پرچم -d، اندازهٔ پیشفرض تنظیم میشود. (پیشفرض اولیه ۲۰۰۰ است.) با پرچم -i، اندازه برای spawn id نامبرده تنظیم میشود، در غیر این صورت برای فرآیند فعلی تنظیم خواهد شد.
- overlay [-# spawn_id] [-# spawn_id] [...] program [args]
- دستور program args را به جای برنامهٔ فعلی Expect که خاتمه مییابد، اجرا میکند. یک آرگومان خط تیرهٔ تنها (bare hyphen)، یک خط تیره در ابتدای نام دستور قرار میدهد، گویی که یک شل لاگین (login shell) است. تمام spawn_idها بسته میشوند به جز مواردی که به عنوان آرگومان نام برده شدهاند. اینها به شناسههای فایل نامبرده نگاشت میشوند.
- شناسههای
spawn_id برای به
ارث بردن
توسط
برنامهٔ
جدید به
شناسههای
فایل نگاشت
میشوند.
برای مثال،
خط زیر chess را
اجرا
میکند و به
آن اجازه
میدهد
توسط
فرآیند
فعلی کنترل
شود -
مثلاً، یک
استاد
شطرنج.
overlay -0 $spawn_id -1 $spawn_id -2 $spawn_id chess
این روش کارآمدتر از “interact -u” است، با این حال، توانایی انجام تعامل برنامهریزیشده را فدا میکند زیرا فرآیند Expect دیگر در کنترل نیست. - توجه داشته باشید که هیچ ترمینال کنترلی ارائه نمیشود. بنابراین، اگر ورودی استاندارد را قطع کنید یا مجدداً نگاشت نمایید، برنامههایی که کنترل شغل (job control) انجام میدهند (شلها، login و غیره) به درستی کار نخواهند کرد.
- parity [-d] [-i spawn_id] [value]
- مشخص میکند که آیا پاریتی (parity) باید در خروجی فرآیندهای راهاندازیشده حفظ شود یا حذف گردد. اگر value صفر باشد، پاریتی حذف میشود، در غیر این صورت حذف نخواهد شد. بدون آرگومان value، مقدار فعلی برگردانده میشود.
- با پرچم -d، مقدار پیشفرض پاریتی تنظیم میشود. (پیشفرض اولیه ۱ است، یعنی پاریتی حذف نمیشود.) با پرچم -i، مقدار پاریتی برای spawn id نامبرده تنظیم میشود، در غیر این صورت برای فرآیند فعلی تنظیم خواهد شد.
- remove_nulls [-d] [-i spawn_id] [value]
- مشخص میکند که آیا کاراکترهای تهی (null) پیش از تطبیق الگو یا ذخیره در متغیر expect_out یا interact_out، از خروجی فرآیندهای راهاندازیشده حفظ یا حذف شوند. اگر value برابر ۱ باشد، کاراکترهای تهی حذف میشوند. اگر value برابر ۰ باشد، کاراکترهای تهی حذف نمیشوند. بدون آرگومان value، مقدار فعلی برگردانده میشود.
- با پرچم -d،
مقدار
پیشفرض
تنظیم
میشود.
(پیشفرض
اولیه ۱
است، یعنی
کاراکترهای
تهی حذف
میشوند.)
با پرچم -i،
مقدار برای
spawn id نامبرده
تنظیم
میشود، در
غیر این
صورت برای
فرآیند
فعلی تنظیم
خواهد شد.
چه کاراکترهای تهی حذف شوند یا نشوند، Expect بایتهای null را در لاگ و stdout ثبت خواهد کرد.
- send [-flags] string
- رشتهٔ string را
به فرآیند
فعلی ارسال
میکند.
برای مثال،
دستور
send "hello world\r"
کاراکترهای h e l l o <blank> w o r l d <return> را به فرآیند فعلی ارسال میکند. (زبان Tcl شامل یک دستور شبه-printf (به نام format) است که میتواند رشتههایی با هر میزان پیچیدگی دلخواه بسازد.)
- کاراکترها
بلافاصله
ارسال
میشوند،
اگرچه
برنامههای
دارای
ورودی
میانگیرشدهٔ
خطی (line-buffered) تا
زمانی که
کاراکتر return
ارسال نشود
کاراکترها
را نخواهند
خواند.
کاراکتر return
با “\r” نشان
داده
میشود.
پرچم -- باعث میشود آرگومان بعدی به جای یک پرچم، به عنوان یک رشته تفسیر شود. قبل از هر رشتهای میتوان “--” قرار داد، چه در ظاهر شبیه پرچم باشد و چه نباشد. این سازوکار مطمئنی را برای مشخص کردن رشتههای متغیر بدون تداخل با مواردی که تصادفاً شبیه پرچم هستند، فراهم میکند. (تمام رشتههایی که با “-” شروع میشوند برای گزینههای آینده رزرو شدهاند.)
پرچم -i اعلام میکند که رشته به spawn_id نامبرده ارسال شود. اگر spawn_id برابر user_spawn_id باشد و ترمینال در حالت raw قرار داشته باشد، کاراکترهای خط جدید (newline) در رشته به توالیهای return-newline ترجمه میشوند تا طوری به نظر برسند که گویی ترمینال در حالت cooked قرار دارد. پرچم -raw این ترجمه را غیرفعال میکند.
پرچم -null کاراکترهای null (بایتهای ۰) را ارسال میکند. بهطور پیشفرض، یک null ارسال میشود. یک عدد صحیح میتواند پس از -null بیاید تا تعداد کاراکترهای null ارسالی را مشخص کند.
پرچم -break یک وضعیت break ایجاد میکند. این تنها در صورتی معنا دارد که spawn id به یک دستگاه tty باز شده از طریق “spawn -open” اشاره کند. اگر فرآیندی مانند tip را راهاندازی کردهاید، باید از قرارداد tip برای ایجاد break استفاده کنید.
پرچم -s باعث میشود خروجی به صورت “آهسته” ارسال شود، تا بدین ترتیب از وضعیت رایجی که در آن رایانه سریعتر از بافر ورودی تایپ میکند (بافری که برای یک انسان طراحی شده که هرگز با آن سرعت تایپ نمیکند) جلوگیری شود. این خروجی توسط مقدار متغیر “send_slow” کنترل میشود که یک لیست دو عنصری میگیرد. اولین عنصر یک عدد صحیح است که تعداد بایتهایی را که باید به طور یکپارچه (اتمیک) ارسال شوند توصیف میکند. عنصر دوم یک عدد حقیقی است که تعداد ثانیههایی را مشخص میکند که ارسالهای اتمیک باید با آن از یکدیگر فاصله داشته باشند. برای مثال، دستور “set send_slow {10 .001}” دستور “send -s” را وادار میکند تا رشتهها را با ۱ میلیثانیه فاصله میان هر ۱۰ کاراکتر ارسالشده بفرستد.
پرچم -h باعث میشود خروجی (تا حدی) شبیه به تایپ واقعی یک انسان ارسال شود. تاخیرهای انسانگونه در میان کاراکترها ظاهر میشوند. (الگوریتم بر پایه توزیع وایبل (Weibull) است، همراه با تغییراتی متناسب با این کاربرد خاص.) این خروجی با مقدار متغیر “send_human” کنترل میشود که یک لیست پنج عنصری میپذیرد. دو عنصر اول، میانگین زمان بین ورود (interarrival time) کاراکترها بر حسب ثانیه هستند. عنصر اول بهطور پیشفرض استفاده میشود. عنصر دوم در انتهای کلمات استفاده میشود تا مکثهای نامحسوسی را که گاهی اوقات در چنین گذارهایی رخ میدهند شبیهسازی کند. پارامتر سوم مقیاسی از متغیر بودن است که در آن ۰٫۱ کاملاً متغیر، ۱ تا حد معقولی متغیر، و ۱۰ کاملاً نامتغیر است. حالتهای حدی از ۰ تا بینهایت هستند. دو پارامتر آخر به ترتیب حداقل و حداکثر زمان بین ورود هستند. حداقل و حداکثر در آخر استفاده میشوند و زمان نهایی را محدود (clip) میکنند. اگر حداقل و حداکثر مقادیر کافی را برش بزنند، میانگین نهایی میتواند کاملاً متفاوت از میانگین دادهشده باشد.
به عنوان مثال، دستور زیر یک تایپیست سریع و یکدست را شبیهسازی میکند:
set send_human {.1 .3 1 .05 2} send -h "I'm hungry. Let's do lunch."در حالی که دستور زیر ممکن است پس از یک شبزندهداری سنگین مناسبتر باشد:set send_human {.4 .4 .2 .5 100} send -h "Goodd party lash night!"توجه داشته باشید که خطاها شبیهسازی نمیشوند، اگرچه میتوانید خودتان با گنجاندن اشتباهات و تصحیحات در یک آرگومان send، وضعیتهای تصحیح خطا را ایجاد کنید.پرچمهای ارسال کاراکترهای null، ارسال breakها، اجبار به خروجی آهسته و خروجی به سبک انسان مانعةالجمع هستند. تنها موردی که در آخر مشخص شود اعمال خواهد شد. علاوه بر این، هیچ آرگومان string نمیتواند همراه با پرچمهای ارسال کاراکترهای null یا break مشخص شود.
ایدهٔ خوبی است که قبل از اولین send به یک فرآیند، یک expect قرار دهید. expect منتظر شروع فرآیند خواهد ماند، در حالی که send نمیتواند این کار را انجام دهد. به ویژه اگر اولین send پیش از شروع اجرای فرآیند تکمیل شود، با خطر نادیده گرفته شدن دادههایتان مواجه میشوید. در شرایطی که برنامههای تعاملی اعلان اولیه (prompt) ارائه نمیدهند، میتوانید قبل از send یک تاخیر قرار دهید، مانند:
# To avoid giving hackers hints on how to break in, # this system does not prompt for an external password. # Wait for 5 seconds for exec to complete spawn telnet very.secure.gov sleep 5 send password\r
دستور exp_send یک نام مستعار برای send است. اگر از Expectk یا نسخه دیگری از Expect در محیط Tk استفاده میکنید، send توسط Tk برای هدفی کاملاً متفاوت تعریف شده است. exp_send برای سازگاری میان محیطها ارائه شده است. نامهای مستعار مشابهی برای سایر دستورهای send در Expect نیز ارائه شده است..TP send_error [-flags] string مانند send است، با این تفاوت که خروجی بهجای فرایند فعلی، به stderr ارسال میشود.
- send_log [--] string
- مانند send است، با این تفاوت که رشته فقط به فایل ثبت وقایع ارسال میشود (به log_file مراجعه کنید). اگر هیچ فایل ثبت وقایعی باز نباشد، آرگومانها نادیده گرفته میشوند.
- send_tty [-flags] string
- مانند send است، با این تفاوت که خروجی بهجای فرایند فعلی، به /dev/tty ارسال میشود.
- send_user [-flags] string
- مانند send است، با این تفاوت که خروجی بهجای فرایند فعلی، به stdout ارسال میشود.
- sleep seconds
- باعث میشود اسکریپت به مدت ثانیههای مشخصشده به خواب برود. ثانیهها میتوانند یک عدد اعشاری باشند. وقفهها (و در صورت استفاده از Expectk، رویدادهای Tk) در حین به خواب رفتن Expect پردازش میشوند.
- spawn [args] program [args]
- فرایند جدیدی را ایجاد میکند که program args را اجرا مینماید. ورودی استاندارد (stdin)، خروجی استاندارد (stdout) و خطای استاندارد (stderr) آن به Expect متصل میشوند تا بتوان توسط سایر دستورهای Expect در آنها نوشت و از آنها خواند. اتصال با close یا در صورتی که خود فرایند هر یک از شناسههای فایل را ببندد، قطع میشود.
- هنگامی که فرایندی با spawn آغاز میشود، متغیر spawn_id روی توصیفکنندهای تنظیم میشود که به آن فرایند ارجاع دارد. فرایندی که توسط spawn_id مشخص میشود، فرایند فعلی در نظر گرفته میشود. spawn_id را میتوان خواند یا نوشت که در عمل امکان کنترل کارها را فراهم میکند.
- user_spawn_id یک
متغیر
سراسری
شامل
توصیفکنندهای
است که به
کاربر
ارجاع دارد.
برای مثال،
هنگامی که
spawn_id روی این
مقدار
تنظیم شود،
expect مانند expect_user
رفتار
میکند.
error_spawn_id یک متغیر سراسری شامل توصیفکنندهای است که به خطای استاندارد ارجاع دارد. برای مثال، هنگامی که spawn_id روی این مقدار تنظیم شود، send مانند send_error رفتار میکند.
- tty_spawn_id یک
متغیر
سراسری
شامل
توصیفکنندهای
است که به /dev/tty
ارجاع دارد.
اگر /dev/tty وجود
نداشته
باشد (مانند
یک اسکریپت
cron، at، یا batch)،
آنگاه tty_spawn_id
تعریفنشده
است. این
موضوع را
میتوان به
صورت زیر
بررسی کرد:
if {[info vars tty_spawn_id]} { # /dev/tty exists } else { # /dev/tty doesn't exist # probably in cron, batch, or at script } - دستور spawn شناسه فرایند یونیکس را برمیگرداند. اگر هیچ فرایندی ایجاد نشود، 0 بازگردانده میشود. متغیر spawn_out(slave,name) روی نام دستگاه اسلیو pty تنظیم میشود.
- بهطور پیشفرض، spawn نام دستور و آرگومانهای آن را بازتاب (echo) میدهد. پرچم -noecho مانع از انجام این کار توسط spawn میشود.
- پرچم -console
باعث
میشود
خروجی
کنسول به
فرایند
ایجادشده
بازهدایت
شود. این
قابلیت در
همه
سیستمها
پشتیبانی
نمیشود.
در درون، spawn از یک pty استفاده میکند که به همان شیوه tty کاربر مقداردهی اولیه میشود. همچنین تنظیمات آن طوری مقداردهی اولیه میشوند که همه موارد “معقول” (مطابق با stty(1)) باشند. اگر متغیر stty_init تعریف شده باشد، به سبک آرگومانهای stty به عنوان پیکربندی بیشتر تفسیر میشود. برای مثال، دستور “set stty_init raw” باعث میشود ترمینالهای فرایندهای بعدیِ ایجادشده در حالت خام (raw) آغاز به کار کنند. -nottycopy از مقداردهی اولیه بر اساس tty کاربر صرفنظر میکند. -nottyinit از مقداردهی اولیه “معقول” صرفنظر میکند.
- بهطور
معمول،
اجرای spawn
زمان کمی
میبرد. اگر
متوجه شدید
که spawn زمان
قابلتوجهی
صرف
میکند،
احتمالاً
با ptyهایی
مواجه شده
است که
مسدود (wedged)
شدهاند.
تعدادی
آزمایش روی
ptyها انجام
میشود تا
از درگیر
شدن با
فرایندهای
سرکش
جلوگیری
شود. (این
آزمایشها
برای هر pty
مسدودشده
۱۰ ثانیه
زمان
میبرند.)
اجرای Expect با
گزینه -d
نشان
میدهد که
آیا Expect با
چندین pty در
وضعیتهای
نامتعارف
مواجه شده
است یا خیر.
اگر
نمیتوانید
فرایندهایی
را که این
ptyها به
آنها متصل
هستند
خاتمه
دهید، تنها
چاره ممکن
است
راهاندازی
مجدد سیستم
(reboot) باشد.
اگر program به دلیل شکست exec(2) نتواند با موفقیت ایجاد شود (مثلاً هنگامی که program وجود ندارد)، یک پیام خطا توسط دستور بعدی interact یا expect بازگردانده میشود، به طوری که گویی program اجرا شده و پیام خطا را به عنوان خروجی تولید کرده است. این رفتار، پیامد طبیعی نحوه پیادهسازی spawn است. در درون، spawn عمل fork را انجام میدهد که پس از آن فرایند ایجادشده هیچ راهی برای برقراری ارتباط با فرایند اصلی Expect به جز ارتباط از طریق spawn_id ندارد.
پرچم -open باعث میشود که آرگومان بعدی به عنوان یک شناسه فایل Tcl (یعنی بازگرداندهشده توسط open) تفسیر شود. سپس شناسه spawn میتواند به گونهای استفاده شود که گویی یک فرایند ایجادشده است. (دیگر نباید از شناسه فایل استفاده شود.) این امکان را فراهم میسازد تا با دستگاههای خام، فایلها و خطلولهها مانند فرایندهای ایجادشده بدون استفاده از pty رفتار شود. مقدار 0 برای نشان دادن اینکه هیچ فرایند مرتبطی وجود ندارد برگردانده میشود. هنگامی که اتصال به فرایند ایجادشده بسته شود، شناسه فایل Tcl نیز بسته خواهد شد. پرچم -leaveopen مشابه -open است، با این تفاوت که -leaveopen باعث میشود شناسه فایل حتی پس از بسته شدن شناسه spawn باز بماند.
پرچم -pty باعث باز شدن یک pty میشود، اما فرایندی ایجاد نمیگردد. مقدار 0 برای نشان دادن اینکه هیچ فرایند مرتبطی وجود ندارد برگردانده میشود. Spawn_id طبق معمول تنظیم میگردد.
متغیر spawn_out(slave,fd) روی شناسه فایل متناظر با اسلیو pty تنظیم میشود. میتوان آن را با استفاده از “close -slave” بست.
پرچم -ignore سیگنالی را مشخص میکند که باید در فرایند ایجادشده نادیده گرفته شود. در غیر این صورت، سیگنالها رفتار پیشفرض را دریافت میکنند. نامگذاری سیگنالها مانند دستور trap است، با این تفاوت که هر سیگنال به یک پرچم جداگانه نیاز دارد.
- strace level
- باعث
میشود
عبارات
بعدی پیش از
اجرا چاپ
شوند.
(دستور trace در Tcl
متغیرها را
ردگیری
میکند.) level
مشخص
میکند که
ردگیری تا
چه عمقی از
پشته
فراخوانی (call
stack) ادامه
یابد. برای
مثال،
دستور زیر
Expect را در
حالی اجرا
میکند که ۴
سطح اول
فراخوانیها
را ردگیری
میکند،
اما سطوح
پایینتر
از آن را
ردگیری
نمینماید.
expect -c "strace 4" script.exp
پرچم -info باعث میشود strace توصیفی از جدیدترین آرگومانهای غیر info دادهشده را برگرداند..TP stty args حالتهای ترمینال را مشابه با دستور خارجی stty تغییر میدهد.
بهطور پیشفرض، به ترمینال کنترلکننده دسترسی پیدا میشود. با افزودن «< /dev/tty...» به دستور میتوان به سایر ترمینالها دسترسی یافت. (توجه داشته باشید که آرگومانها نباید در یک آرگومان واحد گروهبندی شوند.)
درخواستهای بررسی وضعیت، آن را به عنوان نتیجه دستور بازمیگردانند. اگر وضعیتی درخواست نشود و به ترمینال کنترلکننده دسترسی پیدا شود، وضعیت پیشین مشخصههای raw و echo به شکلی بازگردانده میشود که بعداً بتواند توسط این دستور مورد استفاده قرار گیرد.
برای نمونه، آرگومانهای raw یا -cooked ترمینال را در حالت raw قرار میدهند. آرگومانهای -raw یا cooked ترمینال را در حالت cooked قرار میدهند. آرگومانهای echo و -echo ترمینال را به ترتیب در حالت echo و noecho قرار میدهند.
- مثال زیر
نشان
میدهد که
چگونه
میتوان
پژواک (echoing) را
موقتاً
غیرفعال
کرد. این
روش
میتواند
در
اسکریپتهایی
که در غیر
این صورت
خودکار
هستند
استفاده
شود تا از
تعبیه
گذرواژهها
در آنها
جلوگیری
شود.
(توضیحات
بیشتر در
این مورد را
در زیر، در
بخش EXPECT HINTS
ببینید.)
stty -echo send_user "Password: " expect_user -re "(.*)\n" set password $expect_out(1,string) stty echo
- system args
- مقدار args را به عنوان ورودی به sh(1) میدهد، درست مانند اینکه به عنوان دستوری از یک ترمینال تایپ شده باشد. Expect تا زمان پایان یافتن شل منتظر میماند. وضعیت بازگشتی از sh به همان روشی مدیریت میشود که exec وضعیت بازگشتی خود را مدیریت میکند.
- برخلاف exec که stdin و stdout را به اسکریپت هدایت میکند، system هیچ تغییر مسیری انجام نمیدهد (مگر آنچه توسط خود رشته مشخص شده باشد). بنابراین، امکان استفاده از برنامههایی که باید مستقیماً با /dev/tty ارتباط برقرار کنند وجود دارد. به همین دلیل، نتایج system در گزارش (log) ثبت نمیشوند.
- timestamp [args]
- یک برچسب
زمانی (timestamp)
بازمیگرداند.
بدون هیچ
آرگومانی،
تعداد
ثانیههای
سپریشده
از مبدأ
زمانی (epoch)
بازگردانده
میشود.
پرچم -format رشتهای را معرفی میکند که بازگردانده میشود، اما جایگزینیهایی طبق قوانین POSIX برای strftime در آن اعمال میگردد. برای نمونه، %a با نام مخفف روز هفته (مثلاً Sat) جایگزین میشود. سایر موارد عبارتند از:
%a نام مخفف روز هفته %A نام کامل روز هفته %b نام مخفف ماه %B نام کامل ماه %c تاریخ-زمان مانند: Wed Oct 6 11:45:56 1993 %d روز ماه (01-31) %H ساعت (00-23) %I ساعت (01-12) %j روز (001-366) %m ماه (01-12) %M دقیقه (00-59) %p am یا pm %S ثانیه (00-61) %u روز (1-7، دوشنبه نخستین روز هفته است) %U هفته (00-53، نخستین یکشنبه، نخستین روز از هفته اول است) %V هفته (01-53، به سبک ISO 8601) %w روز (0-6) %W هفته (00-53، نخستین دوشنبه، نخستین روز از هفته اول است) %x تاریخ مانند: Wed Oct 6 1993 %X زمان مانند: 23:59:59 %y سال (00-99) %Y سال مانند: 1993 %Z منطقه زمانی (یا خالی در صورت عدم امکان تعیین) %% یک علامت درصد تنها
سایر مشخصههای % تعریفنشده هستند. سایر نویسهها بدون تغییر عبور داده خواهند شد. تنها لوکال C پشتیبانی میشود.پرچم -seconds تعدادی ثانیه از epoch را معرفی میکند تا به عنوان مبنایی برای قالببندی استفاده شود. در غیر این صورت، از زمان جاری استفاده میشود.
پرچم -gmt خروجی برچسب زمانی را ملزم میکند تا از منطقه زمانی GMT استفاده کند. بدون این پرچم، از منطقه زمانی محلی استفاده میشود.
- trap [[command] signals]
- باعث
میشود که
command
مشخصشده
هنگام
دریافت هر
یک از
سیگنالهای
دادهشده
در آینده،
اجرا شود.
دستور در
دامنه
سراسری (global scope)
اجرا
میشود. اگر
command وجود
نداشته
باشد، کنش
فعلی
سیگنال
بازگردانده
میشود. اگر
command رشته SIG_IGN
باشد،
سیگنالها
نادیده
گرفته
میشوند.
اگر command رشته
SIG_DFL باشد، کنش
سیگنالها
به حالت
پیشفرض
سیستم
بازگردانده
میشود. signals
یا یک
سیگنال تکی
است یا
فهرستی از
سیگنالها.
سیگنالها
ممکن است به
صورت عددی
یا نمادین
مطابق با signal(3)
مشخص شوند.
پیشوند «SIG»
میتواند
حذف شود.
بدون آرگومان (یا با آرگومان -number)، دستور trap شماره سیگنالِ تلهای را که هماکنون در حال اجراست بازمیگرداند.
پرچم -code کد بازگشتی دستور را به جای کدی که Tcl در هنگام شروع اجرای دستور قرار بود بازگرداند، استفاده میکند.
پرچم -interp باعث میشود دستور با استفاده از مفسری ارزیابی شود که در زمان شروع اجرای دستور فعال بوده است، نه زمانی که تله اعلان شده بود.
پرچم -name باعث میشود دستور trap نام سیگنالِ تلهای را که هماکنون در حال اجراست بازگرداند.
پرچم -max باعث میشود دستور trap بزرگترین شماره سیگنالی را که میتوان تنظیم کرد، بازگرداند.
برای نمونه، دستور «trap {send_user "Ouch!"} SIGINT» هر بار که کاربر ^C را فشار دهد، عبارت "Ouch!" را چاپ خواهد کرد.
بهطور پیشفرض، SIGINT (که معمولاً با فشردن ^C ایجاد میشود) و SIGTERM باعث خروج Expect میشوند. این رفتار به دلیل تلهٔ زیر است که بهطور پیشفرض هنگام شروع Expect ایجاد میشود.
trap exit {SIGINT SIGTERM}اگر از پرچم -D برای شروع اشکالزدا (debugger) استفاده کنید، SIGINT برای شروع اشکالزدای تعاملی بازتعریف میشود. این رفتار به دلیل تلهٔ زیر است:trap {exp_debug 1} SIGINTتلهٔ اشکالزدا را میتوان با تنظیم متغیر محیطی EXPECT_DEBUG_INIT روی یک دستور تلهٔ جدید تغییر داد.البته میتوانید هر دوی اینها را صرفاً با افزودن دستورهای trap به اسکریپت خود بازنویسی کنید. بهویژه، اگر دستور «trap exit SIGINT» اختصاصی خود را داشته باشید، جایگزین تلهٔ اشکالزدا خواهد شد. این کار زمانی مفید است که بخواهید به کلی از دسترسی کاربران به اشکالزدا جلوگیری کنید.
اگر میخواهید تلهٔ سفارشی خود را روی SIGINT تعریف کنید اما همچنان هنگام فعال بودن اشکالزدا به آن تلهگذاری شود، از عبارت زیر استفاده کنید:
if {![exp_debug]} {trap mystuff SIGINT}همچنین، میتوانید با استفاده از سیگنال دیگری به اشکالزدا تله بگذارید.دستور trap به شما اجازه نخواهد داد کنش مربوط به SIGALRM را بازنویسی کنید، زیرا این سیگنال به صورت داخلی توسط Expect استفاده میشود. دستور disconnect مقدار SIGALRM را روی SIG_IGN (نادیدهگرفتن) تنظیم میکند. تا زمانی که آن را در طول دستورهای بعدی spawn غیرفعال کنید، میتوانید دوباره آن را فعال نمایید.
برای اطلاعات بیشتر signal(3) را ببینید..TP wait [args] تا زمانی که یک فرایند ایجادشده (یا فرایند فعلی در صورت مشخص نشدن هیچ فرایندی) پایان یابد، درنگ میکند.
- دستور wait
بهطور
معمول
فهرستی از
چهار عدد
صحیح را
برمیگرداند.
اولین عدد
صحیح، pid
فرایندی
است که
منتظر آن
بودهایم.
دومین عدد
صحیح، spawn id
متناظر است.
سومین عدد
صحیح در
صورت وقوع
خطای
سیستمعامل،
-1 و در غیر
این صورت 0
است. اگر
عدد صحیح
سوم 0 باشد،
عدد صحیح
چهارم
وضعیتی (status)
است که توسط
فرایند
ایجادشده
بازگردانده
شده است.
اگر عدد
صحیح سوم -1
باشد، عدد
صحیح چهارم
مقدار errno
تعیینشده
توسط
سیستمعامل
است. متغیر
سراسری errorCode
نیز
مقداردهی
میشود.
عناصر دیگری نیز ممکن است در انتهای مقدار بازگشتی از wait ظاهر شوند. یک عنصر پنجم اختیاری، ردهای از اطلاعات را مشخص میکند. در حال حاضر، تنها مقدار ممکن برای این عنصر CHILDKILLED است که در این صورت، دو مقدار بعدی نام سیگنال به سبک C و یک توصیف متنی کوتاه خواهند بود.
- پرچم -i
فرایندی را
مشخص
میکند که
باید
متناظر با spawn_id
نامبردهشده
منتظر آن
ماند (نه
شناسه
فرایند یا process
id). درون یک
گرداننده
SIGCHLD، امکان
انتظار
برای هر
فرایند
ایجادشده
با استفاده
از spawn id -1 وجود
دارد.
پرچم -nowait باعث میشود که انتظار بلافاصله با نشانه یک انتظار موفقیتآمیز بازگردد. هنگامی که فرایند (بعداً) خارج شود، بدون نیاز به یک انتظار صریح، بهطور خودکار ناپدید و پاک خواهد شد.
دستور wait همچنین میتواند برای انتظار برای یک فرایند فورکشده با استفاده از آرگومانهای "-i -1" استفاده شود. برعکس استفاده از آن با فرایندهای ایجادشده، این دستور در هر زمانی قابل اجرا است. هیچ کنترلی روی اینکه کدام فرایند درو (reap) شود وجود ندارد. با این حال، مقدار بازگشتی را میتوان برای دریافت شناسه فرایند بررسی کرد.
کتابخانهها (LIBRARIES)
برنامه Expect بهطور خودکار از دو کتابخانه توکار برای اسکریپتهای Expect آگاه است. این کتابخانهها توسط دایرکتوریهای نامبرده در متغیرهای exp_library و exp_exec_library تعریف میشوند. هر دوی آنها برای نگهداری فایلهای ابزاری که میتوانند توسط اسکریپتهای دیگر استفاده شوند در نظر گرفته شدهاند.
متغیر exp_library شامل فایلهای مستقل از معماری است. متغیر exp_exec_library شامل فایلهای وابسته به معماری است. بسته به سیستم شما، ممکن است هر دو دایرکتوری کاملاً خالی باشند. وجود فایل $exp_exec_library/cat-buffers نشان میدهد که آیا /bin/cat شما بهطور پیشفرض بافر (buffer) انجام میدهد یا خیر.
زیبانویسی (PRETTY-PRINTING)
یک تعریف vgrind برای زیبانویسی (pretty-printing) اسکریپتهای Expect در دسترس است. با فرض اینکه تعریف vgrind ارائهشده همراه با توزیع Expect بهدرستی نصب شده باشد، میتوانید از آن به صورت زیر استفاده کنید:
vgrind -lexpect file
مثالها (EXAMPLES)
شاید نحوه کنار هم قرار دادن تمام مواردی که این صفحه راهنما شرح میدهد بلافاصله آشکار نباشد. توصیه میکنم مثالهای موجود در دایرکتوری example از توزیع Expect را مطالعه کرده و امتحان کنید. برخی از آنها برنامههای واقعی هستند. برخی دیگر صرفاً نشاندهنده تکنیکهای خاصی میباشند و البته، چندتایی هم صرفاً ترفندهای سریع و موقتی هستند. فایل INSTALL مروری سریع بر این برنامهها دارد.
مقالههای Expect (به بخش SEE ALSO مراجعه کنید) نیز مفید هستند. اگرچه برخی مقالهها از نحو مربوط به نسخههای قبلی Expect استفاده میکنند، اما مبانی منطقی همراه آنها همچنان معتبر است و به جزئیات بسیار بیشتری نسبت به این صفحه راهنما میپردازد.
هشدارها (CAVEATS)
افزونهها ممکن است با نام دستورات Expect تداخل داشته باشند. برای مثال، send توسط Tk برای هدفی کاملاً متفاوت تعریف شده است. به همین دلیل، بیشتر دستورات Expect به صورت "exp_XXXX" نیز در دسترس هستند. دستورات و متغیرهایی که با "exp"، "inter"، "spawn" و "timeout" شروع میشوند نام مستعار (alias) ندارند. اگر به این سازگاری میان محیطها نیاز دارید، از نامهای گسترشیافته دستورات استفاده کنید.
Expect دیدگاهی تا حدودی باز و منعطف نسبت به حوزه متغیرها (scoping) دارد. بهویژه، متغیرهایی که توسط دستورات اختصاصی برنامه Expect خوانده میشوند، ابتدا در حوزه محلی جستجو میشوند و در صورت پیدا نشدن، در حوزه سراسری. برای مثال، این ویژگی نیاز به قرار دادن "global timeout" در هر رویهای که مینویسید و در آن از expect استفاده میشود را برطرف میسازد. از سوی دیگر، متغیرهای نوشتهشده همیشه در حوزه محلی هستند (مگر اینکه دستور "global" صادر شده باشد). رایجترین مشکلی که این موضوع ایجاد میکند زمانی است که spawn در یک رویه اجرا میشود. در خارج از رویه، spawn_id دیگر وجود ندارد، بنابراین فرایند ایجادشده صرفاً به دلیل حوزه متغیر دیگر در دسترس نخواهد بود. به چنین رویههایی یک "global spawn_id" اضافه کنید.
اگر نمیتوانید قابلیت چندایجادی (multispawning) را فعال کنید (یعنی سیستم شما نه از select (BSD *.*)، نه از poll (SVR>2) و نه از چیزی معادل آنها پشتیبانی میکند)، Expect تنها قادر خواهد بود در هر لحظه یک فرایند را کنترل کند. در این حالت، تلاشی برای مقداردهی spawn_id نکنید، و همچنین نباید در حالی که یک فرایند ایجادشده در حال اجرا است، فرایندهایی را از طریق exec اجرا نمایید. علاوه بر این، قادر نخواهید بود بهطور همزمان از چندین فرایند (از جمله کاربر به عنوان یکی از آنها) expect کنید.
پارامترهای ترمینال میتوانند تأثیر بزرگی روی اسکریپتها داشته باشند. برای مثال، اگر اسکریپتی برای بررسی پژواک (echoing) نوشته شده باشد، در صورت خاموش بودن پژواک رفتار نادرستی نشان خواهد داد. به همین دلیل، Expect بهطور پیشفرض پارامترهای ترمینال معقول (sane) را اعمال میکند. متأسفانه این امر میتواند شرایط را برای سایر برنامهها ناخوشایند کند. به عنوان مثال، پوسته emacs میخواهد نگاشتهای «معمول» را تغییر دهد: خطوط جدید بهجای carriage-return newlines به newlines نگاشت میشوند و پژواک غیرفعال میشود. این به فرد امکان میدهد از emacs برای ویرایش خط ورودی استفاده کند. متأسفانه، Expect به هیچ وجه نمیتواند این موضوع را حدس بزند.
میتوانید درخواست کنید که Expect تنظیمات پیشفرض پارامترهای ترمینال خود را بازنویسی نکند، اما در این صورت باید هنگام نوشتن اسکریپت برای چنین محیطهایی بسیار محتاط باشید. در مورد emacs، از وابستگی به مواردی مانند پژواک و نگاشتهای پایان خط خودداری کنید.
دستوراتی که آرگومانها را درون آکولاد به عنوان یک فهرست واحد میپذیرند (انواع expect و interact) از یک روش ابتکاری (heuristic) برای تشخیص اینکه آیا فهرست واقعاً یک آرگومان است یا چندین آرگومان استفاده میکنند. این روش ابتکاری تنها در حالتی ممکن است ناموفق باشد که فهرست در واقع نماینده یک آرگومان منفرد باشد که دارای چندین \n درونسازیشده به همراه نویسههای غیرفاصلهای در میان آنها است. این حالت به قدر کافی بعید به نظر میرسد، با این حال میتوان از آرگومان "-nobrace" برای اجبار به رفتار با یک آرگومان منفرد به صورت یک آرگومان واحد استفاده کرد. از این گزینه میتوان در کدهای Expect تولیدشده توسط ماشین استفاده نمود. بهطور مشابه، -brace رفتار با یک آرگومان منفرد به عنوان چندین الگو/عمل را اجباری میکند..SH "گزارش باگها (BUGS)" نامگذاری این برنامه به «sex» (مخفف «Smart EXec» یا «Send-EXpect») واقعاً وسوسهانگیز بود، اما عقل سلیم (یا شاید فقط سختگیری اخلاقی) چیره شد.
در برخی سیستمها، هنگامی که یک شل فراخوانی (spawn) میشود، از عدم دسترسی به tty شکایت میکند اما با این وجود اجرا میشود. این بدان معناست که سیستم شما سازوکاری برای به دست آوردن tty کنترلی دارد که Expect از آن بیخبر است. لطفاً دریابید آن چیست و این اطلاعات را برای من ارسال کنید.
سیستمعامل Ultrix 4.1 (حداقل آخرین نسخههای موجود در اینجا) مهلتهای زمانی (timeout) بالاتر از 1000000 را معادل 0 در نظر میگیرد.
سیستمعامل Digital UNIX 4.0A (و احتمالاً نسخههای دیگر) در صورتی که یک گرداننده برای سیگنال SIGCHLD تعریف کنید، از تخصیص ptyها خودداری میکند. برای اطلاعات بیشتر صفحهٔ grantpt را ببینید.
سیستمعامل IRIX 6.0 مجوزهای دسترسی pty را بهدرستی مدیریت نمیکند، بهطوری که اگر Expect تلاش کند یک pty را که پیشتر توسط شخص دیگری استفاده شده تخصیص دهد، با شکست مواجه میشود. به IRIX 6.1 ارتقا دهید.
برنامهٔ Telnet (تنها تحت SunOS 4.1.2 تأیید شده) اگر TERM تنظیم نشده باشد معلق (hang) میشود. این مسئله در cron، at و اسکریپتهای cgi که TERM را تعریف نمیکنند یک مشکل است. بنابراین باید آن را بهطور صریح تنظیم کنید - نوع آن معمولاً بیاهمیت است؛ فقط باید روی مقداری تنظیم شده باشد! نمونهٔ زیر احتمالاً برای بیشتر موارد کافی است.
set env(TERM) vt100
برنامهٔ Tip (تنها تحت BSDI BSD/OS 3.1 i386 تأیید شده) اگر SHELL و HOME تنظیم نشده باشند معلق میشود. این مسئله در cron، at و اسکریپتهای cgi که این متغیرهای محیطی را تعریف نمیکنند، مشکلساز است. بنابراین باید آنها را بهطور صریح تنظیم کنید - نوع آنها معمولاً بیاهمیت است؛ فقط باید روی مقداری تنظیم شده باشند! نمونهٔ زیر احتمالاً برای بیشتر موارد کافی است.
set env(SHELL) /bin/sh set env(HOME) /usr/local/bin
برخی از پیادهسازیهای pty بهگونهای طراحی شدهاند که هسته هر خروجی خواندهنشده را ۱۰ تا ۱۵ ثانیه (تعداد واقعی به پیادهسازی بستگی دارد) پس از بسته شدن توصیفگر فایل توسط فرایند، دور میریزد. بنابراین برنامههای Expect مانند
spawn date sleep 20 expectبا شکست مواجه خواهند شد. برای جلوگیری از این وضعیت، برنامههای غیرتعاملی را به جای spawn با exec فراخوانی کنید. اگرچه چنین وضعیتهایی قابلتصور هستند، اما در عمل هرگز با شرایطی مواجه نشدهام که خروجی نهایی یک برنامهٔ واقعاً تعاملی به دلیل این رفتار از دست برود.
از سوی دیگر، ptyهای Cray UNICOS هر خروجی خواندهنشده را بلافاصله پس از بسته شدن توصیفگر فایل توسط فرایند دور میاندازند. من این موضوع را به Cray گزارش کردهام و آنها در حال کار بر روی اصلاح آن هستند.
گاهی اوقات به تأخیری میان اعلان (prompt) و پاسخ نیاز است؛ مانند زمانی که یک رابط tty در حال تغییر تنظیمات UART یا تطبیق نرخهای باود (baud rate) با بررسی بیتهای start/stop است. معمولاً تمام آنچه نیاز است، توقف (sleep) برای یک یا دو ثانیه است. یک روش مطمئنتر، تلاش مجدد تا زمانی است که سختافزار برای دریافت ورودی آماده شود. مثال زیر از هر دو راهبرد بهره میبرد:
send "speed 9600\r";
sleep 1
expect {
timeout {send "\r"; exp_continue}
$prompt
}
دستور trap -code با هیچ دستوری که در حلقهٔ رویداد Tcl قرار دارد (مانند sleep) کار نخواهد کرد. مشکل این است که در حلقهٔ رویداد، Tcl کدهای بازگشتی گردانندههای رویداد ناهمگام (async) را نادیده میگیرد. یک راهحل جایگزین این است که پرچمی را در کد trap تنظیم کنید؛ سپس بلافاصله پس از اجرای آن دستور (یعنی sleep) پرچم را بررسی کنید.
دستور expect_background آرگومانهای -timeout را نادیده میگیرد و بهطور کلی هیچ مفهومی از مهلت زمانی ندارد.
نکات EXPECT (EXPECT HINTS)
چندین نکته دربارهٔ Expect وجود دارد که ممکن است غیربدیهی به نظر برسند. این بخش سعی دارد با چند پیشنهاد به برخی از این موارد بپردازد.
یک مشکل رایج در expect نحوهٔ تشخیص اعلانهای شل (shell prompts) است. از آنجا که این اعلانها توسط افراد مختلف و در شلهای گوناگون بهشکل متفاوتی سفارشیسازی میشوند، خودکارسازی قابلحمل rlogin بدون دانستن اعلان میتواند دشوار باشد. یک عرف منطقی این است که از کاربران خواسته شود یک عبارت باقاعده (regular expression) دربردارندهٔ توصیف اعلان خود (بهویژه بخش انتهایی آن) را در متغیر محیطی EXPECT_PROMPT ذخیره کنند. کدی شبیه به نمونهٔ زیر میتواند مورد استفاده قرار گیرد. اگر EXPECT_PROMPT وجود نداشته باشد، کد همچنان شانس خوبی برای کارکرد صحیح دارد.
set prompt "(%|#|\\$) $" ;# default prompt
catch {set prompt $env(EXPECT_PROMPT)}
expect -re $prompt
من شما را
تشویق
میکنم
الگوهای expect
را طوری
بنویسید که
انتهای هر
آنچه را که
انتظار
دیدنش را
دارید در بر
گیرند. این
کار از این
احتمال که
به یک پرسش
پیش از
مشاهدهٔ
کامل آن
پاسخ داده
شود
جلوگیری
میکند.
علاوه بر
این، در
حالی که
ممکن است
بتوانید
پیش از
مشاهدهٔ
کامل پرسش
به آن پاسخ
دهید، اگر
زود پاسخ
دهید ممکن
است پژواک
پاسخ شما در
میانهٔ
پرسش
پدیدار شود.
به عبارت
دیگر،
گفتگوی
نهایی صحیح
خواهد بود
اما آشفته و
درهمریخته
به نظر
میرسد.
بیشتر اعلانها شامل یک نویسهٔ فاصله در انتهای خود هستند. برای نمونه، اعلان ftp از 'f'، 't'، 'p'، '>' و <blank> (فاصله) تشکیل شده است. برای تطبیق این اعلان، باید تکتک این نویسهها را به حساب آورید. عدم درج نویسهٔ فاصله یک اشتباه رایج است. فاصله را بهطور صریح قرار دهید.
اگر از الگویی به شکل X* استفاده کنید، نویسهٔ * تمام خروجیهای دریافتشده از انتهای X تا آخرین چیز دریافتشده را مطابقت میدهد. این موضوع شهودی به نظر میرسد اما میتواند تا حدی گیجکننده باشد؛ زیرا عبارت «آخرین چیز دریافتشده» بسته به سرعت رایانه و پردازش I/O توسط هسته و گردانندهٔ دستگاه میتواند متغیر باشد.
بهطور خاص، انسانها تمایل دارند خروجی برنامه را در قالب تکههای بسیار بزرگ (بهصورت یکپارچه و اتمیک) در حال دریافت ببینند، در حالی که در واقعیت بیشتر برنامهها خروجی را خط به خط تولید میکنند. با فرض این موضوع، نویسهٔ * در الگوی بند پیشین ممکن است تنها انتهای خط فعلی را تطبیق دهد، حتی اگر به نظر برسد دادههای بیشتری وجود دارد؛ زیرا در لحظهٔ تطبیق، تمام خروجی دریافتشده همان بوده است.
دستور expect هیچ راهی برای دانستن این موضوع ندارد که آیا خروجی بیشتری در راه است یا خیر، مگر اینکه الگوی شما مشخصاً آن را در نظر گرفته باشد.
حتی اتکا به بافرینگ خطمحور نیز غیرهوشمندانه است. نه تنها برنامهها بهندرت تعهدی دربارهٔ نوع بافرینگی که انجام میدهند ارائه میکنند، بلکه ناهماهنگیها و وقفههای سیستمی میتواند خطوط خروجی را تکهتکه کند بهطوری که خطوط در مکانهایی ظاهراً تصادفی شکسته شوند. بنابراین، اگر میتوانید هنگام نوشتن الگوها چند نویسهٔ آخر یک اعلان را بیان کنید، عاقلانه است که حتماً این کار را انجام دهید.
اگر در آخرین خروجی یک برنامه منتظر الگویی هستید و برنامه در عوض خروجی دیگری صادر کند، قادر نخواهید بود با کلیدواژهٔ timeout آن را تشخیص دهید. دلیل آن این است که expect دچار مهلت زمانی (timeout) نمیشود - در عوض نشانگر eof را دریافت خواهد کرد. به جای آن از این نشانگر استفاده کنید؛ یا حتی بهتر، از هر دو بهره ببرید. به این ترتیب، اگر آن خط روزی جابهجا شود، نیازی به ویرایش خود خط نخواهید داشت.
هنگامی که خروجی توسط گردانندهٔ ترمینال صادر میشود، خطوط جدید (newlines) معمولاً به توالیهای carriage return و linefeed تبدیل میشوند. بنابراین، اگر الگویی میخواهید که صراحتاً با دو خط ناشی از مثلاً printf("foo\nbar") مطابقت داشته باشد، باید از الگوی "foo\r\nbar" استفاده کنید.
تبدیل مشابهی هنگام خواندن ورودی از کاربر از طریق expect_user رخ میدهد. در این حالت، زمانی که کلید return را فشار میدهید، به یک newline تبدیل میشود. اگر Expect سپس آن را به برنامهای بفرستد که ترمینال خود را روی حالت خام یا raw تنظیم کرده باشد (مانند telnet)، مشکلی پیش خواهد آمد؛ زیرا آن برنامه انتظار یک return واقعی را دارد. (برخی برنامهها در واقع بخشنده هستند و newlineها را بهطور خودکار به return تبدیل میکنند، اما بیشتر آنها اینطور نیستند.) متأسفانه، هیچ راهی برای آگاهی از اینکه برنامهای ترمینال خود را روی حالت raw قرار داده است وجود ندارد.
به جای جایگزینی دستی newline با return، راهکار استفاده از دستور "stty raw" است که این تبدیل را متوقف میسازد. با این حال توجه داشته باشید که این به معنای از دست دادن ویژگیهای ویرایش خط در حالت پردازششده (cooked) خواهد بود.
دستور interact بهطور ضمنی ترمینال شما را روی حالت raw تنظیم میکند، بنابراین این مشکل در آن زمان پیش نخواهد آمد.
اغلب مفید است که گذرواژهها (یا دیگر اطلاعات محرمانه) در اسکریپتهای Expect ذخیره شوند. این کار توصیه نمیشود، زیرا هر چیزی که روی یک رایانه ذخیره میشود ممکن است در دسترس دیگران قرار گیرد. بنابراین، درخواست تعاملی برای گذرواژهها از درون اسکریپت، ایدهٔ هوشمندانهتری نسبت به درج مستقیم و تحتاللفظی آنها است. با این وجود، گاهی اوقات چنین درجی تنها گزینهٔ ممکن است..PP متأسفانه، سیستمفایل UNIX روش مستقیمی برای ایجاد اسکریپتهایی که قابل اجرا اما غیرقابل خواندن باشند ندارد. سیستمهایی که از اسکریپتهای شل با setgid پشتیبانی میکنند، میتوانند این وضعیت را بهطور غیرمستقیم به شرح زیر شبیهسازی کنند:
اسکریپت Expect (که حاوی دادههای محرمانه است) را طبق روال معمول بسازید. مجوزهای دسترسی آن را روی 750 (-rwxr-x---) قرار داده و مالکیت آن را به یک گروه قابل اعتماد، یعنی گروهی که مجاز به خواندن آن است، اختصاص دهید. در صورت نیاز، یک گروه جدید برای این منظور ایجاد کنید. سپس، یک اسکریپت /bin/sh با مجوزهای 2751 (-rwxr-s--x) ایجاد کنید که متعلق به همان گروه قبلی باشد.
نتیجه، اسکریپتی است که میتواند توسط هر کاربری اجرا (و خوانده) شود. هنگامی که فراخوانی شود، اسکریپت Expect را اجرا میکند.
همچنین ببینید (SEE ALSO)
Tcl(3), libexpect(3)
"Exploring Expect: A Tcl-Based Toolkit for Automating Interactive
Programs" اثر Don Libes، ص.
۶۰۲، ISBN 1-56592-090-2،
انتشارات O'Reilly
and Associates، ۱۹۹۵.
"expect: Curing Those Uncontrollable Fits of Interactivity"
اثر Don Libes، Proceedings of the Summer
1990 USENIX Conference, Anaheim, California, June 11-15, 1990.
"Using expect to Automate System Administration Tasks"
اثر Don Libes، Proceedings of the 1990 USENIX
Large Installation Systems Administration Conference, Colorado Springs,
Colorado, October 17-19, 1990.
"Tcl: An Embeddable Command Language" اثر
John Ousterhout، Proceedings of the Winter 1990 USENIX
Conference, Washington, D.C., January 22-26, 1990.
"expect: Scripts for Controlling Interactive Programs"
اثر Don Libes، Computing Systems, Vol. 4,
No. 2, University of California Press Journals, November 1991.
"Regression Testing and Conformance Testing Interactive
Programs", اثر Don Libes, Proceedings of the
Summer 1992 USENIX Conference, pp. 135-144, San Antonio, TX, June 12-15,
1992.
"Kibitz - Connecting Multiple Interactive Programs Together",
اثر Don Libes، Software - Practice &
Experience, John Wiley & Sons, West Sussex, England, Vol. 23, No. 5,
May, 1993.
"A Debugger for Tcl Applications", اثر Don
Libes، Proceedings of the 1993 Tcl/Tk Workshop, Berkeley, CA,
June 10-11, 1993.
نویسنده (AUTHOR)
Don Libes، مؤسسه ملی استانداردها و فناوری (NIST)
قدردانیها (ACKNOWLEDGMENTS)
با تشکر از John Ousterhout برای Tcl، و Scott Paisley برای الهامبخشی. با تشکر از Rob Savoye برای کد پیکربندی خودکار Expect.
فایل HISTORY بخش عمدهای از سیر تکامل expect را مستند کرده است. خواندن آن جالب است و میتواند بینش عمیقتری نسبت به این نرمافزار به شما بدهد. با تشکر از افرادی که نامشان در آن ذکر شده و اصلاحات باگها را فرستاده و کمکهای دیگری ارائه دادند.
طراحی و پیادهسازی Expect تا حدی توسط دولت ایالات متحده تأمین مالی شده و بنابراین در مالکیت عمومی (public domain) قرار دارد. با این حال، در صورت استفاده از این برنامه و مستندات یا بخشهایی از آنها، نویسنده و NIST تمایل دارند نام و اعتبارشان حفظ شود.
| 29 December 1994 |