Как жить в локальной сети без dns для локальных ресурсов
Или сказ о том, как перестать бояться и начать раздавать динамические адреса в локальной сети.
Задача:
- необходимо автоматизировать распределение имен различным устройствам в сети.
Проблемы
- доисторический (ископаемый) роутер, который не умеет dd-wrt/openwrt и иже. А вместе с этим он не умеет статические адреса или локальный dns.
- много iot-желаза в локальной сети к которому хочется получать доступ по имени (доменному конечно же).
- Очень много железа, которое появляется в сети лишь на короткое время, а доступ к нему по сети нужен (ну не прописывать же ему постоянно статику?)
- большое количество скриптов автоматизации, которым надо откуда-то брать именя устройств.
Проблему можно решить несколькими путями:
- Поставить слабую железку, поставить на нее bind, поднять локальную доменную зону и убрать с роутера роль dhcp и dns-сервера. Минус в том, что слабой железки может и не быть.
- Поменять роутер на менее доисторический. Минус в том, что роутера может не быть под рукой.
- Воспользоваться протоколом zeroconf. Минусы тоже есть - возможный конфликт имен устройств.
Если с первыми двума вариантами все более-менее понятно, то на третьем стоит остановиться подробно. Так как он решает проблему наименее затратным способом. Протокол описывает:
- назначение адресов устройствам в сети (диапазон 169.254.*)
- разрешение имен
- обнаружение сервисов
Поскольку адреса у устройств уже есть (dhcp же), то нас будет интересовать только та часть протокола, где рассказывается про обнаружение сервисов и разрешение имен. Это mDNS+DNSSD. В nix\bsd за эту часть протокола отвечает сервис avahi В ряде дистрибутивов он включен и нормально настроен сразу. На примере федоры посмотрим как его поставить и настроить.
$ sudo dnf install avahi-daemon avahi-utils
$ sudo systemctl enable avahi-daemon
$ sudo systemctl start avahi-daemon
Если у вас в сети уже есть устройства, где активирован avahi, то можно посмотреть на то, найдет ли оно какие-либо устройства
$ avahi-browse -alr
+ eth0 IPv4 workstation Remote Disk Management local
= eth0 IPv4 workstation Remote Disk Management local
hostname = [workstation.local]
address = [192.168.1.10]
port = [22]
txt = []
Как видим что-то нашло.
Мы можем попробовать его попинговать.
$ ping workstation.local
ping: unknown host workstation.local
Если вы увидели такую картину, то это означает лишь одно - mdns для получения имен доменов у вас не подключен. Чтобы его включить требуется отредактировать /etc/nsswitch.conf.
В строчку hosts нужно добавить mdns_minimal [NOTFOUND=return] перед dns.
hosts: files mdns_minimal [NOTFOUND=return] dns myhostname mymachines
После перезагрузки или перезапуска соотвествующего сервиса пингуем снова.
$ ping -c 4 workstation.local
PING workstation.local (192.168.1.10) 56(84) bytes of data.
64 bytes from workstation.local (192.168.1.10): icmp_req=1 ttl=64 time=0.449 ms
64 bytes from workstation.local (192.168.1.10): icmp_req=2 ttl=64 time=0.469 ms
64 bytes from workstation.local (192.168.1.10): icmp_req=3 ttl=64 time=0.467 ms
64 bytes from workstation.local (192.168.1.10): icmp_req=4 ttl=64 time=0.393 ms
--- workstation.local ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 0.393/0.444/0.469/0.037 ms
Если у вас очень медленно резолвятся локальные домены, то стоит попробовать использовать модуль mdns4_minimal.
Задача раздачи локальных имен полностью решена. В данном случае я не затрагиваю dnssd поскольку цель была лишь обеспечить доступность хостов по имени.
При желании поднять zeroconf можно как на ардуине, так и на модулях esp8266.
Вы можете столнуться с проблемами из-за того, что некоторые продукты используют зону local для своих целей.
Например торренты часто используют retracker.local для обозначения внутрисетевого трекера.
Обновление нескольких git-репозитариев в папке
Порой у нас в каталоге накапливается много-много git-репозитариев, которые хочется обновить в один заход. Для этого есть маленький скрипт, который обновляет все репозитарии, которые сможет найти в папке, переданной в качестве аргумента.
#!/bin/bash
if test "$#" -ne 1; then
echo "usage: $0 <dirname>"
echo "Find and update all git repos in specified folder"
exit 1
fi
if [-d $1]; then
find $1 -type d -name .git | xargs -n 1 dirname | sort | while read line; do echo "Update repo $line" && pushd `pwd` > /dev/null && cd $line && git pull && popd > /dev/null; done
else
echo "\"$1\" does not exists"
fi
Использование очень простое
$ gitup ~/projects
PHPStorm (PyCharm и др.) и XMonad
После запуска PHPStorm вместо самое среды появляется лишь серое окно без ничего.
Работаю я в xmonad и произошло это после очередной правки конфига под себя.
В документации сказано, что для java-приложений нужен
startupHook = setWMName "LG3D"
Но этот хук перестал почему-то оказывать должный эффект (без него в ряде java-приложений тоже был пустой экран).
А все оказалось просто: я добавил хук ewmhDesktopsEventHook.
handleEventHook = do
ewmhDesktopsEventHook -- вот он
docksEventHook
fullscreenEventHook -- Full screen setup
Хук нужен для перехвата сообщений по активации окна, перемещению его на другой рабочий стол и переключении рабочих столов. Можно почитать документацию и код.
Но беда в том, что этот хук трет имя wm, которое устанавливается в конфиге (ставит “xmonad”). Этот wmname (который lg3d) служит решением для бага из awt.
Чтобы использовать ewmhDesktopsEventHook нужно указать java окольными путями, что она работает в “non reparenting” (не подобрал я нормального перевода :)) окружении.
Для этого служит переменная окружения _JAVA_AWT_WM_NONREPARENTING.
Пишем в ~/.bashrc или ~/.profile
export _JAVA_AWT_WM_NONREPARENTING=1
И теперь все хорошо.
Raspbian - это не Debian
Raspbian - это не Debian. Хотя картинка нас убежлает в обратном.
В чем проблема? Проблема в обозначении архитектуры.
Давеча захотел я поставить на малинку пакет из репозитария собранного под Debian.
Прописал как положено в /etc/apt/sources.list.d/
deb <repourl> wheezy main
Установил и получил segmentation fault. Казалось бы - архитектура armhf (как на малинке), но почему-то не работает.
А дело все в том, что разработчики raspbian перекомпилировали дебиановский armhf (ARMv7) для совместимости с ARMv6, но название архитектуры не поменяли. В итоге попытки установить какой-нибудь пакет *.armhf из дебиана может закончится сегментейшнфаултом.
Для того, чтобы решить все проблемы с софтом из дебиановских репозитариев нужно использовать архитектуру armel, которой разработчики обозначают как раз v6. И явно ее указывать в настройках.
В итоге конфигурация репозитариев deb будет выглядеть так:
deb [arch=armel] <repourl> wheezy main
Ключевое здесь - добавить спецификацию архитектуры как [arch=armel] и таким образом можно успешно подключать даже репозитарии с какого-нибудь ланчпада.
Redis: как скопировать базу без простоя проекта (ну почти)
Ага. У нас проблемы: нам нужно переехать сервер редиса без даунтайма проекта. Но нам надо не только переехать, но еще и данные сохранить.
Чаще всего предлагается решение в виде остановки проекта, копирования базы в новый инстанс, его запуск, переключение проекта и другие танцы.
Существует даже команда migrate, которая гарантирует атомарное копирование ключей и данных.
Но она работает в рамках одной бд (а по дефолту у редиса их целых 16), а так же обладает рядом негативных последствий ввиду своей атомарности. Поэтому подходит она совершенно для других целей.
Сразу на ум приходят репликации :) А данное решение их умеет.
Допустим у нас два сервера (у меня они на портах 6379 и 6479 соответственно). И нам нужно переключить проект с первого на второй сервер. Второй нулевой только что поднятый. А с первым ведется работа.
Посмотрим, что в каждой из баз покажет команда
keys *
Основной редис
Новый редис
Как видим пока базы не синхронизированы.
Теперь нужно сделать новую базу репликой старой
> slaveof 127.0.0.1 6379
OK
> info
...
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
Дополнительно может потребоваться авторизоваться на мастере чтобы началась репликация
config set masterauth <password>
После этого можем опять посмотреть, что в базу скопировалось
keys *
Как видим: все данные успешно засинхронизировались (вполне возможно это займет продолжительное время ввиду объема данных).
После того, как репликация завершена нам нужно сделать две вещи:
- превратить слейва в мастер
- настроить приложение на работу с новым мастером
slaveof no one
Эта команда выключает копирование данных с мастера (но не удаляет их) и теперь уже дело за настройкой приложения.
Да. Небольшой даунтайм все же был (секунд 10-15), но это гораздо лучше, чем предлагаемые решения.
Однако, обратите внимание, что если вы активно пишете в редис, то при такой миграции баз часть данных можно и потерять.