Powershell и объектный pipe
Я задумался над тем, чтобы показать как могла бы выглядеть обработка логов на PowerShell. Как я уже говорил, pipe в PowerShell объектный, то есть по нему идёт не монолитный текст, а набор объектов. Вот я и попробую на примере показать что это.
Для начала настроим лог Apache так, чтобы его было удобнее парсить. К примеру, можно ввести символы табуляций — в логе они не встречаются и вполне подходят на роль разделителя:
LogFormat "%h\t%l\t%u\t%t\t\"%r\"\t%>s\t%b" common
CustomLog logs/access.log commonВ логе у нас есть: хост клиента, его ident, имя пользователя (если была произведена
127.0.0.1 - - [03/Jan/2010:16:35:30 +0300] "GET /favicon.ico HTTP/1.1" 404 1976
127.0.0.1 - - [03/Jan/2010:16:35:32 +0300] "GET /a.html HTTP/1.1" 200 521
127.0.0.1 - - [03/Jan/2010:16:35:33 +0300] "GET /favicon.ico HTTP/1.1" 404 1976Предположим, наша задача — разобрать лог, отобрать только те запросы, у которых код ответа 200, отсортировать по размеру контента и вывести в табличном виде название метода, URL и размер контента.
cat access.log | %`
{
$o = "" | Select-Object host, logname, user, date, url, code, len, method
$o.host, $o.logname, $o.user, $o.date, $o.url, $o.code, $o.len = $_.Split("`t")
[datetime]$o.date = $o.date -replace '^.([^:]+):(.+).$', '$1 $2'
"logname", "user", "len" | %{ If ($o.$_ -eq '-') { $o.$_ = $false } }
$o.method, $o.url = $o.url.SubString(1).Split()[0..1]
$o
} | ?{ $_.code -eq 200 } | Sort-Object -property len | Format-Table method, url, lenИтак, что здесь происходит. Читаем лог, проходимся по каждой его строке (%{ }), внутри цикла странным хаком
Последней строкой цикла выводим получившийся объект. До цикла по pipe шли объекты попроще — всего лишь наборы строк («System.String»), теперь идут более интересные объекты («System.Management.Automation.PSCustomObject» с заданными нами полями).
Из этих объектов мы вибираем только те, у которых поле «code» содержит значение 200 («?{}» — это короткий алиас
method url len
------ --- ---
GET / 4701
GET / 4701
GET / 4701
GET / 4701
GET /a.html 521
GET /a.html 521Надо будет после праздников взглянуть на PowerShell 2.0, говорят, там очень много нового и интересного добавили.
Комментарии 26
Я не знаю Ruby, но около года попрограммировал на Python и пару месяцев на PS (плюс прочитал две книги), на мой взгляд, сделать из Python shell очень тяжело, надо делать обвязку. Ну попробуйте, для пример, скопировать там файлы по маске в другой каталог. Сделать это возможно, конечно, но так же просто как в
Shell это ведь не только возможности как таковые, это определённая область, под которую язык надо затачивать.
Потом я пересел на Unix, и вообще забыл о проблеме качественного скриптинга. Но иногда хочется как раз интеграции с GUI винды, типа там видео проиграть, получить свойства объектов, кодеки там у видео, и всё такое. А в Cygwin c этим никак. И. насколько я понимаю, в винде с этим вообще никак было до появления PowerShell…
С другой стороны, нафиг мне эта винда, когда везде или Unix c его перлами/башами, либо MacOS с AppleScipt?..
Надо делать то, что надо, а что не надо — делать не надо.
Комментарий для jankkhvej.blogspot.com:
Сравнивать PS и bash некорректно, PS более молодая и продуманная вещь, сравнение будет не в пользу bash, конечно же. Как shell Perl тоже хуже, чем PS.
Ну как же никак? Можно было сходить из Windows Script Host из реестр и WMI и там всё выяснить, просто это не так удобно как сейчас.
На винде можно логи IIS запрашивать. Парсить их не надо, они уже придут в объектном виде, а логи Apache можно парсить и на других ОС: http://en.wikipedia.org/wiki/Pash_%28software%29
Именно это и ужасало.
где-то необходимо использовать IIS?
Что до сравнений, очевидно же, если я на перле потрачу 2 минуты на написание нужного мне скрипта, то на изучение PS…
Кстати, неужели ещё
Комментарий для jankkhvej.blogspot.com:
что-то писать.
Ну, PS изучается очень быстро. Не две минуты, конечно, но за две минуты на нём уже можно
А что с ним не так? Раньше это было дырявое ведро, но вот уже несколько последних лет — очень производительныйвеб-сервер.
PS тяжелее bash так как тянет весь .Net framework. А bash есть на дистрибутивах «на дискетку».
Интерактивная консоль в IronRuby (Ruby внутри .Net) так же имеет доступ ко всем Windows API.
Я не знаю Python, но Ruby очень гибкий и вопрос удобства — просто в наборе удобных методов.
File.readlines('access.log').map { |i| i.split(«\t») }.reject { |i| '200' != i[5] }.sort { |a, b| a[6] b[6] }.each { |i| request = i[4].split(' '); puts «#{request[0]} #{request[1]} #{i[6]}» }
И всё решение в одну строчку с помощью удобных механизмов работы с массивами из функциональных ЯП (в Python Они тоже есть, но синтаксис больно некрасивый).
Комментарий для iskin.myopenid.com:
Ну, в общем, про Ruby ничего сказать не могу. Я его дажечуть-чуть не знаю.
dotNet framework, вроде как, не слишком много занимает. Не «на дискетку» (кому нужны сейчас дискетки?:), но по нынешним временам не кажется огромным. Да и в новых виндах он встроен, впрочем, как и PowerShell.
Мне не кажется некрасивым. Вполне себе сопоставимый синтаксис. Выглядеть будет примерно так же.
Комментарий для Евгения Степанищева:
Если на компьютере нет «новых виндов», то для этого, наверное, есть причины.
Возможно, те же самые, по которым «не слишком много» может оказываться многовато.
(Да и не все верят, что от перехода к новой его версии не сломается то, что раньше работало.)
А «на дискетку» — это newLISP, да.
Но его тоже придётся изучать.
Ну, старые машины, бог с ними.Когда-нибудь они вымрут, это не причина задерживать прогресс. Один из компьютеров у меня — довольно старый Pentium-III, на нём стоит Windows XP, много лет без переустановки.
На этой XP, соответственно, уже может работать PS (Windows 7 там не заработает — памяти всего 512МБ).
«На дискетку» — имеется в виду роутеры и другие мелкие железки. То есть PS нельзя заложить в основу ОС, как sh в UNIX. Те же низкоуровневые скрипты включения ОС или куча мелких системных скриптов — тут точно не место виртуальной машине.
Комментарий для iskin.myopenid.com:
Пройдёт2-3 года и в роутерах станет больше памяти, не проблема, правда же?
Как это «в основу OС»?
bash является интерфейсом по умолчанию, следовательно должен работать на любых устройствах — вырастет память у роутеров (не будем думать зачем там .Net ;) ), так Linux будут ставить на мелкие датчики, которые будут разбрасывать по лесу для контроля погоды («умная пыль») и там тоже понадобится bash для сервисных нужд.
В основе ОС — это значит, что bash используется в скриптах запуска ОС (/etc/init.d/) в куче мелких системных утилит, которые часто запускаются. Грузить для этого всю
Комментарий для iskin.myopenid.com:
А как эта библиотека называется?
Комментарий для iskin.myopenid.com:
Мораль такова — что сейчас кажется нехеровым расходом, завтра окажется обыденностью.
Я смотрю куча мелких системных утилит, чем дальше, тем больше, переползает на Python. Да и в init.d никто не мешает использовать другой язык.
Комментарий для jankkhvej.blogspot.com:
А что вам даёт основание это утверждать?
del a.txt — удаление файла a.txt
del variable:a — удаление переменной «a»
del hkcu:AppEvents — удаление ветки реестра HKCU/AppEvent
Это к концепции «всё файл» (хотя это объекты, конечно). Добраться до WMI не настолько тривиально, но тоже довольно просто.
Можно ли прочитать данные из произвольного устройства, типа флешки или сети, простой функцией из стандартной библиотеки? В Unix можно.
А вот в Windows надо вызывать PowerShell. Вот и вся разница.
А… мы на недостатки Windows и отдельные достоинства других ОС перешли? Не, я не хочу об этом спорить :) Я про PowerShell и исключительно про него.
В DOS, как не странно, эта концепция присутствовала. Например, принтер там был prn, COM1 — com1, а с HIMEM можно было общаться через файл XMSXXXX0.
А во времена DOS были сканеры?