RFC (Request for Comments, Запрос на комментарии) - серия документов, публикуемая сообществом исследователей и разработчиков, руководствующихся практическими интересами, в которой описывается набор протоколов и обобщается опыт функционирования Интернет.
Дано N разноцветных шариков, M коробок различной вместимости, а также стол бесконечной вместимости. Нужно получить список всех возможных размещений (не путать с размещением в комбинаторике) шариков по коробкам и столу. Вместо шариков могут быть яблоки или посылки, а вместо коробок — корзины или грузовики, суть от этого не меняется. Решение на Haskell:
module Placements where
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:
pkg_add -r unbound
После установки пишем в /usr/local/etc/unbound/unbound.conf что-то вроде:
server:
# принимаем пакеты только с локалхоста
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 прописываем:
unbound_enalbe="YES"
Запускаем:
/usr/local/etc/rc.d/unbound start
Проверяем:
tcpdump -i tun0 udp port 53
dig @127.0.0.1 intra.company.example.ru
В /etc/resolv.conf прописываем:
nameserver 127.0.0.1
Чтобы resolv.conf не перезаписывался благодаря DHCP провайдера, в /etc/dhclient.conf пишем:
interface "rl0" {
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:
Host *.i-server.example.ru
IdentityFile ~/.ssh/id_rsa.i-server
User myusername
Повторяем описанные действия для i от 1 до N.
4. Настройка pptp под FreeBSD
Устанавливаем pptpclient:
pkg_add -r pptpclient
Правим /etc/ppp/ppp.conf:
company:
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 серверу:
route add -host 33.33.33.1 192.168.0.1
Проверяем:
pptp 33.33.33.1 company
Варнинги типа «/bin/ip: not found» игнорируем, логи смотрим в /var/log/ppp.log. По умолчанию в ppp.conf прописано «enable dns», что приводит к перезаписи resolv.conf. Если вы оставили эту опцию, то после разрыва соединения с VPN сервером должны вручную восстановить resolv.conf:
nameserver 192.168.0.1
Также после разрыва соединения понадобится восстановить шлюз по умолчанию:
route add default 192.168.0.1
Напоминаю, что посмотреть все роуты можно командой «netstat -nr».
5. Создание мгновенного снимка ФС во FreeBSD
Снапшоты файловой системы во FreeBSD можно создать несколькими способами. Наиболее простым, по моим представлениям, является следующий:
# pkg_add -r freebsd-snapshot
$ echo "1111" > test.txt
# snapshot make -g4 /usr:backup
Здесь флаг -g задает максимальное количество снапшотов. Если превысить это число, происходит автоматическая ротация.
# snapshot list /usr
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 создание мгновенного снимка происходит очень быстро (на то он и мгновенный), а место на диске расходуется с умом.
Дан список URL и поисковых запросов, по которым продвигаются соответствующие страницы. Следующий скрипт проверяет, заголовки каких страниц следует оптимизировать:
#!/usr/bin/perl
# check-header.pl v 0.1
# (c) Alexandr A Alexeev 2012 | http://eax.me/
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 $cddev = "/dev/cd0";
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:
pkg_add -r sloth
Эта программа бомбит процесс сигналами SIGSTOP и SIGCONT, что существенно замедляет его выполнение:
Если для вашей системы не оказалось готового пакета, вы можете собрать sloth из исходников. Последние представляют собой сотню строк на языке Си.
10. Исправление кодировки без использования iconv
Недавно мне попался дамп базы данных с испорченной кодировкой. Декодер студии Артемия Лебедева определил, что исправить кодировку можно путем перекодирования текста из cp1252 в cp1251. Но ни enconv, ни iconv никак не могли справиться этой, казалось бы, элементарнейшей задачей. В итоге пришлось написать такой скрипт:
Как обычно, я буду несказанно рад вашим вопросам и дополнениям. Также мне было бы интересно узнать, какие пункты этого выпуска мини-заметок больше всего вам понравились и почему.