среда, 3 ноября 2021 г.

Сброс пароля пользователя в 1С 8.3.17 ...

-- Переименовать таблицу v8users
EXEC sp_rename 'v8users', 'v8users_tmp'
GO
-- Переименовать users.usr в users.usr_tmp
UPDATE Params
SET FileName = 'users.usr_tmp'
WHERE FileName = 'users.usr'
GO  
-- Создать пустую таблицу v8users
create   table v8users(
ID binary(16) NOT NULL,
Name nvarchar(64) NOT NULL,
Descr nvarchar(128) NOT NULL,
OSName nvarchar(128) NULL,
Changed datetime2(0) NOT NULL,
RolesID numeric(10,0) NOT NULL,
Show binary(1) NOT NULL,
Data varbinary(max) NOT NULL,
EAuth binary(1) NULL,
AdmRole binary(1) NULL,
UsSprH numeric(10,0) NULL,
PRIMARY KEY (ID)
);

-- меняем пароль

-- удаляем таблицу
DROP TABLE v8users
GO
-- возвращаем копию таблицы
EXEC sp_rename 'v8users_old', 'v8users'
GO
UPDATE Params
SET FileName = 'users.usr'
WHERE FileName = 'users.usr_old'
GO  

Центос не обновляется

Надо было сделать:
unset LD_LIBRARY_PATH

Пишет:
[root@vm-ora7 yum.repos.d]# yum update
Plugin "refresh-packagekit" can't be imported
Loaded plugins: fastestmirror, priorities, security
Determining fastest mirrors
 * base: centos.tt.co.kr
 * updates: centos.tt.co.kr
base                                                                                                                                   | 3.7 kB     00:00
Traceback (most recent call last):
  File "/usr/bin/yum", line 29, in <module>
    yummain.user_main(sys.argv[1:], exit_code=True)
  File "/usr/share/yum-cli/yummain.py", line 276, in user_main
    errcode = main(args)
  File "/usr/share/yum-cli/yummain.py", line 129, in main
    result, resultmsgs = base.doCommands()
  File "/usr/share/yum-cli/cli.py", line 434, in doCommands
    self._getTs(needTsRemove)
  File "/usr/lib/python2.6/site-packages/yum/depsolve.py", line 99, in _getTs
    self._getTsInfo(remove_only)
  File "/usr/lib/python2.6/site-packages/yum/depsolve.py", line 110, in _getTsInfo
    pkgSack = self.pkgSack
  File "/usr/lib/python2.6/site-packages/yum/__init__.py", line 883, in <lambda>
    pkgSack = property(fget=lambda self: self._getSacks(),
  File "/usr/lib/python2.6/site-packages/yum/__init__.py", line 668, in _getSacks
    self.repos.populateSack(which=repos)
  File "/usr/lib/python2.6/site-packages/yum/repos.py", line 294, in populateSack
    sack.populate(repo, mdtype, callback, cacheonly)
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 164, in populate
    if self._check_db_version(repo, mydbtype):
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 222, in _check_db_version
    return repo._check_db_version(mdtype)
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 1263, in _check_db_version
    repoXML = self.repoXML
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 1462, in <lambda>
    repoXML = property(fget=lambda self: self._getRepoXML(),
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 1454, in _getRepoXML
    self._loadRepoXML(text=self)
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 1444, in _loadRepoXML
    return self._groupLoadRepoXML(text, self._mdpolicy2mdtypes())
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 1419, in _groupLoadRepoXML
    if self._commonLoadRepoXML(text):
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 1237, in _commonLoadRepoXML
    result = self._getFileRepoXML(local, text)
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 1015, in _getFileRepoXML
    size=102400) # setting max size as 100K
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 837, in _getFile
    size=size
  File "/usr/lib/python2.6/site-packages/urlgrabber/mirror.py", line 408, in urlgrab
    return self._mirror_try(func, url, kw)
  File "/usr/lib/python2.6/site-packages/urlgrabber/mirror.py", line 394, in _mirror_try
    return func_ref( *(fullurl,), **kwargs )
  File "/usr/lib/python2.6/site-packages/urlgrabber/grabber.py", line 985, in urlgrab
    return self._retry(opts, retryfunc, url, filename)
  File "/usr/lib/python2.6/site-packages/urlgrabber/grabber.py", line 886, in _retry
    r = apply(func, (opts,) + args, {})
  File "/usr/lib/python2.6/site-packages/urlgrabber/grabber.py", line 980, in retryfunc
    apply(cb_func, (obj, )+cb_args, cb_kwargs)
  File "/usr/lib/python2.6/site-packages/yum/yumRepo.py", line 1501, in _checkRepoXML
    repoXML = repoMDObject.RepoMD(self.id, filepath)
  File "/usr/lib/python2.6/site-packages/yum/repoMDObject.py", line 124, in __init__
    self.parse(srcfile)
  File "/usr/lib/python2.6/site-packages/yum/repoMDObject.py", line 140, in parse
    parser = iterparse(infile)
  File "/usr/lib/python2.6/site-packages/yum/misc.py", line 1169, in cElementTree_iterparse
    _cElementTree_import()
  File "/usr/lib/python2.6/site-packages/yum/misc.py", line 1164, in _cElementTree_import
    import cElementTree
ImportError: No module named cElementTree

четверг, 2 сентября 2021 г.

Mikrotik vpn server sstp, pptp, l2tp, ikev2

Микротик

:global dnsServer  192.168.1.100;
:global radiusServer 192.168.1.100;
:global radiusSecret IEASrfghasdkalilagf234sdfD;
:global ipsecSecret KudOmjirortuk7Drie;
:global vpnRange 192.168.20.0/24;
:global vpnLocalIp 192.168.20.1;
:global splitNetworks 192.168.0.0/23,192.168.7.0/24;

# ip pool for vpn users
/ip pool add name=vpn-pool ranges=$vpnRange
# profile for pptp,l2tp,sstp
/ppp profile add dns-server=$dnsServer local-address=$vpnLocalIp name=XXtp remote-address=vpn-pool use-compression=yes use-encryption=yes use-mpls=yes wins-server=$dnsServer
#use radius for auth
/ppp aaa set use-radius=yes
/radius add address=$radiusServer secret=$radiusSecret service=ppp,ipsec
#seting up pptp, l2tp, sstp
/interface l2tp-server server set authentication=mschap2 default-profile=XXtp enabled=yes ipsec-secret=$ipsecSecret use-ipsec=yes
/interface pptp-server server set authentication=mschap2 default-profile=XXtp enabled=yes
/interface sstp-server server set authentication=mschap2 certificate=vpn.myreis.ru.pem_0 default-profile=XXtp enabled=yes port=10443 tls-version=only-1.2
#seting up ikev2 ipsec
/ip ipsec policy group add name=ikev2-policies
/ip ipsec profile set [ find default=yes ] enc-algorithm=aes-256,aes-192,aes-128,3des
/ip ipsec profile add enc-algorithm=aes-256,aes-192,aes-128 hash-algorithm=sha256 name=ikev2-profile
/ip ipsec peer add exchange-mode=ike2 name=ikev2-peer passive=yes profile=ikev2-profile send-initial-contact=no
/ip ipsec proposal set [ find default=yes ] auth-algorithms=sha256,sha1 pfs-group=none
/ip ipsec proposal add auth-algorithms=sha256,sha1 name=ikev2-proposal pfs-group=none
/ip ipsec proposal add name=proposal1
/ip ipsec mode-config add address-pool=vpn-pool name=ikev2-cfg split-dns=$dnsServer split-include=$splitNetworks static-dns=$dnsServer system-dns=no
/ip ipsec identity add auth-method=eap-radius generate-policy=port-strict mode-config=ikev2-cfg notrack-chain=prerouting peer=ikev2-peer policy-template-group=ikev2-policies
/ip ipsec policy add dst-address=$vpnRange group=ikev2-policies proposal=ikev2-proposal src-address=0.0.0.0/0 template=yes
/ip ipsec settings set xauth-use-radius=yes

#allow vpn connections
/ip firewall filter add action=accept chain=input protocol=gre
/ip firewall filter add action=accept chain=input protocol=ipsec-esp
/ip firewall filter add action=accept chain=input protocol=ipsec-ah
/ip firewall filter add action=accept chain=input dst-port=443,1701,1723,10443 protocol=tcp
/ip firewall filter add action=accept chain=input dst-port=1701,500,4500 protocol=udp
/ip firewall raw add action=notrack chain=prerouting dst-address=0.0.0.0/0 src-address=$vpnRange
/ip firewall raw add action=notrack chain=prerouting dst-address=$vpnRange src-address=0.0.0.0/0

Certbot

certbot certonly --preferred-challenges=dns --manual -d vpn.domen.ru

И добавляем в letsencrypt-routeros.sh строчку которая обновляет сертификаты для ipsec
$routeros /ip ipsec identity set certificate="$DOMAIN.pem_0,$DOMAIN-chain.pem_0,$DOMAIN-chain.pem_1" numbers=0

Windows 10 sstp клиент

SSTP
$vpn_type = 'sstp'
$vpn_server = 'vpn.myreis.ru'
$vpn_name = $vpn_server+'_'+vpn_type
$vpn_nets = '192.168.0.0/23 192.168.7.0/24'
Remove-VpnConnection -Name $vpn_name -Force -PassThru
Add-VpnConnection -Name $vpn_name -TunnelType $tunel_type -ServerAddress "$($vpn_server):10443" -SplitTunneling -DnsSuffix 'alliancetravel.ru' -RememberCredential -PassThru
$vpn_nets.Split(" ") | foreach { Add-VpnConnectionRoute -ConnectionName $vpn_name -DestinationPrefix $_ -PassThru }

L2TP
$vpn_type = 'l2tp'
$l2tp_psk = 'l2tppsk'
$vpn_server = 'vpn.myreis.ru'
$vpn_name = $vpn_server+'_'+$vpn_type
$vpn_nets = '192.168.0.0/23 192.168.7.0/24'
Remove-VpnConnection -Name $vpn_name -Force -PassThru
Add-VpnConnection -Name $vpn_name -TunnelType $tunel_type -ServerAddress $vpn_server -SplitTunneling -DnsSuffix 'alliancetravel.ru' -L2tpPsk $l2tp_psk -RememberCredential -PassThru -Force
$vpn_nets.Split(" ") | foreach { Add-VpnConnectionRoute -ConnectionName $vpn_name -DestinationPrefix $_ -PassThru }

Остальные типы ВПН настраиваем по аналогии, надо только отключить "использовать впн соединение как шлюз по умолчанию" в ikev2 маршруты добавятся сами. 

понедельник, 29 июня 2020 г.

Подключаем несколько ИБП APC к одному компьютеру

1. Надо сделать так, чтобы ИБП получал каждый раз одно и тоже имя например /dev/usb/ups-1.
Добавляем в UDEV правила:
KERNEL=="hiddev*", ATTRS{manufacturer}=="American Power Conversion", ATTRS{serial}=="AS0000001", OWNER="root", SYMLINK+="usb/ups-1"
KERNEL=="hiddev*", ATTRS{manufacturer}=="American Power Conversion", ATTRS{serial}=="AS0000002", OWNER="root", SYMLINK+="usb/ups-2"
2. Надо для каждого ИБП сделать свой конфигурационный файл, и повесить на разные порты
/etc/apcupsd/ups-1.conf
/etc/apcupsd/ups-2.conf  
3. Для каждого ИБП делаем свой сервис apcupsd
Написал скрипт, чтобы это всё автоматизировать:

#!/bin/bash

BASEDIR=/etc/apcupsd
SYSDDIR=/etc/systemd/system/
UDEVDIR=/etc/udev/rules.d
UPSNAMES=(ups-6        ups-7)
SNUMBERS=(3S1331X04067 AS0945299131)
PORTS=(3556 3557)

if [ ${#UPSNAMES[*]} -eq ${#SNUMBERS[*]} ]
then
    for i in ${!UPSNAMES[*]}
    do
        UPSNAME=${UPSNAMES[$i]}
        SNUMBER=${SNUMBERS[$i]}
        PORT=${PORTS[$i]}
        APCFILE=$UPSNAME.conf
        SRVFILE=apc$UPSNAME.service
        UDEVFILE=$UDEVDIR/$UPSNAME.rules
        # echo $i $UPSNAME $SNUMBER $APCFILE $SRVFILE
        ## create udevrule file
        echo KERNEL==\"hiddev*\", ATTRS{manufacturer}==\"American Power Conversion\", ATTRS{serial}==\"$SNUMBER\", OWNER=\"root\", SYMLINK+=\"usb/$UPSNAME\" > $UDEVFILE
        ##
        ## creating apcupsd config
        cd $BASEDIR
        cp -f ups-template.conf $APCFILE
        sed -i "s/ups_XX/$UPSNAME/g" $APCFILE
        sed -i "s/sn_XX/$SNUMBER/g" $APCFILE
        sed -i "s/355XX/$PORT/g" $APCFILE
        ##
        ## creating systemd service config for each UPS and enable it
        cp -f apcupsd.service_template $SYSDDIR/$SRVFILE
        sed -i "s/ups_XX/$UPSNAME/g" $SYSDDIR/$SRVFILE
        systemctl enable $SRVFILE
        systemctl restart $SRVFILE
        ##
        ## add fw rules
        firewall-cmd --permanent --add-port=$PORT/tcp
        ##
    done
else
    echo "number of upsnames and serial number are not equal"
fi
 

Настроить ipip тунель между linux и mikrotik

/etc/sysconfig/network-scripts/ifcfg-tun0
DEVICE=tun0
MY_OUTER_IPADDR=136.243.153.28
PEER_OUTER_IPADDR=212.158.169.174
MY_INNER_IPADDR=192.168.3.22/30
PEER_INNER_IPADDR=192.168.3.21/30
TYPE=IPIP
TTL=255
ONBOOT=yes

И если надо маршрут в сеть:
/etc/sysconfig/network-scripts/route-tun0
192.168.10.0/24 via 192.168.3.21

На микротике:
Сделать ipip интерфейс. назначить адрес.


пятница, 7 апреля 2017 г.

Резервное копирование Postgre SQL на Windows с помощью Bacula, pg_dump

Дано:
Windows 2012 R2 Standart
Исполняемые файлы установлены сюда:
C:\Program Files\PostgresPro 1C\9.4
Папка с Postgres тут
D:\pgsql\9.4\data

Первая часть, pg_dump

Написал скрипт на powershell
Если передать ему в качетсве параметра имя базы, он сделает дамп одной базы. Если запустить его без параметров, он сделает дамп всех баз кроме template0, template1, postgres.

[CmdletBinding()]
param(
    [String]$dbname="",
    [String]$dumpdir= 'd:\tmp\bacula\pgsql',
    [String]$PGDUMP="C:\Program Files\PostgresPro 1C\9.4\bin\pg_dump.exe",
    [String]$PSQL="C:\Program Files\PostgresPro 1C\9.4\bin\psql.exe",
    [String]$dbserver='localhost',
    [String]$dbuser='postgres',
    [String]$dbpassword='uekmrf'
)

$sql_listdb="select datname from pg_database where not datname in ('template0','template1','postgres') order by datname;"
$env:PGPASSWORD = $dbpassword
$datestamp = Get-Date -UFormat "%Y%m%d-%H%M%S"

Write-Verbose -message dumpdir=$dumpdir
Write-Verbose -message PGDUMP=$PGDUMP
Write-Verbose -message PSQL=$PSQL
Write-Verbose -message dbserver=$dbserver
Write-Verbose -message dbuser=$dbuser
Write-Verbose -message dbpassword=$dbpassword
Write-Verbose -message dbname=$dbname
Write-Verbose -message datestamp=$datestamp

Write-Verbose -message "Проверяем, существует ли папка $dumpdir"
if(!(Test-Path -Path $dumpdir )){
Write-Verbose -message "Cоздаём папку $dumpdir"
    New-Item -ItemType directory -Path $dumpdir | Out-Null
} else {
Write-Verbose -message "Удаляем папку с дампами"
Remove-Item -path $dumpdir -Force -Recurse | Out-Null
    New-Item -ItemType directory -Path $dumpdir | Out-Null
}

Write-Verbose -message "Проверяем указана ли база данных для копирования"
if ($dbname -eq "") {
    Write-Verbose -message "Копируем все базы кроме template0, template1, postgres"
    $dblist = &$PSQL -t -h $dbserver -U $dbuser -c $sql_listdb
    foreach($db in $dblist) {
        $db = $db.TrimStart()
        if ($db -ne "") {
            $dbname=$db
            Write-Verbose -message "Копируем базу данных $dbname"
            &$PGDUMP -h $dbserver -U $dbuser --dbname=$dbname --file=$dumpdir\$dbname-$datestamp.sql.gz --compress=1
        }
    } 
} else {
    Write-Verbose -message "Копируем указанную базу данных $dbname"
    &$PGDUMP -h $dbserver -U $dbuser --dbname=$dbname --file=$dumpdir\$dbname-$datestamp.sql.gz --compress=1
}
Write-Verbose -message "Создание дампов завершено"

Скрипт запускаем из бакулы следующим образом:
ClientRunBeforeJob = "PowerShell.exe -ExecutionPolicy Bypass -File D:\\pgsql\\9.4\\backup_postgres.ps1"
Скрипт удалит папку d:\tmp\bacula\pgsql, создаст её заново и сложит все дампы в неё.
Бакуле останется только забрать их от туда.


--
Ратнер Арсений
Писать: arsenyratner@gmail.com
Звонить: +7 985 273 2090
Skype: arseny.ratner

среда, 17 августа 2016 г.

Мониторинг температуры процессора

Если в WMI информации о температуре процессора нет, тогда делаем следующее: 
Пользуемся опытом товарища:
немного модифицирую скрипт:
На выходе будем получать Name и Sensortype
Забиксу передадим {#NAME_WMI} и {#SENSORTYPE_WMI}

Прототип Item делаем так:
Name: OHM Sensor: {#NAME_WMI} {#SENSORTYPE_WMI}
Key: wmi.get[Root\OpenHardwareMonitor,SELECT value FROM Sensor WHERE Name LIKE "% {#NAME_WMI}%" AND SensorType = "{#SENSORTYPE_WMI}"]

-- 
Ратнер Арсений
Писать: arsenyratner@gmail.com
Звонить: +7 985 273 2090
Skype: arseny.ratner

пятница, 12 августа 2016 г.

Просмотреть лог postfix по отправителю

# for MailID in $(cat /var/log/maillog | grep  from@domain.dom | awk '{ print $6}' | uniq); do echo $MailID; grep $MailID /var/log/maillog ; done

Покажет информацию по каждому письму для отправителя from@domain.com

--
Ратнер Арсений
Писать: arsenyratner@gmail.com
Звонить: +7 985 273 2090
Skype: arseny.ratner

вторник, 25 декабря 2012 г.

Надо было расширить раздел на LVM.
Пытаюсь отмонтировать
Пишет что занят.
отмонтирую c помощью umount -l
fsck пишет что раздел занят
Перезагрузил nfs
После этого fsck удалось запустить.

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

Mikrotik + YOTA LU150 Работает!


Попала ко мне в руки железяка Mikrotik RB751U-2HnD, нужно было убедиться что она работает с новыми модемами YOTA, теми что LU150.

Железяку Mikrotik, прислал, мне магазин http://mikc.ru, магазину всяческий респект за скорость рекакции, 
опыт общения с ним заслуживает отдельной публикации, разрожусь ею позже, скажу лишь, что эмоции
сугубо положительные.

Если совсем коротко:
Протестировал. Работает.

Если чуть длиннее, то всё оказалось очень просто:
Под рукой модема не оказалось, пришлось напряч Серёг, ребята занимаются восстановлением данных http://itm-lab.ru, они используют у себя в офисе Yota.
На всякий случай прошился до последней стабильной версии прошивки 5.17, на 5.15 тоже заработало.
Подключил модем
Включить роутер, нужно именно включить с подключенным модемом, после подключения на горячую, lte1 в списке интерфейсов не появилось.
Проверяем появилось ли новое устройство, в терминале пишем:

/system resource usb print

В ответ получаем:
 # DEVICE VENDOR                                                 NAME                                               SPEED
 0 1:1                                                           RB400 EHCI                                         480 Mbps
 1 1:3    GCT SEMICONDUCTOR Inc                                  Modem Yota                                         480 Mbps

Ура, устройство определилось (Modem Yota). Если интерфейса lte1 не появилось, отключим роутер от сети питания и включим.

Появился новый интерфейс lte1
Добавим DHCP клиент для этого интерфейса и NAT для этого интерфейса, в терминале напишем:
/ip dhcp-client add disabled=no interface=lte1
/ip firewall nat add action=masquerade chain=srcnat out-interface=lte1 to-addresses=0.0.0.0

После этого на интерфейсе lte1 появился IP адрес, и у меня заработал интернет. Ура!
Ну и несколько фоток:





вторник, 10 января 2012 г.

PXE-E55

Появлялась ошибка PXE-E55
Убрал из параметров на DHCP сервере опцию 60 PXEClient
Ошибка пропала.

четверг, 17 ноября 2011 г.

закгразука потаблично дампа мускуль базы

Полезнаю чтука, закгразука потаблично дампа мускуль базы
http://ru-shell.livejournal.com/31675.html

cat dump.sql | awk 'BEGIN {
output = "comments"; } $data ~ /^CREATE TABLE/ {
close(output);
output = substr($3,2,length($3)-2); }
{ print $data >> output }'

На выходе получим по одному файлу на каждую таблицу. Для разбивки такого файла по инсертам можно использовать вот такой скрипт:
awk '/INSERT/{if (n) close(output); output= f n++} n {print >> output }' f=prefix tbl.dump.sql

Затем я запустил for i in prefix*; do mysql --password=****** --database=mydb < $i; echo "$i done"; done

среда, 9 ноября 2011 г.

Как заставить ldapsearch выдвать из Active Directory на русском

Для того чтобы ldapsearch выдавал результаты по русски а не в base64 Надо передать вывод на такой перловый однострочник:
perl -MEncode -MMIME::Base64 -lpe 'if (/::/) { ($attr,$_)=split ; Encode::from_to($_=decode_base64($_),"utf8","utf8") ; $_="$attr : $_" }'

пятница, 23 сентября 2011 г.

Bacula, SATA Диски вместо ленточек

Использую Bacula для резервного копирования. Хранил все резервные копии на RAID массиве, но в один прекрасный момент место на нём стало подходить к концу. Решил попробовать организовать резервное копирование на внешние диски (USB, eSATA, SATA).

О системе: ОСь CentOS 5.6, Bacula 5.0.3 (из репозитория http://www.pramberger.at/ ), vchanger (http://sourceforge.net/projects/vchanger/), autofs, все диски одного объема по 1,5 тБ.

Будем считать что у вас уже имеется настроенная и рабочая система. Если нет, тогда вам сюда: http://wiki.bacula.org, http://www.bog.pp.ru/work/bacula.html

Терминология:
Чейнджер - виртуальное устройство которое создает vchanger
Ленточка - файл в который происходит запись, он же "том" (volume) в бакуле.
Магазин - наш сменный диск с "ленточками"
Количество слотов - сколько ленточек может быть в магазине
Отсеки для магазинов - сколько одновременно магазинов можно использовать.

Настроим autofs, чтобы при обращении к поддиректории в директории /bacula/uuid, происходила попытка смонтировать диск с одноименным UUID:
В файл /etc/auto.master добавим строчку:
/bacula/uuid /etc/auto.uuid --timeout=10

Создадим файл /etc/auto.uuid, добавим туда:
* -fstype=auto,rw :/dev/disk/by-uuid/&

Надо проверить что диск монтируется автоматически.
cd /bacula/uuid/ИдентификаторРазделаДиска
В результате должна появиться папка ИдентификаторРазделаДиска и в неё же подмаонтироваться наш раздел.

Настроим vchanger, программа для эмуляции ленточного ченжера.
Мы будем использовать один ченжер для дисков одинакого объёма.
Создадим файл /etc/bacula/c1500.conf:
# 1500 gb диски
# Использую это имя и в бакуле тоже
changer_name = "c1500"
work_dir = "/var/lib/bacula/c1500"
logfile = "/var/lib/bacula/c1500/c1500.log"
log_level = LOG_EMERG
# Число приводов - сколько одновременно ленточек можно записывать
Virtual_Drives = 4
# Сколько ленточек умещается в магазине, определяем как (объем диска - 15%)/(max volume size из свойств пула в бакуле)
slots_per_magazine = 60
# Сколько одновременно магазинов (дисков) можно использовать, у меня это количество свободных eSATA портов
magazine_bays = 4
# Папка, где будут монтироваться магазины
automount_dir = /bacula/uuid
# Теперь нам нужно перечислить магазины с ленточками которые мы используем
magazine = "UUID:69ceced2-a9ab-4b10-9314-177e912279e7" #1 inc
magazine = "UUID:c83dad52-bd34-49bf-a1dd-fe49e9f6f9bf" #2 diff
# Бывает что по UUID vchanger не может подмонтировать диск, тогда укажем папку.
# В итоге, я настроил все через папки, чтобы было всё единообразно.
magazine = "/bacula/uuid/60182fad-27bc-451f-a4e1-123a619bba2e" #3 full
magazine = "/bacula/uuid/7e68d7be-a98f-47fd-be0d-49d2bea9be24" #4 inc
magazine = "/bacula/uuid/6e834c12-cf8f-4266-8791-4731fdd58207" #5 diff
magazine = "/bacula/uuid/3d4d3dfb-6159-43da-b9d3-75dc802a0e07" #6 full


На этом настройка vchanger завершена. Мы получили виртуальный ченжер с четырьмя приводами для записи ленточек, возможность подключить одновременно 4 магазина с ленточками по 60 ленточек в каждом.

Теперь приступим к настройке бакулы. в конфигурационный файл директора добавляем:
Пулы:
Pool {
Name = "chg-full"
Pool Type = backup
Storage = c1500
Maximum Volume Bytes = 20gb # Тут определяется максимальный размер каждой ленточки
Volume Retention = 200 days
Recycle = Yes
}

Pool {
Name = "chg-diff"
Pool Type = backup
Storage = c1500
Maximum Volume Bytes = 20gb
Volume Retention = 60 days
Recycle = Yes
}

Pool {
Name = "chg-inc"
Pool Type = backup
Storage = c1500
Maximum Volume Bytes = 20gb
Volume Retention = 14 days
Recycle = Yes
}

Обращу ваше вниманеи вот на какой параметр:
Maximum Volume Bytes = 20gb. Тут определяется максимальный размер каждой ленточки, а количество ленточек в магазине (в нашем случае диске) определяется в настройках vchangerа, собственно по этому, если хотим использовать один пул для объединения леточек с дисков разного объёма, мы вынуждены создавать отдельный ченжер для дисков каждого объёма.

Теперь добавим ресурс Storage для нашего виртуальног ченжера:
Storage {
Name = c1500
Address = bacula-sd.local
Password = "123456"
Device = c1500
Media Type = File
Autochanger = yes;
Maximum Concurrent Jobs = 20
}


Создадим расписание расписание для тестирования, Полная копия в 12-05, дифиринциальная в 16-05, и инкрементальные примерно раз в час с 8 до 23. Каждый уровень резервного копирования будет использовать свой пул.
Schedule {
Name = test-gfsCycle
Run = Level=Full Pool=chg-full at 12:05
Run = Level=Differential Pool=chg-diff at 16:05
Run = Level=Incremental Pool=chg-inc at 8:05,9:20,10:20,11:20,14:20,15:20,17:20,18:20,19:20,20:20,21:20,22:20,23:20
}


Для окончательной настройки осталось добавить задания для резервного копирования.
# Сделаем шаблон задания с нашим расписанием и пулом.
JobDefs {
Name = "DefaultJobchg"
Maximum Concurrent Jobs = 20
Type = Backup
Schedule = "test-gfsCycle"
Messages = Standard
Priority = 10
Pool = chg-inc
SpoolData = yes
Spool Size = 300 GB
}
# Сделаем тестовое задание, по шаблону выше
Job {
Name = "at0038-test-job"
JobDefs = "DefaultJobchg"
Write Bootstrap = "/var/lib/bacula/at0038-test.bsr"
Client = at0038-fd
FileSet = "at0038-test-FileSet"
Enabled = Yes
}
# Сделаем набор файлов для архивирования по заданию
FileSet {
Name = "at0038-test-FileSet"
Include {
Options {
signature = MD5
compression = GZIP
}
File = /etc/bacula
}
}


С директором закончили, едем дальше. Настраиваем стораж демон. Создаем авто ченджер с четырьмя приводами и описываем каждый привод.
Autochanger {
Name = c1500
Device = c1500-drive-0
Device = c1500-drive-1
Device = c1500-drive-2
Device = c1500-drive-3
Changer Command = "/usr/local/bin/vchanger %c %o %S %a %d"
Changer Device = "/etc/bacula/c1500.conf"
}

Device {
Name = c1500-drive-0
DriveIndex = 0
Autochanger = yes;
DeviceType = File
MediaType = File
ArchiveDevice = /var/lib/bacula/c1500/0/drive0
RemovableMedia = no;
RandomAccess = yes;
Spool Directory = /bacula/spool/0
Maximum Spool Size = 200 GB
Maximum Job Spool Size = 60 GB
Maximum Concurrent Jobs = 20
}

Device {
Name = c1500-drive-1
DriveIndex = 1
Autochanger = yes;
DeviceType = File
MediaType = File
ArchiveDevice = /var/lib/bacula/c1500/1/drive1
RemovableMedia = no;
RandomAccess = yes;
Spool Directory = /bacula/spool/1
Maximum Spool Size = 200 GB
Maximum Job Spool Size = 60 GB
Maximum Concurrent Jobs = 20
}
Device {
Name = c1500-drive-2
DriveIndex = 2
Autochanger = yes;
DeviceType = File
MediaType = File
ArchiveDevice = /var/lib/bacula/c1500/2/drive2
RemovableMedia = no;
RandomAccess = yes;
Spool Directory = /bacula/spool/2
Maximum Spool Size = 200 GB
Maximum Job Spool Size = 60 GB
Maximum Concurrent Jobs = 20
}

Device {
Name = c1500-drive-3
DriveIndex = 3
Autochanger = yes;
DeviceType = File
MediaType = File
ArchiveDevice = /var/lib/bacula/c1500/3/drive3
RemovableMedia = no;
RandomAccess = yes;
Spool Directory = /bacula/spool/3
Maximum Spool Size = 200 GB
Maximum Job Spool Size = 60 GB
Maximum Concurrent Jobs = 20
}


Теперь надо подготовить диски, я использую 6 дисков по 1,5 тБ. По два в каждом пуле.
Создаем разделы на всех. Узнаём их идентификаторый и записываем их в конфигурацию vchangera.
Права на раздел должны принадлежать пользователю от которого запускается vchanger. В моем случае это тпользователь bacula.
magazine = "/bacula/uuid/60182fad-27bc-451f-a4e1-123a619bba2e" #3 full
Это значит что на диске нарисована маркером цифра 3, а в бакуле он добавлен в chg-full пул
После этого инифиализируем диск в vchangerе:
vchanger -u bacula -g bacula /etc/bacula/c1500.conf initmag 1

Теперь необходимо применить настройки и промаркировать ленточки в наших маназинах.
В консоле управления бакулы:
label storage=c1500 pool=chg-full slot=1-60 barcodes
label storage=c1500 pool=chg-full slot=121-180 barcodes (если диск, например, в третьем слоте для магазинов)
Обновим информацию о ленточках в слотах магазинов, в консоле:
update slots storage=c1500

Ну вот пожалуй и всё с настройкой.
При эксплуатации выявились некоторые нюансы. Привод не всегда отпускал ленточку после завершения резервного копирования (звучит так как будт-то разговор идёт о реальном приводе :). Пришлось сделать задание с наименьшим прироритетом которое запускается после заданий на резервное копирование и даёт команду освободить приводы. И ещё одна проблема когда вставляешь диск, бакула не знает какая ленточка в каком слоте, для решение также сделал задание в бакуле, с наивысшим приоритетом, который запускается перед всеми остальными и загружает ленточки в слоты.

Добавляем в конфигурацию директора шаблон и задания
JobDefs {
Name = "DefaultJobchgAdmin"
Maximum Concurrent Jobs = 20
Type = Admin
Schedule = "gfsCycle"
Messages = Standard
Priority = 10
Pool = chg-full
Fileset = Default
}

Job {
Name = at0038-updateslots
JobDefs = "DefaultJobchgAdmin"
Client = at0038-fd
RunBeforeJob = "/etc/bacula/scripts/chg_update_slots.sh >> /tmp/chg_update_slots.log"
Priority = 8
}

Job {
Name = at0038-releasestorage
JobDefs = "DefaultJobchgAdmin"
Client = at0038-fd
Schedule = "WeeklyCycleAfterBackup"
RunAfterJob = "/etc/bacula/scripts/chg_release_tapes.sh >> /tmp/chg_release_tapes.log"
Priority = 30
}


Создаем файл chg_release_tapes.sh
#!/bin/bash
bconsole="/usr/bin/bconsole -s -c /etc/bacula/bconsole.conf"
$bconsole <<EOD
release storage=c1500 drive=0
release storage=c1500 drive=1
release storage=c1500 drive=2
release storage=c1500 drive=3
release storage=c500 drive=0
release storage=c500 drive=1
release storage=c500 drive=2
release storage=c500 drive=3
quit
EOD

Создаем Файл chg_update_slots.sh
#!/bin/bash
bconsole="/usr/bin/bconsole -s -c /etc/bacula/bconsole.conf"
$bconsole <<EOD_UPSLOTS
update slots storage=c1500 drive=0
quit
EOD_UPSLOTS


ну вот теперь всё.

Спасибо создателям vchanger, людям на http://wiki.bacula.org, и http://www.bog.pp.ru/work/bacula.html. Неоценимо помогли эти материалы.