среда, 7 августа 2013 г.

Выборка в одну колонку

С чем только не приходится сталкиваться на работе.
Вот и с MSAccess встретился.
Суть: делаю джойн двух таблиц получается примерно следующее:
Col1| Col2
----+-----
1 | A
1 | B
1 | C
2 | D
2 | E
3 | F

Нужно получить вот такое:

Col1| Col2
----+-----
1 | A, B, C
2 | D, E
3 | F

В разных СУБД делается по разному. В Oracle есть функция wm_concat, в MSSQL это делается через xml.
А в MSAccess такого нет. Для этого используется (кто бы сомневался) Visual Basic.
Я поискал и нашел. Во первых оригинал.
Во вторых, как я использую эту функцию:

select accountid, 
       ConcatRelated("resource", 
                     "resources", 
                     "resourcetype in ('Телефонный номер') 
                      and accountid = " & [c.accountid]
                     ) as phoneslist
from customers c

Создается функция ConcatRelated, у нее 5 параметров:
1. Поле, которое вынимаем - "resource"
2. Таблица, из которой берем поле - "resources"
3. Любое условие WHERE, но если мы собираемся связывать таблицу с внешним запросом, то делается это так: "resourcetype in ('Телефонный номер') and accountid = " & [c.accountid], где с - таблица из внешнего запроса
4. Порядков сортировки (необязательно). Просто перечисляем поля, например "BeginDate, type"
5. Разделитель (необязательно). Если кому-то не нравится запятая и пробел, то можно использовать, например вот это "|"

А вообще много ответов на разные вопросы я нашел на этом сайте

четверг, 13 июня 2013 г.

Гениально!

Отпарсили CSV одним запросом.
Красота

И свой вариант (с оракловым синтаксисом):
Таблицы:
Attribs (name varchar2(20), value_list blob) с данными в поле value_list, разделенными символом ;
afl (id int) - вспомогательная, с последовательными числами в поле ID


SELECT A.Name,  
NullIf(SubStr(';'||to_char(value_list)||';', 
              afl.ID, 
              instr(';'||to_char(value_list)||';',
                    ';',
                    afl.ID) - afl.ID),
       '') AS Word
FROM afl, ATTRIBS A
WHERE afl.ID <= Length(';'||to_char(value_list)||';')
AND SubStr(';'||to_char(value_list)||';', afl.ID - 1, 1) = ';' 
AND instr( ';'||to_char(value_list)||';', ';',afl.ID) - afl.ID > 0

понедельник, 3 июня 2013 г.

Не поднимается сеть. CentOS

При старте network получаю ошибку "Error, some other host already uses address"
Сначала думал, что проблемы где-то на уровне DNS-DHCP, там все в порядке, адрес не занят, все чисто.
Посмотрел в таблице ARP - тоже ничего такого.
Но я был близко. А дело вот в чем: при запуске сети arping проверяет соответствие мака и IP-адреса.
Решение драконовское, но иного не нашел: открываем /etc/sysconfig/network-scripts/ifup-eth
Находим вот эти строки:

if ! /sbin/arping -q -c 2 -w 3 -D -I ${REALDEVICE} ${ipaddr[$idx]} ; then
  net_log $"Error, some other host already uses address ${ipaddr[$idx]}."
  exit 1
fi

И комментируем их.
Решение нашел здесь

среда, 18 июля 2012 г.

Создание сайта из шаблона, пользователя и БД

Работа с башем, MySQL-ем.
Скрипт по переданным ему параметрам создает БД, пользователя в системе и в БД, берет шаблоны сайтов nginx-а и apache и на основании их создает conf-файлы.


#!/bin/bash

# Create database
/usr/bin/mysql -u root -pXXXXX -e 
   "CREATE DATABASE "$1" CHARACTER SET utf8 COLLATE utf8_general_ci;"
# Create database user
/usr/bin/mysql -u root -pXXXXX -e 
   "CREATE USER '"$2"'@'localhost' IDENTIFIED BY '"$3"' ;"
/usr/bin/mysql -u root -pXXXXX -e 
   "GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,DROP ON "$1".* TO '"$2"'@'localhost' ;"

# Create directories
/bin/mkdir /var/www/vhosts/$4
/bin/mkdir /var/www/vhosts/$4/www/
/bin/mkdir /var/www/vhosts/$4/tmp/
/bin/mkdir /var/www/vhosts/$4/cgi/

# Create system user
/usr/sbin/useradd -b /var/www/vhosts/$4 -g www-data -s /bin/bash $2
/bin/echo $2:$3|/usr/sbin/chpasswd
/bin/chown -R $2:www-data /var/www/vhosts/$4

# Create conf files from template
/bin/bash -c "/bin/sed -e 's/CHANGEME/"$4"/g' 
   /etc/httpd/sites-available/template > /etc/httpd/sites-available/"$4
/bin/ln -s /etc/httpd/sites-available/$4 /etc/httpd/sites-enabled/$4
/bin/bash -c "/bin/sed -e 's/CHANGEME/"$4"/g' 
   /etc/nginx/sites-available/template > /etc/nginx/sites-available/"$4
/bin/ln -s /etc/nginx/sites-available/$4 /etc/nginx/sites-enabled/$4


вызывать его надо примерно так:

[root@localhost]# script.sh DBName username password sitename.com

воскресенье, 8 июля 2012 г.

sed и cut за работой

Чтоб не забыть или потерять.
Задача: есть файл с настройками DNS-зон, из него надо выдергивать названия этих зон и по ним создавать конфиг для nginx-а из шаблона.
Готовый результат:


#!/bin/bash

for i in $(grep 'zone' /etc/named/conf.local | sed -e 's/zone "//g' | sed -e 's/" {//g')
do
  echo $i
  if ! [ -e /etc/nginx/sites-available/$i ]; then
    /bin/bash -c "/bin/sed -e 's/CHANGEME/"$i"/g' 
     /etc/nginx/sites-available/template > /etc/nginx/sites-available/"$i
    /bin/ln -s /etc/nginx/sites-available/$i /etc/nginx/sites-enabled/$i
  fi
done;
/etc/init.d/nginx restart
 

Самый большой интерес представляет первая строчка, которая в for. Вот ее же вариант, только с использованием cut. Спасибо за помощь Грузину!

grep 'zone' conf.local | cut -d " " -f 2 | cut -d "\"" -f 2
 

Еще надо на awk сделать для коллекции.

понедельник, 14 мая 2012 г.

Падение интерфейса

Чтоб не забыть что я делал и где искал:
На сервере ASUS Z8NR-D12 при большом потоке трафика отваливается сетевой интерфейс Intel 82574L.
В момент перед потерей коннекта top показывает:

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
15 root 20 0 0 0 0 R 55.8 0.0 138:19.63 ksoftirqd/2
19 root 20 0 0 0 0 R 55.8 0.0 169:28.29 ksoftirqd/3
35 root 20 0 0 0 0 R 55.8 0.0 135:13.21 ksoftirqd/7
31 root 20 0 0 0 0 R 55.5 0.0 151:44.32 ksoftirqd/6
23 root 20 0 0 0 0 S 54.8 0.0 152:04.43 ksoftirqd/4
27 root 20 0 0 0 0 S 54.2 0.0 28:23.75 ksoftirqd/5
3 root 20 0 0 0 0 S 52.8 0.0 161:36.75 ksoftirqd/0

То есть ksoftirqd забивает память и съедает все процессорное время. Помогал только ребут.

Решение нашел здесь.
Правда предлагалось добавить репозиторий отсюда. Но для моей федоры 16 он не подошел бы, поэтому я скачал дрова с sourceforge.
Берем дрова, распаковываем, читаем README и делаем все по Installation.
В /etc/modprobe.d создал файл eth.conf с содержимым

# new network driver
alias em1 e1000e
alias em2 e1000e

пятница, 4 мая 2012 г.

Ротация логов

Клевый скрипт. И он работает! Особенности:
1) ротация проходит по интервалу в днях,
2) в названии файлов используется год-месяц-день, то есть ротация по имени, а не по времени создания файла (хотя и это сделать можно)
3) для каждой папки надо создавать 3 записи в settings.ini: откуда, куда и маска файлов
4) в settings.ini используются названия fromN toN maskN, где N число
Вобщем вот пример settings.ini

[local]
logfile = Rotation.log

[copy]
dayinterval = 11
count = 3

from1 = D:\Router_xxx_xx_x_x\abonent\
to1 = K:\Router_xxx_xx_x_x\abonent\
mask1 = NF_%Y_%m_%d

from2 = D:\Router_xxx_xx_x_x\authorize\
to2 = K:\Router_xxx_xx_x_x\authorize\
mask2 = NF_%Y_%m_%d

from3 = D:\NAS_xxx-xx-xx-xx\
to3 = K:\NAS_xxx-xx-xx-xxx\
mask3 = %Y-%m-%d


В скрипте маленькая функция, которая архивирует файлики

### Archive and remove
def arch (filename, archivename, isrm):
        if not os.path.exists (os.path.dirname (archivename)):
                os.makedirs (os.path.dirname (archivename))
        try:
                os.chdir (os.path.dirname (archivename))
                fout = gzip.open (os.path.basename(archivename), 'wb')
        except IOError:
                print ('Error creating archive file')
                return
        fin = open (filename, 'rb')                                
        fout.writelines (fin)
        fout.close()
        fin.close()
        if isrm:
                os.remove (filename)


А вот сам скрипт

###   MAIN        
if __name__ == '__main__':
        import gzip
        import configparser
        import time
        import re
        import os
        from datetime import date
        from datetime import timedelta

        cfg = configparser.RawConfigParser()
        cfg.read ('settings.ini')
        logfile = open (cfg.get ('local', 'logfile'), 'a')
        logfile.writelines (time.strftime 
        ("\n[%Y-%m-%d %H:%M:%S] ") +'Service starts')
        dayinterval = cfg.get ('copy', 'dayinterval')
        date_from = date.today() - timedelta (days=int(dayinterval))
        cnt = cfg.get ('copy', 'count')
        i = 1
        while i <= int(cnt) :
                dir_from = cfg.get ('copy', 'from'+str(i))
                dir_to = cfg.get ('copy', 'to'+str(i))+
                date_from.strftime ("%Y-%m\\")
                filemask = cfg.get ('copy', 'mask'+str(i))
                datemask = date_from.strftime (filemask)
                mask = re.compile (datemask, re.IGNORECASE)
                flist = filter (mask.search, os.listdir(dir_from))
                for f in flist:
                        logfile.writelines (time.strftime 
                        ("\n[%Y-%m-%d %H:%M:%S] ") + dir_from+f)
                        arch (dir_from+f, dir_to+f+'.gz',True)
                i = i + 1
        logfile.writelines (time.strftime 
        ("\n[%Y-%m-%d %H:%M:%S] ") +'Service ends')
        logfile.close()



UPD: приделал раскладывание файлов по месяцам.