SEO
Статья на тему DevOps.
Не будем занудствовать, а просто скинем пару лайф-хаков.
Как забэкапить 1С 8.3 в Windows, если есть синхронизация бэкапов в Яндекс.Cloud через Duplicaty?
@echo off
rem бэкапим базу 1С во временное хранилище, для синхронизации с облаком
"C:\Program Files\7-zip\7z.exe" a -t7z -mx5 -scsWIN -ssw "D:\backup\1c\1Cback-%date%-%time:~0,2%.%time:~3,2%.%time:~6,2%.7z" "C:\1c_base"
rem перемещаем файлы из временной папки Duplicaty в конечное хранилище
forfiles -p "D:\backup\1c" -s -m *.7z -d -3 -c "cmd /c if /i @isdir equ false move @path D:\backup\"
rem удаляем старые файлы из хранилища
forfiles -p "D:\backup" -s -m *.7z -d -60 -c "cmd /c if /i @isdir equ false del /q /s @path"
Как видно всё просто. Почти, и вот это "почти" и приходиться "обходить" дополнительной папкой. С Duplicaty есть проблема в том, что он АБСОЛЮТНО не смотрит на давность файлов. Он заливает ВСЁ как есть на диске. И существующая в ней функция удаления применима ТОЛЬКО к самим архивами создаваемым Duplicaty на удалённом сервере.
Создаём .bat файл с данным содержимым и в "Планировщике заданий" Виндовс указываем путь до него и периодичность запуска.
Расшифруем параметры:
a -t7z -mx5 -scsWIN -ssw | указываем степень сжатия и тип архива |
%date%-%time:~0,2%.%time:~3,2%.%time:~6,2% | "вызываем" системное время в имя файла |
-s -m *.7z -d -60 -c | удалить файлы старше 60-ти дней |
/c if /i @isdir equ false del /q /s @path | где и как их искать |
Как забэкапить 1С 7.7 в Ubuntu?
5 0 * * 6 tar --exclude='/var/www/html/zod/edo' -cP /var/www | /bin/gzip -9 -c > /media/hdd/backup/ubun_1c77_`date '+\%Y-\%m-\%d'`.tar.gz
40 4 * * * cp /media/hdd/backup/ubun_1c77_`date '+\%Y-\%m-\%d'`.tar.gz /var/backmedia/ubun_1c77_`date '+\%Y-\%m-\%d'`.tar.gz
30 18 * * 7 find /var/www/html/termit/out/ -mtime +730 -not \( -name "body.html" -o name "*.dt" \) -delete;
Тут посложнее.
На нужно набрать комманду sudo crontab -e и попасть в CRON, где и прописать задание.
Расшифруем параметры:
5 0 * * 6 | время запуска (тут каждую субботу в 00:05) |
tar -cP /var/www | все папки со своей структурой помещаем в "портфель" (верхним каталогом будет корень системы) |
tar --exclude='/var/www/html/zod/edo' | Исключение файлов и папок - exclude ВСЕГДА ставится перед тем что копируем |
| /bin/gzip -9 -c > | создать архив из pipe и вывести его в файл с "родным" расширением .tar.gz |
cp | что куда копируем в резервное хранилище |
`date '+\%Y-\%m-\%d'` | выводим в имя файла год-месяц-день |
find. -mtime +730 -not \( -name "body.html" -o name "*.dt" \) | Заодно чистим файлы изменённые старше 730 дней, кроме HTML и баз данных (не забываем пробелы) - delete ВСЕГДА ставится в конце |
В конце нажать Ctrl+X, подтвердить изменение нажав Y, потом Enter.
Как забэкапить ВСЮ MySQL базу в Ubuntu?
40 1 * * * /usr/bin/mysqldump -uXXXX -P3306 -h127.0.0.1 -p'YYYYY' --all-databases | /bin/gzip -9 -c > /media/hdd/backup/mysql_db_`date '+\%Y-\%m-\%d'`.gz
А тут надо "почесать репу".
Делаем аналогично предыдущему через CRON, но незабываем, что он очень капризен к нестандартному синтаксису!
Расшифруем параметры:
mysqldump -XXXX | что будем бэкапить |
-PXXXXX -h127.0.0.1 -p'XXXXXX' | порт, адрес, пароль от базы |
--all-databases | какие базы будем бэкапить |
Как забэкапить 1С 7.7 в Windows, вместе со всеми файлами?
@echo off
setlocal enableextensions enabledelayedexpansion
:: directory for backup in Petrozavodsk
set drS=G:\
set drD=D:\backup
set drL=D:\backup\logs
:: set time mark
set d=%DATE:~0,2%
set m=%DATE:~3,2%
set y=%DATE:~6,4%
set curdate=%y%.%m%.%d%
set h=%time:~0,2%
set m=%time:~3,2%
set s=%time:~6,2%
set curtime=%h%.%m%.%s%
:: exception file or folder
set incl=D:\backup\exclus.txt
:: name archive
set arh=ZZ-1C77-%date%.zip
:: max LZMA2
echo started at backup_%date%_%curtime% >> "%drL%\backup_log_%date%.txt"
"%ProgramFiles%\7-Zip\7z.exe" a -tzip -ssw -mx=5 -scsWIN "%drD%\%arh%" "%drS%" -x@"%incl%" -bso2 2>> "%drL%\backup_log_%date%.txt"
echo stoped at backup_%date%_%curtime% >> "%drL%\backup_log_%date%.txt"
:: upload Moscow base 1C to our server
"%ProgramFiles%\7-zip\7z.exe" x "%drD%\http\msk\YY-1C81-%date%.7z" -r -y -o"G:\YYYY\" 2>> "%drL%\backup_log_%date%.txt"
:: upload Sankt-Petersburg base 1C to our server
"%ProgramFiles%\7-zip\7z.exe" x "%drD%\http\spb\XX-1C77-%curdate%.7z" -r -y -o"G:\XXX\XXX\" 2>> "%drL%\backup_log_%date%.txt"
:: recursive delete old arhive & MMSQL files & files
forfiles -p "%drD%" -s -m *.zip -d -4 -c "cmd /c if /i @isdir equ false del /q /s @path"
forfiles -p "%drD%" -s -m *.bkp -d -4 -c "cmd /c if /i @isdir equ false del /q /s @path"
forfiles -p "%drD%" -s -m *.bak -d -4 -c "cmd /c if /i @isdir equ false del /q /s @path"
forfiles -p "%drD%" -s -m *.7z -d -4 -c "cmd /c if /i @isdir equ false del /q /s @path"
del /f /s /q "D:\1c_base\sale\*"
endlocal
exit
Ну это вообще МЕГА "палочка-выручалочка". Но не забывайте, что в "старых" версиях Windows, BAT выполняется в DOS в кодировке OEM 866! Для начала создайте файл в Notepad++ и смените в нём кодировку "Кирилица" - "OEM 866".
Ещё один момент - это использования файла списка исключений при бэкапе "exclus.txt". Каждая новая строка в нём - новое исключение.
G:\System Volume Information
G:\temp
*.LCK
Как забэкапить 1С 7.7 в SQL Express Windows?
Тут надо создать файл 1CMMSQLEbackup.sql вот с таким содежимым.
declare @path varchar(max)=N'D:\backup\backup_'+convert(varchar(max),getdate(),102)+'.bkp'
BACKUP DATABASE [ncm] TO DISK = @path WITH COPY_ONLY, NOFORMAT, NOINIT, NAME = N'ncm-backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
Расшифруем параметры:
declare @path | указываем директорию |
N | это декларируемое имя - величина произвольная, как хотите так и называйте |
'+convert(varchar(max),getdate(),102)+' | задаём дату файла от системного времени |
[ncm] | название нашей базы данных |
При желании, можете задать и проверку архива.
declare @backupSetId as int
declare @path varchar(max)=N'D:\backup\backup_'+convert(varchar(max),getdate(),102)+'.bkp'
select @backupSetId = position from msdb..backupset where database_name=N'ncm-backup' and backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=N'ncm-backup' )
if @backupSetId is null begin raiserror(N'Ошибка верификации. Сведения о резервном копировании для базы данных "ncm-backup" не найдены.', 16, 1) end
RESTORE VERIFYONLY FROM DISK = @path WITH FILE = @backupSetId, NOUNLOAD, NOREWIND
GO
Создаём в "Планировщике заданий" Виндовс задачу - указываем периодичность запуска и путь до самой программы.
"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE"
И указываем дополнительный аргумент.
-S .\sqlexpress -i "D:\backup\1CMMSQLEbackup.sql"
Расшифруем параметры:
...\SQLCMD.EXE | SQL в коммандной строке |
-S .\sqlexpress | тут имя Вашего экземпляра SQL сервера |
-i "D:\backup\1CMMSQLEbackup.sql" | путь до запускаемого файла |
Один момент! Если Вы переносите базу с сервера на сервер! То слетают привязки к пользователю! По непонятной причине данные привзки храняться в мастере донора, и нужно переназначать права в реципиенте КАЖДЫЙ РАЗ, когда восстанавливается база!
USE [ncm]
GO
EXEC [nw].dbo.sp_changedbowner @loginame = N'nw', @map = false
GO
Как уменьшить файл журнала .LDF SQL Express Windows?
Тут надо создать файл 1CMSSQLElogcleared.sql вот с таким содежимым.
USE [ncm]
GO
ALTER DATABASE [ncm] SET RECOVERY SIMPLE
GO
DBCC SHRINKFILE (N'ncm_log' , 0,)
ALTER DATABASE [ncm] SET RECOVERY FULL
GO
Расшифруем параметры:
SET RECOVERY SIMPLE | переводим базу в режим архивирования SIMPLE |
N'ncm_log' | это имя лог файла |
SET RECOVERY FULL | возвращаем базу в режим архивирования FULL |
[ncm] | название нашей базы данных |
Тут надо понимать, что РАБОЧАЯ база данных ВСЕГДА должна архивироваться в режиме FULL! А вот сервисные операции легче делать в режиме SIMPLE. Да, никто не спорит, что можно открыть SQL Server Management Studio (SSMS) и выполнить все манипуляции от туда. По сути, все скрипты выше и взяты напрямую из SSMS. Но не забываем, что у нас SQL Express и 90% автоматической работы с базами ему недоступны.
Как настроить SFTP в Windows 10?
Начнём с простого. FTPS - это FTP over SSL, его легко настроить в IIS, но толку с него 0.0%. Если мы хотим шифровать ВЕСЬ трафик, то нужен STPS - это SSH FTP, т.е. передача данных идёт в шифрованном туннеле. Для этого используем стандартный OpenSSH сервер перекочивавший в Win10.
Идём по пути "Пуск - Параметры - Приложения - Дополнительные параметры - Добавить компонент - Добавление дополнительного компонента - Сервер OpenSSH". Ждём окончания установки. И в "Службах Виндовс" ищем sshd OpenSSH SSH Server, его надо будет переключить в автоматический режим работы (лучше с задержкой старта) и запустить!
Запуск нужен для создания файлов в директории "C:\ProgramData\ssh\". А редактировать будем sshd_config. Ниже пункты которые должны быть или раскоментированны, или добавлены в файл:
PermitRootLogin no
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
AllowUsers you_sftuser
Subsystem sftp sftp-server.exe
Match User you_sftuser
AllowTcpForwarding no
ChrootDirectory C:\...\you_data
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
Расшифруем параметры:
you_sftuser | имя пользователя (имена или группы, тогда Group пишем) в Windows, для которого открываем доступ |
C:\...\you_data | это директория к которой мы даём доступ данному пользователю (это решит проблему с брадмауером блокирующим 22 порт, но незабудьте выдать на эту директорию права в самой ОС) |
PermitRootLogin | блочим доступ "суперу" |
...Keys... | ключи по умолчанию лежат в папке самого пользователя; если не хотите создавать свои ключи и сертификаты - НИЧЕГО НЕ ТРОГАЙТЕ! |
Теперь о подключении. Если у нас Windows, то в BAT файле пишем:
cd /d "D\backup\curl\bin\"
start /wait curl.exe -k sftp://XXX.XXX.XXX.XXX:1XX2/spb/ -u login:password -T "D\backup\sql.zip"
Не забываем, что curl, дожен быть с поддержкой SSL! Кроме этого, аргумент "-k" нужен Windows, чтобы обходить ошибочное понимание этого сертификата.
Если у нас Linux, то в Crontab пишем:
0 14 * * 6 lftp sftp://user:password@XXX.XXX.XXX.XXX:YYYY -e "put -c -O /ptz/ /var/backmedia/ptz_mail-chat_`date '+\%Y-\%m-\%d'`.tar.gz; exit"
Не забываем, что lftp, дожен быть с ключами SSL! Для этого, под root, сначала авторизируемся через sftp, и на вопрос о сохранении ключей пишем yes. При устаревании ключа или замене сервера удаляем файл по пути root/.ssh/known_host, или ключ старого сервера в этом файле!
sftp -oPort=1XXX2 login@XXX.XXX.XXX.XXX
Как использовать Robocopy в Windows 10 для копирования файла?
Robocopy - это программа для копирования файлов и папок, в том числе по сети и с атрибутами. Расширенный аналог copy и xcopy!
robocopy C:\Users\samba\Favorites\backup\ \\XXX.XXX.XXX.XXX\backup\ ваш_файл.7z /z /r:3 /mt
Расшифруем параметры:
/z | режим перезапуска |
/r:3 | кол-во попыток (по умолчанию один миллион!), обычно идёт с параметром /w - ждать сколько-то секунд (по умолчанию 30сек.) |
/mt | режим многопоточности (по умолчанию выставит 8 потоков), эксперименты показали, что ставить больше, чем по умолчанию, есть смысл при локальном копировании множества файлов на многоядерном CPU |
С Robocopy есть 2 проблемы. Во-первых, как видите, он не допускает ЭКРАНИРОВАНИЯ пути! Ну и параметр /z - абсолютно НИВЕЛИРУЕТ многопоточность; проблема в том, что при передаче по сети он проверяет каждый заголовок пакета, и файл в 3Гб с ним копируется 15 минут, а без него 1,5 минуты.
Как сверить файл при копировании на удалённый сервер, через hach file?
Тут задачу разбиваем на две части. Сначала получаем сам хэш, через встроенную в Windows утилиту.
certutil -hashfile "%drD%\1C77.bkp" MD5 | findstr ^[0-9a-f]$ >> "%drD%\1C77-sql-hash-ptz.txt"
Расшифруем параметры:
MD5 | режим хэширования, вплоть до SHA 256 |
| findstr ^[0-9a-f]$ >> | "поток выводим" в текстовой файл |
Теперь вторая проблема. Хэш в зависимости от центрального процессора, типа операционной системы, программы посчёта. Может быть разным, и записывается в текстовый файл то же, как угодно. Поэтому нужно искать железо и ПО - одного рода. Остальное, решаем кодом сравнения хэша файла созданного на удалённой машине, и хэша с файла полученного на текущей машине.
FC /C /W /L "%drD%\1C77-sql-hash-ptz.txt" "%drD%\1C77-sql-hash-spb.txt"
if %errorlevel%==0 (goto step1) else (goto erase-spb-file)
:erase-spb-file
del /f /s /q "%drD%\1C77.bkp
:step1
Расшифруем параметры:
FC /C /W /L | утилита сравнения: без регистра, без пробелов и табуляции, в формате ASCII |
%errorlevel%==0 | уровень ошибок, их всего 4, нас интересует только 0 |
goto step1 и goto erase-spb-file | если хэш верен - идём дальше, если нет, то стираем бракованный файл |
Как записывать разговоры и идентифицировать звонящего на MyPBX SOHO в связке с 1С
Вколачиваем код ниже в файл mypbx\persistent\var\lib\asterisk\db\custom-cfg\extensions_custom.conf (папка виртуальная, не пугаемся) соответственно Вашим транкам. Не забываем чистить папку souds-monitor вручную! Этот код сам этого не делает, и кода память станции закончится - она завистнет наглухо!!!
[macro-trunkdial-failover-0.3]
exten = s,1,NOOP(do call out)
exten = s,2,GotoIf(${DB_EXISTS(oblacklist/${ARG3})}?Blacklist-Handle,s,1)
exten = s,3,Gotoif($[${LEN(${FromSystemAlert})}>0]?6:4)})
exten = s,4,Gotoif($[${LEN(${ARG$[${ARG1}+4]})}>0]?5:6)
exten = s,5,Goto(s,6)
exten = s,6,Set(TCOUNT=4)
exten = s,n,Set(CDR(userfield)=Outbound)
exten = s,n,Set(OldCallerID=${IF($[${LEN(${PINUSER_CONTEXT})} > 0]?${PINUSER_CONTEXT:13}:${MACRO_CONTEXT:13})})
exten = s,n,Set(TOUCH_MONITOR=${OldCallerID}-${ARG3})
exten = s,n,NOOP(${DOD_${ARG${TCOUNT}}_${OldCallerID}})
exten = s,n(callnamed),Set(fname=out_${STRFTIME(${EPOCH},,%Y.%m.%d-%H.%M.%S)}-${CALLERID(number)}-${ARG3})
exten = s,n(callrecord),MixMonitor(/persistent/var/lib/asterisk/sounds/monitor/${fname}.wav,b)
exten = s,n,Set(TIMEOUT(absolute)=${IF($[${LEN(${ABSOLUTE_TIMEOUT_${OldCallerID}})} > 0]?${ABSOLUTE_TIMEOUT_${OldCallerID}}:${ABSOLUTE_TIMEOUT})})
exten = s,n,Set(DLSTAT=UNKNOW})
exten = s,n,SetCktCustom(sendrpid,no,no)
exten = s,n,Gotoif(${ARG1}>0?1-dial,1)
exten = 1-dial,1,Gotoif($[$[${TCOUNT}-3]>${ARG1}]?nextrouter,1)
exten = 1-dial,2,Gotoif($[${LEN(${DOD_${ARG${TCOUNT}}_${OldCallerID}})} > 2]?setdod,1:1-dial,3)
exten = 1-dial,3,Set(CALLERID(name)=${IF($[${LEN(${CID_${ARG${TCOUNT}}})} > 2]?${CID_${ARG${TCOUNT}}}:${CALLERID(name)})})
exten = 1-dial,4,Set(CALLERID(num)=${IF($[${LEN(${CID_${ARG${TCOUNT}}})} > 2]?${CID_${ARG${TCOUNT}}}:${CALLERID(num)})})
exten = 1-dial,5,Set(_SIPSRTP=${SIPPEER(${ARG${TCOUNT}},srtpcapable)})
exten = 1-dial,6,Set(OUTDIALOPT=${IF($[${LEN(${GSM_${ARG${TCOUNT}}})} > 0]?tTkKWwXxr:${DIALOPTIONS})})
exten = 1-dial,7,NOOP(null for std)
exten = 1-dial,8,Gotoif($[${LEN(${FromSystemAlert})}>0]?sys-dial,1)})
exten = 1-dial,9,Dial(${${ARG${TCOUNT}}}/${ARG2}${PREFIX_${ARG${TCOUNT}}}${ARG3},,${OUTDIALOPT})
exten = 1-dial,n,Goto(1-${DIALSTATUS},1)
exten = sys-dial,1,Macro(sysdial,${${ARG${TCOUNT}}}/${ARG2}${PREFIX_${ARG${TCOUNT}}}${ARG3},,${OUTDIALOPT})
exten = setdod,1,Set(CALLERID(name)=${DOD_${ARG${TCOUNT}}_${OldCallerID}})
exten = setdod,2,Set(CALLERID(num)=${DOD_${ARG${TCOUNT}}_${OldCallerID}})
exten = setdod,3,Goto(1-dial,5)
exten = 1-BUSY,1,Set(DLSTAT=9-${DIALSTATUS})
exten = 1-BUSY,2,Goto(2-dial,1)
exten = 1-CHANUNAVAIL,1,Set(DLSTAT=9-${DIALSTATUS})
exten = 1-CHANUNAVAIL,2,Goto(2-dial,1))
exten = 1-CONGESTION,1,Set(DLSTAT=9-${DIALSTATUS})
exten = 1-CONGESTION,2,Goto(2-dial,1)
exten = 2-dial,1,Set(TCOUNT=$[${TCOUNT}+1])
exten = 2-dial,2,Goto(1-dial,1)
exten = 1-out,1,playback(all-busy-now-try-call-later)
exten = 1-out,2,Hangup()
exten = 9-BUSY,1,playback(all-busy-now-try-call-later)
exten = 9-BUSY,2,Hangup()
exten = 9-CHANUNAVAIL,1,playback(all-busy-now-try-call-later)
exten = 9-CHANUNAVAIL,2,Hangup()
exten = 9-CONGESTION,1,playback(all-busy-now-try-call-later)
exten = 9-CONGESTION,2,Hangup()
exten = nextrouter,1,GotoIf($[${LEN(${NEXTROUTER})} > 0]?${NEXTROUTER},${ORGINEXTEN},1:${DLSTAT},1)
exten = h,1,NOOP(no thing to do)
[macro-incoming_pstnin]
exten = s,1,Set(CDR(userfield)=Inbound)
exten = s,n,GotoIf(${DB_EXISTS(blacklist/${CALLERID(num)})}?Blacklist-Handle,s,1)
exten = s,n,FindForMobile(${CALLERID(num)})
exten = s,n,GotoIf($[${LEN(${MobileToExten})}>1]?mobile-exten-match,${MobileToExten},1)
exten = s,n,Set(TRUNKDID=${IF($[${ARG2}=s]?${CALLERID(name)}:${ARG2})})
exten = s,n,Set(CALLERID(name)=PTZ)
exten = s,n(callnamed),Set(fname=in_${STRFTIME(${EPOCH},,%Y.%m.%d-%H.%M.%S)}-${CALLERID(number)}-${ARG2})
exten = s,n(callrecforwarding),Set(AUDIOHOOK_INHERIT(MixMonitor)=yes)
exten = s,n(callrecord),MixMonitor(/persistent/var/lib/asterisk/sounds/monitor/${fname}.wav,b)
Если нужны пояснения по каждым аргументам, то можно почитать старую книжку Asterisk: The Future of Telephony by O'Reilly
Yeastar уже не выпускает такие станции, но такой код может ещё помочь в старших версиях. В нижнем сигменте теперь продают S20, там уже всё из коробки. Но в последних версиях, поменяна философия настроек! Особенно "больно" пришлось межстанционым звонкам. Теперь для входящего звонка нужно в нашей АТС создать "Входящий маршрут", в нём указать "Шаблон DID" номера нашей станции, указать линии группы, и в "Направление" указать номера нашей станции, на которые возможен вызов.