Главные темы шестого выпуска: комбинаторика на Haskell, исправление кодировки без использования iconv, полуавтоматическая поисковая оптимизация заголовков, настройка unbound и pptp, а также создание мгновенного снимка файловой системы под FreeBSD. Предыдущие выпуски: первый , второй , третий , четвертый и пятый .
1. Размещение «шариков» по «коробкам» на Haskell
Дано N разноцветных шариков, M коробок различной вместимости, а также стол бесконечной вместимости. Нужно получить список всех возможных размещений (не путать с размещением в комбинаторике ) шариков по коробкам и столу. Вместо шариков могут быть яблоки или посылки, а вместо коробок — корзины или грузовики, суть от этого не меняется. Решение на Haskell:
import Data . List
— первый аргумент — список «шариков»
— второй аргумент — вместимость «коробок»
placements :: Eq a => [ a ] -> [ Int ] -> [ [ [ a ] ] ]
placements itemsList [ ] = [ [ itemsList ] ]
placements itemsList ( maxItems:maxItemsTail ) =
[ ( s:t ) | s <- seqList , t <- allTails s ]
where
— все варианты размещения «шариков» в текущей «коробке»
seqList = filter ( s -> length s <= maxItems )
$ subsequences itemsList
— все варианты размещения «шариков»
— в остальных «коробках» и на «столе»
allTails s = placements ( itemsList \ s ) maxItemsTail
Если вам попадалось готовое решение, поделитесь, пожалуйста, ссылкой.
2. Настройка unbound
Поднятие локального DNS сервера может быть целесообразным по крайней мере в двух случаях. Первый — когда вам хочется ускорить загрузку веб-страниц за счет кэширования ответов DNS сервера провайдера. Если у провайдера тормозной DNS, прирост скорости весьма ощутим. Второй случай — когда часть доменных имен вы хотите резолвить на одних DNS серверах, а часть — на других, например, если вы работаете дома через VPN.
Для этих целей идеально подходит DNS сервер unbound:
После установки пишем в /usr/local/etc/unbound/unbound.conf что-то вроде:
# принимаем пакеты только с локалхоста
interface: 127.0.0.1
access-control: 127.0.0.0/8 allow
# минимальный и максимальный TTL
cache-min-ttl: 21600
cache-max-ttl: 86400
forward-zone:
# за адресами доменов компании ходим по VPN
name: «company.example.ru.»
forward-addr: 33.33.33.1
forward-addr: 33.33.33.2
forward-zone:
# остальные домены резолвим у провайдера
name: «.»
forward-addr: 192.168.0.1
В /etc/rc.conf прописываем:
Запускаем:
Проверяем:
dig @ 127.0.0.1 intra.company.example.ru
В /etc/resolv.conf прописываем:
Чтобы resolv.conf не перезаписывался благодаря DHCP провайдера, в /etc/dhclient.conf пишем:
supersede domain-name-servers 127.0.0.1;
}
Некоторые приложения понадобится перезапустить, иначе они не увидят новых настроек.
3. Использование разных ssh-ключей для разных серверов
Что делать, если требуется получить доступ к N серверам с одной машины, используя различные identity file для каждого сервера?
Копируем закрытый ключ для i-го сервера, например, в ~/.ssh/id_rsa.i-server (также копируем открытый ключ в id_rsa.pub.i-server — чтобы не потерять), меняем права доступа на 600, а затем пишем в ~/.ssh/config :
IdentityFile ~/.ssh/id_rsa.i-server
User myusername
Повторяем описанные действия для i от 1 до N.
4. Настройка pptp под FreeBSD
Устанавливаем pptpclient:
Правим /etc/ppp/ppp.conf:
set authname mylogin
set authkey mypassword
set timeout 0
set ifaddr 0 0
# весь трафик — через VPN!
# add default HISADDR
# через VPN ходим только в заданную подсеть
set 123.45.67.0/24 HISADDR
# … и к заданному хосту
set 45.67.89.10 HISADDR
Указываем, через какой шлюз гнать трафик к VPN серверу:
Проверяем:
Варнинги типа «/bin/ip: not found» игнорируем, логи смотрим в /var/log/ppp.log. По умолчанию в ppp.conf прописано «enable dns», что приводит к перезаписи resolv.conf. Если вы оставили эту опцию, то после разрыва соединения с VPN сервером должны вручную восстановить resolv.conf:
Также после разрыва соединения понадобится восстановить шлюз по умолчанию:
Напоминаю, что посмотреть все роуты можно командой «netstat -nr».
5. Создание мгновенного снимка ФС во FreeBSD
Снапшоты файловой системы во FreeBSD можно создать несколькими способами. Наиболее простым, по моим представлениям, является следующий:
$ echo «1111» > test.txt
# snapshot make -g4 /usr:backup
Здесь флаг -g задает максимальное количество снапшотов. Если превысить это число, происходит автоматическая ротация.
Filesystem User User% Snap Snap% Snapshot
/usr 146GB 25.8% 346MB 0.1% backup.0
# mkdir /mnt/backup
# snapshot mount /usr:backup.0 /mnt/backup
# cat /mnt/backup/home/eax/test.txt
1111
$ echo «2222» > test.txt
# cat /mnt/backup/home/eax/test.txt
1111
# snapshot umount /mnt/backup
# ls -la /usr/.snap/
total 357652
drwxrwxr-x 2 root operator 512 4 май 11:40 .
drwxr-xr-x 17 root wheel 512 14 окт 21:59 ..
-r——— 1 root operator 627341157960 4 май 12:12 backup.0
# snapshot make -g0 /usr:backup
Мгновенные снимки часто используются при резервном копировании. Например, если на сервере крутится некая СУБД, мы можем останавливаем ее (или временно запретить запись и скинуть все данные на диск), создать снапшот файловой системы, после чего снова запускаем СУБД (разрешить запись) и сделать резервную копию из снапшота.
В результате сервер не простаивает, а мы получаем резервную копию данных в непротиворечивом состоянии. За счет использования механизма copy-on-write создание мгновенного снимка происходит очень быстро (на то он и мгновенный), а место на диске расходуется с умом.
6. Полуавтоматическая поисковая оптимизации заголовков
Дан список URL и поисковых запросов, по которым продвигаются соответствующие страницы. Следующий скрипт проверяет, заголовки каких страниц следует оптимизировать:
# check-header.pl v 0.1
# (c) Alexandr A Alexeev 2012 | http://remontka.com/
use strict ;
use warnings ;
use utf8 ;
use Mojo :: UserAgent ;
my $ua = Mojo :: UserAgent -> new ( ) ;
while ( my $line = <> ) {
chomp ( $line ) ;
my ( $url , $query ) = split /t/ , $line ;
utf8 :: decode ( $query ) ;
my $title ;
eval {
$title = $ua -> get ( $url )
-> res -> dom -> html -> head -> title -> text ;
} ;
if ( $@ ) {
print «ERROR: t $url n » ;
next ;
}
if ( titleMatch ( $title , $query ) ) {
print «OK: t $url n » ;
} else {
utf8 :: encode ( $query ) ;
print «FIXME: t $url t $query n » ;
}
}
sub titleMatch {
my ( $title , $query ) = @_ ;
$title = lc $title ;
$query = lc $query ;
my @tmp = split /s+/ , $query ;
for my $q ( @tmp ) {
return 0 if ( index ( $title , $q ) < 0 ) ;
}
return 1 ;
}
Проверка довольно топорная — если страница продвигается по запросу «купить яблоки», то в title должны содержаться слова «купить» и «яблоки». Этот скрипт удобно использовать со скриптом из десятого пункта предыдущего выпуска мини-заметок .
7. Как скопировать музыку с CD под UNIX
В портах FreeBSD есть такая замечательная утилита audio/ripit, предназначенная для конвертирования музыки с CD дисков в MP3. Устанавливаем, немного правим /usr/local/bin/ripit.pl:
my $outputdir = «/home/user/cdrip» ;
Затем просто вставляем диск в CD привод и говорим из под рута «ripit». Музыка в формате MP3 магическим образом окажется в директории $outputdir.
8. Удобные сочетания клавиш в bash
Недавно коллега показал мне два очень удобных сочетания клавиш в bash. До этого я умел пользоваться только стрелочками Вверх и Вниз, а также клавишей Tab.
Сочетание Ctr+R позволяет быстро выполнять команды, набранные ранее. Жмем Ctr+R и вводим часть команды. Если bash предложил то, что мы хотели, жмем Enter. Если снова нажать Ctr+R , будет предложена другая команда. Нажатие Escape возвращает нас в нормальный режим.
Сочетание Alt+точка подставляет в вводимую команду последний использованный аргумент. Например, если выполнить команду «ls -la» , затем набрать «cat » и нажать Alt+точка , команда превратиться в «cat -la» . Повторное нажатие Alt+точка подставляет другие аргументы, используемые ранее. Это сочетание особенно удобно при выполнении нескольких команд над файлами, к которым мы обращаемся по абсолютным или длинным относительным путям.
Может, есть еще какие-то сочетания клавиш, которые мне давно следовало бы держать на вооружении?
9. Утилита sloth
Если какой-то фоновый процесс съедает много ресурсов, а (re)nice не помогает, попробуйте утилиту sloth:
Эта программа бомбит процесс сигналами SIGSTOP и SIGCONT, что существенно замедляет его выполнение:
MD5 (PCBSD9.0-x86-DVD.iso) = 805eebb4d24e2ada0466d5baa1997b45
real 1m46.598s
user 0m17.914s
sys 0m7.744s
$ time sloth 5000 md5 PCBSD9.0-x86-DVD.iso
MD5 (PCBSD9.0-x86-DVD.iso) = 805eebb4d24e2ada0466d5baa1997b45
real 7m16.996s
user 0m18.523s
sys 0m7.713s
Если для вашей системы не оказалось готового пакета, вы можете собрать sloth из исходников . Последние представляют собой сотню строк на языке Си.
10. Исправление кодировки без использования iconv
Недавно мне попался дамп базы данных с испорченной кодировкой. Декодер студии Артемия Лебедева определил, что исправить кодировку можно путем перекодирования текста из cp1252 в cp1251. Но ни enconv, ни iconv никак не могли справиться этой, казалось бы, элементарнейшей задачей. В итоге пришлось написать такой скрипт:
# decoder.pl v 0.2
# (c) Alexandr A Alexeev 2012 | http://remontka.com/
use strict ;
use warnings ;
use utf8 ;
use List :: MoreUtils qw/uniq/ ;
# http://www.artlebedev.ru/tools/decoder/advanced/
my @bad = split //,
‘??????????????????????????????????????????????????????????????????’ ;
my @good = split //,
‘абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ’ ;
my % map ;
$map { $_ } = shift @good for ( @bad ) ;
while ( my $line = <> ) {
utf8 :: decode ( $line ) ;
$line = join » , (
map { defined $map { $_ } ? $map { $_ } : $_ } ( split //, $line )
) ;
utf8 :: encode ( $line ) ;
print $line ;
}
Как обычно, я буду несказанно рад вашим вопросам и дополнениям. Также мне было бы интересно узнать, какие пункты этого выпуска мини-заметок больше всего вам понравились и почему.
Дополнение: Мини заметки — выпуск 7