С помощью smartmontools
состояние SMART у дисков на контроллере HP SmartArray P410 проверяется следующей командой
smartctl -d sat+cciss,N -x /dev/sda
где N — номер диска.
С помощью smartmontools
состояние SMART у дисков на контроллере HP SmartArray P410 проверяется следующей командой
smartctl -d sat+cciss,N -x /dev/sda
где N — номер диска.
В последнее время у некоторых крупных производителей ПО пошла мода считать себя умнее пользователей. В частности Microsoft в последнем выпуске Office 2016 не даёт возможности в установщике выбрать устанавливаемые компоненты: есть всего одна кнопка Установить, нажатие которой ставит полный комплект. Это, конечно, удобно ряду пользователей, кому больше одной кнопки и не нужно, однако, что делать если пользователю не нужны разные One Note, Publisher или они не пользуются Outlook? Или по ряду причин хотят сохранить место на системном жёстком диске или просто не любят ничего лишнего.
Решение, к счастью, есть. Не совсем тривиальное, но рабочее. Реализуем его на стандартном пакете Home & Business.
Для кастомной установки сначала качаем Office 2016 Deployment Tool, помещаем его в пустую директорию, которая будет в итоге директорией с нашим дистрибутивом. Получаем в итоге 2 файла: setup.exe, configuration.xml. Первый это, очевидно, сам установщик, а второй файл конфигурации, по которому этот установщик работает. Правим его согласно первоисточнику, например, следующим образом:
В этой конфигурации мы явно указали продукт, разрядность, язык и исключили компоненты, которые не нужны (в том числе и те, которых нет в выбранной поставке. Так, на всякий случай). Далее запускаем закачку дистрибутивов выбранных компонентов
setup.exe /download configuration.xml
И после закачки запускаем саму установку по заданной конфигурации
setup.exe /configure configuration.xml
Бинго! Поставили только то, что нужно.
В разного рода скриптах иногда нужно получить значение предыдущих дат, на несколько дней назад. В стандартном линуксовом шелле bash это делается
$ date -u "+%F" -d "-3 day"
Однако, вышеуказанный способ не обязательно работает для других интерпретаторов. Для BSD стандартный шелл обычно csh, там аналогичный результат возвращается командой
$ date -v-2d "+%F"
В большинстве случаев на серверные системы Linux
ставится на RAID, железный или программный. В простом случае программный рейд создаётся при помощи mdadm
, в форме зеркала. Корень и разделы системные и данных легко ставятся на получившиеся /dev/mdX
-разделы и такое решение отлично защищает от потери данных в случае аппаратной неисправности жесткого диска. Однако, в стандартной установке загрузчик ставится только на один жёсткий диск и в случае его поломки система не загрузится. Поставим задачу зарезервировать ещё и загрузку, т.е. сделать систему загружаемой с любого из дисков зеркала.
Будем рассматривать наиболее простую конфигурацию и разбиение носителей — 2 NVMe-тома, на которых всего по 2 раздела: для UEFI и для корня системы. Например:
# fdisk /dev/nvme0n1 ... Device Start End Sectors Size Type /dev/nvme0n1p1 2048 526335 524288 256M EFI System /dev/nvme0n1p2 526336 879097934 878571599 419G Linux RAID
Имеем первый раздел для EFI и второй под корень системы. Корень уже в mdadm массиве уровня 1, с ним все уже в порядке. Второй такой же носитель /dev/nvme1n1
имеет в точности такую же разбивку.
После установки получим efi
-раздел, монтируемый в /boot/efi
и параметры загрузки EFI вроде
# efibootmgr -v BootCurrent: 0000 Timeout: 1 seconds BootOrder: 0000,0002,0006,0005 Boot0000* debian HD(1,800,80000,0496eff8-477c-4335-ada1-ce9200ddff6e)File(\EFI\debian\grubx64.efi) Boot0002* UEFI: Built-in EFI Shell Vendor(5023b95c-db26-429b-a648-bd47664c8012,)..BO Boot0005* UEFI: Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,0)MAC(MAC(0cc47ada7688,1)..BO Boot0006* UEFI: IP4 Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,0)MAC(MAC(0cc47ada7688,1)..BO Boot0007* UEFI: Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,1)MAC(MAC(0cc47ada7689,1)..BO Boot0008* UEFI: IP4 Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,1)MAC(MAC(0cc47ada7689,1)..BO
Раздел /dev/nvme0n1p1
непустой и содержит загрузчик. Аналогичный раздел со второго носителя /dev/nvme1n1p1
пустой. Запишем загрузчик в него и добавим его в последовательность загрузки. В случае BIOS срабатывал штатный grub-install
на второй диск. Здесь аналогичный способ перепишет строчку в последовательности загрузки efiboot
выше и по сути переключит загрузку на второй диск. Поступим иначе, а именно наново сделаем загрузку на второй диск, её сохраним, и затем вернём загрузку с первого.
Для начала подменим уже смонтированный раздел /dev/nvme0n1p1
аналогичным со второго диска
umount /boot/efi mount -o umask=0077 /dev/nvme1n1p1 /boot/efi
и убедимся, что смонтировался именно он. Если этот раздел не отформатирован при загрузке сделаем это сейчас
mkfs.vfat -F32 /dev/nvme1n1p1
FAT32
может не быть в системе изначально, он доустанавливается из dosfstools
. Раздел должен быть пустым.
Далее стандартными средствами, по мануалу дебиана прописываем загрузчик:
apt-get install --reinstall grub-efi grub-install /dev/nvme1n1 update-grub
В результате получаем загрузчик в /boot/efi (смонтированный на /dev/nvme1n1p1) и строчку в последовательности UEFI
-загрузки
# efibootmgr -v BootCurrent: 0000 Timeout: 1 seconds BootOrder: 0000,0002,0006,0005 Boot0000* debian HD(1,800,80000,37194fa6-dca2-491e-a0cf-a7fded36e2c5)File(\EFI\debian\grubx64.efi) Boot0002* UEFI: Built-in EFI Shell Vendor(5023b95c-db26-429b-a648-bd47664c8012,)..BO Boot0005* UEFI: Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,0)MAC(MAC(0cc47ada7688,1)..BO Boot0006* UEFI: IP4 Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,0)MAC(MAC(0cc47ada7688,1)..BO Boot0007* UEFI: Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,1)MAC(MAC(0cc47ada7689,1)..BO Boot0008* UEFI: IP4 Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,1)MAC(MAC(0cc47ada7689,1)..BO
Посмотрим таблицу идентификаторов UUID
# blkid /dev/nvme0n1p1: UUID="AC77-0809" TYPE="vfat" PARTUUID="0496eff8-477c-4335-ada1-ce9200ddff6e" /dev/nvme0n1p2: UUID="9643fce5-dcfb-1ff3-d03d-14004857da61" UUID_SUB="f5c3d323-29ec-3079-0e58-3259275e26db" LABEL="s00:0" TYPE="linux_raid_member" PARTUUID="d37e4df1-07ef-467e-acf8-ab98bbb60f87" /dev/nvme1n1p1: UUID="4072-D808" TYPE="vfat" PARTUUID="37194fa6-dca2-491e-a0cf-a7fded36e2c5" /dev/nvme1n1p2: UUID="9643fce5-dcfb-1ff3-d03d-14004857da61" UUID_SUB="f5e0f678-9b1d-3111-df00-74096ddf7e6d" LABEL="s00:0" TYPE="linux_raid_member" PARTUUID="660ba68e-7e25-4287-a646-3f555b510533" /dev/md0: UUID="ce3f9f38-e7d9-4c89-ae36-2127a71670e0" TYPE="ext4" /dev/nvme0n1: PTUUID="86a68d04-a4d9-4296-8a1a-48d02b7171fb" PTTYPE="gpt" /dev/nvme1n1: PTUUID="1bc21b63-6011-42e9-80ab-1fd120b69907" PTTYPE="gpt"
и убедимся, что в последовательности загрузки стоит идентификатор именно второго диска. Но оригинальная строчка с загрузчиком первого диска перезаписана. Поэтому, вручную добавим строчку для второго диска под другим номером и под другим названием аналогично существующей:
efibootmgr -c -d /dev/nvme1n1 -p 1 -L "debian1" -l "\EFI\debian\grubx64.efi"
Проверяем результат
# efibootmgr -v BootCurrent: 0000 Timeout: 1 seconds BootOrder: 0000,0002,0006,0005 Boot0000* debian HD(1,800,80000,37194fa6-dca2-491e-a0cf-a7fded36e2c5)File(\EFI\debian\grubx64.efi) Boot0001* debian1 HD(1,800,80000,37194fa6-dca2-491e-a0cf-a7fded36e2c5)File(\EFI\debian\grubx64.efi) Boot0002* UEFI: Built-in EFI Shell Vendor(5023b95c-db26-429b-a648-bd47664c8012,)..BO Boot0005* UEFI: Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,0)MAC(MAC(0cc47ada7688,1)..BO Boot0006* UEFI: IP4 Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,0)MAC(MAC(0cc47ada7688,1)..BO Boot0007* UEFI: Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,1)MAC(MAC(0cc47ada7689,1)..BO Boot0008* UEFI: IP4 Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,1)MAC(MAC(0cc47ada7689,1)..BO
И меняем порядок загрузки на необходимый
# efibootmgr -o 0000,0001,0002
Вторая часть — это вернуть обратно первый загрузчик. Перемонтируем обратно раздел с ним на оригинальный с первого диска
umount /boot/efi mount /boot/efi
Убеждаемся, что смонтировался именно он, и стандартными средствами записываем загрузчик
apt-get install --reinstall grub-efi grub-install /dev/nvme1n1 update-grub
Аналогичное можно было сделать и с помощью efibootmgr
, как это делали для второго раздела.
В любом способе в конечном варианте загрузки должны видеть примерно следующую последовательность UEFI
# efibootmgr -v BootCurrent: 0000 Timeout: 1 seconds BootOrder: 0000,0001,0002 Boot0000* debian HD(1,800,80000,0496eff8-477c-4335-ada1-ce9200ddff6e)File(\EFI\debian\grubx64.efi) Boot0001* debian1 HD(1,800,80000,37194fa6-dca2-491e-a0cf-a7fded36e2c5)File(\EFI\debian\grubx64.efi) Boot0002* UEFI: Built-in EFI Shell Vendor(5023b95c-db26-429b-a648-bd47664c8012,)..BO Boot0005* UEFI: Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,0)MAC(MAC(0cc47ada7688,1)..BO Boot0006* UEFI: IP4 Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,0)MAC(MAC(0cc47ada7688,1)..BO Boot0007* UEFI: Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,1)MAC(MAC(0cc47ada7689,1)..BO Boot0008* UEFI: IP4 Intel(R) I350 Gigabit Network Connection ACPI(a0341d0,0)PCI(3,3)PCI(0,1)MAC(MAC(0cc47ada7689,1)..BO
Таким образом загрузка будет происходить с любого из дисков, даже если один из них выйдет из строя.
Бывает, что в создаваемых виртуальных машинах LXC нужно доступ к разным подсетям посредством нескольких интерфейсов. А изначальный конфиг виртуалки содержит настройки одного интерфейса. Дополнительный интерфейс добавляется в том же конфиге по аналогии с первым, например:
lxc.network.type = veth lxc.network.name = eth0 lxc.network.link = lxcbr0 lxc.network.ipv4 = 12.34.56.78 lxc.network.flags = up lxc.network.type = veth lxc.network.link = br1 lxc.network.ipv4 = 10.0.3.5/24 lxc.network.name = eth1 lxc.network.flags = up
Linux в связке с qemu является отличной платформой для виртуализации, в том числе Windows-систем. Ключевой особенностью виртуализации в случае "инородных" систем является использование под эту систему файла-образа или отдельного блочного устройства. И то и другое обычно занимает достаточно много места. Попробуем минимизировать используемое место в этом случае.
Среди поддерживаемых qemu форматов образов есть как обычные бинарные образы (img), так и сжатые и несжатые qcow/qcow2. Последний формат в сжатом варианте показывает очень хорошие результаты по использованию места: его образы занимают мало места и при этом размер "внутреннего" жесткого диска в виртуальной системе может быть очень большим. Использоавать этот формат можно изначально, при создании виртуальной машины с помощью qemu-img, или конвертацией образа другого формата в qcow2
qemu-img convert -O qcow2 -c win10.img win10.qcow2
Сжатие в формате qcow2 используется в режиме "только для чтения", т.е. если что-то из образа переписывается, то перезапись происходит уже в несжатом формате. Получается, что сжатой будет статичная часть системы и данных в образе, которые в зависимости от задачи вируталки могут занимать основную часть данных. Для таких машин это формат будет наиболее подходящим.
Руководство qemu-img также предупреждает, что при использовании сжатия несколько уменьшается производительность. Однако, субъективно разницы между несжатым и сжатым форматом мне заметить не удалось.
При конвертации в qcow2 и сжатии следует заранее позаботиться о "чистоте" образа: занулить всё неиспользуемое на нём пространство. В Руководстве Proxmox подробно описываются способы, которыми это можно сделать. Наиболее короткий — очистить диск с помощью майкросовтовской утилиты sdelete, например:
sdelete -z C:
В последней версии утилиты 2.0 есть баг — она зависает на 100%. В этом случае имеет смысл использовать более старую версию 1.6. Есть также вариант использовать графическую Eraser, но это обычно более длинный путь.
В ходе использования образ понемного увеличивается в размере. После длительного использования образ можно сократить в размере тем же самым способом: занулив свободное места и переконвертацией его в qemu-img:
qemu-img convert -O qcow2 -c win9.qcow2_backup win9.qcow2
Естественно, как и перед очисткой образа, так и его пережатием крайне желательно сделать бэкап.
В результате перечисленных выше нехитрых операций можно уменьшить размер образов на порядок, т.е. в 10 раз и более.
Иногда на Linux бывает полезна графическая оболочка, причём в режиме удалённого доступа. Подключение к графике удалённо типично производят с помощью VNC. Рассмотрим простую настройку VNC-сервера на Debian Jessie для эпизодических графических сессий.
В качестве сервера будем использовать tightvncserver, в качестве рабочего стола XFCE. Для начала ставим необходимый софт
apt-get install xfce4 xfce4-goodies gnome-icon-theme tightvncserver
Стартуем VNC
$ vncserver
при первом старте (в случае пустой директории с конфигурацией ~/.vnc
) он запросит пароль на соединение и создаст конфигурацию. В конце скрипта ~/.vnc/xstartup
добавляем запуск XFCE4
xfce4-session &
Завершить VNC-сервер можно
$ vncserver -kill :1
и это имеет смысл сделать для последующей настройки.
Проверяем, что VNC-сервер запускается и корректно работает. Для этого его запускаем
$ vncserver -geometry 1024x600
проверяем, что соответствующий процесс действительно слушает 5901 порт
netstat -tpan | grep :59
и подключаемся к нему. В случае успеха мы увидим рабочий стол созданной сессии.
Вышеперечисленные операции старта-остановки целесообразно несколько автоматизировать. Для этого создаем скрипт по аналогу демоновских скриптов из /etc/init.d/
с содержанием вроде:
#!/bin/bash PATH="$PATH:/usr/bin/" DISPLAY="1" DEPTH="16" GEOMETRY="1280x1024" #GEOMETRY="1024x768" OPTIONS="-depth ${DEPTH} -geometry ${GEOMETRY} :${DISPLAY}" case "$1" in start) /usr/bin/vncserver ${OPTIONS} ;; stop) /usr/bin/vncserver -kill :${DISPLAY} ;; restart) $0 stop $0 start ;; esac exit 0
и помещаем его в директорию локальных скриптов /usr/local/bin/mvnc
.
Тогда VNC-сервером можно управлять командами, полностью по аналогии с демонами:
mvnc start mvnc stop mvnc restart
Делать это можно из под простого пользователя, что в случае простой конфигурации вполне достаточно. При желании можно сделать более сложный init.d-скрипт и поместить его в /etc/init.d/
в автостарт, но это не всегда нужно, если VNC используется эпизодически.
При длительной работе в терминале по SSH
, особенно с длительными перерывами, очень удобно, чтобы подключение сохранялось всё это время. Если не отсылать и получать данные в открытом подключении, то через некоторое время сессия разрывается по таймауту, что обычно неудобно. Исправим это.
В протоколе реализована возможность сохранения сессии, TCPKeepAlive
, клиент или сервер посылает "пустой" пакет, тем самым оживляет сессию и держит её открытой. Фича реализована как на клиенте, так и на сервере. На клиенте она включается в пользовательском конфиге ssh ~/.ssh/config
ServerAliveInterval 90
Клиент будет каждые 90 секунд отправлять пакет серверу и тем самым поддерживать соединение.
Можно настроить периодическое оживление и в общем случае, для всех клиентов сервера. В конфигурации демона /etc/ssh/sshd_config
добавляем или правим
ClientAliveInterval 90 ClientAliveCountMax 960
В этих настройках сервер будет отправлять пакет каждые 90 секунд и максимум делать это 960 раз. В результате соединение продержится до суток (90*960 = 86400 = 24h).
С выходом самбы 4.2 поменялись настройки безопасности, которые идут по умолчанию из коробки. В частности, в дефолтной версии отключена поддержка старого протокола аутентификации для защиты от MTM-атак (человек по середине).
В результате этого старые ОС (Windows XP и похожего срока древности) не могут аутентифицироваться и работать с windows-шарами под samba
. Тем не менее, кое-где ещё используются такие динозавры, поэтому нужно включить в самбе старый протокол и не бояться MTM.
Вот что пишут в apt-listchanges к пакету:
Suggested further improvements after patching:
It is recommended that administrators set these additional options,
if compatible with their network environment:server signing = mandatory
ntlm auth = noWithout "server signing = mandatory", Man in the Middle attacks
are still possible against our file server and
classic/NT4-like/Samba3 Domain controller. (It is now enforced on
Samba’s AD DC.) Note that this has heavy impact on the file server
performance, so you need to decide between performance and
security. These Man in the Middle attacks for smb file servers are
well known for decades.Without "ntlm auth = no", there may still be clients not using
NTLMv2, and these observed passwords may be brute-forced easily using
cloud-computing resources or rainbow tables.
Из некоторого анализа новых фич и изменённых настроек становится ясно, что включается поддержка нужного протокола одной строчкой global-секции:
ntlm auth = no
которая позволяет аутентифицироваться и работать старым ОС, при этом понижая общую безопасность.
Для отладки да и просто для статистики полезно мониторить какие запросы идут к named
-серверу, какие из них выполняются корректно и какие некорректные. Демон bind
позволяет настроить гибкое логирование запросов, затем эти логи можно анализировать сторонней утилитой. В качестве такой утилиты удобно использовать систему мониторинга munin
с bind
-плагинами "из коробки".
Первое, что сделаем — включим нужные плагины. Их в директории с готовыми плагинами два, оба и подключим
cd /etc/munin/plugins ln -s /usr/share/munin/plugins/bind9 ln -s /usr/share/munin/plugins/bind9_rndc
Эти плагины — перловские скрипты. Из их исходного текста можно увидеть, что первый из них (bind9
) парсит стандартный лог неймсервера /var/log/bind9/query.log
, второй (bind9_rndc) — парсит данные rndc
из /var/run/named.stats
и выдаёт расширенную статистику по запросам к DNS
-серверу. В большинстве задач достаточно будет и общего плагина, однако, сконфигурируем их оба.
Конфигурируем параметры запуска скрипта мониторинга. Соответственно, общего плагина в файле /etc/plugin-conf.d/bind9
:
[bind9] user bind env.logfile /var/log/named/query.log
Стандартная директория для логов bind /var/log/named
, а мунин их читает из /var/log/bind9
. Поэтому, явно указываем в конфиге путь к логу (как сделано выше). Как альтернатива, чтобы вносить меньше правок в конфигурацию, можно сделать симлинк:
cd /var/log ln -s named bind9
Далее, настроим сбор логов от неймсервера в лог. Для этого создаем файл (например /etc/bind/logging.conf
) с указанием данных, которые нужно писать в лог. Не будем мелочиться и настроим наиболее полное логирование, причем разных каналов в разные файлы.
logging { channel default_file { file "/var/log/named/default.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel general_file { file "/var/log/named/general.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel database_file { file "/var/log/named/database.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel security_file { file "/var/log/named/security.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel config_file { file "/var/log/named/config.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel resolver_file { file "/var/log/named/resolver.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel xfer-in_file { file "/var/log/named/xfer-in.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel xfer-out_file { file "/var/log/named/xfer-out.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel notify_file { file "/var/log/named/notify.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel client_file { file "/var/log/named/client.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel unmatched_file { file "/var/log/named/unmatched.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel queries_file { file "/var/log/named/query.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel network_file { file "/var/log/named/network.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel update_file { file "/var/log/named/update.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel dispatch_file { file "/var/log/named/dispatch.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel dnssec_file { file "/var/log/named/dnssec.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; channel lame-servers_file { file "/var/log/named/lame-servers.log" versions 5 size 10m; severity dynamic; print-category yes; print-severity yes; print-time yes; }; category default { default_file; }; category general { general_file; }; category database { database_file; }; category security { security_file; }; category config { config_file; }; category resolver { resolver_file; }; category xfer-in { xfer-in_file; }; category xfer-out { xfer-out_file; }; category notify { notify_file; }; category client { client_file; }; category unmatched { unmatched_file; }; category queries { queries_file; }; category network { network_file; }; category update { update_file; }; category dispatch { dispatch_file; }; category dnssec { dnssec_file; }; category lame-servers { lame-servers_file; }; };
Для munin
потребуется только лог запросов query.log
, остальное — в отладочных целях и смело можно вычеркнуть.
Включаем этот файл в конфиге бинда
include "/etc/bind/logging.conf";
рестартуем демон и проверяем, что файлы лога создались и пишутся корректно. Заранее создаем директорию под логи и выставляем на неё нужные права.
Далее, нужно убедиться, что лог читаем для парсера плагина, что делается штатной муниновской командой
munin-run bind9
В случае корректной настройки тест вернёт количество запросов разного типа. Или не вернёт — тогда нужно искать ошибку в конфигурации. Типичная ошибка происходит с правами доступа, поэтому или выставляем доступные права для /var/named/* или настраиваем запуск плагина от рута.
Включаем сам плагин для сбора статистики rndc
в /etc/plugin-conf.d/bind9_rndc
и настраиваем его параметры:
[bind9_rndc] user bind env.querystats /var/cache/bind/named.stats
Путь для файла статистики намеренно указан нестандартный, поскольку apparmor в дистрибутивах Debian/Ubuntu ограничивает запись в стандартную директорию /var/run/named
. Поэтому указываем файл в директории для кеша, где нет явных ограничений на запись.
Теперь включим расширенную статистику rndc
со стороны bind
. Включаем в конфигурации (обычно /etc/bind9/named.conf.options
) строчку:
statistics-file "/var/cache/bind/named.stats";
и рестартуем bind9
.
Аналогично вышеуказанному плагину проверяем, что плагин работает корректно
munin-run bind9_rndc
По окончании, чтобы мунин подхватил новые настройки, его демон нужно перезапустить. Перезапускаем мунин
/etc/init.d/munin-node restart
и проверяем, что логи корректно парсятся и в отчётах мунина присутствует статистика по DNS-запросам. В хорошем случае получаем картинки такого вида
В процессе работы с базами данных MS SQL
с полным логом транзаций через некоторое время этот лог разрастается до внушительных размеров и начинает занимать места больше, чем сама база данных. Есть несколько путей очистки этого лога.
1. Короткий и скорее нерекомендуемый путь
backup log [dbname] TO DISK='NUL' go DBCC SHRINKDATABASE ([dbname], 10, TRUNCATEONLY) go
2. Более длинный, но скорее более надёжный способ (из обсуждения)
USE dbname; GO -- Truncate the log by changing the database recovery model to SIMPLE. ALTER DATABASE dbname SET RECOVERY SIMPLE; GO -- Shrink the truncated log file to 1 MB. DBCC SHRINKFILE (2, 1); -- here 2 is the file ID for trasaction log file,you can also mention the log file name (dbname_log) GO -- Reset the database recovery model. ALTER DATABASE dbname SET RECOVERY FULL; GO
PS: Естественно, экспериментировать с БД и обрезать логи необходимо после полного бэкапа БД заранее.
В Windows версий выше 6.0 есть отличный способ получить доступ к огромному списку настроек из одного окна. Для этого создаем папку с именем
GodMode.{ED7BA470-8E54-465E-825C-99712043E01C}
Часть названия до точки может быть любой, а после точки — это GUID соответствующей фичи. После создания "папки" у неё меняется иконка и она ведёт в очень удобную управлялку.
Причём этот способ не является каким-то волшебством, его механизм описан очень давно. Похожим образом можно создать "ярлык" для многих других управлялок, что подробно описано в справке Майкрософта. Интересно, что в этой справке нет GUID для вышеупомянутой панели, несмотря на то, что она даже успела засветиться в Википедии.
Майкрософт, к сожалению, продолжает свою давнюю традицию выключения из системы полезных утилит, а включить их бывает не всегда быстро. В семерке такому изгнанию подвергся стародавний терминальный клиент telnet
, поэтому если в коммандной строке наберем соответствующую команду, то получим ответ, что telnet "не является внутренней или внешней командой, исполняемой программой или пакетным файлом".
Ясно, что всегда можно найти (и часто более удобную) альтернативу, но иногда предпочтительнее нативный клиент. Как его включить? Это возможно с помощью DISM
. Для этого запускаем консоль (cmd) с правами администратора и выполняем в ней:
dism /online /Enable-Feature /FeatureName:TelnetClient
В результате, спустя некоторое и весьма продолжительное время и зачем-то потребовав перезагрузку (!) клиент ставится.
В поддержке legacy-кода и обновлении скритов нередко возникает задача их перекодирования в utf-8
. Это хорошо выполняется стандарной утилитой iconv
, вот её использование для одного файла:
iconv -f cp1251 -t utf8 orig-in-cp1251.php -o out-in-utf8.php
При этом не удастся указать одинаковое входное и выходное названия: iconv начнёт писать до получения входа и получится файл нулевой длины. В этом случае станартный вывод полезно "замочить в губке" с помощью sponge
. Сделаем однострочный скрипт, который делает всё сразу, он понадобится далее (назовём его to-utf8.sh
):
#!/bin/sh /usr/bin/iconv -f cp1251 -t utf8 "$1" | sponge "$1"
В качестве единственного аргумента он берет имя файла и рекодит его полностью.
Обычно требуется сконвертить все файлы определённого расширения в целой директории. Подключаем ещё find
:
find /here-is-my-files/ -type f -iname "*.js" -exec to-utf8.sh "{}" \;
На часть файлов iconv
может ругнуться в STDERR
и эти файлы целесообразно проверить/перекодировать вручную.
Ещё более сложный (и достаточно частый) случай, когда есть файлы в разных кодировках и их необходимо перевести в одну. iconv
в этом случае может сконвертировать ещё раз и испортить файл. То есть, нужно распознать исходную кодировку и рекодить только "не те" файлы.
Тогда помогает самый лучший вариант: утилиты enca/enconv
. Из них первая только распознаёт кодировку, а вторая ещё и перекодирует.Интерфейс enconv
до безобразия простой: в случае одного параметра она перекодирует файл из исходной (ЛЮБОЙ распознанной!) кодировки в ту, что указана в locale
. Кодировку можно указать явно, тогда вся задача решается одной строкой
find /here-is-my-files/ -type f -iname "*.js" -exec enca "{}" \;
Для улучшения точности язык также можно "подсказать", с помощью параметра (-L ru
).
Последний, enca
-способ, похоже самый оптимальный для большинства задач.
exim4
— отличный почтовый сервер для исходящей почты. По умолчанию он сохраняет заголовки полностью и добавляет ещё свои. В большинстве случаев эти заголвки делают письмо излишне информативным для получателя и этого желательно избежать.
Первое, что стоит сделать в типовой конфигурации сервера — скрыть внутреннюю структуру сети в отправляемых сообщениях, поскольку exim оставляет в заголовках оригинального отправителя. В типичном случае получатель увидит примерно следующее:
Received: from srv12 ([10.0.0.12]) by mymail.example.com with esmtp (Exim 4.84) (envelope-from) id 1cPEo3-0003N7-Jj for user@example.com; Thu, 05 Jan 2013 20:38:39 +0000
или следующее
x-originating-ip: [10.54.14.36]
Как видим, почтовый сервер раскрывает адрес отправителя. Этим отправителем может быть сервер во внутренней сети или обычный пользователь с почтовым клиентом. В любом случае эта информация излишняя для получателя: адрес и имя самого почтового сервера в заголовках вполне достаточно. Почистить историю до почтовика можно срезав заголовки Received на этапе получаения почтовиком письма.
Если письмо генерируется автоматически, некоторые интерпретаторы по умолчанию добавляют информацию о себе и о запускаемом скрипте. В частности, этим отличается PHP:
X-PHP-Originating-Script: 0:myscript.php
Поэтому, также вырезаем заголовок X-PHP-Originating-Script
.
Если же почтовый сервер обслуживает офис, то из заголовков можно узнать используемый почтовый клиент. Например,
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:45.0) Gecko/20100101 Thunderbird/45.5.1
или
X-Mailer: Microsoft Outlook 14.0
Обычно, эта информация вполне безопасна. Информацию о клиенте оставляют многие публичные почтовые сервисы. Однако, её тоже не всегда имеет смысл раскрывать. Особенно, если это веб-клиент или внутренняя CRM. Таким образом, можно ещё срезать заголовок User-Agent
.
Существуют ещё много вариантов, в которых желательно отсечь излишне информативные заголовки. Замечательно, что в exim
это сделать очень просто. Для этого необходимо в начале основной конфигурации сервера включить использоваие фильтра и указать файл конфигурации к нему
system_filter = /etc/exim4/filter
А в самом /etc/exim4/filter
прописать вырезаемые заголовки. Например:
headers remove X-PHP-Originating-Script headers remove Received
После этой доработки, количество заголовков заметно уменьшается и излишняя информация не раскрывается. Естественно, это происходит с сохранением DKIM-подписи (подписывает сервер), поскольку заголовки вырезаются до её формирования.
Ранее я описывал отличную схему инкрементных резервных копий, основанную на использовании жёстких ссылок. Схема позволяет хорошо сохранять место на разделе для бэкапов и на уровне приложений резервные копии видны полностью. Обратной стороной такого удобства является сложность переноса таких бэкапов с одного раздел на другой в случаях, когда это потребуется, например, при физической смене жёстких дисков или рейда для резервирования. Стандартные утилиты вроде cp
воспринимают всю директорию с бэкапами как "нормальную" директорию и копируют полностью, что в результате даёт копию большого, примерно n*[размер одного бэкапа] размера. Кроме объёма, такое копирование занимает огромное количество времени.
Как скопировать быстро и сохранением симлинков? Задача, оказывается, хорошо решается всё той же проверенной утилитой rsync
, которая может работать как локально, так и удалённо. При запуске ее с ключами:
rsync -aH /src-path /dst-path
она выполняет в точности, что и требуется.
Наиболее оптимальным набором параметров для локальных копий показал себя следующий
rsync -aH --delete --numeric-ids /src-path /dst-path
Таким образом полностью копируются права доступа и цифровые владелец-группа (что критично важно для копирования бэкапов LXC-контейнеров, да и не только их) и удаляется всё лишнее, что есть в директории назначения.
Естественно, утилита может копировать и по сети, что делает способ ещё более удобным, особенно со сжатием (-z
).
В ряде случаев бывает необходимо скопировать пользователей и их права (привилегии) на другой сервер БД. Типичная ситуация, когда это требуется — подготовка чистого сервера БД в качестве реплики, при этом пользователи берутся с мастера. Гугл предлагает готовым решением Percona Toolkit
, однако, это дополнительно устанавливаемый софт, попробуем обойтись без него. Для этого скрипт, который вытягивает пользователей из базы-источника и формирует sql
-файл для импорта.
#!/bin/sh mysql -e"SELECT DISTINCT CONCAT('SHOW GRANTS FOR ', '\'', user, '\'@\'', host, '\';') AS QUERY FROM mysql.user" | sed '1d' | while read query; do mysql -e"$query" | sed '1d' | awk '{print $0";"}' done echo -e "FLUSH PRIVILEGES;\n";
На выходе получится sql
-код для исполнения на слейве. Естественно, по файлу стоит пройтись вручную и удалить пользователей, которых добавлять не надо.
Стандартная установка Atlassian Confluence вешает его по умолчанию на 8090 http
-порт. Софтину в целях совместимости и безопасности целесообразно ставить в виртуалку и обращаться к ней по http, при этом сама виртуалка может находится в недоступной извне локальной сети. Поэтому, возникает задача проксировать траффик 8090 порта конфлюенса вовне. Ниже описывается, как это меньшими средствами сделать с помощью nginx
.
В документации Atlassian рассматривается вариант проксирования траффика, в том числе энжинксом. Предлагаемый в документации способ предполагает правки в xml-конфиге самого Confluence, что есть не лучшее решение. Можно обойтись настройкой только nginx, без правок оригинального конфига конфлюенса, что обычно намного разумнее. Вот пример проксирования:
location / { proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; port_in_redirect off; proxy_pass http://confluence-vhost:8090; proxy_redirect http://confluence-vhost:8090/ /; proxy_connect_timeout 600; #proxy_redirect off; }
Аналогичным способом можно завернуть траффик в SSL и отдавать его через https, что существенно повышает безопасность работы.
На Debian-based операционках есть очень удобная директория /etc/network/if-up.d/, в которой находятся скрипты, запускаемые системой при интерфейса. В CentOS и других RHEL-based системах подход директорий conf.d не такой популярный и запуск скриптов после поднятия интерфейса реализован по другом. А именно, внимательным глазом в конце скрипта /etc/sysconfig/network-scripts/ifup-post
можно обнаружить строки:
if [ -x /sbin/ifup-local ]; then /sbin/ifup-local ${DEVICE} fi
Таким образом, если создать файл /sbin/ifup-local
, в него можно прописать собственный firewall или что-то иное, необходимое в сети. Можно (и обычно удобнее) пойти и дальше, и запускать из этого скрипта готовые стандартные скрипты:
test -x /usr/local/bin/fw && /usr/local/bin/fw test -x /usr/local/bin/fw6 && /usr/local/bin/fw6
Так можно реализовать в центе модульность, которой изначально нет.
Типичным решением для создания отказоустойчивых систем является установка корня Linux на зеркальный RAID. Это решение позволяет защитить как данные на корневом разделе, так и возможность загрузки в случае отказа одного из дисков.
В случае использования для этой цели mdadm
настройка массива производится ещё при установке. К сожалению, установщик Debian ставит загрузчик grub
только на первый (hd0) из физических дисков, второй при этом остается незагрузочных (хотя и зеркалирует данные). Если разметка диска делается через GPT, то стандартная команда grub-install /dev/sdb
хотя и прописывает загрузчик на второй диск, но загрузочным разделом все равно указывает hd0
, а значит система без hd0 не грузится и задача резервирования загрузчика проваливается.
Для резервирования нужно на каждом из физических дисков прописать в качестве загрузочного раздела — раздел с того же физического диска. Штатным путем в grub-install
указать загрузочный раздел не получается, но можно пойти следующим обходным путем. Изначально по установке ОС имеет корректный загрузчик на /dev/sda
(hd0), и этот загрузчик указывает на тот же hd0. Сделаем то же для sdb
. Это можно сделать "обманув" grub-install
. А именно:
grub-mkdevicemap
файл /boot/grub/device.map
.device.map
диски (hd0) и (hd1) местами так, чтобы (hd0) теперь указывал на /dev/sdb
.grub-install /dev/sdb
.device.map
(или, в качестве альтернативы, прописываем в нем (hd0) на оба диска sda и sdb).Всё! В результате при отказе любого из загрузочных sda или sdb система загрузится с массивом в degraded-режиме, но полностью сохранит работоспособность.