PostgreSQL >= 9.3 и SHMMAX

Начиная с PostgreSQL >= 9.3 изменился механизм выделения памяти для shared buffers. Теперь он использует mmap() и необходимость в изменении системных параметров kernel.shmmax и kernel.shmall отпала.

At 9.3 the mechanism for shared memory allocation has changed. Now it uses
mmap(). And so, there is no more need to adjust the SHMMAX parameter (at
least not more than the 1KB).

So the answer to your question is basically that you don’t need to mess
sysctl.conf anymore to change SHMMAX (at least not in CentOS). You still
may need to tweak there to change semaphores limits.

Источник

Особенности pdebuild и dpkg-checkbuilddeps: Unmet build dependencies

Если ответить кратко, то процитирую lists.debian.org:

>> >> dpkg-checkbuilddeps: Unmet build dependencies: python-all cdbs docbook-xsl
>> >> W: Unmet build-dependency in source
>> >> ...
>> >>
>> >> How can I make pbuilder fetch these required dependencies?
>
> pbuilder does install the necessary dependencies. But it does so
> *inside* the chroot. But before it runs the "clean" target in the
> debian rules file. So you need the build-dependencies at your system
> too. But there pdebuild won't install them. You have to change the
> pdebuild action orders:
>
> [snip]
>> dpkg-checkbuilddeps: Unmet build dependencies: python-all cdbs docbook-xsl
>> dpkg-buildpackage: warning: Build dependencies/conflicts unsatisfied;
>> aborting.
>> ...
>
> Read about the --use-pdebuild-internal switch:
> http://www.netfort.gr.jp/~dancer/software/pbuilder-doc/pbuilder-doc.html#pdebuild

Если ответить развернуто. Без использования --use-pdebuild-internal выполнение pdebuild приводит к выполнению следующего набора команд

    if ! dpkg-checkbuilddeps -B ; then
        log "W: Unmet build-dependency in source"
    fi
    echo "dpkg-buildpackage -S -us -uc -r${BUILDSOURCEROOTCMD} $DEBBUILDOPTS" | \
        perl -pe 's/(^|\s)-[AbBF](\s|$)/$1$2/g' | \
        /bin/bash
    ${PBUILDERROOTCMD} \
        ${PDEBUILD_PBUILDER} \
        --build \
        ${EXTRA_CONFIGFILE[@]/#/--configfile } \
        --buildresult "${BUILDRESULT}" \
        --debbuildopts "" \
        --debbuildopts "${DEBBUILDOPTS}" \
        "$@" \
        ../"${PKG_SOURCENAME}_${PKG_VERSION}".dsc

Таким образом pdebuild изначально проверяет присутствие зависимостей пакета на основной системе через вызов dpkg-checkbuilddeps -B. В случае не успешного завершения выполнение ограничивается исключительно предупреждением и продолжением выполнения сценария.

После этого предпринимается отчаянная попытка создания исходного (source) набора файлов вызовом команды dpkg-buildpackage -S -us -uc. Только в случае успешного завершения этого этапа будет выполнена команда pbuilder --build ... *.dsc, которая соберет в чистом chroot окружении пакет.

Подвох кроется в выполнении команды dpkg-buildpackage -S -us -uc, которая на одном из своих этапов выполняет команду в основной системе

fakeroot  debian/rules  clean

Для успешного завершения которой требуется установка всех Build-Dep на основной системе.

Необходимое лекарство кроется в $HOME/.pbuilderrc
USE_PDEBUILD_INTERNAL=yes
или указании ключа --use-pdebuild-internal при каждом запуске pdebuild.

gearman и постоянное хранилище PostgreSQL

В новой версии gearman поменялся синтаксис для подключения PostgreSQL хранилища в качестве persistent backend. В частности большинство руководств оперирует оператором -q libpq. Попытки запустить gearman версии 1.0.6 с указанной комбинацией приведет к ошибке

  ERROR 2013-12-11 14:21:45.985137 [  main ] Unknown queue libpq initialize(UNKNOWN_OPTION) -> libgearman-server/queue.cc:214

Для корректной работы необходимо использовать -q postgres или --queue-type=postgres. Например,

/usr/sbin/gearmand --queue-type=postgres --libpq-conninfo='host=localhost user=gearman password=passoword dbname=gearman' --libpq-table=queue

Приключения продолжаются. Разработчики заботливо позаботились о том, чтобы нам не пришлось править скрипты инициализации. О чем свидетельствуют строчки в /etc/default/gearman-job-server:

# This is a configuration file for /etc/init.d/gearman-job-server; it allows
# you to perform common modifications to the behavior of the gearman-job-server
# daemon startup without editing the init script (and thus getting prompted by
# dpkg on upgrades).  We all love dpkg prompts.

В последних версиях скрипт инициализации видоизменили и теперь он использует upstart. Однако зависимость /etc/default/gearman-job-server забыли подключить. Таким образом сервис будет запускаться всегда как

exec start-stop-daemon --start --chuid gearman --exec /usr/sbin/gearmand -- --log-file=/var/log/gearman-job-server/gearman.log

Идеальным вариантом является сборка локального пакета с необходимыми модификациями upstart сценария. Для флегматиков можно предложить дождаться включения необходимых изменений в основной пакет. Для холериков можно предложить вариант модификации /etc/init/gearman-job-server.conf на месте. Для этого необходимо привести его к следующему виду

# -*- upstart -*-

# Upstart configuration script for "gearman-job-server".

description "gearman job control server"

start on (filesystem and net-device-up IFACE=lo)
stop on runlevel [!2345]

respawn

script
    . /etc/default/gearman-job-server
    exec start-stop-daemon --start --chuid gearman --exec /usr/sbin/gearmand -- $PARAMS --log-file=/var/log/gearman-job-server/gearman.log
end script

Из-за особенностей экранирования не получится просто указать в конфигурационном файле /etc/default/gearman-job-server следующую настройку (ссылка на обсуждение):

# РАБОТАТЬ НЕ БУДЕТ!
PARAMS="--queue-type=postgres --libpq-conninfo='host=localhost user=gearman password=passoword dbname=gearman' --libpq-table=queue"

В качестве обходного варианта можно использовать переменные окружения

export PGHOST=localhost
export PGUSER=gearman
export PGPASSWORD=password
export PGDATABASE=gearman
PARAMS="--queue-type=postgres --libpq-table=queue"

upstart vs InitV

Сегодня столкнулись с ситуацией, когда поведение service snmpd restart отличается от поведения /etc/init.d/snmpd restart.

root@develop /etc/init # /etc/init.d/snmpd restart
 * Restarting network management services:                                      root@develop /etc/init # ps uaxwww| grep snmpd
snmp      1097  0.2  0.0  52372  4412 ?        S    11:50   0:00 /usr/sbin/snmpd -Lsd -Lf /dev/null -u snmp -g snmp -I -smux -p /var/run/snmpd.pid
root      1099  0.0  0.0  10612   940 pts/0    S+   11:50   0:00 grep --color=auto snmpd
root@develop /etc/init # snmpget -v1 -Cf -c public localhost .1.3.6.1.4.1.8072.1.3.2.4.1.2.6.105.111.115.116.97.116.161
Error in packet
Reason: (noSuchName) There is no such variable name in this MIB.
Failed object: iso.3.6.1.4.1.8072.1.3.2.4.1.2.6.105.111.115.116.97.116.161

root@develop /etc/init # service snmpd restart
 * Restarting network management services:                                      root@develop /etc/init # ps uaxwww| grep snmpd
snmp      1123  0.5  0.0  52372  4412 ?        S    11:50   0:00 /usr/sbin/snmpd -Lsd -Lf /dev/null -u snmp -g snmp -I -smux -p /var/run/snmpd.pid
root      1125  0.0  0.0  10612   944 pts/0    S+   11:51   0:00 grep --color=auto snmpd
root@develop /etc/init # snmpget -v1 -Cf -c public localhost .1.3.6.1.4.1.8072.1.3.2.4.1.2.6.105.111.115.116.97.116.161
iso.3.6.1.4.1.8072.1.3.2.4.1.2.6.105.111.115.116.97.116.161 = STRING: "3.23"
root@develop /etc/init # 

Наглядно видно, что для случая использования /etc/init.d/snmpd restart, OID не доступен. Командная строка запуска не отличается, конфигурационный файл сервиса не изменяется.

Разрушители легенд: мифы о Redis

Крайне полезная для ознакомления документация (на анлийском языке), посвященная концептуальным вопросам взаимодействия подсистем операционной системы применительно к хранилищу Redis. Уделяется много внимания вопросу в каких подсистемах ОС искать виновника потерянных Вами данных.

Вторая статья, которую хочется порекомедовать к ознакомлению, Disks from the Perspective of a File System, известного Marshall Kirk McKusick, описывающая проблемы с которыми сталкиваются файловые системы и какие техники применяются в борьбе с уловками дисковых накопителей.

Восстанавливаем RAID1 с двумя неисправными жесткими дисками

Долгое время не выдавалось интересных задачек, которые можно было бы освятить в заметке. Вчера всё-таки нашлась интересная с моей точки зрения.

В исходных данных имеем RAID1 массив, построенный на mdadm, оба диска в котором имеют ошибки на чтение в нескольких секторах. Система говорит о том, что в обоих из них Unrecovered read error — auto reallocate failed:

Aug 21 21:53:11 one kernel: [112350.663076] sd 2:0:0:0: [sda] Unhandled sense code
Aug 21 21:53:11 one kernel: [112350.663081] sd 2:0:0:0: [sda] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
Aug 21 21:53:11 one kernel: [112350.663089] sd 2:0:0:0: [sda] Sense Key : Medium Error [current] [descriptor]
Aug 21 21:53:11 one kernel: [112350.663133] sd 2:0:0:0: [sda] Add. Sense: Unrecovered read error - auto reallocate failed
Aug 21 21:53:11 one kernel: [112350.663144] sd 2:0:0:0: [sda] CDB: Read(10): 28 00 3a 38 53 b0 00 00 08 00
Aug 21 21:53:11 one kernel: [112350.663160] end_request: I/O error, dev sda, sector 976769972

Попытки пройти long тест в S.M.A.R.T не увенчиваются успехом. Вырезки из S.M.A.R.T

# smartctl -a /dev/sda
...
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Extended offline    Completed: read failure       90%     32520         976769972
...
# smartctl -a /dev/sdb
...
Num  Test_Description    Status                  Remaining  LifeTime(hours)  LBA_of_first_error
# 1  Extended offline    Completed: read failure       90%     32519         55084971

Таким образом становиться ясно, что пока в массиве представлено 2-а жестких диска он «малость» работает исправно. Перекидывая неудачные попытки чтения с одного диска на другой диск. Это выражается в следующих сообщениях:

Aug 22 09:12:18 one kernel: [153097.501298] end_request: I/O error, dev sdb, sector 750558140
Aug 22 09:12:18 one kernel: [153097.508526] raid1: sdb4: rescheduling sector 695471160
Aug 22 09:12:18 one kernel: [153097.515736] raid1: sdb4: rescheduling sector 695471408
Aug 22 09:12:30 one kernel: [153109.603257] sd 4:0:0:0: [sdb] Unhandled sense code
Aug 22 09:12:30 one kernel: [153109.603259] sd 4:0:0:0: [sdb] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
Aug 22 09:12:30 one kernel: [153109.603262] sd 4:0:0:0: [sdb] Sense Key : Medium Error [current] [descriptor]
Aug 22 09:12:30 one kernel: [153109.603277] sd 4:0:0:0: [sdb] Add. Sense: Unrecovered read error - auto reallocate failed
Aug 22 09:12:30 one kernel: [153109.603281] sd 4:0:0:0: [sdb] CDB: Read(10): 28 00 2c bc 9b b5 00 00 08 00
Aug 22 09:12:30 one kernel: [153109.603287] end_request: I/O error, dev sdb, sector 750558140
Aug 22 09:12:30 one kernel: [153109.610682] raid1:md3: read error corrected (8 sectors at 695471248 on sdb4)
Aug 22 09:12:30 one kernel: [153110.033913] raid1: sda4: redirecting sector 695471160 to another mirror
Aug 22 09:12:31 one kernel: [153110.177597] raid1: sda4: redirecting sector 695471408 to another mirror

В случае окончательного выхода из строя одного из дисков массив никогда не сможет восстановиться, потому что чтение с любого диска заканчивается провалом.

# dd if=/dev/sda of=/dev/null bs=1M
dd: reading `/dev/sda': Input/output error
476938+1 records in
476938+1 records out
500106223616 bytes (500 GB) copied, 5724.82 s, 87.4 MB/s

Разумеется, существует вариант сделать копию системы штатным tar архивом. После этого заменить жесткие диски и развернуть ранее сохраненную систему. Еще один из вариантов попытаться заменить один жесткий диск, создать на нем изначально RAID1 массив с одним missing диском, после этого попытаться синхронизировать систему с оставшегося диска с помощью tar или rsync.

Однако было замечено, что у дисков недоступные для чтения сектора находятся в различных местах. Таким образом возникла идея попытаться форсировать remapping испорченных секторов на одном из дисков и попытаться после этого восстановить данные в них с использованием другого полудохлого диска. В ходе этой операции мы получим один диск с полной копией наших данных, с которого можно эти данные полностью прочитать без ошибок. Останется заменить второй полудохлый диск новым, mdadm автоматически прочитает данные и синхронизирует их с новым диском. При желании после синхронизации можно заменить диск, на котором произвели remapping секторов.

Для того, чтобы форсировать жесткий диск произвести remapping секторов необходимо произвести запись в указанный сектор. С минимальной математической частью можно ознакомиться в статье Forcing a hard disk to reallocate bad sectors. В нашем случае эмпирическим путем было выяснено, что сектора с 976769972 по 976769979 имеют проблемы на жестком диске sda

# hdparm --read-sector 976769972 /dev/sda

/dev/sda:
reading sector 976769972: FAILED: Input/output error
...
# hdparm --read-sector 976769979 /dev/sda

/dev/sda:
reading sector 976769979: FAILED: Input/output error
#

Таким образом производим фиктивную запись в указанный диапазон секторов

for sector in $(seq 976769972 976769979); do
  hdparm --write-sector $sector --yes-i-know-what-i-am-doing /dev/sda;
done

После этого можно убедиться, что данные сектора доступны для чтения (предыдущей командой командой мы их полностью обнулили)

for sector in $(seq 976769972 976769979); do
  hdparm --read-sector $sector /dev/sda;
done

Теперь необходимо в указанные области записать информацию с соседнего диска из зеркала. Так как нам известно смещение 976769972 и что количество поврежденных секторов равно 8 копируем указанную область целым блоком. Обратите внимание копируем область с диска sdb, записываем на диск sda:

# dd if=/dev/sdb of=copy skip=976769972 count=8
8+0 records in
8+0 records out
4096 bytes (4.1 kB) copied, 9.3381e-05 s, 43.9 MB/s
# dd if=copy of=/dev/sda seek=976769972 oflag=direct count=8
8+0 records in
8+0 records out
4096 bytes (4.1 kB) copied, 0.000874658 s, 4.7 MB/s

Обнуление через вызов hdparm не является обязательным. Можно напрямую записать сектора требуемыми данными через dd командой

for sector in $(seq 976769972 976769979); do
  dd if=/dev/sdb of=/dev/sda skip=$sector seek=$sector oflag=direct count=1
done

Осталось убедиться, что все данные с диска можно прочитать

dd if=/dev/sda of=/dev/null bs=1M
476940+1 records in
476940+1 records out
500107862016 bytes (500 GB) copied, 5622.88 s, 88.9 MB/s

Таким образом в ходе описанных манипуляций у нас есть условно рабочий жесткий диск sda, который мы оставляем в системе и меняем жесткий диск sdb. По завершении синхронизации на диск sdb производим замену sda. По завершении синхронизации имеем полностью исправный массив с целостными данными.

В заключении хочется отметить, что в поиске неисправных секторов незаменимой может оказаться команда

dd if=/dev/sda of=/dev/null bs=512 conv=sync,noerror

При желании можно перенаправить сохранение бинарной копии системы на отдельный носитель в этом случае ключ sync просто незаменим. В случае ошибок сбойные сектора на копии будут заполнены NUL (нулями). Таким образом полученная копия будет полностью соответствовать с точки зрения размера оригиналу.

Вторым незаменимым помощником может служить команда badblocks. Важно помнить, что для ее вызова необходимо указать размер блока равный 512 байтам. По умолчанию программа используется значение 1024. Таким образом вызов будет выглядеть следующим образом

badblocks -v -b 512 /dev/sda

Программа будет считывать сектор за сектором и отображать информацию о секторах, которые не удалось прочитать. Например,

# badblocks -v -b 512 /dev/sda 
Checking blocks 0 to 1565565871
Checking for bad blocks (read-only test): 578915880
578915881
578915882
578915883
578915884
578915885
578915886
578915887
578915888
578915889
578915890
578915891
578915892
578915893
578915894
578915895

В этом случае остается сохранить вывод программы в файл и последовательно перезаписать полученные сектора с другого диска.

Интересные материалы для ознакомления:

ipmi_si: Could not set up I/O space

&nbps; До этого IPMI на протяжении нескольких лет исправно работал без каких-либо дополнительных вмешательств на протяжении CentOS 5.x. С приходом на эти машины ubuntu-12.04 был получен неутешительный ответ в виде:

# dmesg | grep ipmi
[233616.922708] ipmi_si: SMBIOS: mem 0xca2 regsize 1 spacing 4 irq 0
[233616.922710] ipmi_si: Adding SMBIOS-specified kcs state machine
[233616.922714] ipmi_si: Trying SMBIOS-specified kcs state machine at mem address 0xca2, slave address 0x20, irq 0
[233616.922717] ipmi_si: Could not set up I/O space

Проверяем через dmidecode


# dmidecode --type 38
# dmidecode 2.11
SMBIOS 2.5 present.

Handle 0x0043, DMI type 38, 18 bytes
IPMI Device Information
        Interface Type: KCS (Keyboard Control Style)
        Specification Version: 2.0
        I2C Slave Address: 0x10
        NV Storage Device: Not Present
        Base Address: 0x0000000000000CA2 (Memory-mapped)
        Register Spacing: 32-bit Boundaries

Как мы видим, адреса совпадают в обоих случаях. Однако при этом инициализации не происходит. Решением явилось явное задание адреса. Создаем файл

cat <<EOF > /etc/modprobe.d/ipmi.conf 
options ipmi_si type=kcs ports=0xca2
EOF

После этого выполняем

service openipmi restart

Проверяем корректность инициализации

# dmesg | grep ipmi | tail -5
[237809.878533] ipmi_si: Adding hardcoded-specified kcs state machine
[237809.878536] ipmi_si: Trying hardcoded-specified kcs state machine at i/o address 0xca2, slave address 0x0, irq 0
[237810.003893] ipmi_si ipmi_si.0: Found new BMC (man_id: 0x0028c5, prod_id: 0x0004, dev_id: 0x22)
[237810.003901] ipmi_si ipmi_si.0: IPMI kcs interface initialized
[237810.007457] ipmi device interface
# ipmitool sel info
SEL Information
Version          : 1.5 (v1.5, v2 compliant)
Entries          : 0
Free Space       : 8192 bytes 
Percent Used     : 0%
Last Add Time    : Not Available
Last Del Time    : 10/18/2011 07:03:08
Overflow         : false
Supported Cmds   : 'Reserve' 'Get Alloc Info' 
# of Alloc Units : 512
Alloc Unit Size  : 16
# Free Units     : 512
Largest Free Blk : 512
Max Record Size  : 2
#

Ubuntu 12.04 preseed и PXELINUX

Ранее используемая строка инициализации ubuntu 10.04 для автоматической установки по сети с использованием pxelinux.0

  APPEND  initrd=ubuntu/10.04/netboot/ubuntu-installer/amd64/initrd.gz debian-installer/locale=en_US.UTF-8 console-setup/ask_detect=false console-setup/layoutcode=us netcfg/choose_interface=auto netcfg/get_hostname=unassigned-hostname url=http://domain.tld/url

перестала работать с выходом новой 12.04 версии. При загрузке вываливается окно с предложением выбора языка для клавиатуры. Как выяснилось параметр console-setup/layoutcode=us был заменен параметром keyboard-configuration/layoutcode=us. Таким образом итоговый результат

  APPEND  initrd=ubuntu/12.04/netboot/ubuntu-installer/amd64/initrd.gz locale=en_US.UTF-8 keyboard-configuration/layoutcode=us console-setup/ask_detect=false netcfg/choose_interface=auto netcfg/get_hostname=unassigned-hostname url=http://domain.tld/url

mdadm says device is inactive

    Сегодня столкнулся с ситуацией, что программный RAID1 запустился следующим образом:

md0 : inactive sda1[0](S) sdb1[1](S) sdc1[2](S)
      6288192 blocks

    В устройстве md0 было 4-е партиции, т.к. производили замену жесткого диска, одна утеряна. Но проблема в другом: устройство в состоянии inactive — это раз, два — все устройства подключились как spare drive. Партиция принадлежит /boot поэтому следующий трюк выдал желаемый результат:

# mdadm  --stop /dev/md0 
mdadm: stopped /dev/md0
# mdadm --assemble --force /dev/md0
mdadm: /dev/md0 has been started with 3 drives (out of 4).
# cat /proc/mdstat
...

md0 : active raid1 sda1[0] sdc1[2] sdb1[1]
      2096064 blocks [4/3] [UUU_]

    Дело в шляпе. Добавляем свежеиспеченный жесткий диск

# mdadm --add /dev/md0 /dev/sdd1 
mdadm: added /dev/sdd1
# cat /proc/mdstat 
...
md0 : active raid1 sdd1[4] sda1[0] sdc1[2] sdb1[1]
      2096064 blocks [4/3] [UUU_]
      [=======>.............]  recovery = 38.7% (812544/2096064) finish=2.3min speed=8952K/sec
#