LE Blog

Инженер с поэтической душой

25.03.2011 firtree_right Во времени

Наденька отвезла мою благоверную супругу на отдых в Севастополь. Меня же ожидают пять дней холостяцкого быта. В доме уже практически совсем порядок и можно приглашать гостей, но не больше двух человек за раз :)

♯♯♯

У нас в Универе было специальное тёплое и тихое место для фанатов Magic: The Gathering. Я даже слышал, что некоторые, увлёкшись этой игрой, вылетали из Бауманки почти так же быстро, как увлёкшиеся Counter Strike. Когда я их видел, то, конечно, хихикал над ними. Кто бы мог подумать, что спустя тринадцать лет я буду регулярно, почти каждую неделю, ходить на дружеские матчи по MTG под коньяк.

♯♯♯

Ещё рассказывал ребятам про курение. В своей жизни я, как и любой другой человек, принимал множество решений: учиться, не учиться, жениться, не жениться, переезжать, не переезжать, покупать, не покупать, ехать, не ехать, увольняться, не увольняться, говорить, не говорить и т.п. О любом из них можно пожалеть, но если ты принял решение перестать курить и осуществил его, то никогда об этом не пожалеешь. Не так много решений, которые могут это гарантировать.

А какие у вас произошли трансформации, о которых бы вы хихикая рассказали себе в прошлом?

25.03.2011 firtree_right Кроты как эволюционировавшие черви

После долгого молчания обновился бложек. Начал эту статью писать, правда, ещё до переезда. О том, что казалось невозможным: рекурсия в регулярных выражениях.

23.03.2011 firtree_right Рекурсия в регулярных выражениях

Пролог

Что-то большие перерывы в написании статей входят в привычку. Способность некоторых коллег по цеху регулярно выдавать что-нибудь полезное и интересное вызывает уважение.

worm

Введение

С тех самых пор, как я только узнал про регулярные выражения, я слышал об их несовершенстве и моральном устаревании. Регулярные выражения продолжали использоваться, а недовольные теоретики — сетовать. Основной претензией было то, что регулярные выражения не позволяют исследовать вложенности паттернов в виду своей линейности. Действительно, соглашался я, невозможно проверить правильность открытия и закрытия тегов или получить выражение в самых внутренних скобках.

Однако, как оказалось, человечество шагнуло далеко вперёд в вопросе совершенствования регулярных выражений. Об одном из новшеств хочу сегодня рассказать.

mole_worm

Именованные группы

В регулярных выражениях руби 1.9 появились именованные группы. Вот, как выглядит их элементарное использование:

if /\A(?<first>[a-zA-Z]+)\s+(?<last>[a-zA-Z]+)\Z/ =~ "Vassily Poopkine"
  puts [first, last].inspect
end

if md = /\A(?<first>[a-zA-Z]+)\s+(?<last>[a-zA-Z]+)\Z/.match("Vassily Poopkine")
  puts [md[:first], md[:last]].inspect
end

То есть мы не только выделяем группу скобками, как обычно, назначая ей тем самым порядковый номер (по номеру открывающей скобки), но и даём имя. И использовать его можно не только в локальных переменных и объекте MatchData, но и в самом регулярном выражении.

Более того, обращение к объявленным группам внутри может быть рекурсивным. Мне сразу же захотелось написать давнишнюю мою задумку о функции, раскрывающей вложенные скобки. Вот так:

str = "1 + 2 * (3 - 4 / {5 + 6} + [7 - 8 * (9 + 10 * 11) + 12 * {13 - 14}] + 15) + 16 * (17 + 18)"

re = %r{
        (?<fill>[0-9+\-*/\s]+){0}
        (?<expression>\g<fill>*\g<brackets>\g<fill>*|\g<fill>){0}
        (?<braces>\{\g<expression>+\}){0}
        (?<squarebrackets>\[\g<expression>+\]){0}
        (?<parentheses>\(\g<expression>+\)){0}
        (?<brackets>\g<braces>|\g<squarebrackets>|\g<parentheses>)
}x

def calculator(str)
  if str =~ /\A[0-9+\-*\/\s]+\Z/
    eval str
  else
    raise "Invalid expression: #{str}"
  end
end

f =-> s do
  if $~[:expression] == $~[:fill]
    calculator($~[:fill])
  else
    calculator($~[:brackets][1..-2].gsub(re, &f))
  end
end

puts calculator(str.gsub(re, &f))
puts eval(str.gsub(/(?<left>\{|\[)|\}|\]/) { |s| $~[:left] ? "(" : ")" })

Итак, в регулярном выражении присутствует 6 именованных групп: fill (заполнения пространства между скобками), expression (выражение, содержащее одни или ни одних нераскрытых скобок), braces (фигурные скобки), squarebrackets (квадратные скобки), parentheses (круглые скобки), brackets (любые скобки). Как видите, выражение описывается через скобки, а скобки — через выражение.

Для проверки правильности расчёта, используем обычный eval, заменив все скобки на круглые.

mole

Сделав этот пример, я был доволен, как стадо слонов, но потом решил проверить, а что будет, если скобки расставлены неправильно?

str = "1 + 2 * (3 - 4 / {5 + 6} + [7 - 8 * (9 + 10 * 11) + 12 * {13 - 14]} + 15) + 16 * (17 + 18)"

re = %r{
        (?<fill>[0-9+\-*/\s]+){0}
        (?<expression>\g<fill>*\g<brackets>\g<fill>*|\g<fill>){0}
        (?<braces>\{\g<expression>+\}){0}
        (?<squarebrackets>\[\g<expression>+\]){0}
        (?<parentheses>\(\g<expression>+\)){0}
        (?<brackets>\g<braces>|\g<squarebrackets>|\g<parentheses>)
}x

str =~ re

И я не смог дождаться завершения работы оператора =~ для такого длинного выражения. Это, конечно, неприятно. В причины я вникал не особо, но похоже, это связано с поведением недетерминированной машины Тьюринга. По крайней мере вот ответ на похожую проблему. Для нас это всего лишь означает, что проверять правильность расстановки скобок нужно отдельно и другим способом. Чем я предлагаю заняться пытливому читателю самостоятельно.

Материалы для самостоятельного изучения

  1. Исходный код статьи.
  2. Новый синтаксис и прочие вкусняшки в руби 1.9. Для тех, кто заметил =->.
  3. Глобальные переменные с непонятными именами. Для тех, кто заметил $~.
  4. Ещё немного базовых приёмов в регулярных выражениях руби.

11.03.2011 firtree_right Пере

В наш век цифровых технологий переезд можно считать состоявшимся, на мой взгляд, только тогда, когда по дому разливается густой жирный интернет из кабеля. Ёта-Итсо, конечно, хорошо, но от него какое-то походное ощущение, типа твиттер в палатке почитать.

Этот переезд мне обещали звёзды, на него намекала супруга, да и сам я уже хотел, но состоялся он резко и по объективным обстоятельствам. Что, конечно, создало море плюсов и возможностей. Например, сумму, которую я бы мог потратить на агента и залог, я потратил на ремонт и теперь у нас красиво, новая дверь, и новенькая кухня с посудомойкой. Или, например, я бы не стал искать квартиру на кольцевой линии, но оказалось, что местоположение вполне стоит своих денег.

Интересно отметить, что 6 лет без переездов дают о себе знать. Если на предыдущую квартиру мы носили вещи сами и в тот же день вечером принимали гостей, то сейчас были грузчики, дополнительная ходка с техникой и в первую ночь мы не смогли даже заночевать на новом месте.

Так же забавно, что каждый год, который мы встречали не дома, мы переезжали. А в этот раз переехаи туда, где гуляли после новогоднего шампанского.

Меня же больше всего занимает вопрос, почему не получается всё сделать сразу и идеально. Дверная фирма приятная, дверь хорошая, но установщики неаккуратно разворотили дверь, удлинив ремонт на пару дней. Икеевскую кухню привезли и собрали отлично, но сборщик забыл гаечный ключ, и мне пришлось ездить дважды на рынок, и он потом не стал подключать электрику. Электрики всё подключили, и всё работает, но неаккуратно выглядит местами. Стиральную машинку быстро привезли и подключили, но у неё что-то сломалось в первую стирку, и теперь нужно разбираться с гарантийной заменой. Сама квартира с удобным местоположением, тёплая, но в подъезде какие-то сумасшедшие соседи попадаются, которые не пускают к щитку протянуть провод интернета.

Никакого внятного ответа на вопрос «зачем все эти неприятные мелочи» я не нахожу. Ведь их наличие ничего принципиально не меняет. Не добавляет интереса, не особо чему-то учит полезному. Но по какой-то причине появляется всегда шероховатость.

Супруга, однако, сообщает мне, что я — самый прекрасный мужчина на свете.

03.02.2011 firtree_right Литра

В школе самым презираемым мной человеком был Виссарион Григорьевич Белинский. Возможно, я уже тогда чувствовал, насколько яд чужой авторитетной оценки окружающих явлений или меня самого способен отравить мою реальность. И старался от подобного себя оградить. Юношеский максимализм распространил ограждение на всю литературу, надолго лишив меня радости прочтения книги. Это было и до знакомства с творчеством Белинского, но когда я узнал о его существовании, то вся нелюбовь к тому, что кто-то выбирает, какие произведения мне «проходить», вылилась на него. Он как бы воплотил в себе ту фигуру, которая говорит, что в литературе важно, как нужно это интерпретировать и почему любить.

Всем моим друзьям я уже по несколько раз рассказал историю, которая даёт представление о масштабе катастрофы. Каждое лето я уезжал к бабушке в деревню. И меня заставляли отрываться от велосипеда и читать по часу в день книги из списка заданного на лето. И у меня была книга, в которой были два произведения: «повесть о настоящем человеке» и «судьба барабанщика». Так вот в этих ежедневных часовых муках я прочитал треть «судьбы барабанщика», пока понял, что «повесть о настоящем человеке» уже закончилась, и это совсем другая история.

Потом, конечно, долгие годы я учился (да и продолжаю до сих пор) самостоятельно определять, что из того, что делаю я или другие, мне нравится, а что нет. Шекспир так и остался для меня маленьким говнюком, Пелевин, не смотря на тухлые отзывы, всё так же нравится, «Цветочный крест», не смотря на Букер и понравившееся мне эпатажное начало, имеет сомнительную литературную ценность, а Ильф с Петровым появились в моей жизни поздновато: прочти я их в школе — полюбил бы ещё больше.

Не надо иметь искусствоведческое образование, чтобы определить, нравится тебе «Герника» Пикассо или нет. Есть, конечно, такая вещь, как вкус, но он критикой не воспитывается. А воспитывается он через соприкосновение по своей воле с большим количеством объектов творчества.

Поэтому, если у вас есть книга или спектакль, которые из последнего вам понравились (без объяснения причин), то порекомендуйте мне их в комментариях.

А если у вас завтра (то есть уже сегодня, 3-го февраля) есть свободное время вечером, то сходите на спектакль Паперного «Река». Сегодня (то есть уже вчера) у Иры был день рождения, и мы пошли на этот спектакль. И когда мы на него пошли, то я даже не знал, кто такой Алексей Паперный. Удовольствия от этого меньше не стало.

02.01.2011 firtree_right 2010

Ушедший год совместил в себе две, казалось бы, несовместимые тенденции: с одной стороны в течение всего года нарастало ощущение усталости и истощения, а с другой стороны весь год я ввязывался во всё более и более масштабные мероприятия. Результаты некоторых будут видны в наступившем году, а некоторых — и того далее.

♯♯♯

В формате хит-парада:

  1. Женщина года — моя прекрасная супруга.
  2. Природный катаклизм года — если выбирать между холодами зимы в январе, дымом торфяников в жару летом и ледяным дождём в декабре, то, безусловно, торфяники лидируют. Всё это время я был в Москве.
  3. Фильм года — Inception. Уже давно фильм не дарил мне устойчивого изменённого состояния сознания.
  4. Игра года — Mass Effect 2. Не так давно начал ещё одного персонажа и прошёл им первую часть игры и уже почти закончил вторую. С нетерпением жду третью, о выходе которой как раз объявили на VGA-2010
  5. Операционная система года — Google Android. Очень воодушевляет.
  6. Курорт года — остров Бали.
  7. Открытие года — Латвия.
  8. Прорыв года — ssh-туннель
  9. Компания года — neq4. Довольно большую часть моей жизни в этом году я посвятил вот этим ребятам. Мне очень нравится, что удаётся проявлять свои сильные стороны и иметь прикрытыми слабые. Так же отличное место для развития новых навыков.
  10. Трудность года — подчинённые. С одной стороны приходится учиться заново, а с другой — есть определённые трудности, которые были у меня с этим всегда.
  11. Самое странное увлечение года — Dog Whisperer. Было бы забавно узнать, как бы я реагировал на пса с о. Бали, если бы посмотрел эти передачи до того.

♯♯♯

Планов на наступивший год — огромное количество. Но всё это не для жж. Главное — чтобы дао было позабористее.

♯♯♯

С Новым Две Тысячи Одиннадцатым Годом!

21.11.2010 firtree_right Метод съёма

Кстати, про офисы. Мне уже приходилось участвовать в съёмах офисов. И каждый раз совершенно железно следующий офис лучше предыдущего. Это такое правило. С квартирами у меня так же было.

Офис в СГА мне нравится. Он отлично подходит под наши способы работы. И самое прикольное было в момент выбора. Мы посмотрели несколько офисов в разных местах и были разногласия и вопросы. Я, например, склонялся к офису на Винзаводе, Маше нравилась Арма ну и т.д. Но потом мы сели вчетвером и посовещались, и после этого стало совершенно однозначно понятно, что нужно снимать именно этот. И никаких споров и уговоров. Просто этот оказался самый подходящий.

20.11.2010 firtree_right Выплеск

Вот уже некоторое время мы сняли офис на территории Современной гуманитарной академии. Чтобы это написать, я ждал пока будут урегулированы формальности.

Здесь Советский Союз: проходная с пропусками, 17-тиминутная прогулка от метро, сдача ключей на охрану в таких трогательных тубусиках с пластилином, столовая работает до 15:00 (где можно пообедать за 150 рублей), списки уполномоченных пребывать не территории после 22:00. Короче, почти монастырские условия. Мне нравится. Даже общественный туалет на этаже забавляет. Возможно, это сказывается чтение огромной вызывающе одетой женщины в возрасте, нежно любимой программистами, но заходя в туалет иногда возникает мысль, что не смывший за собой мужчина хочет таким образом показать метафизической мамочке, что он хорошо покакал.

Но сегодня о другом. О тамошнем интернет-провайдере. Когда мы только въехали, мы, конечно, соблазнились на шкафчики с патч-панелями и сетевые розетки на стенах. Но тут же выяснилось, что нет, мы не можем сами открывать шкафчик, и не можем ставить туда своё оборудование, и подсоединить розетку в сеть стоит 1800 рублей (тысяча восемьсот, сука, рублей) за то чтобы мальчик пришёл с ключиком, открыл шкафчик и воткнул один проводок). Посмотрите, вот эти высокотехнологичные ребята рассказывают о своей работе в академии.

Я прямо так и представляю себе облапошенного начальника ИТ-службы академии, с которым не делятся ни те, что получают арендную плату, ни телепорт-сервис со своих бешеных тарифов на интернет, отшив его под предлогом, что у него в собственности шкафчики и розеточки. А он, такой, мечтательно закатывает глаза и подсчитывает свои активы: «В каждой комнате от 6 до 12 розеточек, каждая по 1800 рубликов, это же несметные богатства!» Но кого волнует судьба обманутого начальника службы (который просто не может от себя предлагать эти услуги по причине отсутствия лицензии на оказание услуг связи), если на всех документах и актах стоит печать телепорт-сервиса?

Короче говоря, мы сняли ещё одну комнату и захотели соединить наши владения в одну сеть. К этому моменту (прошла неделя) они уменьшили аппетиты до 850 рублей за розетку. До первого прихода специалиста прошла неделя, три письма-заявки и два телефонных звонка. Пришедший специалист во-первых заявил, что хочет усложнить жизнь себе и нам (воткнуть не один проводочек, а три), во-вторых он не может объяснить причины этого пожелания начальства. Когда я добрался до офиса, выяснилось, что специалист не прозвонил кабели, не проверил свою работу и соединения попросту нет. Ещё звонок, ещё приход специалиста, прозвон соединения. Сеть, наконец-то есть. На следующий день опять проблемы. Выясняется, что в соединении теряются пакеты. Новый вызов специалиста, который приходит только на следующий день, проверка кабелей на соответствие заявленной категории. Оказалось, что в одном из кабинетов НИ ОДНА розетка на стене не соответсвует заявленной категории соединения. Восемьсот пятьдесят, сука, рублей, две недели мытарств, чтобы соединить две комнаты!

Конечно, я купил Ёту, конечно, мы написали заявку на разрешение прокинуть свой кабель над потолком между комнатами, конечно, я буду всеми силами стараться не связываться с телепорт-сервисом. Потому что если твои безлимитные 8 мегабит в месяц стоят 18250 (восемьнадцать тысяч двести пятьдесят) рублей в месяц, то предоставлять розетки в комнатах по такой цене, с такими трудностями и такого качества — это мудачество. Всего в наших комнатах около 40 сетевых розеток. Половина отклеивается от стен, и 6 из остальных уже точно нельзя использовать. И хрен с ними.

07.11.2010 firtree_right Отдых

В выходные был какой-то временной сдвиг. Я был уверен, что отдыхаю до вторника, а оказалось что 8-е — это понедельник.

В качестве отдыха приобрёл и прошёл сюжетные DLC (загружаемый контент) к Mass Effect 2. Получил удовольствие, конечно. Даже на минуточку захотелось создать нового героя и пройти первую и вторую часть от начала до конца. Задумался, почему им нужно делать прогрессирующую шкалу плохиша или кибальчиша. Сюжетно мне нравятся выборы положительного героя: больше персонажей остаётся в живых, больше потом приколов. Но многие диалоги у отрицательного героя лучше подходят. А иному персонажу с ноги заехать — самая адекватная реакция. Но если выбирать то так, то так, то потом недоступны ни те ни другие опции.

Ходил на день рождения к другу. Он сказал мне, что снова бросил учиться в семинарии. На вопрос: «Почему?» — показал вот это. Сказал: «Тот, Кто создал такое, не может быть в Своём уме». Я его понимаю.

Написал статью про ротацию логов в приложениях на rails. Ира к ней нарисовала картинку. Надеюсь на продолжение плодотворного сотрудничества. Хотя обычно я дольше ищу и исследую сюжет для статьи, чем Ира рисует картинку.

А как вы провели выходные?

05.11.2010 firtree_right Ротация логов рельсового приложения

hay roller

Введение

Это уже давно известная тема, и я не претендую на открытие Америки, но для себя зафиксирую это знание.

Даже если вы используете капистрано для выкладывания проекта в сеть, логи приложения хранятся в одном и том же месте (папка shared/log и разрастаются до огромных размеров. Можно, конечно, запускать после каждого обновления файлов проекта комманду:

rake log:clear

Но есть более цивилизованные методы. Тем более, после определённого времени код проекта начинает обновляться всё реже и реже.

С помощью системы

Существует прекрасный системный инструмент, который назвается logrotate. С его помощью архивируются логи апача, баз данных и даже менеджера пакетов.

Чтобы организовать это удовольствие для своего проекта нужно создать файл /etc/logrotate.d/my_project:

/path/to/my_project/shared/log/*.log {
  weekly
  missingok
  rotate 10
  nomail
  compress
  delaycompress
  sharedscripts
  postrotate
    touch /path/to/my_project/current/tmp/restart.txt
  endscript
}

Здесь написано:

  1. weekly — разбивать лог еженедельно;
  2. missingok — не выходить с ошибкой, если файла нет;
  3. rotate 10 — хранить 10 предыдущих томов;
  4. nomail — не высылать удаляемые тома на электронную почту;
  5. compress — архивировать;
  6. delaycompress — архивировать не сразу, т.к. после переименования файла и до перезапуска пэссенджера логи пишутся в тот же переименованный файл;
  7. sharedscripts — запускать скрипт один раз для всех логов по маске;
  8. postrotate...endscript — скрипт, который нужно запустить после ротации: в данном случае перезапустить пэссенджер.

Файлом должен владеть root:root. Теперь можно проверить и запустить принудительно, убедившись, что наш файл включается в общий список:

sudo logrotate -dv /etc/logrotate.conf
sudo logrotate -fv /etc/logrotate.conf

С помощью руби

В руби есть встроенный метод ротации логов. Достаточно в файе config/environment.rb написать внутри блока Rails::Initializer.run один из вариантов:

config.logger = Logger.new(config.log_path, "weekly")

или

config.logger = Logger.new(config.log_path, 10, 1.megabyte)

Первый вариант осуществляет ротацию раз в неделю, а второй — по достижении файлом размера в 1 мегабайт и хранит 10 старых томов. Только в данном случае архивацию, если она нужна, придётся организовывать отдельно.

Было бы интересно

Для логротейт можно написать такую маску, которая бы включала в себя все логи всех рельсовых проектов. Но мне неизвестен способ потом написать такой скрипт, который бы перезапускал именно те проекты, для которых была сделана ротация. Например, если логротэйт не нашёл нужного файла, то и скрипт не запустит. А если мы указываем путь типа /path/to/*/shared/.log, то и скрипт должен перебирать все эти проекты и создавать или просто менять дату редактирования файлов restart.txt. Или можно просто перезапускать апач.

Материалы для самостоятельного изучения

  1. Документация logrotate (по-русски)
  2. Что ещё можно делать с логами приложения на рельсах