"Не клопы ли вас кусают?"
вторник, 31 января 2023 г.
понедельник, 30 января 2023 г.
суббота, 28 января 2023 г.
пятница, 27 января 2023 г.
CMD Script Добавить правила файервола по маске 1cv*.exe
Говорят, если запретить 1С выход в интернет, то она работает быстрее. Сервисами чел не пользуется, так что решил на нем потренироваться и описал такой скрпит:
@echo off
set Prg="%systemdrive%\progra*"
SETLOCAL EnableDelayedExpansion
FOR /D %%i in ("!Prg!") do (
FOR /D %%j in ("%%i\1cv8\8*") do (
echo %%j
set pathProg=%%j\bin
set ver=!pathProg:*1cv8\=!
FOR /F "tokens=*" %%k in ('dir /b "!pathProg!\1cv*.exe"') do (
echo. %%k
set nameEXE=!pathProg!\%%k
set nameFW="Block1C_%%k_!ver!"
netsh advfirewall firewall show rule name=!nameFW! >null && set RuleExist=1 || set RuleExist=0
if !RuleExist! EQU 0 (
netsh advfirewall firewall add rule name="!nameFW!" dir=out program="!nameEXE!" profile=any action=block
) else (
echo. Rule !nameFW! are exist
)
)
echo.
)
echo.
)
SETLOCAL DisableDelayedExpansion
Что он делает - проверяет на наличие (по имени сформированному им самим) и добавляет, при отсутствии, правила блокировки для \Progra*\1cv8\8*\bin\1cv*.exe, т.е. неважно какая платформа, какая разрядность или какой клиент.
Вот так просто получаем список правил:
Как видим, задача решена простым перебором во вложенных циклах. Данный скрипт оставляю на память:
- Использование EnableDelayedExpansion для передачи значения перебора в/за цикл
- Программное добавление правил брандмауера Windows
- Костыльная передача результата команды в переменную (конструкция && ||)
- Циклы (перебор директории и результата программы)
- Cmd replace (!pathProg:*1cv8\=!) с подстановкой значений
1СОшибка УТ данные инн и кпп уже указаны для другого контрагента ответственный -
Ошибка обычная, но в моем случае она превратилась в маленький ад, потому как нигде этого контрагента нет. А точнее - его нет в видимых разделах, но на него есть невидимые ссылки в различных объектах. А консоль запросов показывает, но при попытке перейти по ссылке, открывается форма создания нового контрагента. ТиС не помог.
В итоге проблема была решена при помощи простенькой самописной обработки, которая просто нашла по ИНН контрагента и пометила его на удаление. Дальше обнаруживались и удалялись связи с другими объектами при попытке удаления помеченных.
четверг, 26 января 2023 г.
1СЗаготовка СБИС сопоставление номенклатуры по наименованию
Для УТ очень надо. Форма ФормаПросмотраДокумента. Добавить на форму Команду и связать с процедурой. Также добавить Булево Отладка или удалить кусок кода
//arshanskiyav+
&НаСервере
Функция НайтиНоменклатуруПоНаименованию(Наименование)
Номенклатура=Справочники.Номенклатура.НайтиПоНаименованию(Наименование,Истина);
Возврат(Новый Структура("Номенклатура,ЕдИзм",Номенклатура,Номенклатура.ЕдиницаИзмерения));
КонецФункции
&НаСервере
Функция НайтиЕдИзмПоНаименованию(Наименование)
Возврат(Справочники.УпаковкиЕдиницыИзмерения.НайтиПоНаименованию(Наименование,Истина));
КонецФункции
&НаКлиенте
Процедура СопоставитьПоНаименованию(Команда)
//СопоставитьПоНаименованиюНаСервере();
Для Каждого СтрокаТЧ Из ТабличнаяЧасть Цикл
Элементы.ТабличнаяЧасть.ТекущаяСтрока=СтрокаТЧ.ПолучитьИдентификатор();
Если НЕ ЗначениеЗаполнено(СтрокаТЧ.Номенклатура) Тогда
ТабЧасть = сбисЭлементФормы(ЭтаФорма,"ТабличнаяЧасть");
СбисСтрокаТабличнаяЧастьДоИзменения(МестныйКэш, ТабЧасть);
НайденнаяНом=НайтиНоменклатуруПоНаименованию(СтрокаТЧ.Название);
СтрокаТЧ.Номенклатура=НайденнаяНом.Номенклатура;
Если ЗначениеЗаполнено(СтрокаТЧ.Номенклатура) Тогда
СтрокаТЧ.ЕдИзмОрг=НайденнаяНом.ЕдИзм;
КонецЕсли;
Если НЕ ЗначениеЗаполнено(СтрокаТЧ.ЕдИзмОрг) и ЗначениеЗаполнено(СтрокаТЧ.ЕдИзм) Тогда
СтрокаТЧ.ЕдИзмОрг=НайтиЕдИзмПоНаименованию(СтрокаТЧ.ЕдИзм);
КонецЕсли;
Если Отладка Тогда
Сообщить(СтрокаТЧ.Название);
Сообщить(НайденнаяНом);
КонецЕсли;
ТабЧасть = сбисЭлементФормы(ЭтаФорма,"ТабличнаяЧасть");
СбисСтрокаТабличнаяЧастьПриИзменении(МестныйКэш, ТабЧасть);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
//arshanskiyav-
Продуктивностью не отличается, т.к. сбисовские обработчики регистрируют каждое изменение в dbf, но это намного быстрее, нежели вручную!
вторник, 24 января 2023 г.
Восстановление ACL
Переносил 4Тб данных при помощи rsync и не учел сложную структуру доступа, переносить по новой с правильными ключами - ждать еще 8 часов. Поэтому я выгрузил рекурсивно ACL:
root@server:~$ getfacl -R /archive_mount/archive > /home/user/archive2023.acl
и хотел загрузить вот так:
user@server:~$ sudo setfacl -R --set-file=archive2023.acl /archive/archive/
но, эта фигня зависла на всю ночь и никакого результата не дала, в итоге я нашел как именно восстановить ACL:
user@server:~$ sudo setfacl --restore=/home/user/archive2023.acl | tee /home/user/report_acl.log
Для проверки я повторно выгрузил ACL после восстановления, т.к. восстановление заняло не больше пяти минут, а выгрузка из оригинала длилась полчаса. Собственно выгрузка за те же пять минут подсказала, что проблема скорее в дисковой подсистеме источника, а не в частичном восстановлении ACL
root@server:/home/user# getfacl -R /archive_mount/archive > /home/user/archive2023_2.acl
root@server:/home/user# tar -cf archive2023.tar archive2023*
root@server:/home/user# gzip archive2023.tar
root@arhive:/home/user# ll /home/user/
root@arhive:/home/user# ll archive2023_2*
-rw-rw-r-- 1 user user 392713145 Jan 24 10:58 archive2023_2.acl
-rw-r--r-- 1 user user 384913154 Jan 23 23:21 archive2023.acl
-rw-r--r-- 1 root root 29577829 Jan 24 11:01 archive2023.tar.gz
Можно было бы сравнить эти два файла прямо на сервере (cmp), но как видим из вывода выше - новый файл больше старого, т.е. они уже разные, поэтому я решил сравнить их при помощи Notepad++
Сравнивать не имеет смысла, т.к. при выгрузке использовались ID групп и пользователей, т.к. сервер, на котором проводилась операция, вне домена и не имеет этих пользователей, а вот новый файл был уже с буквенными обозначениями групп и имен пользователей.
понедельник, 23 января 2023 г.
Crontab использует временную зону отличную от системной
Собрал сервер, поправил временную зону, добавил задания в cron, а они не выполняются с запозданием в 3 часа, т.е. во временной зоне +6. А для sa-stats.pl это критично, т.к. в кроне задание висит в 23.59, а выполняется оно в 02.59 О_О
Не помню, перезагружал я сервер или нет, но вот на что стоит обратить внимание:
user@server:~$ grep -i cron /var/log/syslog
Jan 23 12:48:14 postfix crontab[6204]: (user) BEGIN EDIT (user)
Jan 23 12:49:01 postfix crontab[6204]: (user) REPLACE (user)
Jan 23 12:49:01 postfix crontab[6204]: (user) END EDIT (user)
Jan 23 12:49:01 postfix cron[788]: (user) RELOAD (crontabs/user)
Jan 23 12:49:06 postfix crontab[6261]: (user) LIST (user)
Jan 23 12:49:14 postfix crontab[6262]: (user) BEGIN EDIT (user)
Jan 23 12:49:24 postfix crontab[6262]: (user) REPLACE (user)
user@server:~$ date
Mon Jan 23 17:49:40 MSK 2023
Добавление TZ=Europe/Moscow первой строчкой в cron с перезапуском службы не помогло
user@server:~$ sudo /etc/init.d/cron restart
А вот перезапуск syslog проблему решил. Проконтролировать можно просто запросив вывод задач и снова глянуть в лог:
user@postfix2:~# crontab -l | grep -v "#"
0 12 * * * /usr/bin/certbot renew --quiet
59 23 * * * /opt/postfix-report/postfix-report.sh
30 23 * * * /opt/postfix-backup/postfix-backup.sh
user@postfix2:~# grep -i cron /var/log/syslog | tail -n 2
Jan 23 13:17:01 postfix2 CRON[11501]: (user) CMD ( cd / && run-parts --report /etc/cron.hourly)
Jan 23 13:57:06 postfix2 crontab[12561]: (user) LIST (user)
user@postfix2:~# date
Mon Jan 23 16:57:18 MSK 2023
user@postfix2:~# sudo service cron restart
user@postfix2:~# crontab -l | grep -v "#"
0 12 * * * /usr/bin/certbot renew --quiet
59 23 * * * /opt/postfix-report/postfix-report.sh
30 23 * * * /opt/postfix-backup/postfix-backup.sh
user@postfix2:~# grep -i cron /var/log/syslog | tail -n 4
Jan 23 13:57:06 postfix2 crontab[12561]: (user) LIST (user)
Jan 23 13:57:28 postfix2 cron[12579]: (CRON) INFO (pidfile fd = 3)
Jan 23 13:57:28 postfix2 cron[12579]: (CRON) INFO (Skipping @reboot jobs -- not system startup)
Jan 23 13:57:33 postfix2 crontab[12601]: (user) LIST (user)
user@postfix2:~# sudo service syslog restart
user@postfix2:~# crontab -l | grep -v "#"
0 12 * * * /usr/bin/certbot renew --quiet
59 23 * * * /opt/postfix-report/postfix-report.sh
30 23 * * * /opt/postfix-backup/postfix-backup.sh
user@postfix2:~# grep -i cron /var/log/syslog | tail -n 6
Jan 23 13:17:01 postfix2 CRON[11501]: (user) CMD ( cd / && run-parts --report /etc/cron.hourly)
Jan 23 13:57:06 postfix2 crontab[12561]: (user) LIST (user)
Jan 23 13:57:28 postfix2 cron[12579]: (CRON) INFO (pidfile fd = 3)
Jan 23 13:57:28 postfix2 cron[12579]: (CRON) INFO (Skipping @reboot jobs -- not system startup)
Jan 23 13:57:33 postfix2 crontab[12601]: (user) LIST (user)
Jan 23 16:58:04 postfix2 crontab[12652]: (user) LIST (user)
user@postfix2:~# date
Mon Jan 23 16:58:12 MSK 2023
воскресенье, 22 января 2023 г.
sa-stats.pl Указать интервал времени
sa-stats.pl пример сутки:
user@server:~$ ./sa-stats.pl -s `date -d '-1 day'` -e `date` > file.txt
sa-stats.pl пример от текущего до полуночи в прошлое:
user@server:~$ ./sa-stats.pl -s 'midnight' -e 'now' > file.txt
Картины: Ярек Пучель
Вызывает ощущения схожие с ощущениями от пришедшего когда-то давно в голову сюжета картины
Ubuntu Вывод на экран и в разные файлы
Задача банальна - перенести 4Тб с диска на одном сервере, на диск на другом. Вариантов решения куча, и один из них - rsync. Проблема только в одном - видеть что процесс идет, а если я вижу, то я могу не увидеть чего то важного, например промелькнувшей ошибки. Поэтому надо осуществить вывод и на экран и в файл, в этом мне может помочь tee, но листать файл на несколько миллионов строк в поисках ошибок - такое себе, надо как-то вывести ошибки в отдельный файл, а вот и готовая строка:
user@server:~$ sudo rsync -avh --ignore-errors --delete root@vsv02:/archive_mount/* /archive/ > >(tee -a /home/user/rsync.log) 2> >(tee -a /home/user/rsync-error.log >&2)
Собственно у меня, после исправления ошибок на уровне доступа к файлам, ошибок 0
суббота, 21 января 2023 г.
вторник, 17 января 2023 г.
воскресенье, 15 января 2023 г.
Linux mount loop img read-only (ro)
Задался таким вопросом, потому как случайно скопировал перезаписью не в ту сторону, благо это была копия
user@postfix:~$ sudo mount -o ro,loop postfix.img /OLD_POSTFIX/
Ошибку "mount: /OLD_POSTFIX: cannot mount /dev/loop0 read-only. "
user@postfix:~$ sudo mount -o ro,norecovery,loop postfix.img /OLD_POSTFIX/
Если образ содержить несколько разделов, то нужно указать смещение
user@postfix:~$ sudo mount -o ro,norecovery,loop,offset=1048576 postfix.img /OLD_POSTFIX/
Также можно указать тип ФС
user@postfix:~$ sudo mount -o ro,norecovery,loop,offset=1048576 -t ext4 postfix.img /OLD_POSTFIX/
суббота, 14 января 2023 г.
Xen get version
Для Ubuntu (не забываем про xl/xm)
user@xen2:~$ sudo xl info | grep -i ver
version : #154-Ubuntu SMP Thu Jan 5 17:03:22 UTC 2023
xen_version : 4.11.4-pre
А вот для RH
more /etc/redhat-release
пятница, 13 января 2023 г.
1СОшибка В сеансе существуют изменяющие расширения
Как обычно, раз в квартал, обновлял РИБ, при том две. Конфигурации 1-в-1, расширение одно и оно идентично. Одна база обновилась ну всех узлах успешно, а вот подчиненный узел второй базы начал выеживаться, постоянно выдавая ошибки загрузки данных/применения новой конфигурации. Ничего не помогало, в итоге решил выгрузить свежий образ и:
Не удалось создать начальный образ по причине: В текущем сеансе существуют изменяющие данные расширения конфигурации, неиспользуемые в распределенной информационной базе.
Это было удивительно. Ладно, гугел указывает что ошибка аж с 2020 года существует, поставил самую свежую платформу, но и это не помогло. В настройках расширения галка на РИБ стоит. На одном из форумов предложили снять с поддержки, но меня такой вариант не устраивает. Удалять расширение тоже не вариант, так как в моих реквизитах уже есть записи.
Отключил расширение и создал начальный образ БД. Развернул на другом ПК и выяснил что расширение перенесено не было. Загрузил его вручную. В оригинальной базе включил расширение и попробовал синхронизировать и тут возникла не предвиденная ситуация - выгрузка зациклилась О_О
А проблема оказалась в том, что ранее зарегистрированные изменения имели номер сообщения много больший, нежели текущие номера. Решается двумя способами:
- снимаем регистрацию (ведь они уже выгружены)
- изменяем номер исходящего сообщения на номер из регистрации, проводим обмен и ок
среда, 11 января 2023 г.
вторник, 10 января 2023 г.
CMD script мониторинг DNS записи
Простенький однострочный скрипт для мониторинга обновления dns записи. Для мониторинга SOA записи не очень подходит, т.к. на днс яндекса записи некоторое время бесятся, а вот верификация - да
FOR /L %N IN () DO nslookup -type=soa domen.ru 77.88.8.8 2> NULL |findstr /i "dns-hosting.yandex.ru" && (echo OK && ping -t 127.0.0.1 ) || (echo not && ping -n 10 127.0.0.1 > NULL && cls)
С человеческим таймаутом
FOR /L %N IN () DO nslookup -type=soa domen.ru 77.88.8.8 2> NULL |findstr /i "dns-hosting.yandex.ru" && (echo OK && ping -t 127.0.0.1 ) || (echo not && timeout 10 && cls)
Пока не появится фраза "dns-hosting.yandex.ru" в выдаче команды nslookup будет выдаваться not, как только появится - пойдет непрекращающийся пинг. Открывает в пол отдельного монитора и смотрим крайем глаза. Пример цикла пока истина
воскресенье, 8 января 2023 г.
суббота, 7 января 2023 г.
пятница, 6 января 2023 г.
Excel VBA Найти имя группировки
Допустим есть сгруппированная таблица, где в столбце С уникальные идентификаторы (артикулы) и нужно получить имя группировки, вот функция это и делает. Применение: =FindGroupName(ячейка_шаблон;диапазон)
Excel VBA Найти заголовки группировок и вывести с родителями
Заметка по VBA В excel. Макрос находит ячейки в диапазоне A7:A20000 на первом листе (по индексу) длиной более 3 и выводит списком. К ним прибавляет также уровень группировки, номер строки и номер строки родителя, пригодится при построении иерархий
Excel VBA Получить уровень группировки
Функция возвращает уровень группировки ячейки, применение =GetGroupLevel(A1)
Function GetGroupLevel(RCell As Range)
GetGroupLevel = Rows(RCell.Cells(1, 1).Row).OutlineLevel
End Function
А вот этот вариант работает только для текущего листа
Этот вариант работает с любого листа
Function GetGroupLevel(RCell As Range)
GetGroupLevel = Worksheets(RCell.Parent.Name).Rows(RCell.Row).OutlineLevel
End Function
четверг, 5 января 2023 г.
среда, 4 января 2023 г.
1СЗаготовка ADODB.Connection OLEDB UTF-8
Загружал прайс сварога и получил кривую кодировку. Посмотрел какая кодировка и выснилось, что стоит UTF-8. Сначала решений не было, но вернувшись к вопросу пару месяцев спустя нашел случайно ответ
Функция ПрочитатьCSVвТЗ_ADO(ИмяФайла, Разделитель=";", ЗаголовкиИзПервойСтроки = Ложь)
ТаблицаРезультат = Новый ТаблицаЗначений;
Файл = Новый Файл(ИмяФайла);
Connection=Новый COMОбъект("ADODB.Connection");
Connection.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+Файл.Путь+";Extended Properties=""text;HDR=No;IMEX=1;FMT=Delimited;CharacterSet=65001""");
Схема = СтрШаблон("[%1]
|ColNameHeader=%2
|Format=Delimited(%3)
|DecimalSymbol=.", Файл.Имя, Формат(ЗаголовкиИзПервойСтроки, "БЛ=False; БИ=True"), Разделитель);
ФайлСхемы = Новый ТекстовыйДокумент;
ФайлСхемы.УстановитьТекст(Схема);
ФайлСхемы.Записать(Файл.Путь + "Schema.ini", "CESU-8"); // UTF-8 без BOM
RecordSet=Новый COMОбъект("ADODB.Recordset");
RecordSet.ActiveConnection = Connection;
ЗапросЛист="select * from "+Файл.Имя;
RecordSet.Open(ЗапросЛист, Connection);
//Здесь читаем файл в ТаблицаРезультат
RecordSet.Close();
Connection.Close();
Возврат(ТаблицаРезультат);
КонецФункции
Собственно кодировка указывается в настройке подключения
вторник, 3 января 2023 г.
Bash script WOL для списка
user@server:~$ head -n 2 /opt/scripts/backup/compoff.txt
#Номер;Имя ПК;имя пользователя;айпи (не обязательно);мак адрес;выключать или нет
1;AIVANOV;aivanov;10.21.2.140;D8:BB:C1:5B:6E:5D;1
Собственно сам скрипт обходит список, шлет WOL, ожидает и проверяет по пингу включился ли ПК, если да, то помещается в массив для обработки, иначе репорт на почту. Хорошо работает вот уже лет 7. Но иногда есть потребность во включении определенного ПК из этого списка, и дабы автоматизировать поиск, отправку WOL и проверку, написал скрипт. Также нужно учесть то, что компьютеры находятся в разных сегментах сети, поэтому посыл будет с двух серверов.
Bash script обход аргументов скрипта/функции
Ранее такой фокус провернул на Mikrotik, там проблема была в том, что неизвестно количество входящих аргументов. В bash есть специальная переменная $#, которая содержит количество параметров. Кстати, правильной проверкой будет именно:
if [ $# -ne 0 ]
then
echo "Run script"
else
exit
fi
а не:
# -n "$1" - вернет истина, если длина более 0
if [ -n "$1" ]
then
echo "Run script"
else
exit
fi
Почему?, потому что второй вариант не учитывает вероятность наличия количества аргументов менее или более необходимого, а вот первый вариант это может учесть. Что позволит не проверять наличие каждого аргумента
if [ $# -gt 2 ]
then
echo "Run script"
else
echo "less than 2 arguments"
exit
fi
Собственно знание количества аргументов позволяет описать обход так:
if [ $# -ne 0 ]
then
echo "Set is $# arg"
for (( a = 1; a <= $#; a++ ))
arg=$(eval echo \$$a)
echo $arg
done
else
exit
fi
Пример выше обработает только 9 параметров, для обработки большего количества необходимо номер поместить в фигурные скобки
if [ $# -ne 0 ]
then
echo "Set is $# arg"
for (( a = 1; a <= $#; a++ ))
arg=$(eval echo \${$a})
echo $arg
done
else
exit
fi
Такую конструкцию можно использовать например в скрипте с поиском шаблона/шаблонов
Также не стоит забывать о наличии $* - все аргументы строкой и $@ - все аргументы "массивом"
if [ $# -ne 0 ]
then
echo "Set is $# arg"
count=1
for param in "$@"
do
echo "\$@ Parameter #$count = $param"
count=$(( $count + 1 ))
done
else
exit
fi
понедельник, 2 января 2023 г.
1СОшибка РеквизитФормыВЗначение("Объект") Недопустимое значение параметра
Казалось бы, банальная операция вызов процедуры/функции модуля объекта из модуля формы, но тут я был сбит, как бейсбольной битой, этой ошибкой и засомневался во всем что накопил в голове своей за прошедшие 10 лет периодической возни с 1С.
Поясню, есть внешняя печатная форма, в связи хотелкой прогресс бара вынужден перенести часть функций в модуль объекта, а дальше извращаться с их вызовом через:
ОбработкаОбъект=РеквизитФормыВЗначение("Объект");
ОбарботкаОбъект.МояПроцедура(ПараметрыПроцедуры);
Но тут я получаю ошибку:
{Обработка.ЗагрузкаПрайсЛиста.Форма.Форма1.Форма(317)}: Ошибка при вызове метода контекста (РеквизитФормыВЗначение)
ОбарботкаОбъект=РеквизитФормыВЗначение("Объект");
по причине:
Недопустимое значение параметра (параметр номер '1')
Недопустимое значение параметра (параметр номер '1')
И думаю что за дичь такая, еще удивляюсь почему в подсказке не было варианта "Объект", в итоге это и был ответ, у объекта на форме не определен был тип: