expect دستیار باهوش شما در شل اسکریپتها!
اگر تا به حال شل اسکریپت نوشته باشید، اگر حد اعتیادتان به آن اندازه باشد که بخواهید هر کاری را آسانتر کنید، اگر تنبلیتان گرفته باشد که بعد از آسان شدن کارهایتان با یک شل اسکریپت، رمزهای جاهای مختلف را به یاد آورید تا اسکریپتتان درست کار کند، یا آنقدر به مغزتان فشار آورید که جواب صحیح یک سوال اسکریپت را پیدا کنید، آن وقت میتوانید درک کنید که expect چه ابزار خارقالعادهای است.
کار expect خیلی ساده است، بعد از اجرای اسکریپتتان، منتظر میماند که اتفاق خاصی رخ دهد، مثلا دستوری در اسکریپت از شما رمز بخواهد، آن وقت expect وارد میدان میشود و رمز را وارد میکند. یعنی دیگر نیازی نیست که شما دخالتی داشته باشید. اگر فکر میکنید که خوب این که کار سختی نیست و از این حرفها که خوب اول باید بگویم که کور خواندهاید و دوم این که بیخیال ادامهٔ این متن شوید ;-)
حالا شیوهٔ عملکرد expect معلوم شد، بهتر است نگاهی بیاندازیم به وضعیت من. بنا به دلایل کاملا غیر عادی و نامعلومی، در کشوری کاملا آزاد، نیاز دارم که از sshuttle برای انجام برخی امور استفاده کنم. این برنامه برای انجام دادن درست کارهایش، نیاز به iptables دارد که خوب من دوست ندارم که کاربر عادیام به آن دسترسی داشته باشد. پس همین دوست نداشتن من یک مرحلهٔ اضافه در فرآیند استفاده از sshuttle هزینه دارد. یعنی یک همچین چیزی:
su
Vared Kardan Ramz
cd /home/shahin/bin/sshutle
./sshuttle ...
Vared Kardan Ramz
که خوب بعد از اولین تلاش کانکت نمیشود و باید دوباره دستور را بزنم و منتظر بمانم تا پرامپت رمز ssh ظاهر شود و باقی قضایا. خوب کمی سخت است. البته این را هم اضافه کنم که خوب میدانم میتوانم کانکت بدون رمز ssh داشته باشم. میتوانم دستور را درون یک path قرار دهم. میتوانم، میتوانم… ولی این روشی است که من کار میکنم ;-)
این است که دست به دامن expect میشوم و همچین اسکریپتی مینویسم:
#!/usr/bin/expect -f
if {[llength $argv] != 5} {
puts "usage: ssh.exp client_root_pass username password server port"
exit 1
}
set rootpass [lrange $argv 0 0]
set username [lrange $argv 1 1]
set password [lrange $argv 2 2]
set server [lrange $argv 3 3]
set port [lrange $argv 4 4]
set timeout -1
spawn su -c "/home/shahin/bin/sshuttle/sshuttle --dns -r $username@$server:$port 0/0 -vv"
match_max 100000
expect "Password:\*"
send -- "$rootpass\r"
expect "\*?assword:\*"
send -- "$password\r"
send -- "\r"
expect eof
حالا همانطور که معلوم است کافی است همچین دستوری را تایپ کنم:
./ssh.exp client_root_pass username password server port
حالا میشود این اسکریپت را بدون هیچ ضرر اضافهای به path اضافه کرد و حالش را برد. برای این که بفهمید این اسکریپت چطور کار میکند راهنماهای زیادی در اینترنت مییابید. man page خود برنامه هم میتواند کمک خوبی باشد. ضمن این که اگر اسکریپت نویسی بدانید، چیز زیادی برای یاد گرفتن پیشرویتان نیست ;-)