Категории

вторник, 23 декабря 2014 г.

taskhost.exe "Thread exit" CPU high usage

Обнаружил, что Windows 8.1, установленная в Linux KVM со всеми необходимыми kvm драйверами после небольшого простоя начинает необоснованно потреблять процессор - 100%.
Решение было не сложным - проблема в одной из штатных запланированных задач Windows:
Go to "Task Scheduler" "Microsoft" "Windows" "DiskFootPrint" and disable the "Diagnostics" Task.

1. taskhost.exe DfpCommon.dll thread high CPU utilization

вторник, 18 ноября 2014 г.

MAC OS Hardware compatible table

MB Model Driver Chip
P8B75mle VoodoHDA VT1708s VT1708s
P7BH55D-M ALC892 ALC892
P8Z77-V ALC887 ALC887
P8H67 ALC887 ALC887

пятница, 7 ноября 2014 г.

Mikrotik WPA2-EAP WDS MESH

Постановка задачи, реализовать Wi-Fi сеть WPA2-EAP с авторизацией через LDAP учетки или сертификаты с бесшовным роумингом, используя WDS-MESH. При этом трафик Wi-Fi клиентов завернуть во vlan(tagged), а трафик самого роутера оставить без тега (untagged).
  1. Сброс кнопкой Reset на корпусе.
  2. Подключаемся через Windox по кабелю 2-5 порты или Wifi, в открывшемся диалоговом окне сброс пока не нажимаем!
  3. Прописываем статический ip на ether1, основной шлюз, DNS сервер.
    /ip address add address=10.10.0.101/24 interface=ether1 network=10.10.0.0
    /ip dns set servers=10.10.10.254
    /ip route add distance=1 gateway=10.10.0.1
  4. Жмем сброс настроек в диалоговом окне (см п.2).
  5. Роутер произведет сброс заводских настроек, но оставит пользовательские (см п.3.)
  6. Если роутер, спустя минуту не ушол в ребут - делаем вручную.
  7. Подключаемся по статическому ip (см п.3) и делаем остальные настройки, Identity(я выбрал простой нейминг точек ap1, ap2...), clock, SNTP, отключаем ненужные сервисы (telnet, api) и т.д...
    /system ntp client set enabled=yes primary-ntp=10.10.10.254
    /system clock set time-zone-name=Asia/Novosibirsk
    /system identity set name=ap1
    /ip service set telnet disabled=yes
    /ip service set ftp disabled=yes
    /ip service set api disabled=yes
    /ip service set api-ssl disabled=yes
    
  8. Добавляем интерфейс vlan5 от ether1.
    /interface vlan add interface=ether1 l2mtu=1594 name=vlan5 vlan-id=5
  9. Создаем Bridge интерфейс, называем его например br-vlan5, добавляем в него порты wlan1, vlan5.
    /interface bridge add name=br-vlan5
    /interface bridge port add bridge=br-vlan5 interface=wlan1
    /interface bridge port add bridge=br-vlan5 interface=vlan5
  10. Создаем Mesh интерфейс, называем его например Mesh-Interface, добавляем в него порт br-vlan5.
    /interface mesh add hwmp-rann-propagation-delay=5 name=Mesh-Interface
    /interface mesh port add interface=br-vlan5 mesh=Mesh-Interfacee
    
  11. Создаем Security Profle:
  12. /interface wireless security-profiles add authentication-types=wpa2-eap management-protection=allowed mode=dynamic-keys name=WPA2-EAP-MESH
    1. Name: WPA2-EAP-MESH
    2. Mode: dynamic keys
    3. Authentication Types: [v] WPA2 EAP
    4. Unicast & Group Ciphers: aes ccm
    5. Supplicant Identity: ap1 (для каждой точки свой, на всякий случай, если вдруг точка начнет авторизовываться в RADIUS, будет легче найти проблемную).
    6. Management Protection: Disabled
    7. EAP Methods: passthrough
    8. TLS Mode: no certificates
    9. TLS Certificate: none
  13. Настраиваем wlan1 интерфейс:
  14. /interface wireless set [ find default-name=wlan1 ] band=2ghz-b/g/n disabled=no l2mtu=2290 mode=ap-bridge radio-name=AP1 security-profile=WPA2-EAP-MESH ssid=YOUR_SSID wds-default-bridge=Mesh-Interface wds-mode=dynamic-mesh wireless-protocol=802.11
    1. Выбираем канал (частоту, я выбрал 2412) (ВАЖНО, для работы WDS необходимо, чтобы канал на ВСЕХ роутерах был один).
    2. Mode: ap bridge
    3. Band: 2GHz-B/G/N
    4. Прописываем SSID сети.
    5. Wireless Protocol: 802.11.
    6. Security Profile: WPA2-EAP-MESH (см п.10).
    7. Bridge Mode: Enabled.
    8. WDS Mode: Dynamic-Mesh; WDS Default Bridge: Mesh-Interface.
  15. Производим настройку WDS:
    1. Создаем Security-Profile, чтобы роутеры могли авторизовывать друг друга.
      /interface wireless security-profiles add authentication-types=wpa2-psk eap-methods="" mode=dynamic-keys name=4WDS supplicant-identity="" wpa2-pre-shared-key=wpa2password4wds
      1. Name: 4WDS
      2. Mode: dynamic keys
      3. Authentication Types: [v] WPA2 PSK
      4. Unicast & Group Ciphers: aes ccm
      5. WPA2 Pre-Shared Key: ОдинаковыйПарольНаВсехРоутерах
      6. Management Protection: Disabled
    2. Создаем Connect-List и добавляем в него MAC-адреса каждого роутера.
      /interface wireless connect-list add interface=wlan1 security-profile=4WDS wireless-protocol=802.11 mac-address=4C:5E:0C:XX:XX:01 comment=ap2
      /interface wireless connect-list add interface=wlan1 security-profile=4WDS wireless-protocol=802.11 mac-address=4C:5E:0C:XX:XX:10 comment=ap3
      1. Interface: Wlan1
      2. Mac Address: XX:XX:XX:XX:XX:XX
      3. [V] Connect
      4. Wireless Protocol: 802.11
      5. Security Profile: 4WDS (см п.12.1.1)
  16. Добавляем информацию о RADIUS сервере:
  17. /radius add address=10.10.10.254 secret=supersecretpwd service=wireless
    1. Service: [v] wireless
    2. Address: 10.10.10.254 (у меня RADIUS на этом сервере).
    3. Secret: ***** (Пароль от радиус сервера).
    4. Authentication Port: 1812 (стандартный)
    5. Accounting Port: 1813 (стандартный)
  18. Настройка RADIUS сервера:
Продолжение следует...



  1. Manual:Interface/Wireless
  2. Wireless WDS Mesh
  3. Контроллер Wi-Fi точек доступа на Mikrotik

четверг, 6 ноября 2014 г.

Zimbra: Отправка от списка рассылки

Для начала необходимо переключиться на учетную запись zimbra:
user@mail$ sudo su zimbra
Для выдачи пользователю права на отправку от списка рассылки:
zimbra@mail$ zmprov grr dl list@example.tld usr user@example.tld sendAsDistList
Для отзыва, соответственно:
zimbra@mail$ zmprov rvr dl list@example.tld usr user@example.tld sendAsDistList

Есть еще вариант, который не пробовал: Preferences - Accounts - Add Persona
- Persona Name: ListName
- Settings for Sent Messages _From: ListName list@example.ltd
- Reply-to [v]: ListName list@example.ltd
- Use this persona: [v] list@example.ltd

Письмо будет уходить от его учетки, но в имя будет вписано то, что указано в поле "From", ответ клиенты будут отправлять на адрес и имя, которое указано в "Reply-to". Так же, будет выбираться автоматически отправитель, при ответе на письма, пришедшие на адрес list@example.ltd (на самом деле это список рассылки и скорей всего у клиента будут указаны все участники списка рассылки).

1. Отправка от списка рассылки

пятница, 5 сентября 2014 г.

Скрипт для исправления проблем в Ubuntu GRUB в 1 клик.

Скрипт для исправления проблем в GRUB в 1 клик. Возможно применение в автоматизированных скриптах.
#!/bin/sh

load_default_grub() {
 . /etc/default/grub
}

get_yes_no() {
 while [ true ]; do
  echo -n "$1 (Y/N) ? "
  read a
  echo
  if [ $? != 0 ]; then
   a='No'; return;
  fi
  case $a in
   [Yy][Ee][Ss]|[Yy]) a='Yes'; return;;
   [Nn][Oo]|[Nn]) a='No'; return;;
   *) ;;
  esac
 done
}

# Load config and uncomment variable.
load_default_grub
if (grep -qwai '^#GRUB_DISABLE_RECOVERY=' /etc/default/grub >/dev/null); then
 echo 'INFO: Uncomment the GRUB_DISABLE_RECOVERY variable.'
 sed -i 's/^#GRUB_DISABLE_RECOVERY=\(.*\)/GRUB_DISABLE_RECOVERY=\1/' /etc/default/grub
fi
# Load config again, check value and set if need.
load_default_grub
if [ "$GRUB_DISABLE_RECOVERY" != 'true' ]; then
 if [ -z "$GRUB_DISABLE_RECOVERY" ]; then
  echo 'INFO: Add GRUB_DISABLE_RECOVERY="true"'
  echo 'GRUB_DISABLE_RECOVERY="true"' >> /etc/default/grub
 else
  echo 'INFO: Set GRUB_DISABLE_RECOVERY to "true"'
  sed -i 's/^GRUB_DISABLE_RECOVERY=.*/GRUB_DISABLE_RECOVERY="true"/' /etc/default/grub
 fi
fi

# Delete deprecated options GRUB_HIDDEN_TIMEOUT*.
if (grep -qwai '^GRUB_HIDDEN_TIMEOUT.*' /etc/default/grub >/dev/null); then
 echo 'INFO: Delete deprecated options GRUB_HIDDEN_TIMEOUT*'
 sed -i '/^GRUB_HIDDEN_TIMEOUT.*/d' /etc/default/grub
fi

# Add option GRUB_RECORDFAIL_TIMEOUT=15 for automatic boot on fail.
if ! (grep -qwai '^GRUB_RECORDFAIL_TIMEOUT=.*' /etc/default/grub >/dev/null); then
 echo 'INFO: Add option GRUB_RECORDFAIL_TIMEOUT=15 for automatic boot on fail.'
 echo 'GRUB_RECORDFAIL_TIMEOUT=15' >> /etc/default/grub
fi


#GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
if (grep -qwai '^GRUB_CMDLINE_LINUX_DEFAULT=.*' /etc/default/grub >/dev/null); then
 # Load config again, check value and set if need.
 load_default_grub
 for i in $GRUB_CMDLINE_LINUX_DEFAULT; do
  case "$i" in
   'splash') i='nosplash' ;;
   'quiet') i='noquiet' ;;
  esac
  if [ -n "$GRUB_CMDLINE_LINUX_DEFAULT_OUT" -a -n "$i" ]; then
   GRUB_CMDLINE_LINUX_DEFAULT_OUT="$GRUB_CMDLINE_LINUX_DEFAULT_OUT $i"
  else
   GRUB_CMDLINE_LINUX_DEFAULT_OUT="$i"
  fi
 done
 sed -i -e "s/^GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT=\"${GRUB_CMDLINE_LINUX_DEFAULT_OUT}\"/" /etc/default/grub
fi

#Finnaly re-generate grub.cfg.
get_yes_no "Do you want to run update-grub"
[ $a = 'Yes' ] && update-grub

четверг, 28 августа 2014 г.

Приводим документ к одному типу ident - expand, unexpand и немного про alignment.

user@ubuntu~$ echo -e "    1\n     2" | unexpand -t4 > 1.txt
Получим в 1.txt:
<-->1
<--> 2
user@ubuntu~$ expand -t4 1.txt > 2.txt
Получим в 2.txt:
    1
     2
Получаем некий аналог dos2unix и unix2dos, только для табов и пробелов.
Теперь о применении такого на практике, до недавнего времени я тоже не знал разницу между indentation и alignment. Приведу примеры о чем идет речь.
Это — indentation:
for (int i = 0; i < 10; i++) {
    if (a[i] == 0)
        do_something(i);
}
А вот это — alignment:
int some_variable = 0;
int v1            = 0;
Соль в том, что identation не поплывет в разных редакторах, где размер таба разный, а вот alignment с табами поплывет 100%. Следовательно, если хотим использовать табы, используем только в indentation, но alignment делаем исключительно пробелами. В таком случае использовать expand и unexpand нужно с особой осторожностью, чтобы не задеть aligement.
1. Пора завязывать использовать пробелы вместо табуляции в коде
2. Примиряем любителей пробелов и табов

Инвертируем поведение tail и head

Очень короткая заметка про tail и head. Как известно head и tail работают с началом и концом документа соответственно. Но бывает необходимость получить все строки, кроме, например первых трех, или наоборот кроме последних 3.
Приведу пример работы, вот простой файл:
cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.1 LTS"
Получим из него все строки, кроме первой:
user@Ubuntu:~$ tail -n+2 /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.1 LTS"
А теперь все кроме последних двух:
user@Ubuntu:~$ head -n+3 /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
И живой пример использования, нужно получить из netstat количество соединений сгруппированных по типу, исключив первые 2 строки заголовка:
user@Ubuntu:~$ netstat -ant | tail -n +3 | awk '{print $6}' | sort | uniq -c
      1 CLOSE_WAIT
     34 ESTABLISHED
      8 LISTEN
      2 SYN_SENT
Или для удобства в цикле:
user@Ubuntu:~$ while true; do netstat -ant | tail -n +3 | awk '{print $6}' | sort | uniq -c; echo -----------; sleep 1; done
      1 CLOSE_WAIT
     32 ESTABLISHED
      8 LISTEN
-----------
      1 CLOSE_WAIT
     32 ESTABLISHED
      8 LISTEN
-----------
^C
Остановить цикл можно клавишами Ctrl+c.

среда, 6 августа 2014 г.

Remmina - ошибка "Невозможно подключиться к серверу RDP" при подключении к windows

Перестала подключатся Remmina по RDP, пишет "Невозможно подключиться к серверу RDP".
Решилось все просто, Remmina использует freerdp для работы по протоколу RDP, и все хосты добавляются в файл ~/.freerdp/known_hosts, наподобие как в ssh. Проблема аналогичная как и в ssh - сменился ключ/сертификат - невозможно подключиться к серверу - в ssh нам рекомендуют удалить запись о сервере куда подключаемся из файла known_hosts, аналогично делаем и с freerdp:
user@Ubuntu$ mcedit ~/.freerdp/known_hosts
Формат записей аналогичный - 1 строка - 1 сервер. Удаляем нужную нам запись, сохраняем файл и подключаемся.

понедельник, 4 августа 2014 г.

Ubuntu GRUB2 отключить подтверждение при перезагрузке

В Ubuntu есть проблема - в случае нештатного отключения компьютера (вырубили свет, потом включили) GRUB2 доходит до меню и ждет выбора. Хотелось, чтобы компьютер рестартовал сам при включении света. Как оказалось за это отвечает переменная recordfail, которая по умолчанию выставляется recordfail=1, а после успешной загрузки системы она обнуляется через init.d скрипт /etc/init.d/grub-common.
При загрузке GRUB2 в файле /boot/grub/grub.cfg идет проверка:
if [ ${recordfail} = 1 ]; then
  set timeout=-1
else
  set timeout=0
Таким образом GRUB2 в случае если система была выключена не штатно принудительно выводит меню загрузки и ждет пока администратор в ручную выберет что грузить. Это делается для предотвращения зацикливания загрузки системы, если там что-то серьезно навернулось.
Прямое редактирование /boot/grub/grub.cfg смысла не имеет, т.к. все изменения затрутся, при запуске команды update-grub, поиск по скриптам GRUB2 показал, что в файле /etc/grub.d/00_header есть описание функции recordfail:
function recordfail {
  set recordfail=1
EOF
    FS="$(grub-probe --target=fs "${grubdir}")"
    case "$FS" in
      btrfs | cpiofs | newc | odc | romfs | squash4 | tarfs | zfs)
 cat <<EOF
  # GRUB lacks write support for $FS, so recordfail support is disabled.
EOF
 ;;
      *)
 cat <<EOF
  if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi
EOF
    esac
    cat <<EOF
}
Затем ниже проверка значения переменной recordfail:
make_timeout ()
{
    cat << EOF
if [ "\${recordfail}" = 1 ] ; then
  set timeout=${GRUB_RECORDFAIL_TIMEOUT:--1}
else
EOF
Решение проблемы напрашивается сам собой - установить переменную GRUB_RECORDFAIL_TIMEOUT (таймаут при срабатывании recordfail) в конфигурационном файле GRUB2 /etc/default/grub:
GRUB_RECORDFAIL_TIMEOUT=15
После чего выполнить обновление конфигурации командой:
root@Ubuntu# update-grub

1. правильное выключение + GRUB2 отключить подтверждение при перезагрузке
2. recordfail в grub2 [РЕШЕНО]

среда, 30 июля 2014 г.

Wireshark не видит сетевой интерфейс в Ubuntu

По умолчанию wireshark запускается с правами пользователя и не видит сетевые интерфейсы, использование данной возможности влияет на безопасность, поэтому приходится запускать от root. Если сомневаетесь, то используйте запуск wireshark от root. Dumpcap можно установить таким образом, что члены группы wireshark смогут захватывать пакеты - это более рекомендуемый способ захвата пакетов с помощью Wireshark/Tshark, чем запуск самого Wireshark/Tshark с правами root, так как это позволяет выполнять почти весь код с меньшими правами. Чтобы Wireshark начал видеть интерфейсы нужно разрешить группе wireshark использовать Dumpcap, для этого настраиваем пакет wireshark-common и добавляем своего пользователя в группу wireshark.
root@Ubuntu# dpkg-reconfigure wireshark-common
root@Ubuntu# usermod -aG wireshark $USER

1. Toster: Wireshark не видит сетевой интерфейс в Ubuntu 14.04, что делать?

четверг, 10 июля 2014 г.

PostgreSQL. Создать базу данных и пользователя для нее.

Запускаем psql под пользователем postgres:
su postgres -c psql
Теперь в консоли PostgreSQL вводим следующие команды:
create database dbname with encoding='UNICODE';
create user dbuser with password 'dbpass';
grant all privileges on database dbname to dbuser;
А также не забываем дать доступ новому пользователю к серверу, для этого в файле /var/lib/pgsql/data/pg_hba.conf:
# For dbuser:
host    dbname dbuser   127.0.0.1/32           md5
local   dbname dbuser                          md5
Где dbname – имя базы данных,
dbuser – имя пользователя,
dbpass – пароль пользователя dbuser. И говорим серверу PostgreSQL перечитать измененный конфиг pg_hba.conf:
root@Linux# service postgresql reload
Скрипт для удобства:
#!/bin/sh

PGPORT=

echo 'Input dbname: '
read dbname

dbuser=${dbuser:-$dbname}
echo "Input dbuser: [$dbuser]"  # Generate by dbname.

randpass=$(tr -cd A-Za-z < /dev/urandom | head -c8)
echo "Input dbpass [$randpass]:"  # Generate random.
read dbpass
dbpass=${dbpass:-$randpass}

# Facepalm centos... Need fill path to binary psql: /usr/pgsql-9.3/bin/psql
su - postgres -c "/usr/pgsql-9.3/bin/psql --dbname=$DB --port=$PGPORT <<_EOF
\x
CREATE DATABASE $dbname WITH ENCODING='UNICODE';
CREATE USER $dbuser WITH PASSWORD '$dbpass';
GRANT ALL PRIVILEGES ON DATABASE $dbname TO $dbuser;
_EOF
"
# TODO: check error code here.

# Do backup modified cfg files.
cp /var/lib/pgsql/data/pg_hba.conf /var/lib/pgsql/data/pg_hba.conf_`date +%s`

PGPORT=${PGPORT:-5432}
[ -n "$dbname" -a -n "$dbuser" ] && cat <<-_EOF >>/var/lib/pgsql/data/pg_hba.conf

 # For $dbuser, generated at `date`:
 host    $dbname $dbuser   127.0.0.1/32           md5
 local   $dbname $dbuser                          md5
_EOF

# Do reload.
service postgresql-9.3 reload

Ссылки по теме:
1. PostgreSQL. Как создать базу данных и пользователя для нее.

пятница, 27 июня 2014 г.

Настройка NTP клиента в Windows из cmd, cli, bat

Короткая заметка про настройку NTP клиента в Windows. Для настройки вручную из cmd можно воспользоваться командами:
C:\>net time /setsntp:
The command completed successfully.
C:\>net stop w32time
The Windows Time service is stopping.
The Windows Time service was stopped successfully.
C:\>net start w32time
The Windows Time service is starting.
The Windows Time service was started successfully.
C:\>net time /querysntp
The current SNTP value is: 
The command completed successfully.
Или объединить их в bat или cmd скрипт:
@ECHO OFF

:: IP-адрес или FQDN-имя NTP-сервера локальной сети.
SET "NTP_SRV=ntp.company.local"

net time /setsntp:%NTP_SRV%
net stop w32time
net start w32time
net time /querysntp

1. NTP Server на Linux (ntpd)

пятница, 20 июня 2014 г.

Ubuntu 14.04 и Windows zip архивы - исправляем проблему с кодировками.

Исправляем проблему с zip архивами между Ubuntu 14.04 и Windows:
sudo add-apt-repository ppa:frol/zip-i18n
sudo sed -i'' 's/trusty/precise/g' /etc/apt/sources.list.d/frol-zip-i18n-trusty.list
sudo apt-get update
sudo apt-get install zip unzip p7zip-full
В добавляемом репозитории пока нет пакетов для Ubuntu 14.04 (trusty), но есть для Ubuntu 12.04 (precise). sed'ом вручную переключаемся на ветку precise - пакеты совместимы с trusty.
Должны будут установиться пакеты libnatspec0 и p7zip-full.

Ссылки по теме:
1. http://ppa.launchpad.net/frol/zip-i18n/

среда, 21 мая 2014 г.

Автоматическое создание директории /var/run/php5-fpm после перезагрузки

После установки php-fpm, иногда бывает удобно хранить все его сокеты в отдельной папке, например /var/run/php5-fpm, но если вручную создать такую папку, то после перезагрузки система ее удаляет, а в логе можно увидеть типа:
ERROR: unable to bind listening socket for address '/var/run/php5-fpm/default.sock': No such file or directory.
Это связано с тем, что /var/run монтируется с опцией --bind из /run [1], где файловая система tmpfs, логично, что после перезагрузки все, что создавал пользователь - удаляется! Но не проблема, значит перед запуском демона, нужно проверять, существует ли каталог, если нет, то создавать.
Для решения данной проблемы нужно отредактировать init-скрипт /etc/init.d/php5-fpm, добавив вверху, после переменной SCRIPTNAME строчку:
SOCKETDIR=/var/run/$NAME
А затем, под "do_start() {" добавить еще одну строчку:
[ -d $SOCKETDIR ] || install -m 777 -o www-data -g root -d $SOCKETDIR
-m 777 я указал намеренно, т.к. у меня fpm пулы запускаются от разных uid:gid, если у вас все пулы работают от 1 пользователя, то можете указать -m 755.
Теперь, при запуске php-fpm демона, каталог с сокетами в /var/run будет создаваться автоматически.
UPDATE: 15.10.2014
Для тех кто пользуется upstart, приводим файл /etc/init/php5-fpm.conf к такому виду:
# php5-fpm - The PHP FastCGI Process Manager

description "The PHP FastCGI Process Manager"
author "Ondřej Surý "

start on runlevel [2345]
stop on runlevel [016]

# Precise upstart does not support reload signal, and thus rejects the
# job. We'd rather start the daemon, instead of forcing users to
# reboot https://bugs.launchpad.net/ubuntu/+source/php5/+bug/1272788
#
# reload signal USR2

pre-start script
    [ -d /var/run/php5-fpm ] || install -m 777 -o www-data -g root -d /var/run/php5-fpm
    /usr/lib/php5/php5-fpm-checkconf
end script

respawn
exec /usr/sbin/php5-fpm --nodaemonize --fpm-config /etc/php5/fpm/php-fpm.conf
Изменился блок pre-start, теперь там script, в котором собственно и стоит проверка каталога /var/run/php5-fpm, идея подсмотрена в /etc/init/mysql.conf. Для применения изменений в upstart скрипты, необходимо выполнить команды:
root@Ubuntu# initctl reload-configuration
root@Ubuntu# initctl stop php5-fpm
initctl: Unknown instance: 
root@Ubuntu# initctl start php5-fpm
php5-fpm start/running, process 18467
Обязательно stop (если был запущен демон php5-fpm), а затем start. Если демон php-fpm не был запущен, то restart скажет вам "initctl: Unknown instance:" и не запустит демона. Так что лучше сперва stop и затем start - это избавит от лишних раздумий, как устроена система upstart и почему restart не запускает демона.
Логи запуска через upstart можно подглядеть в dmesg, /var/log/upstart/php5-fpm.log. P.S. команды service php5-fpm start будут обработаны upstart, а init.d скрипты проигнорированы, так вот запутано все в Ubuntu.
Ссылки по теме:
1. Opennet.ru: В Fedora и других Linux-дистрибутивах появится директория /run
2. Создание директории /var/run/php5-fpm после перезагрузки

понедельник, 5 мая 2014 г.

Ubuntu 12.04 не запускается автоматически samba на bridge интерфейсе.

При старте системы демон samba не запускался самостоятельно, точнее он запускался, но был недоступен, а если вручную перезапустить его, то все ок. Сетевые интерфейсы у меня объединены в bridge (br0) wlan0 и eth0. После недолгих расследований логов загрузки, стало ясно, демон smbd успевает запуститься, до того, как bridge сконфигурируется, отсюда и проблема.
Конфигурационный файл /etc/init/smbd.conf привел к такому виду:
description "SMB/CIFS File Server"
author      "Steve Langasek "

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

respawn

pre-start script
 RUN_MODE="daemons"

 [ -r /etc/default/samba ] && . /etc/default/samba

 [ "$RUN_MODE" = inetd ] && { stop; exit 0; }

 install -o root -g root -m 755 -d /var/run/samba
end script

exec smbd -F
А именно, добавил опцию IFACE=br0:
start on (local-filesystems and net-device-up IFACE=br0)
Теперь, при загрузке сервера, демон smbd запускается самостоятельно.
Ссылки по теме:
1. Что такое UpStart

воскресенье, 4 мая 2014 г.

flock - предотвращение повторного запуска программы/скрипта из crontab.

Столкнулся с проблемой, написанный мною бот для сайта запускался раз в минуту и однажды на сервере, где работал бот интернет канал сильно просел, как результат за минуту бот не успел завершить свою работу.
crontab запустил его еще раз, бот снова не успел, а crontab продолжал беспощадно запускать копии бота - последствия были не очень приятными.
Но проблема решилась очень просто, через flock.
Теперь скрипт не запускается до тех пор, пока предыдущий запуск не закончит работу!
Например, запуск произвольного скрипта из crontab раз в минуту:
* * * * * root flock -n /tmp/script.lock -c /path/to/script.sh
Рассмотрим опции: -n /tmp/script.lock - путь до lock файла.
-c /path/to/script.sh - путь до скрипта или программы, которую нужно запустить.
Эта утилита имеется штатно на FreeBSD и Linux.

среда, 30 апреля 2014 г.

GRUB_HIDDEN_TIMEOUT no longer supported, (deprecated).

Столкнулся с проблемой после обновления системы Ubuntu 12.04, а так же Ubuntu 14.04:
root@Ubuntu:/# update-grub
Generating grub configuration file ...
Найден фон: /home/metall/Изображения/grub/about_1600px.png
Предупреждение: Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.
Found background image: /home/metall/Изображения/grub/about_1600px.png
Найден образ linux: /boot/vmlinuz-3.13.0-24-generic
Найден образ initrd: /boot/initrd.img-3.13.0-24-generic
Найден Windows 7 (loader) на /dev/sda1
завершено
root@Ubuntu:/#
При генерации grub.cfg появляется сообщение о том, что GRUB_HIDDEN_TIMEOUT больше не поддерживается:
Предупреждение: Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.
Как выяснилось в установщике Ubuntu имеется баг [1] исправить ситуацию легко, просто закоментируем эту опцию в файле /etc/default/grub:
#GRUB_HIDDEN_TIMEOUT=0
И обновим конфигурацию grub:
root@Ubuntu:/# update-grub
Generating grub configuration file ...
Найден фон: /home/metall/Изображения/grub/about_1600px.png
Found background image: /home/metall/Изображения/grub/about_1600px.png
Найден образ linux: /boot/vmlinuz-3.13.0-24-generic
Найден образ initrd: /boot/initrd.img-3.13.0-24-generic
Найден Windows 7 (loader) на /dev/sda1
завершено
root@Ubuntu:/# 
Как видим проблема ушла. Кстати, если установить конфиг из пакета, то эта опция там закоментирована:
root@Ubuntu# dpkg-reconfigure grub-pc

Ссылки по теме:
1. Warning: Setting GRUB_TIMEOUT to a non-zero value when GRUB_HIDDEN_TIMEOUT is set is no longer supported.

понедельник, 7 апреля 2014 г.

Запуск и адаптация МАРК-SQL 1.5.4 для MySQL 5.x

Столкнулся с проблемой, АИБС "МАРК-SQL" для школьных библиотек 1.5.4 не работала с MySQL, а разработчики заверяли, что программа не совместима с MySQL.
Решил проанализировать запросы, которые ходят между программой и сервером при помощи MySQL-Proxy [2].
И сразу увидел некорректный запрос с использованием зарезервированного слова "SEPARATOR":
SELECT TAG,SUBTAG,FLAGS,SEPARATOR,CAPTION FROM TAG
После добавления обратных кавычек к зарезервированному слову SEPARATOR [1] запрос выполнился в MySQL без проблем:
SELECT TAG,SUBTAG,FLAGS,`SEPARATOR`,CAPTION FROM TAG
Значит для нормальной работы программы АИБС "МАРК-SQL" для школьных библиотек 1.5.4 нужно ловить каждый запрос, и если требуется, экранировать зарезервированные слова MySQL на лету. С этой задачей вполне успешно справится MySQL-Proxy [2] с поддержкой lua [4] скриптов.
После установки, запуска MySQL-Proxy и подключения lua скрипта:
function MyDebug(str)
        -- enable\disable debug messages print to stdout.
        local dbg = 0
        if dbg == 1 then
                print('[DEBUG] ' .. str)
        end
end

function read_query(packet)
        local file = io.open('/var/log/mysql-proxy.log', 'a')
        local q = string.sub(packet, 2)

        MyDebug('Orig. Query: ' .. q)
        file:write('Orig. Query: ' .. q .. '\n')

        -- Таблица зарезервированных слов MySQL.
        -- http://dev.mysql.com/doc/mysqld-version-reference/en/mysqld-version-reference-reservedwords-5-7.html

        q = string.gsub(q, '(SEPARATOR)', '`%1`')
        q = string.gsub(q, '(INT%d)', '`%1`')

        -- Исправление поискового запроса (захардкоженного в marcp.exe) и регистронезависимый поиск.
        local _,_,str1,str2,str3 = string.find(q,"SELECT TERM,CNT FROM (.-) WHERE TERM%s*>=%s*('.-')%s(.*)") -- TODO: проверить всегда ли передаются кавычки в поле WHERE TERM >= ''.
        if str1 ~= nil and str2 ~= nil and str3 ~= nil then
                MyDebug('str1: ' .. str1); MyDebug('str2: ' .. str2); MyDebug('str3: ' .. str3)
                str2 = string.gsub(str2, "^'", '') -- Delete start '.
                str2 = string.gsub(str2, "'$", '') -- Delete end '.
                MyDebug('Fixed str2: ' .. str2)
                q = string.format("SELECT TERM,CNT FROM %s WHERE LOWER(TERM) LIKE LOWER('%s%%') %s",str1,str2,str3)
        end

        -- Исправляем кавычки в запросе.
        q = string.gsub(q, 'SELECT CODE,NAME FROM%s+"(.+)"%s*(.*)', 'SELECT CODE,NAME FROM `%1` %2') -- Del start '.

        MyDebug('Fixed query: ' .. q .. '\n')
        file:write('Fixed query: ' .. q .. '\n')
        file:close()

        proxy.queries:append(2, string.char(proxy.COM_QUERY) .. q, {resultset_is_needed = true})

        return proxy.PROXY_SEND_QUERY
end

function read_query_result(inj)
        if inj.id == 1 and inj.resultset.rows ~= nil then
                local file = io.open('/var/log/mysql-proxy.log', 'a')
                for row in inj.resultset.rows do
                local i = 1
                local fields = {}
                while row[i] do
                        if row[i] == row then break end
                                file:write('Response field: ' .. inj.resultset.fields[i].name .. ' => ' .. row[i] .. '\n')
                                i = i + 1
                        end
                end
                file:close()
                return proxy.PROXY_IGNORE_RESULT
        end
end

В ходе экспериментов для подключения к БД был получен такой конфиг dns.ini для работы с MySQL:
Универс|DRIVER=MySQL ODBC 5.2 Unicode Driver;NO_SSPS=1;MULTI_STATEMENTS=1;AUTO_RECONNECT=1;LOG_QUERY=0;IGNORE_SPACE=1;COMPRESSED_PROTO=1;NO_PROMPT=1;CHARSET=cp1251;DATABASE=marcsql;SERVER=192.168.4.26;PORT=4040;UID=marcsql;PASSWORD=password;
Описание некоторых опций:
  • NO_SSPS=1; - Включение подстановок на стороне клиента, а не сервера (т.е. запросы в которых есть знаки "?").
  • COMPRESSED_PROTO=1; - Включение сжатия (немного повышается скорость работы с большими результатами запросов).
  • NO_PROMPT=1; - Отключение окна запроса, при переподключении к БД.
  • CHARSET=cp1251; - Кодировка в которой будет идти обмен между сервером и клиентом (программа для Windows и работает в cp1251).
  • BASE=marcsql; - Имя базы.
  • SERVER=192.168.4.26; - Адрес сервера MySQL-Proxy.
  • PORT=4040; - Порт на котором работает MySQL-Proxy.
  • UID=marcsql; - Логин, для подключения к БД.
  • PASSWORD=password; - Пароль, для подключения к БД.
Но на этом рано останавливаться, нужно еще привести в порядок запросы в файлах программы да и самой программе объяснить, что мы будем использовать MySQL, а не MS Access: Добавляем в конец информацию о MySQL в bin/db.ini:
[Mysql]

ScriptPath=..\sql\Mysql
CreateTempTable=CREATE TABLE &Table&TabSuf(DOC_ID INTEGER PRIMARY KEY)
DictQuery=SELECT TERM,CNT FROM &Table
В файле DbmsParams.ini:
[Mysql]

$VARCHAR=VARCHAR
$COUNTER=INT AUTO_INCREMENT
$DOUBLE=FLOAT
$LONGTEXT=TEXT
$LONGBINARY=TEXT
$MIDTEXT=TEXT
$TEXT=TEXT
$DBPREF_=marcsql.
$COLUMN=
$TOP1000=
$ALTERCOLUMN=ALTER COLUMN
Добавляем информацию о возрастном маркере в EditMap.ini:
[333a]
EditForm=TECombo
ComboValues=0+  Для дошкольного возраста,6+  Для младшего школьного возраста,12+ Для среднего школьного возраста,16+ Для старшего школьного возраста,18+ Для взрослых
TagValues=Для дошкольного возраста,Для младшего школьного возраста,Для среднего школьного возраста,Для старшего школьного возраста,Для взрослых
Separator=,
OnlyFormEdit=Yes
DefaultMenu=NO

[200e]
EditForm=TECombo
ComboValues=[0+],[6+],[12+],[16+],[18+]
TagValues=[0+],[6+],[12+],[16+],[18+]
Separator=,
OnlyFormEdit=Yes
DefaultMenu=NO
Добавляем редактор LibreOffice в файле marc.ini в секцию [Editors]:
[Editors]

LibreOffice=swriter.exe
Изменяем файл phase.ini под потребности нашей школы:
[Книги]

CreateTags=245anpbco,100ae,700ae,653a,520a,020ac,090ax,084a,110a,260abc,440a,650a,200e,300ab,333a,952be,526cde,250a,998а,773b,773d,773t,773g,013ddee
EditTags=245,100,700,653,520,020,090,084,110,200,260,440,650,300,333,952,526,250,998,773
ViewTags=100a,100e,700a,700e,245a,245b,245o,245p,245n,260a,260b,260c,300a,300b,333a,440a,020a,020c,650a,090a,090x,084a
ShowAllTags=YES
RecType=a
BibLevel=m
В файле RdrData.ini, в секции [Common] исправляем запрос LastReaderQuery:
LastReaderQuery=SELECT RDR_ID FROM &ReadersPrefREADERS ORDER BY LEN(RDR_ID) DESC, RDR_ID DESC LIMIT 1
Теперь SQL файлы, заходим в каталог sql:
Была проблема при удалении записей из таблиц словарей, исправляется в файле delidx.sql: Ищем строку:
DELETE FROM &Table WHERE CNT=0;
Заменяем её на:
DELETE FROM &Table WHERE CNT<=0;
Исправляем проблему с удалением данных из таблицы METAIDX ищем в файле dropdict.sql строку:
DELETE FROM METAIDX WHERE NAME='&Table.TERM'
Заменяем её на:
DELETE FROM `METAIDX` WHERE `NAME` = '&Table.`TERM`';
DELETE FROM `METAIDX` WHERE `NAME` = '&Table.TERM';
Теперь создаем каталог Mysql и копируем все файлы из каталога Access в созданный каталог Mysql (напоминаю, мы должны быть в каталоге sql). Другими словами мы должны получить копию папки sql/Acess, но по адресу sql/Mysql. И приводим в порядок файлы в каталоге sql/Mysql: Файл crdict.sql приводим к такому виду:
INSERT INTO METAIDX(`NAME`,`TYPE`,`MAXLEN`,`TAGS`,`CAPTION`,`SEP`) VALUES('&Table.`TERM`','&Type',&MaxLen,'&Taglist','&Caption','&Sep');

CREATE TABLE &Table (
 `IDX_ID` INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
 `TERM` VARCHAR(&MaxLen),
 `CNT` INTEGER);

CREATE TABLE `&TableX` (
 `IDX_ID` INTEGER NOT NULL,
 `DOC_ID` INTEGER NOT NULL,
 FOREIGN KEY(`IDX_ID`) REFERENCES `&Table`(`IDX_ID`));

CREATE INDEX &TableXB ON &TableX(`DOC_ID`);
CREATE INDEX &TableXC ON &TableX(`IDX_ID`);
Файл rebuild.sql приводим к такому виду:
DROP TABLE IF EXISTS `IDXTEMP`;

CREATE TABLE `IDXTEMP` (`DOC_ID` INTEGER, &Term Text);
$BUILD;
$Инициализация таблицы индексов;
DELETE FROM &TableX;
DELETE FROM &Table;
$Заполнение таблицы индексов;
INSERT INTO &Table(&Term,CNT) SELECT &Term, Count(&Term) FROM IDXTEMP GROUP BY &Term;
$Заполнение таблицы перекрестных ссылок;
INSERT INTO &TableX(IDX_ID,DOC_ID) SELECT &Table.IDX_ID,IDXTEMP.DOC_ID FROM &Table,IDXTEMP
WHERE IDXTEMP.&Term=&Table.&Term;
$Удаление временной таблицы;
DROP TABLE IDXTEMP;
На этом изменения в файлах программы окончены. Пришло время конвертировать базу, я конвертировал при помощи BullZip Access To MySQL[6], на выходе получил .sql файл, который был скопирован на сервер и залит в БД. На этом все.

1. Reserved Words in MySQL 5.0
2. Download MySQL Proxy
3. Download Connector/ODBC
4. 20.1 – Pattern-Matching Functions
5. MySQL On air. Мониторим SQL запросы
6. Access To MySQL
7. MySQL и MarcSQL
8. Версия АИБС "МАРК-SQL" для школьных библиотек находится в свободном доступе для российских школ.

воскресенье, 23 марта 2014 г.

Putty и непечатаемые символы табуляции(<----->) и поробела(.)

После обновления Putty до 0.63 столкнулся с проблемой, не отображались непечатаемые символы (табуляция <----> и пробел .), исправляется установкой опции Change Settings->Window->Colours "Indicate bolded text by changing": в "True Color". Не забываем сохранить настройки в стандартную сессию (efault Session).

Результат:
А вот так выглядит тот же файл, с проблемными, стандартными настройками Putty:

Q: При копировании текста из редактора в буфер обмена тест вставляется с точками и "<---->".
A: Убрать подсветку пробелов и табуляции можно, нажав "alt+shift+-".
1. Ответы на часто задаваемые вопросы

четверг, 20 февраля 2014 г.

Блокирование рекламы в Skype 6.11.66.102 bat,cmd файл.

Для блокировки назойливой рекламы, которая к тому же сделана на Flash, что сильно мешает нормальной работе за комптютером, был написан простенький bat файл:
@ECHO OFF
CHCP 866 >nul

FOR %%a IN (rad.msn.com apps.skype.com) DO (
    TYPE "%SystemRoot%\system32\drivers\etc\hosts" | FIND /I "%%a" | FIND "127.0.0.1" >nul && ECHO.%%a уже заблокирован! || 1>>"%SystemRoot%\system32\drivers\etc\hosts" (ECHO.127.0.0.1 %%a) && ECHO.%%a заблокирован! || ECHO.Ошибка записи! && PAUSE && EXIT
)
PAUSE
EXIT
Скопировать текст скрипта, сохранить как Block_SkypeAD.bat в кодировке cp866 (DOS) и запустить.
Ссылки по теме:
1. Реклама в скайпе
2. Как отключить дурацкую рекламу в скайп???????