# создаёт виртуальный Диск и отображает имя файла виртуального диска, в моём случае /dev/loop15
# список разделов можно посмотреть вот так sudo fdisk -l /dev/loop15
sudo mount /dev/loop15p2 /mnt
# монтирует второй раздел виртуальный диска в директорую /mnt/
# тут какие то работы с данными образами
В инфраструктуре Flask есть фреймворк flask_restful для реализации Rest API и последние несколько лет там начались проблемы с развитием, в результате чего появилось несколько форков. В частности я решил попробовать построить один проект на flask_restx.
В этой заметке я буду описывать, что из этого вышло и насколько это решение хорошо для использования
С помощью RESTX я реализовал следующие API
авторизация на основе JWT токен
обновление JWT токена с помощью Refresh токента
получение и редактирование профиля пользователя
создание точки загрузки файла
загрука файла частями (chunks)
просмотр списка загруженных файлов
просмотр свойств файла по ID
Выглядит хорошо и лаконично, вот например API получения списка публикаций пользователя
Но если смотреть в целом, то приходится для каждой модели базы писать модель сериализации
А ещё больше напрягло то, что фреймворк просто не предлагает ни какого способа пагинации. То-есть, API легко отдаёт всю выборку, а для того чтобы отдать сред выборки в стиле Django, необходимо руками высчитать total и сломать весь красивый механизм marshal_with
Так же, нет интеграции со sqlalchemy, конечно можно найти способ
но как по мне конструкция ModelX.query.filter(**kwargs).all() выглядит так себе
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
При сборке на свежей системе может возникнуть ошибка
./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.
Эта ошибка проявляется если сборщик не может найти библиотку перловых регулярных выражений, решается проблема легко
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 будет отставать от реального количество записей в таблице
после чего сделал 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
Суть метода такова:
создать копию таблицы содержающую только уникальные по ID записи, для этого используется DISTINCT,
затем нужно удалить сигнальное поле x
почистить целевую таблицу
затем перенести данные из временной таблицы в целевую
удалить временную таблицу
Если необходимо обработать все таблицы базы данных то скрипт можно использовать в цикле
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
с помощь транзакций можно предовратить удаление данных в случае проблемного импорта
Задача реализовать прозрачное связывание "союзами" пользователей сайта. Такое необходимо когда пользователь А запросил союз у пользователя Б и тот одобрил этот союз, тогда у обоих пользователей должен обновиться список союзников и табличная связь будет выглядеть следующим образом
таблица пользователей
таблице связей
1
осёл
2
козёл
3
мишка
4
пятачёк
5
винипух
1
2
1
3
4
5
Связав таблицы где 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 и тогда метод выбора союзников пользователя будет выглядет следующим образом
и при переходе на домен перекидывало на предложение о покупке домена за 3695 долларов (на момент покупки это 276 430 рублей).
Поиск отзывов на этот сервис в рунете подтвредил сомнения о том, что это сайт мошеннический, но я обратил внимание на то, что в рунете не было ни одного упоминания, что ктото заплатил за домен и не получил ни домена ни денег. Поиск отзывов на американских форумах подтвердил мысль, о том, что люди очень недовольны что их забытые домены выкупают за $5, а затем предлагают купить им же за $1500, всех смушают цены, но очевидно, что некоторым приходилось выкупать свои домены.
Так же из этих форумов стало известно, что hugedomains.com находится на одном гео.адресе с namebright.com, а hugedomains.com это сервис аренды доменов. То-есть там выстроена схема в которой пользователи покупают и используют домен на namebright.com, а когда домен освобождается (например, в случае когда хозяин забыл оплатить), домен передаются в hugedomains.com, а там работает автоматизированная система продажи домена. У домена настраивается редирект на hugedomains.com, там открывается предложение о покупке и форма ввода данных, включая номер карты и cvv код
Попытки переписываться с компанией приводят к тому, что они высылают электронный счёт к оплате, после которого якобы передадут управление доменов. Для получения управления необходимо завести учётную запись на namebright.com
После оплаты счёта, мы в своём кабинете на namebright.com получили полный контроль над доменом, заменили DNS сервера и домен работает. Остаётся лишь перенести домен к нашим хостерам
У компании Nic.ru есть специальная страничка где можно прочитать отзывы о работе комании, я сегодня оставил там свой отзыв и на всякий случай продублировал его сюда
Ужасный и отвратительный сервис которым приходится пользоваться уже больше 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%, которые ежегодно выкачивают миллиарды денег из госучреждений и частных компаний
орфографию, подчёркивающие эмоции от использования сервиса, сохраняю
Евгений Касперксий приходит в nic.ru и reg.ru и предлагает им дополнительную услугую добавления домена в белый список антивируса Касперского, например по 100 рублей за домен.
После добавления домена в белый список антивируса Касперского данный домен будет отображаться особым и успокаивающим цветом, а домены не добавленные в белый список будут подсвечиваться как опасные для пользователей
А мошенники из nic.ru и reg.ru заключают договор с Касперским и добавляют на своих сервисах обязательную и не отключаемую платную (по 1000р) услугу поддержки Антивируса Касперский всем своим клиентам.
После чего стоимость продления услуги возрастает с 1600 рублей, до 2600 рублей
После блокировки западных стриминговых платных платформ можно оживить устройство 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
Индикаторы самодиагностики на материнской плате 820-2128-B
Светодиод
Название
Цвет
Значение
Необходимо нажать на DIAG_LED
Указание на
Led 1
Sleep
Красный
Выключен; горит, когда компьютер находится в спящем режиме
Да
Спяший режим
Led 2
Standby (Trickle Pwr)
Жёлтый
вкл
Да
Работа от резервного источника питания * **
Led 3
CPU B Error
Красный
выкл
Нет
Процессор Б останавливается на IERR (ошибка инструкции)
Led 4
CPU A Error
Красный
Нет
Процессор A останавливается на IERR (ошибка инструкции)
Led 5
CPU B OT
Красный
выкл
Нет
Перегрев процессор Б
Led 6
CPU A OT
Красный
выкл
Нет
Перегрев процессор А
Led 7
GPU Present
Зелёный
вкл
Да
EFI настроил видеокарту
Led 8
Power Good
Зелёный
вкл
Да
Все силовые шины работают
Led 9
EFI Done
Зелёный
вкл
Да
EFI загружается
Это резервная мощность. Он не позволяет внутренней резервной батарее (или «аккумулятору PRAM») работать, если только питание переменного тока не отключается полностью, например, в случае короткого сбоя питания или отключения компьютера от сети для обслуживания или перемещения.
Указывает, что основная логическая плата обнаружила скачкообразное напряжение от источника питания.
Этот индикатор загорается при подключении iMac к работающему источнику питания переменного тока.
Светодиод остаётся включенным, пока компьютер включен или находится в спящем режиме.
Когда необходимо обработать query_string из урла с помощью JS то самый простой и экономный вариант использовать URLSearchParams и reduce следующим образом
// распасить урл
const searchParams = new URLSearchParams(window.location.search.substring(1));
// преобразовать в обычный Объект
const params = [...searchParams.entries()].reduce((acm, x) => {return {...acm, [x[0]]: x[1] }}, {});
константа params будет содержать словарь с данными из запроса (исключая дубли)
Может статься так, что потребуется передать строку больше чем 2048 байт, в таком случае использовать window.location.search не получится из-за ограничений GET запроса протокола HTTP.
Но можно воспользоваться дополнение window.location.hash это строка Хеш идущая после символа #
в таком случае чуть в код добавляет маленькая вставка