PragmaticPerl8pragmaticperl.
comВыпуск8.
Октябрь2013Другиевыпускииформатыжурналавсегдаможнозагрузитьсhttp://pragmaticperl.
com.
Свопросамиипредложениямипишитенаeditor@pragmaticperl.
com.
Комментарииккаждойстатьеестьвhtml-версии.
Подписатьсянановыевыпускиможнопоссылкеpragmaticperl.
com/subscribe.
Авторыстатей:ВладимирЛеттиев,ДенисФедо-сеевКорректор:АндрейШитовВыпускающийредактор:ВячеславТиханов-ский(vti)Ревизия:2014-11-2916:12PragmaticPerlОглавление1Отредактора12РазворачиваниеPSGI/Plackприложения33КонсольныеприложениянаCurses244Миграциявеб-приложенийсDancerнаDancer2625ОбзорCPANзасентябрь2013г.
836Интервьюсchromatic907PerlGolf1138ОтветынаPerlQuiz1201ОтредактораВэтомномеревместоPerlQuizпопробуемPerlGolf.
Есливамэтобольшепонравится,пожалуйста,скажитенамобэтомвкоммен-тариях,попочтеиличерезсоциальныесе-ти.
Читайтетакжевномереинтервьюсchromatic,авторомпопулярнойисво-боднодоступнойкнигиосовременномPerl—ModernPerl.
Мыпродолжаемискатьавторовдляследу-ющихномеров.
Еслиувасестьидеиилиже-ланиепомочь,пожалуйста,свяжитесьсна-ми.
Приятногочтения.
ВячеславТихановский2РазворачиваниеPSGI/Plackприложе-нияСпоявлениемPlackупрограммистовпропаланеобходимостьзатачиватьсвоеприложениеподкаждыйизвозможныхвариантовразвертыванияприложений.
Однакоуадминистраторовникуданепропаланеобходимостьнастроексервераподэтосамоеприложение.
Иеслидляопытногопрограммиста/администратораэтотвопросневызваетзатруднений,тоуновичковввебетрудностивылезаютвполнеощутимые.
Итак,вниманиюблагодарнойпубликипредставляетсясборникрецептовпораз-вертываниюминимальногоPSGI/Plackприложениянавсехпопулярныхвидаххостингов.
Вкачестветестовогоприложениямыбу-демиспользоватьнемножкоизмененноеприложение,автоматическисозданноефреймворкомсназванием,начинающим-сянаM.
Тем,комуненравитсяфреймворкнаМ,могутиспользоватьфреймворкнаD.
илилюбойдругойпосвоемувкусусподдержкойPlack.
Plackпредствляетсобойстандартизи-рованныйинтерфейсмеждусерверомиприложением.
Вобычномслучаеприло-жениюдаженетнеобходимостизнать,вкакомрежимеискакимсерверомонорабо-тает,чтооченьупрощаетжизньпростомупрограммисту.
Итак,поехали.
Иходникприложения:1#!
/usr/bin/envperl2useMojolicious::Lite;34get'/'=>sub{5my$self=shift;6$self>render('index');7};89get'/test'=>sub{10my$self=shift;11$self>render('test');12};1314app>start;15__DATA__1617@@index.
html.
ep18%layout'default';19%title'Welcome';20WelcometotheSuperPuperapp!
2122@@test.
html.
ep23%layout'default';24%title'Test';25Routetestpage!
2627@@layouts/default.
html.
ep2829303132Начнемотпростогоксложному.
Внимание!
Всеконфигурациидлясерверовприведенывминимальномварианте.
Безненужныхвданномслучаенастроектипавиртуальныххостов,защитотботов,ддос,нападенияинопланетянипролитиякофенаклавиатуру.
Вобщем,завыкаченныебезизмененийнабоевойсерверконфигиавторответственностиненесет.
NginxreverseproxyЗдесьвсепросто,увасестьсобственныйсервер/VDS,естьвашеприложение,за-пущенноелюбымудобнымспособом,иnginxпростопрокидываетнанегозапроспользователя.
1$.
/testdaemon2[WedOct206:16:372013][info]Listeningat"http://*:3000".
3Serveravailableathttp://127.
0.
0.
1:3000.
Лучше,конечно,использоватьprefork-сервертипаStarman,новнашемслучаеэтонепринципиально.
ЗапущенноеM.
-приложениепоумолча-ниюзапускаетсяна3000-мпорту.
Его-томыибудемиспользоватьпоумолчаниювезде,гденамнуженпортвконфигурациисервера.
Создаемконфигnginx:1server{2listen*;34location/{5proxy_passhttp://127.
0.
0.
1:3000/;6proxy_set_headerXRealIP$remote_addr;7proxy_set_headerHost$http_host;8proxy_set_headerXForwardedFor$proxy_add_x_forwarded_fo;9}1011#Передаемдиректориюдляstaticфайловнаобработкуnginx12locationjpg|jpeg|gif|png|ico|css|pdf|ppt|txt|bmp|rtf|js)${13root/path/to/your/app/public/;#Путькпапкедляpublicфайлов14expires3d;#кешируемуклиентана3дня15}16}Способхорошсвоейпростотойимасшта-бируемостью.
Чтобыувеличитьколичествообрабатываемыхконнектов,достаточноза-пуститьприложениеподStarmanилилюбымдругимсерверомиполучитьпрактическилинейныйростчислаобра-батываемыхклиентов(поканеупремсявмощьностьсервера,конечно).
Минусэтогоспособа—заприложениемпридетсяследитьсамомуиписатьдопол-нительнуюобвязкунаслучайперезагрузкисервера/приложения.
НоздесьнампоможетUbic.
УстанавливаемизCPAN:1#cpaniUbic2#ubicadminsetupСоздаемминимальныйфайлконфигура-ции:1#vim/etc/ubic/service/site.
ini23[options]4bin=/path/to/your/app/super_app.
pldaemonСтартуемсервис:1#ubicstartsiteИполучаемработающийзаnginxбекэнд.
Еслиприложениевнезапноупадет,Ubicзапуститегообратно.
Естественно,вместоtestdaemonлучшеиспользоватькакой-либоизспециализированныхсерверов,напримерStarman.
РассматриватьспособдеплоячерезNginx/FastCGIнеимеетособогосмыслат.
к.
отличиявконфигурациибуквальновдвухстрочках.
НоNginx,вотличииотApache,неумеетавтоматическизапускатьзапрошенноеприложение.
Такчтоздесьнеобойтисьбезвнешнегоменедждера,ипропадаетвообщекакой-либосмыслиспользованияFastCGI.
Перейдемкустаревшемуварианту.
Допу-стим,чтовыделенногосервераунаснет,аестьshared-хостингсApacheиподдержкойPerl.
Apache/CGIВариант,отличающийсяпростотойна-стройки,работоспособностьювезде,гдеестьApacheиPerl,атакжесамойвысокойтормознутостьюизвсехвозможныхкиспользованиювариантов.
ВCookbookпредлагаетсядляэтогослучаяпрописатьScriptAlias1ScriptAlias//home/sri/myapp/script/myapp/Проблемаэтогометодавтом,чтоэтади-рективанеработаетв.
htaccess,аправитьфайлконфигурациивиртуальногохоставамниктонедаст.
Сдругойстороны,ес-лиувасестьдоступкредактированиюконфигурациивиртуальныххостов,зачемнастраиватьCGIВобщеммы,какнастоящиегерои,пойдемвобходивсенастройкибудемделатьчерез.
htaccess.
Вдиректории,гдележитсайт,создаемфайл.
htaccessсоследующимсо-держимым:1Options+ExecCGI2AddHandlercgiscript.
pl3DirectoryIndexindex.
plindex.
pl—этоприложение,котороедолжнообрабатыватьзапрос.
Внимательнопроверьтеатрибутыфайла,поумолчаниюM.
создаетфайлсатрибутами744,такчтоApacheнесможетегозапуститьивыдастошибку500.
Длянормальнойработынадосменитьатрибутына755.
Заходимнасайт,проверяем—маршрутынеработают.
Дляэтоговоспользуемсявоз-можностямимодуляmod_rewrite,такимобразомApacheобучаетсяделатьто,чтонамнужно.
Полный.
htaccess:1CharsetDisableOn23#ПринудительновыставляемкодировкуUTF8ибо21векнадворе!
4AddDefaultCharsetutf856#РазрешаемCGI7AddHandlercgiscript.
pl8Options+ExecCGI910#Включаемmod_rewrite11RewriteEngineon1213#Проверяемчтозапрошенныйресурснереальныйфайлилидиректория14RewriteCond%{REQUEST_FILENAME}!
f15RewriteCond%{REQUEST_FILENAME}!
l16RewriteCond%{REQUEST_FILENAME}!
d1718#ипередаемпутьнашемуобработчику19RewriteRule^(.
*)$index.
pl/$1[L]Все,наэтомнастройкуApache/CGIвцеломможносчитатьзаконченной.
Apache/mod_perlБолеепрогрессивныйспособпосравне-ниюсCGI,позволяетзапускатьприложе-ниеавтоматическиивыдаетдостаточнонеплохуюскорость.
Вминусах—доступенневезде,иестьнебольшиезаморочкиснаписаниемкодаподmod_perl.
Такчто,возможно,понадобитсянебольшаядоработкаприложения,еслинеповезет.
Какминимум,дляэтогоспособапонадо-битсяустановитьPlackизCPAN,т.
к.
нампонадобитсяPlack::Handler::Apache2.
Настройка.
htaccess:12$ENV{PLACK_ENV}='production';3$ENV{MOJO_HOME}='/var/www/index.
pl';4$ENV{MOJO_TEMPLATE_CACHE}=0;56SetHandlerperlscript7PerlHandlerPlack::Handler::Apache28PerlSetVarpsgi_app/var/www/index.
pl910#Включаемmod_rewrite11RewriteEngineon1213#Проверяем,чтозапрошенныйресурснереальныйфайлилидиректория14RewriteCond%{REQUEST_FILENAME}!
f15RewriteCond%{REQUEST_FILENAME}!
l16RewriteCond%{REQUEST_FILENAME}!
d1718#Передаемпутьобработчику19RewriteRule^(.
*)$index.
pl/$1[L]Разворачиваемнашеприложениеираду-емсяжизни.
Apache/FastCGIВцеломвсеаналогичнопредыдущимпунктам,заисключениемнеобходимостинебольшойдоработкиприложения.
Строку1app>start;необходимозаменитьна:1app>start('fastcgi');Ивсеэтосопроводитьследующим.
htaccessфайлом:1#ОбъявляемхэндлердляFastCGIприложения2SetHandlerfcgidscript3Options+ExecCGI45#Включаемmod_rewrite6RewriteEngineon78#Проверяем,чтозапрошенныйресурснереальныйфайлилидиректория9RewriteCond%{REQUEST_FILENAME}!
f10RewriteCond%{REQUEST_FILENAME}!
l11RewriteCond%{REQUEST_FILENAME}!
d1213#Передаемпутьобработчику14RewriteRule^(.
*)$index.
pl/$1[L]1516#Запросбезуказанияпутипередаемобработчику17#принудительно,иначеполучим40318RewriteRule^$index.
pl[L]Инапоследокрассмотримспособразверты-ваниячерезApache/mod_proxy.
Apache/mod_proxyДа,какэтонистранно,Apacheтожеумеетработатьврежимереверс-прокси.
Этотрежимпримечателентем,чтопозволяетиспользоватьвсюмощьмодулейApacheиприэтомобработкунепосредственнопри-ложениявозложитьнаотдельныйсервер.
Уменяработаетконфигурация,вкоторойApacheосуществляетSSO-авторизациюпользователейчерезmod_kerberosипослеэтогонаправляетихнаприложение,кото-роекрутитсяподStarman.
Позволяетубитьдвухзайцевсразу—вбраузерахсподдерж-койSSOпользователюнетнеобходимостивводитьсвойдоменныйлогин/пароль,сдругойстороны—мненетнеобходимостизаниматьсявопросамиаутентификациипользователей,еслиавторизациячерезKerberosнепройдет—тоApacheпростонепропуститпользователядоприложения.
Сплошнаяэкономия,хотядлясайтоввинтернететехнологияпрактическинеприменимая.
Итак,приступимкнастройке,.
htaccessнамздесьуженепомощник,будемправитьфайлвиртуальногохоста:12DocumentRoot/var/www/345Orderdeny,allow6Allowfromall789ProxyViaOn1011#ПревращаемпеременныеApacheвпеременные%ENV12ProxyPassInterpolateEnvOn13ProxyRequestsOff14ProxyPreserveHostOn15ProxyPass/http://localhost:3000/keepalive=On16ProxyPassReverse/http://localhost:3000/17RequestHeadersetXForwardedHTTPS"0"18КонфигнеотличаетсязатейливостьюиестьвCookbook,заоднимисключением:1ProxyPassInterpolateEnvOnЭтаопциязаставляетApacheпрокинутьвсесвоипеременныевпеременные%ENV.
Сильнопомогает,когдавыиспользуетеавторизациючерезApache,например.
Нопростотаквсяэтаконструкциянезара-ботает,нужновключитьдополнительныемодули:1#a2enmodproxy2#a2enmodheaders3#a2enmodproxy_http4#serviceapache2restartНаэтомкраткийпрактикумможносчитатьзаконченным.
Онпокрывает95%процен-товслучаевразвертыванияприложенийнавсевозможныхсерверах,скоторымимнетолькоприходилосьсталкиватьсязавсюсвоютрудовуюдеятельность.
Остав-шиеся5%обычнопредставлялисобойособоэкзотичныенастройкиокруженияshared-хостинговипобеждалисьдопили-ваниемнапильникомвышепреведенныххостинговилитехподдержкихостинг-провайдеров.
ДенисФедосеев3КонсольныеприложениянаCursesПриложениястекстовыминтерфейсом,ра-ботающиевтерминале,по-прежнемуоченьпопулярныиотличноконкурируютсприло-жениямисграфическиминтерфейсом.
Mutt,irssi,vim,tmuxимногиедругиеявляютсянезаменимымивповседневнойработе.
НаCPANестьмодули,позволяющиесоздаватьприложениястекстовыминтерфейсом,втомчислемодульCurses,являющийсяобвязкойкраспространённойC-библиотекеncurses.
ИсторияДлясамыхраннихЭВМвкачествевво-да/выводаинформациииспользовалисьэлектромеханическиетелетайпы(Teletype,илисокращённоTTY),которыепозволяливводитьтекстсклавиатурыипечататьнабумагесимволзасимволом,полученныеотЭВМ.
Позжетелетайпбылзаменёнтер-миналом,гдепринтерзаменилЭЛТ-экран,накоторыйнафиксированныепозицииможнобыловыводитьсимволы.
СамымпервымкомпьютернымтерминаломсталDataPoint3300,которыйимелэкран,позво-ляющийвыводить25рядовпо72символа.
Примечательно,чтоэтоттерминалбылсозданнаосновеобычныхTTL-микросхем,адальнейшиепопыткиупроститьлогикуиуменьшитьразмервнутреннейначинкитерминаласталиоднойизпобуждающихпричинразработкимикропроцессоров.
Какправило,кодномумейнфреймуподуправлениемкакой-либоизUNIX-системподключалосьмножествотерминалов.
ЭВМзапускалапрограммукоманднойобо-лочки,вводивыводкоторойбылсвязансустройствомтерминала.
Оболочкаобра-батывалавводимыекомандыивыводиларезультатыихработынатерминал.
Стандартомде-фактонадолгиевременасталтерминалVT100,созданныйкомпани-ейDECв1978г.
Терминалподключалсяквычислительноймашинечерезпоследова-тельныйинтерфейс,позволялвыводить80или132символаврядииспользовалдляко-дировкисимволовстандартASCII,атакженаборуправляющихпоследовательностей(escape-последовательностей),которыебы-листандартизованыANSIввидестандартаECMA-48.
Escape-последовательностиполу-чилисвоёназваниеоткодаклавишиEscape,которыйпредварялнаборкодов,определя-ющихуправляющуюпоследовательность.
Управляющиепоследовательностипозво-лялипередвигатькурсор,очищатьэкран,задаватьтолщинусимволовилидажеделатьмигающуюстроку,нацветныхтерминалахпоявиласьвозможностьза-даватьцветфонаисимвола.
Например,последовательностькодовESC[1mзадаётжирныйшрифтдляпоследующихвыво-димыхсимволов,аESC[0mсбрасываетвсеустановленныеатрибуты.
Возможностьманипулироватьрасположе-ниемсимволовиихатрибутаминаэкранеоткрылопутьксозданиюпрограммстек-стовымпользовательскиминтерфейсом.
Вотличиеоткомандногоинтерфейса,втекстовоминтерфейсеспомощьюASCII-символовможнобылоотображатьграницыокон,диалоговыеокна,менюилитаблицы,атакжекнопкииполяввода.
Сростомчислатерминаловсталавозни-катьпроблемасподдержкойвсехихвидоввнутрипрограмм.
В1978г.
БиллДжой,приработенадтекстовымрадакторомviдляBerkeleyUnix,выделилкоддляподдержкиразныхтиповтерминаловвотдельнуюбиб-лиотекуподназваниемtermcap,котораясталабазойданныхописанийсуществу-ющихтерминаловипозволялареализо-выватьпрограммы,независимыеоттипатерминала.
Termcapдавалвозможностьпрограммеузнатьширинутерминала,пра-вильнуюпоследовательностьescape-кодовдляперемещениякурсораит.
д.
Вследзаtermcapпоявиласьбиблиотекаterminfo,котораяявляласьулучшеннойреализа-циейtermcapсболеебыстрымдоступомкописаниютерминала.
ИменноterminfoполучиламаксимальноераспространениевUNIX-системах.
В1980г.
большуюпопулярностьполучилаиграRogue,котораядаластартцеломужан-руrogue-подобныхигр,вкоторойигровойперсонажисследуетподземелья,сражаетсясмонстрамииищетсокровища.
Иградлявыводаиспользовалатекстовуюконсоль,монстрыобозначалисьзаглавнымибук-вами,коридорыиграницыподземелийпрорисовывалисьASCII-символами|и.
Одинизразработчиков,КенАрнольд,специальнодляигрысоздалбиблиотеку,котораяабстрагироваласьотработысконкретнымтипомтерминала,вводилаабстрактныепонятияоконкакматрицсимволов,забираянасебявсезаботыповыводуиобновлениюэкрана.
Библиотекаполучиланазваниеcurses(проклятие),чтоявляетсякаламбуромнасловосочета-ниеcursoroptimization.
Первоначальноcursesбылаосновананаtermcap.
Вотличиеотtermcap,котораяфактическиявляласьтекстовойбазойданныхосвойствахтер-миналов,cursesпредоставляладовольновнятноеCAPI.
ПозжепоявилисьбиблиотекиpcursesиPDcurses,которыеявлялисьсвободнымиальтернативамиBSDcurses.
В1991г.
работанадpcursesбылапродолжена,ав1993г.
онабылапереименованавncurses,чтобылосокращениемотnewcurses(новаяcurses),исталаразвиватьсяврамкахпроектаGNU.
Современемкncursesпоявилисьоберткидлядругихязыковпрограммирования,втомчислеиPerl-модульCurses,которыйпозволяетиспользоватьбиблиотекувPerl-программах.
Широкоеиспользованиеаппаратныхтер-миналовпрекратилосьпослепоявлениявидеодисплеев,нотемнеменеепростотаинтерфейсаиколичествосуществующихдлянегопрограммпривелоктому,чтобылисозданыэмуляторытерминала—программы,которыеэмулироваливидео-терминалвнутридругойвидеосистемы,например,XWindow.
Этопозволялопро-должатьиспользоватьпрограммы,зато-ченныедляработывтерминале,ивдругихсистемах.
Наиболеепопулярныеграфиче-скиеэмуляторытерминала—xterm,rxvt,атакжесовременныеgnome-terminalиkonsole.
Использованиеконсольныхприложенийстекстовыминтерфейсомактуальноинасегодняшнийдень.
Такиеприложениякакtop,vim,emacs,mutt,irssi,moc,midnightcommanderиспользуютмногиеипростонепредставляютсебедругойальтернативы.
Терминальноеприложениеможетрабо-татьповерхпоследовательныхлинийиповерхсетинаоченьнизкихскоростях,которыенедоступныVNCилиRDP.
Авотличиеотвеб-интерфейсов,нетребуютотклиентаналичиягигабайтовоперативнойпамятиимногоядерныхпроцессоровдлятого,чтобыудовлетворитьсистемнымтребованиямсовременныхбраузеров.
УстройствотерминалаПосколькуисторическитерминалыявля-лисьвнешнимиустройствамиспосим-вольнымобменоминформациипопосле-довательнымлиниям,товUNIX-системахкаждомутерминалусоответствовалфайлустройствавида/dev/tty*.
Системныеконсолибылидоступнына/dev/tty[0.
.
NN],последовательныепортына/dev/ttyS[0.
.
NN]ит.
д.
(вариацияназва-ниязависелаотконкретнойреализацииUNIX-системы).
Длякаждоготакогоустрой-ствасуществуетвозможностьустановкискоростиобмена,управляющихпоследо-вательностейидругихнастроек.
Текущиенастройкилюбоготакогоустройствамож-ноувидетьспомощьюутилитыstty:1#sttyafile=/dev/tty02speed38400baud;rows64;columns160;line=0;3.
.
.
Дляпроцессов,которымнеобходимарабо-тастерминалом,несвязаннымскаким-тофизическимустройством,создаютсятакназываемыепсевдотерминалы.
Всовре-менныхUNIX-системахдляэмуляторатерминалапозапросусоздаётсяфайлустройствапсевдотерминалавфайловойсистемеdevpts,например/dev/pts/0,cкоторымассоциируютсястандартныефай-ловыедескрипторыввода/выводаSTDIN,STDOUTиSTDERRзапускаемыхэмуляторомдочернихпроцессов.
Эмулятортерминалаопределяет,какимбудеттиптерминала,ка-ковбудетразмерэкрана(количествострокисимволоввстроке)идругиепараметры.
Длязапущеногожевпсевдотерминалеприложениянетникакогоотличияработа-етлионвпсевдотерминалеилиналюбомдругомреальномтерминале.
PerlCursesPerl-модульCursesявляетсянизкоуров-невойобвязкойкС-библиотекеncurses.
ИзсуществующейPOD-документациипрактическиневозможнопонять,какпро-граммироватьприложениянаCurses,посколькуподразумевается,чтовыбудетеиспользоватьдокументациюпосамойC-библиотекеncurses.
ПомимоCurses,наCPANсуществуютещёнесколькодистрибутивов,которыепозво-ляютразрабатыватьприложениястексто-выминтерфейсом.
ЧастьихиспользуютCurses,ноимеютболеевысокоуровневыйинтерфейс,удобныйдляразработки.
ЭтотакиемодуликакCurses::UIиCurses::Toolkit.
Естьтакжемодули,которыевообщенепривязаныкncurses,например,Tickit.
Есливыпланируетесозданиесложныхконсольныхприложений,гдебудутактивноиспользоватьсяпримитивыокон,диалогов,меню,форм,функцииоб-ратноговызованасобытия,тоэтимодули,вероятно,наиболеелучшийвыбордляиспользования.
Еслижестоитзадачасозда-ниятривиальногопозиционноговыводаинформации,как,например,вприложе-нииtop,тоиспользованиеCursesможетбытьцелесообразнее.
БиблиотекаCursesработаетсэкраном,ко-торыйпредставляетсяввидепрямоуголь-нойматрицы,каждыйэлементкоторойсвя-занспозициейнаэкранедлявыводасимво-ла.
Началокоординат,позиция(0,0),задаётлевыйверхнийуголэкрана.
Наэкранемо-гутбытьзаданыодноилинесколькооконисубокон—прямоугольныхобластей,длякоторыхопределенысвоисвойствавывода.
СтартсCursesНесколькофункцийбиблиотекиинициали-зируютработуприложениявтекстовомре-жиме:initscr—функцияинициируетрежимcurses,создаётокнопоумол-чанию,производиточисткуэкранаиустанавливаеттекущуюпозициюкурсоравлевыйверхнийугол(0,0);cbreakиraw—функцииотключаютбуферизованныйввод,иприложе-ниесразуполучаетинформациюонажатыхклавишах,приэтомrawтакжеперехватываетиспециальныесочетанияклавиш,такиекакCtrl+CиCtrl+Z;echoиnoecho—включаютиотклю-чаютрежимэха,т.
е.
выводнаэкранвводимыхсклавиатурысимволов.
БиблиотекаCursesимеетОО-интерфейс,вэтомслучаевместоинициализацииок-напоумолчаниючерезinitscrможноиспользоватьвызовnew:1my$win=Curses>new();МногиефункцииС-библиотекиncursesимеютразличныевариацииоднойитойжефункцииспрефиксамиw,mv,иwmv.
Префиксподразумевает,чтопоявляетсякакой-либодополнительныйпараметр:w—объектокна,mv—координатыy,xпозициикурсора.
ВPerl-библиотекеCursesтакиевариациифункцийбылиобъединеныводну,носопциональнымипараметрамиокнаикоординат:1function([win],[y,x],args);Такиефункцииполучилиназваниеунифи-цированных,иихможноиспользоватькакметодыприпрограммированиисисполь-зованиемОО-интерфейса.
ВдокументацииCursesприведёнполныйсписокфункцийиуказано,какиеизнихявляютсяунифици-рованными,акакие—нет.
Вовсехпоследу-ющихпримерахбудетиспользоватьсяОО-интерфейс,поэтомуеслииспользуетсяпря-мойвызовфункций,тоэтоявноподразуме-вает,чтофункциянеявляетсяунифициро-ванной.
Рассмотримпримерприложения,котороевыводитсообщениевцентрэкрана,ожида-етвводпользователяизавершаетработу:1usestrict;2usewarnings;3useCurses;45my$win=Curses>new();67raw();8noecho();910$win>keypad(1);11$win>getmaxyx(my$row,my$col);1213my$str="Yourterminalsize:${row}x$col";1415$win>addstr($row/2,($collength$str)/2,$str);16$win>refresh();1718my$ch=$win>getch();1920endwin();Приложениесоздаётокно.
Методkeypadсозначениемистинывпараметревключа-етобработкуспециальныхклавиш,такихкакF1,F2ит.
д.
Методgetmaxyxпозво-ляетопределитьмаксимальныезначениякоординатнаэкране,т.
е.
размертекуще-готерминала.
Методaddstrпозволяетвывестистрокупозаданнымначальнымкоординатам.
Методrefreshотображаетвсёто,чтомывывелинаэкран.
Методgetchожидаетнажатияклавишиивозвра-щаетвведённыйсимвол.
Функцияendwinзавершаетрежимcurses,возвращаяпреды-дущеесодержимоеэкрана.
ОкнаисубокнаОкнаисубокнаиспользуютсядлятого,что-быустановитьограничениедляконтента,которыйбудетвыводитьсявнутриокна,атакжедлятого,чтобыуправлятьатрибута-мивнутриокна.
Длясозданияновогоокнаиспользуетсяфункцияnewwin:1my$win=newwin($rows,$cols,$y,$x);где$rows,$cols—определяютвысотуиширинуокна,а$y,$x—положениеокнанаэкране.
Окнамогутперекрываться,приэтомвместепересечениябудетотображатьсякон-тенттогоокна,котороебылообновленопоследним.
Еслитребуетсясоздатьокновнутридругогоокна,томожноиспользо-ватьфункциюсозданиясубокнаsubwinилиderwin:1my$subwin=$win>subwin($rows,$cols,$y,$x)23my$subwin=$win>derwin($rows,$cols,$dy,$dx)Отличиеsubwinиderwinвтом,чтовderwinкоординатысубокназадаютсяотносительноверхнеголевогоуглароди-тельскогоокна.
Дляудаленияокнаилисубокнаиспользу-етсяфункцияdelwin1$win>delwin();Окноможноперемещатьпоэкрануспомо-щьюфункцииmvwin(mvderwin—длясуб-кона):1$win>mvwin($newY,$newX)23$subwin>mvderwin($newDX,$newDY);Очиститьсодержимоеокнаможноспомо-щьюфункцииclear:1$win>clear();Существуетвозможностьотобразитьгра-ницыокнаспомощьюфункцииbox:1$win>box(2$win>box(0,0);гдепервыйпараметропределяетсимволдлявертикальныхлиний,авторой—гори-зонтальных.
Еслииспользуетсязначение0(илиundef),тоиспользуютсясимволыграницпоумолчанию.
Еслитребуетсязадатьразличныесимволыдлявсехсторониугловокна,томожновос-пользоватьсяфункциейborder:1$win>border(2$left,$right,$top,$bottom,3$top_left,$top_right,$bottom_left,$bottom_right4);АтрибутыДлякаждоговыводимогосимволаможетбытьустановленыатрибуты,втомчисле:A_BOLD—режимповышеннойярко-сти;A_NORMAL—нормальныйрежимяркости;A_DIM—режимпониженнойяркости;A_UNDERLINE—подчёркнутыйтекст;A_REVERSE—инверсныйтекст;A_BLINK—мерцающийтекст;A_INVIS—невидимыйтекст.
Невсетерминалыподдерживаютуказан-ныеатрибуты(какправило,A_NORMALсовпадаетсA_DIM,анекоторыеатрибутымогутзаменятьсяцветовымвыделением).
Установитьконкретныйатрибутилинаборатрибутовможнофункциейattron:1$win>attron(A_BOLD|A_UNDERLINE);Послечегопривыводетекставданноеок-ноначинаютприменятьсяуказанныеатри-буты.
Такжедляустановкиатрибутовмож-ноиспользоватьфункциюattrset,нодан-наяфункциясброситвседругиеатрибуты,которыебылидоэтогоустановлены:1$win>attron(A_BOLD);#attributesnowA_BOLD2$win>attron(A_REVERSE);#attributesnowA_BOLD+A_REVERSE34$win>attrset(A_UNDERLINE);#attributessettoA_UNDERLINEДляотключенияопределённыхатрибутовиспользуетсяфункцияattroff:1$win>attroff(A_BOLD);ЦветаМногиетерминалыимеютподдержкуцвета.
Длятого,чтобыопределить,под-держиваетлитерминалцвет,можноиспользоватьфункциюhas_colors.
Еслиподдержкацветоввтерминалеприсутству-ет,топередработойсцветовойпалитройтребуетсяинициализироватьцветавызо-вомфункцииstart_color:1die"Yourterminaldoesnotsupportcolor\n"unlesshas_colors;2start_color();Длясозданияпалитрыиздвухцветов(цветфонаицветтекста)используетсяфункцияinit_pair:1init_pair(1,COLOR_BLUE,COLOR_BLACK);Установитьуказаннуюпалитруцветовдлявыводаможновсётойжефункциейattron:1$win>attron(COLOR_PAIR(1));Цветоваяпалитраограничена16цветами,причёмбазовыхцветовтолько8,адополни-тельныецветаполучаютсязасчётисполь-зованияповышеннойяркости(A_BOLD):1COLOR_BLACK02COLOR_RED13COLOR_GREEN24COLOR_YELLOW35COLOR_BLUE46COLOR_MAGENTA57COLOR_CYAN68COLOR_WHITE7Существуетвозможностьпереопределитьлюбойбазовыйцветспомощьюфунк-цииinit_color,котораядлязаданногобазовогоцветаустанавливаетзначенияинтенсивностисоответственнокрасного,зелёногоисинегоцветоввдиапазонеот0до1000:1init_color(COLOR_BLACK,100,100,100);#black>darkgrayНевсетерминалыподдерживаюттакуювозможность,поэтомупередизменени-емцветовпалитрыследуетвыяснить,присутствуетлитакаявозможностьвте-кущемтерминале,спомощьюфункцииcan_change_color.
ОбработкавводаДляполучениязначениявведённогосим-волаиспользуетсяметодgetch.
Вслучаееслибылаактивированаобработкаспеци-альныхклавиш(F1,PgUp,PgDownит.
д.
)спомощьюkeypad(1),тоgetchвозвра-щаетчисловойкодспециальнойклавиши,например,значение338дляPgDown.
Еслижеобработкаспециальныхклавишотклю-чена,тоgetch()вернётлишьпервыйкодизescape-последовательностиклавиши.
ЕслинавводеоказываетсясимволUnicode,тоgetchвоспринимаетлишьпервыйбайтпоследовательности.
СоответственнодляобработкиUnicode-символа,имеющеговнутреннеепредставлениеиздвухбайт,потребуетсядвапоследовательныхвызоваgetch:1$win>keypad(1);2$ch=$win>getch();34if(length$ch>1&&$ch==KEY_F(1)){56#lookslikeaF1key7$win>addstr(1,1,"F1KEY!
");8}9elsif(ord($ch)addstr(1,1,$ch);13}14elsif(ord($ch)>>5==0b110){1516#hack:lookslikeafirstbyteof2bytesUTF8unicodecodepoint17$ch.
=$win>getch();18$win>addstr(1,1,decode_utf8($ch));19}ВCursesопределеныконстантыдляфунк-циональныхклавиш,атакжефункцияKEY_F,возвращающаякодF*-клавиш.
Названияконстантможнонайтивдоку-ментацииCurses,всеониимеютпрефиксKEY_.
ВС-библиотекеncursesw,естьфункцияget_wch,котораяможетобрабатыватьвводширокихсимволов,но,ксожа-лению,онанеперенесенавPerl-обвязкуCurses.
Спомощьюфункцииhalfdelayможноуказать,какоевремя(вдесятыхдоляхсекунды)getchдолженожидатьвводасимвола.
Еслипослеистечениятаймаутаклавишаненажата,getchвернётзначениеERR(-1).
1halfdelay(10)2$ch=$win>getch();3if($ch==ERR){45#Timeout6.
.
.
7}Дляполучениястрокисимволовдосимво-лапереносастроки(илиEOF)можетисполь-зоватьсяфункцияgetstr:1$win>getstr(my$str);2$win>addstr(1,1,"Youtype:$str");УправлениекурсоромПолучитьтекущиекоординатыкурсораможноспомощьюgetyx:1$win>getyx(my$y,my$x);Есливызываетсякакая-либофункциявыво-данаэкранбезуказаниякоординат,товы-водпроизводитсяначинаястекущейпози-циикурсора.
Курсорможнопередвигатьпоэкрануспомощьюфункцииmove:1$win>move($y,$x);ОчисткаэкранаСуществуетвозможностьочисткиэкранаилиегочасти.
Подочисткойпонимаетсязаполнениеегопробельнымисимволами.
Функцияclearочищаетокноцеликом:1$win>clear();Функцииclrtoeolиclrtobotочищаютэкран,начинаястекущейпозициикурсорадоконцастрокииконцаокнасоответствен-но:1$win>ctrloeol();2$win>ctrlobot();Функцииdeletelnиdelchудаляютстро-куисимволсоответственнонатекущейпо-зициикурсора:1$win>deleteln();2$win>delch();Функцияinsdellnвставляетуказанноечислопустыхстрок,начинаястекущейпо-зициикурсора(илиудаляет,еслиаргументотрицательный).
1$win>insdelln(10);ОбработкасобытиймышиCursesпозволяетобрабатыватьсобытия,возникающиеприиспользованиимыши,такиекакнажатиеклавишиперемеще-ниеуказателя.
Передначаломобработкидействиймышинеобходимозадатьмаскусобытий,которыебудетфиксироватьпро-грамма.
Делаетсяэтоспомощьюфункцииmousemask:1mousemask(ALL_MOUSE_EVENTS,my$old_mask);Фиксироватьналичиедействий,произ-ведённыхмышью,можновсётойжефункциейgetch.
Функцияgetmouseпозволяетполучитьструктурупроизошед-шегособытия,кудавходитинформацияобидентификатореустройствамыши(ихмо-жетбытьнесколько),координатахмышивтрёхизмеренияхинепосредственнотипесобытия.
1my$key=$win>getch();2if($key==KEY_MOUSE){3getmouse(my$ev);45#fixalignofshortinCstructure6my($id,$x,$y,$z,$state)=unpack("sx!
[i]i3L",$ev);78if($state&BUTTON1_CLICKED){910#leftbuttonclicked1112}13}ИзменениеразмераэкранаПосколькузачастуюконсольныеприло-жениязапускаютсявнутриграфическогоокнаэмуляторатерминала,тововремяработыприложенияможетпроисходитьизменениеразмеровэкрана,когдаполь-зовательрастягиваетокнотерминалаилинаоборотуменьшает.
ДляэтихслучаевсуществуетсигналSIGWINCH,которымэмулятортерминалаоповещаетзапущен-ныеприложенияобизмененииразмераэкрана.
БиблиотекаCursesустанавливаетобработ-чикэтогосигналаипытаетсяадаптироватьсуществующиеокнаподновыйразмерэкрана.
Конечноневсегдаэтоможетбытьвыполненокорректно,поэтомудляполь-зовательскогоприложенияреализованавозможностьполучитьоповещениеобпро-изошедшемизмененииразмеровэкрана—функцияgetchвозвращаетзначениеKEY_RESIZE:1my$key=$win>getch();2if($key==KEY_RESIZE){34#getnewwindowsize5$win>getmaxyx(my$row,my$col);6}Нестоитпереопределятьобработчиксигна-лаSIGWINCHвкодеприложения,посколькуэтоприведёткзавершениюработыприло-женияпослеполучениясигнала.
Панели,менюиформыВрамкахпроектаncursesсуществуютдо-полнительныебиблиотеки,расширяющиевозможностиncurses:Панели.
Представляютсобойокна,ко-торыемогутперекрыватьдругдруга,приэтомможноуказатьвкакомпо-рядкеследуютпанели,т.
е.
указывает-сятретьеизмерение—глубина.
Пане-лиможноскрывать,отображать,пере-мещатьнаверхвстопке.
Меню.
Позволяетреализовыватьвнутривашихприложенийпривыч-ныеменюсподдержкойвложенно-сти.
Формы.
Позволяютсоздаватьпривыч-ныеэлементыдлявводаданныхвви-детекстовыхполей,которыеможнозаполнятьиредактировать.
Подробноеописаниеэтихрасширенийможетстатьтемойдляещёоднойстатьи,новполневозможно,еслиприложениетребуетподобногофункционала,стоитпосмотретьнаболеемощныеальтернати-вынаCPAN,например,Curses::UIилиTickit.
ВладимирЛеттиев4Миграциявеб-приложенийсDancerнаDancer2ГотовалиноваяверсияфреймворкаDancer2дляиспользованиявпромышленнойэксплуа-тацииСложнолипроизвестимиграциюсу-ществующегоприложениянановуюверсиюфреймворкаКакиепреимуществадастпе-реход,иестьлинедостаткиДаннаяста-тьяпопытаетсядатьответынапостав-ленныевопросыиосветитьподводныекамнимиграции.
ЧтоновогоестьвDancer2НамоментнаписаниястатьинаCPANдо-ступендистрибутивDancer2версии0.
09,вышедший2сентября2013г.
,поэтомувсефакты,изложенныениже,справедливыименнодляэтойверсии.
Dancer2—этолегковесныйвеб-фреймворкдляPerlновогопоколения.
Dancer2былпрактическинаписанзаново,чтобыре-шитьнекоторыесерьёзныенедостаткидизайнаDancer,такиекакиспользованиеглобальныхпеременныхисинглтоновиотсутствиехорошегоиясногообъектно-ориентированноговнутреннегоAPI.
ВновойверсииDancer2сталисполь-зоватьсямощныйилегковесныйООП-фреймворкМоо,которыйпозволиллегкостроитьирасширятьвнутренниеклас-сыфреймворка.
Особоевниманиебылоуделенообратнойсовместимости,чтобынеобходимостьизмененийвкодедляпереходанановуюверсиюфреймворкатребовалоськакможноменьше(видеалененадобылоисправлятьничего).
Но,ксожалению,некоторыешероховатостивмиграцииизадержкасвыпускомновойверсиипривеликтому,чтоDancer2былобъявленнекакзамещение,акакпарал-лельныйпроектсосвоимпространствомимён,вкоторомбудутпоявлятьсяновыефичи,втовремякакDancerпродолжитсвоёсуществованиетольковрежимеподдержкииисправленияошибок.
КромевнутреннихизмененийвDancer2наданныймоментнеткаких-тоновыхубийственныхфич.
НаданномэтапеDancer2лишьпытаетсядогнатьDancerпоподдерживаемымвозможностям.
ОтличияDancer2Примиграциивеб-приложениянаDancer2можностолкнутьсяснеобходимостьювнесенияизмененийкаквкод,такивконфигурациюприложения.
Попробуемразобрать,какиепроизошлиизменения.
ОтличиявконфигурацииВотличиeотDancer,вDancer2под-держиваетсяконфигурационныефайлыразличногоформата:yaml,json,apache,iniипрочие,которыепонимаетмодульConfig::Any.
Такимобразом,есликто-тоиспытываетдискомфортвработесYAML,можетпереписатьконфигурационныйфайлconfig.
ymlвудобныйемуформат.
Dancer2будетпытатьсянайтиконфигура-ционныйфайлнужногоформатаисходяизназваниярасширенияфайла.
Изменилосьописаниеконфигурациишаб-лонизаторовидвижковсессий,например:1template:"xslate"2engines:3xslate:4cache:15cache_dir:"cache"вDancer2этонужнобудетизменитьна:1template:"Xslate"2engines:3template:4Xslate:5cache:16cache_dir:"cache"Т.
е.
добавляетсяпромежуточныйпараметр,указывающийтипдвижка:templateилиsession.
Примеризмененияконфигурациидлядвижковсессий:1session:"memcached"2session_expires:6048003memcached_servers:"127.
0.
0.
1:11211"Изменяетсяна:1session:"Memcached"2engines:3session:4Memcached:5session_duration:6048006memcached_servers:"127.
0.
0.
1:11211"Значениякаталогов,такихкакconfdirиpublic,невозможноустановитьвфай-леконфигурациииличерезвызовsetвприложении.
Единственныйпокаспо-собизменитьихзначенияспомощьюпеременныхокружения:1DANCER_CONFDIR2DANCER_PUBLICЕсливыустанавливаетеэтиперемен-ныеокружениявсамомприложении,тоэтонеобходимоделатьдовызоваuseDancer2,т.
е.
всекцииBEGIN.
ПлагиныDancer2используетООП-фреймворкMoo,чтосерьёзнопоменялотехническуюреали-зациюмодулейплагинов.
Такимобразом,использоватьсуществующиеплагиныдляDancerсталоневозможно,итребуетсяпереписыватьихподDancer2,чтовсвоюочередьможетотразитьсяинаихAPI,инаопцияхконфигурации,ивобщемслучаенельзянавернякасказать—потребуетсяличто-томенятьвкодеприложения,ко-тороеиспользоваловозможностиданногоплагина.
Посмотретьсписоксуществующихпла-гиновдляDancer2можнонастраницепроектанаgithub.
Невсеизнихмогутоказатьсярабочими,таккакAPIплагиновDancer2всёещёвактивнойразработке.
ПодключениеDancer2ВDancer2реализованаподдержкалишьчастиаргументовприподключениимоду-ля:1useDancer2qw(:tests:script!
keyword)Такойчастоиспользуемыйаргументза-грузкимодулякак:syntax,вDancer2отсутствует.
Несмотрянаналичиеопции:script,вDancer2поканереализованаподдержкаконфигурациичерезопциикоманднойстроки.
ИзменениявDSLВDancer2перенесенывседирективызаисключениемтех,которыепомеченыкакустаревшиевDancer.
Например,мнеприпереносенебольшогопроектанаDancer2вкоденепришлосьменятьничего,кромезаменыuseDancerнаuseDancer2.
Развёртываниевеб-приложенийНаиболеерациональныйспособразвёрты-ванияDancer-приложений—этозапускихвstandalone-режимеспомощьюplackupипроксированиекнимзапросовчерезфронтенд-веб-серверApacheилиNginx.
ТакжеможноиспользоватьзапускчерезFCGI.
Вэтомотношенииразвёртываниевеб-приложенийнаDancer2неизмени-лось.
Гораздоинтереснейвариантразвёртыва-ниясиспользованиемmod_perl2иApacheврежимеpreforkилисMPMworker.
Какизвестно,вDancerневозможноврамкаходногопроцессазапускатьдваразныхприложения,таккакониразделяютобщиеданныеконфигурацииимаршрутов.
ЧтожеизменилосьвDancer2Рассмотримконфигурациюсдвумявиртуальнымихо-стами:12StartServers1345PerlSwitchesI/srv/App1/lib6PerlSwitchesI/srv/App2/lib789ServerNameapp1.
local10DocumentRoot"/srv/App1/public"1112SetHandlerperlscript13PerlHandlerPlack::Handler::Apache214PerlSetVarpsgi_app/srv/App1/bin/app.
pl15161718ServerNameapp2.
local19DocumentRoot"/srv/App2/public"2021SetHandlerperlscript22PerlHandlerPlack::Handler::Apache223PerlSetVarpsgi_app/srv/App2/bin/app.
pl2425Проверимихработу:1$curlshttp://app1.
local/|grep''2App11$curlshttp://app2.
local/|grep''2App1Каквидно,вконфигурациисоднимра-бочимпроцессомпервоезапрошенноеприложениефиксируетконфигурацию,ивтороеприложениеначинаетисполь-зоватьшаблоныимаршрутыпервогоприложения,т.
е.
вданнойситуациипове-дениеDancer2нискольконеотличаетсяотDancer.
ЕслиобратитьсякдокументацииDancer2,тодляобъединениядвухприложенийводнорекомендуетсяиспользоватьPlack::Builderвтакомвиде:1useApp1;2useApp2;3usePlack::Builder;45builder{6mount'/app1'=>App1>dance;7mount'/app2'=>App2>dance;8};Такаяконфигурацияподразумеваетработудвухприложенийврамкаходноговирту-альногохоста,иприложенияразделяютсяпопрефиксувURI:/app1и/app2.
Ксожа-лению,напрактикеитакаяконфигурацияявляетсянерабочей,поэтомувопрособиспользованиидвухиболееприложенийDancer2врамкаходногопроцессаостаётсяоткрытым.
ПроизводительностьТестпроизводительностинепретендуетнавысокуюточность,нопозволяетпри-мернооценитьотносительныеизменениявпроизводительностимеждуDancerиDancer2.
Спомощьюутилит,которыегенерируетшаблонноеприложение,со-здадимвеб-приложениянаDancerинаDancer2:1$danceraBench::Dancer1$dancer2aBench::Dancer2Запустимвеб-сервернаосновеTwiggyпоочередидлякаждогоприложенияизапустимутилитудлябенчмаркаab2.
1$plackupIlibEdeploymentsTwiggyabin/app.
plp5001&1$ab2n2000http://127.
0.
0.
1:5001/ДляDancerполучимследующийотчёт:1DocumentLength:5582bytes2Timetakenfortests:10.
657seconds3Completerequests:20004Failedrequests:05Requestspersecond:187.
66[#/sec](mean)6Timeperrequest:5.
329[ms](mean)ДляDancer2отчётбудеттакой:1DocumentLength:5540bytes2Timetakenfortests:12.
192seconds3Completerequests:20004Failedrequests:05Requestspersecond:164.
04[#/sec](mean)6Timeperrequest:6.
096[ms](mean)Абсолютныевеличиныздесьнеинтересны(тестоваясистемасвесьмаскромнойпро-изводительностью),номожнооценить,чтопроизводительностьвDancer2проселана~13%припрочихравныхусловиях.
ОбъёмзанимаемойпамятиОбъёмзанимаемойпамятиPerl-программызависитотверсииинтерпретатораиопцийсборки.
ДляслучаяPerl5.
16.
3,собранноговвидеразделяемойбиблиотекиlibperl.
soдляплатформыx86_64споддержкойтредов,призапускегологоperlполучаемтакуюстатистикуиз/proc/$$/status:1VmSize:19108kB2VmRSS:2028kB3VmData:520kB4VmLib:4524kBТ.
е.
общийобъёмзанятойвиртуальнойпа-мяти—19МБ,изних2МБнаходятсяпосто-янновпамяти,4,5МБ—загруженныераз-деляемыебиблиотеки,0,5МБ—этообъёмсегментаданных.
Попробуемтеперьсравнитьобъёмзани-маемойпамятиминимальныхDancerиDancer2приложенийпризапускевstandalone-режиме:1$perlIlibbin/app.
plСтатистикадляDancer:1VmSize:59296kB2VmRSS:15940kB3VmData:13420kB4VmLib:4924kBСтатистикадляDancer2:1VmSize:78848kB2VmRSS:23028kB3VmData:20252kB4VmLib:5512kBТакимобразом,минимальноеприложениенаDancer2занимаетужена~30%большевиртуальнойпамятиина~45%большере-зидентной.
ЗависимостиDancerиDancer2имеютдовольноболь-шоедеревозависимостей.
Спомощьюутилитыstraceможнооценитьколи-чествомодулей,которыетребуютсяпризагрузкеминимальногоприложения:1$straceeopenodancer.
traceperlIlibbin/app.
pl&2.
.
.
3$grep'\.
pm'dancer.
trace|wcl412756$egrep'perl5.
+\.
so'dancer.
trace|wcl711Такимобразом,Dancerвобщейсложностизагружает127модулейи11разделяемыхбиблиотекXS-модулей.
ДляDancer2статистикасущественнотяже-лее:217модулейи18разделяемыхбиблио-текXS-модулей.
Тоестьна~70%большеза-гружаемыхмодулей,чтоиобъясняетуве-личениезанимаемойпамяти.
Длясравнения—Mooseзагружает109мо-дулей…ВыводыЕслипослепрочтениястатьиувассло-житсявпечатление,чтомигрироватьнаDancer2неимеетсмысла,торекомендуювамвсёжепопробоватьдляэкспериментаэтосделать.
Есличто-тосломается,тоинформацияобэтомможетоказатьсяоченьполезнойдляразработчиков,чтобыкследующемурелизуэтомоглобытьисправлено.
ВладимирЛеттиев5ОбзорCPANзасентябрь2013г.
РубрикасобзороминтересныхновинокCPANзапрошедшиймесяц.
СтатистикаНовыхдистрибутивов—253Новыхвыпусков—988НовыемодулиTickit::DSLМодульреализуетDSL-языкдляописанияконсольныхинтерфейсовприложений,реализуе-мыхнаосновемодуляTickit.
Exporter::TinyАльтернативнаяреали-зацияSub::Exporterпредоставляетвозможностьэкспортафункций,включаявозможностьихпереиме-нования,атакжеподдерживаютсяконфигурациячерезпеременные@EXPORT,каквExporter.
Приэтоммодульнеимеетнебазовыхзависи-мостей.
AnyEvent::WebSocket::ClientРеали-зацияWebSocket-клиентанаосновеAnyEvent.
Error::TinyЛегковеснаяреализацияобработкиисключенийtry/catch.
Ис-ключениевсегдапередаётсявcatchввидеобъекта,чтоудобнодляобработ-ки.
Правда,вотличиеотTry::Tiny,содержимое$@непредохраняется.
ExtUtils::MakeMaker::CPANfileМо-дульвключаетподдержкуфайлаcpanfileвскриптахустановкинаExtUtils::MakeMaker.
ArkВышелпервыйрелизнаCPANужедавносуществующегоCatalyst-подобноговеб-фреймворкаArk.
ElasticsearchВышелофициаль-ныйPerl-клиентдляраспреде-лённогодвижкапоискаиана-лизаElasticsearch.
МодульElasticSearchобъявленустарев-шим.
IO::Socket::TimeoutМодульдобавляетвозможностьустановкитаймаутовдлячтенияизаписивIO::Socket::INET.
SeisМодульдлятрансляцииPerl6синтаксисавPerl5.
ВозможностимодуляещёнеслишкомвеликиидалеконевсеконструкцииPerl6переносимы,нокакконцептмодульоченьинтересен.
Text::Markdown::HoedownМодульобвязкикбиблиотекеHoedown,являющейсяожившимфоркомбиб-лиотекиSundown—парсераформатаmarkdown,котораябылапостраннымпричинамобъявленаустаревшейбезобъявленияпреемника.
ОбновлённыемодулиFile::LibMagic1.
00ВышелмажорныйрелизмодулядляопределениятипаMIME-данныхсиспользованиемlibmagic.
Вновойверсиипоявиласьвозможностьпередаватьссылкунаскалярсданнымидляанализа.
Starman0.
4008Вновомрелизевеб-сервераStarmanсделанонесколькоисправлений,втомчислеобработкасигналаEPIPEприотправкеданныхклиенту.
Cache2.
06Послепродолжительногозабвениявышелновыйрелизмоду-лядляуправлениякэшем.
Вновойверсиипроизошёлпереходнасбор-кусModule::Buildиисправленынекоторыеошибки.
Date::Manip6.
41Вышелновыйбагфикс-релизмодуляDate::Manipдляпроведенияразличныхвычисле-нийсдатами.
Clone0.
35ВновомрелизеCloneис-правленапроблемасSIGSEGVвperlприпопыткеклонированияструкту-ры,вкоторойестьскалярсозначени-емNULL.
Config::Any0.
24Вновойверсиинаконец-тоубралиужаснораздража-ющеепредупреждениеотом,чтонеустановленYAML::XS.
local::lib1.
008018Новаяверсияlocal::libтеперьработаетиприустанов-леннымфлагеT(taint-режим)призапускеPerl.
autodie2.
22Множествоисправленийиулучшенийвработемодуляautodieвновомрелизе.
perlsecret1.
004Обновилсязамеча-тельныйдокументосекретныхопе-раторахиконстантахвPerl.
Вэтомвыпускераскрытновыйсекретныйоператорключкправде0+!
!
Tickit0.
40Вышелновыйрелизинструментальногонаборадлясо-зданияпрограммсконсольныминтерфейсом.
Вданномвыпускеисправленыошибкииобновленадокументация.
ВладимирЛеттиев6Интервьюсchromaticchromatic—авторкнигиModernPerl,участ-вовалвразработкеPerl6иParrot,автормно-гихпопулярныхмодулейнаCPAN.
КогдаикакначалпрограммироватьВкоторыйразКакимногиемоисверстникивштатах(белыедетиизсреднегокласса,выросшиезагородом),впервыйразяувиделком-пьютервначальнойшколе.
Мнебылопятьилишестьлет.
ЭтобылCommodore64.
Втедникомпьютерыпоставлялисьсдокумен-тациейиBASIC,ивдокументациибылоописанокакписатьпростыепрограмынаBASICпрактическинапервыхстраницах.
(Страница32—толькочтопроверил.
Пер-выенесколькостраницрассказывают,какподключитьтелевизорилимониторикакработаетклавиатура.
)Вконцеконцовяуговорилродителейку-питьдлясемьикомпьютер.
Когдаябылвстаршейшколе,моиинте-ресыизменилисьиябольшепроводилвремени,играямузыку,чемпрограмми-руя,новколледжеяпопыталсязанятьсяC++(непошло)иJava(пошлонемноголучше)инапервойвсвоейкарьереработеянаписалнесколькопрограммдляотдела,занимающегосяпринтерамивHP,инашелэтосамымувлекательнымсредивсего,чемязанимался.
КакойредакториспользуешьVim.
КогдаикакпознакомилсясPerlJavaбылановойиинтересной,когдаяначалработатьвHP,нояработалсHP-UXиLinux(RedHat4или5,кажется).
JavaнаLinuxбыласильнопозадивтовремя,нотамхотябыбылабазоваяподдержкаSwing.
Второйсерьезныйпроект,надкоторымяработал,долженбылотправлятьemailспискуклиентовобобновленияхсетевойслужбыподдержкипринтеров.
Янабросалнаколенкеbash-скриптнаверсии,кото-руюподдерживалвтовремяHP-UX9.
Онбылдлинойвдесятьстрок.
ЗатеммнепришлосьпортироватьегонаJava,потомукакотделунужнобылозапускатьегонаWindowsNT.
ВтомвремяJavaбылаещемолодой.
Унеенебылобольшогоколиче-ствабиблиотек.
ДляотправкиemailнужнобылописатьмногокодадляподключениякSMTP-серверуиотправкиправильныхзаголовковипрочего.
Нужнобылона-писатьбольшекодадляинициализацииJava-библиотек,чемнаписатьвсюзадачунаshell.
Яначалискатьдругиеязыки.
Мойбратучилсяиработалстелекоммуникациямивуниверситетевтовремя,имногоеавтома-тизировалспомощьюPerl.
ЯкупилвтороеизданиеCamelbook,прочелееоткоркидокорки,ипонеслась.
Скакимидругимиязыкамиприятнора-ботатьHaskell,заегосистемутипов,котороймож-нопользоваться(атакжезато,чтоонпо-ощряетнаписаниенебольшихкусковкода,которыеразумновзаимодействуют).
Scheme,завозможностьпостроитьхо-рошуюсистемуизнебольшихгодныхкомпонентов.
Хотелось,чтобыиGoпонравился,нодляменяонпоканебылдостаточнополезным.
Продолжаюдумать,чтовC++естьхоро-шийязык,которыйпытаетсявыбраться,номнекажетсяянедостаточноумный,чтобыегообнаружить.
Какое,по-твоему,самоебольшоепреиму-ществоPerlБесцеремонность.
МожнодатьPerlкому-тоснебольшимопытомпрограммированияионилионасделаютчто-тогораздобыстрее,чемвыможетеожидать.
Онилионаско-реевсегонапишуткакую-тожуть—разви-тиедисциплинывпрограмированиитребу-етвременииопыта—нопрагматизмPerlэтобольшоепреимущество.
Какими,по-твоему,особенностямидолж-ныобладатьязыкибудущегоВсезависитотязыка.
Большинстволюдейсчитают,чтоскоростьвыполненийэтоса-маяважнаячасть,ивнекоторыхслучаяхтакиесть.
Есливыхотитеполучитьболь-шоеколичествопользоватлей,необходимодатьимвозможностьделать,чтоонихотят,нераздражаяихнастолько,чтоониуйдуткуда-нибудь.
Опятьже,прагматизмздесьидетнапользу.
УPHPмногопользователейнепотомучтоэтохорошийязык.
УPHPмногопользовате-лейпотомучтоэтосамыйпростойспособсделатьдинамическуювеб-страницу.
Тымногоевложилвэкосистемуиинфра-структуруPerl.
ЧтоявляетсяпричинойэтомуЯхочуупроститьсвоюжизнь.
ХорошиетестыуCPAN-модулейозначают,чтоямогудоверятьCPAN-модулямбольше,чемраньше.
НаличиепростыхихорошихабстракцийдлятакихвещейкакemailилиОО-разработкиозначает,чтоямогувыполнитьсвоюработулучше,затративменьшесил,чемраньше.
Наличиевсвободномдоступехорошейкнигидляначинающих,какойянадеюсьявляетсяModernPerl,означает,чтобольшелюдейначнутписатьхорошийPerl-код,анеплохой,еслибыониучилисьпоужас-ным,устаревшимурокам,которыеможнонайтивсети.
ВтечениесвоейработынадPerl6тызанималсяролями.
ЯвляютсялиониосновойсовременногоООПЭтосе-ребрянаяпуляилиещеодинспособпрострелитьсебеногу,еслиговоритьореальныхбольшихисложныхпроектахЕсличитатьсовременныеООП-уроки,пло-хиебудутобъяснять,чтонаследование,этоосноваяООП.
Этоглупо.
Полиморфизм—этоосноваООП.
(Полиморфизм—важнаячастьвпрограм-мировании.
Есливыненаучилисьработатьсобъектами,разнящимисявмелочах,ноодинаковыхвглавном,увасбудетмногопроблем.
Людичастонеучатсяработатьсмассивами,потомучтохотятимено-ватьперменные$recipe1,$recipe2и$recipe3.
Итолькокогдаониосознают,чтомогутработатьспеременнымикаксэлементамимассива@recipes,ониначи-наютпониматьсилупрограммирования.
)Вовремяразработкиролейядоказывал,чтонамнужнорешитьдвепроблемы:1.
какопределитьдостаточнокон-цептуальнопохожиеповедениеисостояние,чтоонимогутбытьполи-морфными;2.
какделитьсякодомбезнавязыванияметодакакэтоделать(делегирование,наследование,композиция,копипас-та,роли).
АвторыоригинальнойстатьиоSmalltalkTraitsпыталисьрешитьпохожиепро-блемы,поэтому,ядумаю,мыбылинаправильномпути.
МожноимизлоупотреблятьДа.
МожнолипрострелитьсебеногуКонечно.
ЯвляютсялионибазовымидляхорошегоООП-проектаЗависитотпроекта.
Исходяизмоегоопыта,эффективноеиспользованиеролейипараметриче-скихролейулучшилодизайннесколькихпроектов.
Требуетсявремяиопытдляпонимания,какиспользоватьролиэффек-тивно,ноесливыдисциплинированныйпрограммист,которыйхочетпереработатьдизайнсвоейсистемы,когдаэтоможетпотребоваться,ролиэтоещеодининстру-ментвООП-проектированииианализе,накоторыйстоитобратитьвнимание.
ПочемутестированиеважноЯхочуусилитьсвоюуверенностьвтом,чтокод,которыйяиспользую,работает.
Тестированиенедаеттакойуверенности.
Мневполнедостаточно,чтоуменянетсто-процентнойуверенности,ноеслиямогупосмотретьнатестыионимнепонятны,уменястановитсяменьшезабот.
Менясильнонезаботитразницамеждуюнит-,интеграционными,поведенчески-ми,спецификационнымитестамиитакдалее.
Ястараюсьоставатьсяпрагматич-ным.
Яхочузнать,чтоважноеповедение,накотороерассчитываю,работает.
Яхо-чузнать,чтовыподумалиограничныхзначениях.
Яхочузнать,чтоеслиявнесуизменениеисломаючто-нибудь,запусктестоввыявитэто.
Этовсеокачестве,уверенностиинадежно-сти.
Этотакжепоказательдисциплиныикачествапрограммиста.
Вамнеобязатель-ноиметьавтоматическиетестыдляхоро-шегопродукта,ноеслиуваснетавтомати-ческихтестов,яхочузнать,почемуядол-жендоверитьпродукту,которыйвыпише-те.
Попрошествиюужеболеедесятилетсо-ответствуетлиTest::Builderсовремен-нымпрактикамвтестированииВтомчтоонделает—да.
ВтомкаконвыглядитвнутриНет.
Надеюсь,чтоTest::Builder1.
5или2.
0наконецвыйдетиподчиститкод.
ЧтопобудилотебянаписатькнигуModernPerlPerlтребовалоськороткоевведение,кото-роебынепритворялось,чтопокрываетвесьязык.
Яподумал,чтообъяснениефи-лософииязыка,какиспользоватьperldoc,необходимостьCPANидлячегоиспользо-ватьидлячегонеиспользоватьязык,былобыполезным.
ПочемурешилсделатькнигусвободнодоступнойТрипричины.
Во-первых,людивсегдадо-станутеебесплатно,разнымиспособаминарушаякопирайт,еслидействительноэтогозахотят.
Борьбасэтимнестоитмоеговремени.
Во-вторых,янадеялсянаболееширокийохват(спродвижениемплатнойпечатнойиэлектроннойверсии),есликни-габудетдоступнабесплатно.
В-третьих,язнаю,чтоестьлюдиввосточнойЕвропеизападно-восточнойАзииидругихре-гионах,которыебыникогданекупилипечатнуюверсиюиз-задорогойдоставки(илидороговизнысамойкниги).
Янемогуписатьнавсехязыках,номогудатьбес-платноеизданиенаанглийском,котороекто-томожетперевести.
Планируетсялиобновлениекниги,сов-местносэволюциейPerlЯхочувыпуститьновоеизданиедоконцатекущегогода.
Чтослучилосьсperl.
comКажется,чтонебылоникакихобновленийсянваря.
Нетакпростонайтиавторов,аянехочубытьединственнымавтором(какэтонамзнакомо—прим.
ред.
).
Утебянесколькобизнесов.
Чемвоснов-номзанимаешьсясейчасНаданныймоментяконсультируюодинстартапвмедицинскойиндустрии.
КакимвидишьбудущееPerlНадеюсь,чтотакиепроектыкакMOPStevanLittleисигнатурыфункцийPeterMartiniвойдутвядроязыка.
Сомневаюсьвпроектах,которыйхотятпе-ренестиPerlнановыйдвижок,вовсякомслучаебезисправленияситуациисXS.
CPANпродолжитрасти.
Незнаю,чтопроизойдетсрекламойPerl.
(Некоторыелюдиназываютсяэтомарке-тингом.
)Perlпродолжитпомогатьмоимклиенамипроектамполучатьправильныеответы.
ЕстьлиместодляPerl6Еслионнайдетчто-то,чтоонделаетлучшедругихсуществующихязыков,товозмож-но.
Стоитлисоветоватьмолодымпрограм-мистамизучатьPerlЭтозависитоттого,чтоонихотятнаписать.
Вчераяразговаривалсученицейстаршихклассов,котораяхочетизучатькомпьюте-ры,унееестьопытработысHTMLионахочетвыучитьJavaScript.
НуженлиейPerl(ЕстьлипростойWindows-дистрибутив,ко-торый,используямагиюPlack,позволяетразворачитьPerl-программытакжепро-стокакиPHP-программы,нонетребуетиспользованияCGI.
pmВозможно.
)ВопросыотчитателейНаPerlMonksутебявкачествеаватарафутболкаPerl7.
Чтодумаешьодискусси-яхвокругPerl-версийВретроспективе,возможно,названиесле-дующейверсииPerl6в2000годубылонеоченьудачным—ноэтонеизменится,ес-литолькоЛарринезахочетэтого,поэтомумызастрялисPerl5.
что-тотамвобозри-момбудущем.
ЧтодумаешьоситуациивокругsmartmatchУPerl5всегдабылаидея,чтопеременныедолжныбытьполиформными,втовремякакоператоры—мономорфными.
Други-мисловами,есливывидите$a+$b,товызнаете,чтоэтосложение(неважно,чтонаходитсяв$aи$b),иесливывидите$a.
$b,товызнаете,чтоэтоконкатенация(неважно,чтонаходитсяв$aи$b).
Соsmartmatchвсеиначе,икаждыйраз,ко-гдавыотходитеотизначальногодизайнаязыка,вамнеобходимоосторожноучестьвсеплюсыиминусы.
Smartmatchпохожнаспособрешитьнесколькопроблемодновременно.
Приотсутствиичеткогомножествамономорфныхтиповперемен-ных,вынеможетепосмотретьнакодисразужепонять,чтопроисходит.
Такаяжепроблемаиуeach()нассылках;вынеможетепонять,когдаeach$fooвер-нетключиизначенияхешаилииндексыизначениямассива.
Откудаберешьэнергиюдлярегулярныхстатейопрограммированиивсвоембло-геЯвсегдабылписателем,икаклюбоерегу-лярноеупражнение,эторазвиваетмышцы(буквальноифигурально).
Междутем,мояработаиличнаяжизньтребуютмноговремени,ичастотамоихпостовснизиласьотнесколькихразвнеде-людоеженедельныхвыпусков.
Былобыхорошоиметьнемногобольшесвободноговремени.
Былосложнопосленесколькихлетбро-ситьразработкуPerl6Ида,инет.
Мнеужепродолжительноевремяэтонедоставлялоудовольствиепомногимпри-чинам.
Самымбольшимбыло,наверное,моеразочарование,чтопоследевятилетработынаднеоченьинтереснымивеща-ми,такимикакисправлениесегфолтовиоптимизации,досихпорничегонебылоготовымдляиспользованиявработе.
Мнебылосложнооправдатьразработкуврабочиечасы,потомучтоуменябылодостаточноработы,котораятребовалара-ботающегокода,иуменябылодостаточнопотенциальныхпроектов,которымиязанималсявсвободноевремяикоторыемнедействительнонравились.
Сдругойсторой,еслитынадчем-торабо-таешьдевятьлет,утебявозникаетчувствопривязанности.
Ягорднекоторойработой,которуюмысделали,иямногомунаучил-ся,ноеслибымнесказалив2001или2002,чтобудетв2013,ябыпотратилсвоисилыначто-тодругое.
Наэтотурокяпотратилоченьмноговре-мениисил.
Ячувствовалсебявиноватым,чтоэтонавредитParrot,еслименятамнебудет,чтобычинитьбагииписатькод.
Нозатемяосознал,чтонидлякогоParrotнебылполезным,поэтому,наверное,этоихо-рошо.
Еслипроектнеможетвыжить,когдатеряетразработчиков—еслионнеисполь-зуетсядлячего-нибудьпродуктивногоилионникогоневолнует—то,наверное,ресур-сызатрачиваемыенанего,стоитприберечьдлячего-тодругого.
Несомненно,этобыломоеличноепонимание.
Япотратилпрактическидесятилетие,ра-ботаянадэтимипроектами,поэтомуясчитаю,чтосделалвсевозможное,чтобыонибылиуспешными.
Есликто-тодругойхочетпродолжитьмоюработу,кодоткрыт.
Нониодинизэтихпроектовнестоитужемоеговремениилиэнергии,иякомфортносебячувстую,объявляяэто.
Есливывидитесебявпохожейситуации,толюбой,ктопытаетсянавязатьвамчувствовины,есливыдумаетеовещахповажнееразработкипродукта,откоторогоуваснетникакогодохода,поступаетсовершеннонесправед-ливо.
(Дажееслиэтовысебянакручиваете.
)ВкладываниесвоегосвободноговременииталантавсвободноеПОэтодар,иэтотакойдар,которыйвыимеетеправоотменить.
НравятсяPerl-конференцииВтечениегодаянепосещалконференциипонетехническимпричинаминасла-ждалсятем,чтонепутешествую.
Втожевремя,мневсегдадоставляетудовольствиепроводитьвремясредивеликолепныхлюдейPerl-сообщества,поэтомуяскучаюпоэтомугоду.
ВячеславТихановский7PerlGolfPerlGolf—этосоревнованиепопоискуPerl-коданаименьшегоразмера(меньшевсегосим-волов),которыйрешаетпоставленнуюзада-чу.
ПомотивампроведённогонаYAPC::Eurore2013соревнованияпоPerlGolf,устроенногокомпаниейReg.
ru,котороепривлекломно-жестволюдейкрешениюголоволомки,воз-никлаидеяпубликоватьзаданиявжурна-ле,собиратьрешениявтечениемесяцаиделатьвпоследующемномереобзорреше-нийсобъявлениемпобедителясоревнова-ния.
ЦифрыНавернякамногиеизвасвшкольныегодыиграливигруподназваниемЦиф-ры(илиЧисла).
Сутьигрытакова:натетрадныйлиствыписываютсяцифры,каждаяцифразаписываетсявотдельнуюклеточку,слеванаправо,подевятьцифрвряд.
Начальнаяпоследовательностьзафиксирована:112345678921112131413516171819Задачасостоитвтом,чтобызачёркиватьдвесоседниецифры(погоризонталиилиповертикали),которыеимеютодинако-воезначениеилиихсуммаравнадесяти.
Соседнимисчитаютсятецифры,междукоторыминетдругихцифриливсепро-межуточныецифрызачёркнуты.
Крометогосчитается,чтопоследняяцифраря-да,являетсясоседнейспервойцифройпоследующегоряда(т.
е.
следующийрядявляетсяпродолжениемпредыдущегопогоризонтали).
Примерудаленияцифр:1123456789_23456789_2345678_2111213141→_11213141→__12131413516171819516171819516171819Сначалаудаляютсядвецифры1,которыерасположенывертикально,наследующемшагеудаляются9и1,которыеявляютсясо-седними,посколькумеждуниминетдру-гихцифр(промежуточная1былаудаленанапредыдущемшаге).
Количествовариантовдляудаленияможетбытьнесколько,ивэтомизаключаетсяин-тересигры,подобратьтакиесочетания,что-быудалитьмаксимальноечислоцифр.
Кактольковседоступныедляудаленияцифрыбыливычеркнуты,рядцифр,сразупослепоследнейзаписаннойпозиции,дополняетсяпоследовательностью,со-стоящейизоставшихсянаполецифр.
Например:11234567__1234567__2____1314_→____1314_351617181_51617181_4123456713514516171861Послечегопроцессповторяетсядобеско-нечности.
Задачаиграющего—попытатьсяудалитьсполякакможнобольшецифр.
ЗаданиеЗаданиедлясоздаваемойпрограммы:ПолучитьнаSTDINпоследователь-ностьизцифрподевятьсимволоввряд,рядыцифрразделенысимво-ломпереносастроки\n.
Позицияудалённогосимволаобозначаетсяпробелом.
ПрограммадолжнавыдатьнаSTDOUTпоследовательность,вкоторойудале-нывсевозможныесочетанияцифрпоправиламигры(этицифрызаме-няютсясимволомпробела).
Выводидёттакжеподевятьсимволовврядссимволомпереносастрокидляразделениярядов.
Еслипослеудаленияцифродинилинесколькорядовоказалисьпустыми,тоэтирядыдолжныбытьудаленыизвывода.
Понятно,чтодляоднихитехжевходныхданныхможетсуществоватьнескольковариантоввывода.
Норешениембудетпризнаватьсялюбоекорректноерешение,вкоторомнеосталосьвозможныхкомби-нацийдляудаленияинепропалицифры,которыенемоглибытьудаленысогласноправилам.
КакобычновPerlGolf,вдлинурешенияневходитперваястрока,вкоторойуказанше-бангдлявызоваperlипереданныхемупа-раметров:1#!
/usr/bin/perlnНельзяиспользоватькакие-либомодулиивызыватьвнешниепрограммы.
Чтобыубедиться,чтозадачаимеетре-шение,янаписалсвойвариант,которыйкажетсяработает.
Указыватьегоразмернебуду,чтобынепозоритьсябылаинтрига.
Дляучастиявсоревнованиисделайтефоркрепозиторияgolf-08,создайтевдиректорииscriptфайлyour_github_login.
plсвашимвариантомрешения.
Проверьте,чтовашвариантпроходиттесты(спомощьюкомандыprove)исделайтеpullrequestвосновнойрепозиторий.
Дерзайте!
Победителяждёт,какобычно,уважениеипочёт.
ВладимирЛеттиев8ОтветынаPerlQuizОтветыизпредыдущеговыпуска:1)2и4,2)1,3)2,4)2,5)2,6)4,7)3,8)3,9)1,10)4.
野草云服务器怎么样?野草云是一家成立了9年的国人主机商家,隶属于香港 LucidaCloud Limited (HongKong Registration No. 2736053 / 香港網上查冊中心)。目前,野草云主要销售香港、美国的VPS、虚拟主机及独立服务器等产品,本站也给大家分享过多次他家的优惠了,目前商家开启了优惠活动,香港/美国洛杉矶CN2+BGP云服务器,1核1G仅38元/月起!点击...
ReadyDedis是一家2018年成立的国外VPS商家,由印度人开设,主要提供VPS和独立服务器租用等,可选数据中心包括美国洛杉矶、西雅图、亚特兰大、纽约、拉斯维加斯、杰克逊维尔、印度和德国等。目前,商家针对全部VPS主机提供新年5折优惠码,优惠后最低套餐1GB内存每月仅需2美元起,所有VPS均为1Gbps端口不限流量方式。下面列出几款主机配置信息。CPU:1core内存:1GB硬盘:25GB ...
官方网站:点击访问华纳云活动官网活动方案:一、香港云服务器此次推出八种配置的香港云服务器,满足不同行业不同业务规模的客户需求,同时每种配置的云服务都有不同的带宽选择,灵活性更高,可用性更强,性价比更优质。配置带宽月付6折季付5.5折半年付5折年付4.5折2年付4折3年付3折购买1H1G2M/99180324576648直达购买5M/17331556710081134直达购买2H2G2M892444...
rewritecond为你推荐
国际域名国际域名是什么?独立ip空间大家都来看看,下面哪个独立IP空间好域名空间请问域名和空间有什么分别国内免费空间国内有没有好的免费空间啊免费网站域名申请哪有里可以申请免费域名的网站?查询ip如何查IP网址免费vps服务器有没有便宜的vps,最好是免费的免费网站空间申请哪里有免费申请空间的(网页制作)万网虚拟主机万网虚拟主机可以做几个网站长沙虚拟主机长沙IDC,求长沙本地虚拟主机,大伙推荐推荐
Vultr wavecom 搬瓦工官网 win8升级win10正式版 网站被封 免费网页空间 国外ip加速器 英国伦敦 游戏服务器出租 百度云空间 网络速度 国外代理服务器 nnt 石家庄服务器 脚本大全 windowsserver2008r2 phpwind论坛 zencart安装 weblogic部署 宿主机 更多