26 декабря 2022 29 декабря 2022 Всякое
Тест выполняется на разных материнских платах, с разной оперативной памятью и разными процессорами
26 декабря 2022 29 декабря 2022 Всякое
Тест выполняется на разных материнских платах, с разной оперативной памятью и разными процессорами
22 декабря 2022 26 декабря 2022 Python
Два способа цеплять обработчики событий startup и shutdown
@application.on_event("startup")
def create_start_app_handler():
print("start_app")
@application.on_event("shutdown")
def create_stop_app_handler():
print("stop_app")
application.add_event_handler(
"startup",
create_start_app_handler,
)
application.add_event_handler(
"shutdown",
create_stop_app_handler,
)
В данном виде указанные события будут обработаны по 2 раза
22 декабря 2022 27 декабря 2022 Linux
Управление dd образами производится в 4 операции
sudo losetup --partscan --find --read-only --show file.dd
# создаёт виртуальный Диск и отображает имя файла виртуального диска, в моём случае /dev/loop15
# список разделов можно посмотреть вот так sudo fdisk -l /dev/loop15
sudo mount /dev/loop15p2 /mnt
# монтирует второй раздел виртуальный диска в директорую /mnt/
# тут какие то работы с данными образами
sudo umount /mnt
# отмонтировать
sudo losetup -d /dev/loop15
# удалить виртуальный диск
16 декабря 2022 Python
В инфраструктуре Flask есть фреймворк flask_restful для реализации Rest API и последние несколько лет там начались проблемы с развитием, в результате чего появилось несколько форков. В частности я решил попробовать построить один проект на flask_restx.
В этой заметке я буду описывать, что из этого вышло и насколько это решение хорошо для использования
С помощью RESTX я реализовал следующие API
Выглядит хорошо и лаконично, вот например API получения списка публикаций пользователя
Но если смотреть в целом, то приходится для каждой модели базы писать модель сериализации
А ещё больше напрягло то, что фреймворк просто не предлагает ни какого способа пагинации. То-есть, API легко отдаёт всю выборку, а для того чтобы отдать сред выборки в стиле Django, необходимо руками высчитать total и сломать весь красивый механизм marshal_with
Так же, нет интеграции со sqlalchemy, конечно можно найти способ
но как по мне конструкция ModelX.query.filter(**kwargs).all() выглядит так себе
24 ноября 2022 Всякое
Попал в руки это замечательный контроллер и ради профилактики решил заменить. Новую предлагают купить за 23 тысячи.
Но если разобраться то оказывается, там стоит обычный аккумулятор за 600 рублей от старенького Sony Ericson
https://aliexpress.ru/item/32738463692.html
https://ru.dhgate.com/product/4pcs-original-for-sony-us503759-a8h-battery/397887722.html
05 ноября 2022 25 января 2023 Linux Linux OpenVPN Docker
Если нужно быстро запустить VPN на каком то удалённом сервере то проще всего воспользоваться готовым решением https://github.com/kylemanna/docker-openvpn
Затем делаете сколько нужно VPN ключей с помощью этой команды
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full USERNAME nopass
выгружаете в хостовую машину
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_getclient USERNAME > USERNAME.ovpn
И всё, можно пользоваться
Чтобы в дальнейшем сохранилась возможность генерировать новые ключи необходимо восстанавливать значение export OVPN_DATA="ovpn-data-example" и использовать passkey использованный для генерации корневого сертификата
Посмотреть статус OpenVPN сервера можно вот так
docker exec -it funny_varahamihira ovpn_status
Если необходимо запустить VPN клиента на постоянной основе, например на ubuntu сервере, то необходимо сгенерировать ключ для этого сервера, скопировать его в директорию /etc/openvpn/client.conf
и разрешить автозапуск
stemctl enable openvpn@client
При сборке на свежей системе может возникнуть ошибка
./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using --without-http_rewrite_module
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with Angie by using --with-pcre=<path> option.
Эта ошибка проявляется если сборщик не может найти библиотку перловых регулярных выражений, решается проблема легко
sudo apt install libpcre3-dev
for t in $(echo \\dt | psql $BASE |grep public |awk '{print $3}'); do
echo "SELECT setval('$t"_id_seq"', (select max(id)+1 from $t), true);";
done | psql $BASE
Суть проблемы в том, что при репиликации таблицы значение последовательности таблицы автоматически не меняется, по этому после отключения репликации значение last_insert_id будет отставать от реального количество записей в таблице
31 августа 2022 Python
При определении LOGGING.formatters.[name].format можно использовать следующие переменные
Из этих переменны можно составить форматированную строку
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} [{asctime}] {name}:{filename} {lineno} {message}',
},
}
}
Разобраться можно в файле /usr/lib/python3.10/logging/__init__.py:1100
27 июля 2022 Nginx
Недавно подключил к одному сайту ещё несколько доменов и получил вот такое значение
server_name www.server-name.ru www.server-name.it server-name.it server-name.ru servername.ru www.servername.ru www.server-name.ae www.servername.ae;
после чего сделал nginx reload и сервер начал работать как обычно, но после перезагрузки всего сервера Nginx не запустился и вы давал вот такую ошибку
nginx: [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 32
суть ошибки в том, у nginx по умолчанию определён небольшой размер буфера для хранения и обработки server_name
если определить размер этого буфера через переменную server_names_hash_bucket_size в разделе http файла /etc/nginx/nginx.conf то сервер будет нормально перезапускаться и работать
После неудачного эксперимента с бекапами база данных может содержать по несколько копий каждой строки таблицы, это приводит любой ORM в ступор, впрочем и руками удалить такие записи не полуться, так записи имеют одинаковые ID. Ниже решение как легко удалить дубли и оставить только по одной уникальной строке
table_name=auth_users
data_base=breys
echo "
begin;
select count(1) from $table_name ;
create table ttt as select distinct id x, * from $table_name ;
alter table ttt drop column x;
truncate table $table_name;
insert into $table_name (select * from ttt );
drop table ttt ;
select count(1) from $table_name ;
end;
" | psql $data_base
Суть метода такова:
Если необходимо обработать все таблицы базы данных то скрипт можно использовать в цикле
for table_name in $(echo '\dt' | psql $data_base | awk '{print $3}'| grep -v ^$|sort ); do
echo "
begin;
select count(1) from $table_name ;
create table ttt as select distinct id x, * from $table_name ;
alter table ttt drop column x;
truncate table $table_name;
insert into $table_name (select * from ttt );
drop table ttt ;
select count(1) from $table_name ;
end;
" | psql $data_base;
done
с помощь транзакций можно предовратить удаление данных в случае проблемного импорта
29 апреля 2022 Python
Задача реализовать прозрачное связывание "союзами" пользователей сайта. Такое необходимо когда пользователь А запросил союз у пользователя Б и тот одобрил этот союз, тогда у обоих пользователей должен обновиться список союзников и табличная связь будет выглядеть следующим образом
таблица пользователей | таблице связей | ||||||||||||||||
|
|
Связав таблицы где 1 колонка это номер строки хозяин, а вторая колонка это номер строки союзника получется, что у осла в союзниках козёл и мишка, а у пятачка союзник только винипух винипух
С точки зрения базы данных это связь многие ко многим и на Sqlalchemy решается через создание ассоциативной таблиц, а учитывая что помимо союзной связи необходимо сохранить состояние связи и даты создания и обновления, то ассоциативная таблица превращается в полноценную модель
class Union(db.Model):
__tablename__ = "user_unions"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user1_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
user2_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True)
created = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated = db.Column(db.DateTime(timezone=True), onupdate=func.now())
enable = db.Column(db.Boolean, default=False, nullable=False)
def __repr__(self):
if self.enable:
return "союз с {} заключён".format(self.user2)
return "союз с {} не подписан".format(self.user2)
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(40), unique=False, nullable=False)
email = db.Column(EmailType, unique=False)
def add_user(self, user):
""" добавление союза с user"""
union = Union(user1=self, user2=user)
db.session.add(union)
db.session.flush()
Всё будет прекрасно до тех пор пока не потребуется у объектов User обратиться к списку союзных пользователей. Дело в том, что метол обращения к списку союзников выглядит по разному для разныз пользователей. Если для того чтобы узнать список союзников осла неоходимо выбрать все вторые колонки в строка в которых в первой колонке номер строки осла, а чтобы выбрать союзников козла, необходимо выбрать все первые колонки в строках где вторая колонка равна номеру строки козла. Таки образом получается метод выбора союзников осла и козла будет разный, а это не красиво.
Но всё таки можно реализовать универсальный метод поиск союзников для каждого пользователя и в SQL виде он будет выглядеть вот так
select *
from users
where id in (
select user2_id id
from user_unions
where user1_id = 1
union
select user1_id id
from user_unions
where user2_id = 1
)
тут производится выборка id союзников в ассоциативной таблице для обоих типов запросов, затем результаты объединяются и используются во вложенном запросе при обращении к таблице пользователей.
Sqlalchemy позволяет реализовать и такой достаточно сложный запрос с помощью объектного ORM и тогда метод выбора союзников пользователя будет выглядет следующим образом
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(40), unique=False, nullable=False)
email = db.Column(EmailType, unique=False)
created = db.Column(db.DateTime(timezone=True), server_default=func.now())
def get_all_union_users(self):
"""выборка запросов на союз"""
q1 = db.session.query(Union.user2_id.label("id"))
q1 = q1.filter(Union.user1==self)
q2 = db.session.query(Union.user1_id.label("id"))
q2 = q1.filter(Union.user2==self)
return User.query.filter(
User.id.in_(q1.union(q2))
)
def get_union_users(self):
"""выборка подтверждённых союзников"""
q1 = db.session.query(Union.user2_id.label("id"))
q1 = q1.filter(Union.user1==self, Union.enable==True)
q2 = db.session.query(Union.user1_id.label("id"))
q1 = q2.filter(Union.user2==self, Union.enable==True)
return User.query.filter(
User.id.in_(q1.union(q2))
)
Проверяем результат
# проверяем список союзников у каждого пользователя стандартным способом
for u in User.query.all():u, "союзники", u.unions.all()
...
(Пользователь: осёл , 'союзники', [союз с Пользователь: козёл заключён, союз с Пользователь: мишка заключён])
(Пользователь: козёл , 'союзники', [])
(Пользователь: мишка , 'союзники', [])
(Пользователь: пятачёк , 'союзники', [союз с Пользователь: винипух заключён])
(Пользователь: винипух , 'союзники', [])
# проверяем список союзников у каждого пользователя проверяем через универсальный метод
>>> for u in User.query.all():u, "союзники", u.get_union_users().all()
...
(Пользователь: осёл , 'союзники', [Пользователь: козёл , Пользователь: мишка ])
(Пользователь: козёл , 'союзники', [Пользователь: осёл ])
(Пользователь: мишка , 'союзники', [Пользователь: осёл ])
(Пользователь: пятачёк , 'союзники', [Пользователь: винипух ])
(Пользователь: винипух , 'союзники', [Пользователь: пятачёк ])
27 апреля 2022 13 октября 2022 Всякое
По службе пришлось столкнуться с сервисом продажи доменов hugedomains.com, интересующий нас домен определялся с такими данными
Domain Name: CENTERSVET.COM
Registry Domain ID: 2524336753_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.namebright.com
Registrar URL: http://www.NameBright.com
Updated Date: 2021-08-26T18:12:19Z
Creation Date: 2020-05-10T18:15:17Z
Registry Expiry Date: 2023-05-10T18:15:17Z
Registrar: TurnCommerce, Inc. DBA NameBright.com
Registrar IANA ID: 1441
Registrar Abuse Contact Email: support@namebright.com
Registrar Abuse Contact Phone: 17204960020
Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
Name Server: NSG1.NAMEBRIGHTDNS.COM
Name Server: NSG2.NAMEBRIGHTDNS.COM
DNSSEC: unsigned
URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/
и при переходе на домен перекидывало на предложение о покупке домена за 3695 долларов (на момент покупки это 276 430 рублей).
Поиск отзывов на этот сервис в рунете подтвредил сомнения о том, что это сайт мошеннический, но я обратил внимание на то, что в рунете не было ни одного упоминания, что ктото заплатил за домен и не получил ни домена ни денег. Поиск отзывов на американских форумах подтвердил мысль, о том, что люди очень недовольны что их забытые домены выкупают за $5, а затем предлагают купить им же за $1500, всех смушают цены, но очевидно, что некоторым приходилось выкупать свои домены.
Так же из этих форумов стало известно, что hugedomains.com находится на одном гео.адресе с namebright.com, а hugedomains.com это сервис аренды доменов. То-есть там выстроена схема в которой пользователи покупают и используют домен на namebright.com, а когда домен освобождается (например, в случае когда хозяин забыл оплатить), домен передаются в hugedomains.com, а там работает автоматизированная система продажи домена. У домена настраивается редирект на hugedomains.com, там открывается предложение о покупке и форма ввода данных, включая номер карты и cvv код
Попытки переписываться с компанией приводят к тому, что они высылают электронный счёт к оплате, после которого якобы передадут управление доменов. Для получения управления необходимо завести учётную запись на namebright.com
После оплаты счёта, мы в своём кабинете на namebright.com получили полный контроль над доменом, заменили DNS сервера и домен работает. Остаётся лишь перенести домен к нашим хостерам
18 апреля 2022 27 апреля 2022 Всякое
У компании Nic.ru есть специальная страничка где можно прочитать отзывы о работе комании, я сегодня оставил там свой отзыв и на всякий случай продублировал его сюда
оставил такой отзыв на сайте https://www.nic.ru/info/otzyvy/
Ужасный и отвратительный сервис которым приходится пользоваться уже больше 10 лет
и каждый раз когда приходится сделать какую либо манипуляцию непроизвольно испытывают целую гамму негативных эмоций от гнева до презрительного отвращенияс каждым случаем использования стоимость продления увеличивается
и домены купленные за 150 рублей сейчас можно продлить минимум за 1600 рублейпостоянно пытаются навязывать не нужные услуги, и добавляют платные опции, которые раньше были бесплатными и остаются бесплатными у других хостеров
сам по себе сервис технически реализован крайне безграмотно и является сшитым из кусков разных технологий франкленштейном рунет, это какой то позор
причём нужно понимать, что стоимость услуги совершенно не соответствует реальности и является завышенной как минимум на 1000% процентов, у других хостеров регистрация и продление доменов стоят 200-250 рублей в год, и там не навязываются ни какие платные опции в виде скрытого whois или антивируса для домена
особенно гадкая схема вымогания денег заключается в том, что после покупки домена и оплаты его за год, необходимо покупать услугу DNS сервера, которая оплачивается помесячно и ежегодно эта сумма увеличивается
на счёт службы поддержки сервиса: самое главное что нужно знать про эту службу это то, что они заинтересованы запутать вас, запугать и не дать возможности перевести домены к нормальному провайдеру
в качестве небольшой иллюстрации работы сервиса опишу как я переводил домены с nic.ru к другому хостеру
по ссылке Услуги > Мои домены > Перенос доменов
открывается форма на которой можно заказать перенос доменов
необходимо ввести адреса доменов и заказать переноси вот у меня в первый раз страница зависла и висели 15 минут, затем пришлось перезагрузить страницу и повторить ввод данных
после повторного ввода списка доменов, появилась ошибка что они не могут перевести 3 из 2 доменов, да именно 3 из 2
пришлось ещё обновить страницу и в третий раз вести список доменов и заказать перенос, с третьего раза форма обработала и появилось сообщение что ушло письмо с инструкцией
письмо пришло через 3 дня со следующим текстом
An English version of this message is contained below.
Уважаемый клиент!
Истек срок подтверждения администратором согласия на генерацию кодов переноса к другому регистратору. Список доменов, для которых отменен заказ на получение кодов:
пришлось в 4 раз вводить список доменов для переноса, опять вылазила ошибка о невозможности переноса 2 доменов из 2, но после обновления сработало
пришла СМС с кодом и через 30 минут пришло письмо с инструкцией
я подтвердил перенос, получил AuthInfo-коды для доменов, ввёл коды на новом хостинге и получил письма с запросом подтверждения переноса и вроде бы перенос сработал, но это не точно
затем я начал переносить домены с другого акаунта по ранее проделанной схеме
Услуги > Мои домены > Перенос доменов
опять ошибка с вводом списка доменов, опять обновление и повторный ввод и сообщение что ушло письмо с инструкцией и СМС
СМС пришла, а письмо не пришло и видимо не придётся в течении трёх дней, я попробовал сменить почтовый ящик но система не даёт создать заказ переноса так как уже есть созданный ранее заказ
получается, необходимо ждать три дня, затем я получу уведомление что заказ отменён и повторить процедуру
звонить в техподдержку безсполезно, так как
во первых, очень должно дозваниваться, подтверждать свои учётные данные, затем вас переключают на "специалиста" который просит проверить папку спам или перенастроить почту (типичные отмазки) и заканчивается диалог тем, что они якобы выслали письмо и оно вот вот придётписать им на почту так же бесполезно, они просто не отвечаются в приемлимые сроки
я считаю, что nic.ru и reg.ru это монопольные и мощенические конторы, которые взвинтили цены на доменные имена более чем на 1000%, которые ежегодно выкачивают миллиарды денег из госучреждений и частных компаний
орфографию, подчёркивающие эмоции от использования сервиса, сохраняю
18 апреля 2022 27 апреля 2022 Всякое
Идея за 300
Евгений Касперксий приходит в nic.ru и reg.ru и предлагает им дополнительную услугую добавления домена в белый список антивируса Касперского, например по 100 рублей за домен.
После добавления домена в белый список антивируса Касперского данный домен будет отображаться особым и успокаивающим цветом, а домены не добавленные в белый список будут подсвечиваться как опасные для пользователей
А мошенники из nic.ru и reg.ru заключают договор с Касперским и добавляют на своих сервисах обязательную и не отключаемую платную (по 1000р) услугу поддержки Антивируса Касперский всем своим клиентам.
После чего стоимость продления услуги возрастает с 1600 рублей, до 2600 рублей
03 марта 2022 Linux mpd songs amq
После блокировки западных стриминговых платных платформ можно оживить устройство Songs AMQ с помощью MPD
На любом хостинг-сервере ставим mpd
apt install mpd
закачиваем музыку в /var/lib/mpd/music
меняем на неё права
chown -R mpd:nogroup /var/lib/mpd/music/
в файле конфигурации /etc/mpd.conf можно оставить только такие настройки
playlist_directory "/var/lib/mpd/playlists"
db_file "/var/lib/mpd/tag_cache"
log_file "/var/log/mpd/mpd.log"
pid_file "/run/mpd/pid"
state_file "/var/lib/mpd/state"
sticker_file "/var/lib/mpd/sticker.sql"
user "mpd"
bind_to_address "0.0.0.0" # слушаем все вшешние адрес
port "6600"
password "Z2022.02.24@read,add,control,admin"
input {
plugin "curl"
}
audio_output {
type "httpd"
encoder "lame" # кодек lame необходим для работы с Songs AMQ
port "8000"
bitrate "256" # повышенный битрейт
format "44100:16:1"
}
filesystem_charset "UTF-8"
перезапускаем mpd
service mpd restart
Полученную ссылку в виде http://хостинг-сервер:8000 прописываем в songsApp
Всё работает. Управлять можно через приложение GMPC, так же есть приложения управления mpd для Android. Для управления используем адрес [хостинг-сервер], порт 6600, пароль из опции password