Автоматическое переключение на bluetooth-наушники при их подключении в linux

Не совсем уверен почему, но после переустановки арча у меня начались какие-то небольшие проблемы с bluetooth-адаптером. Подозреваю, что проблема в кривых драйверах, хотя в прошлой версии арча все работало ок. В частности, после переустановки перестало автоматически переключаться на подключенные bluetooth-наушники. Кое-как решил эту проблему с помощью udev-правил. Напишу здесь как это делается, чтобы не забыть (думаю, мне это еще пригодится):

  • Узнать mac-адрес наушников командой bluetoothctl, затем devices
  • Подключить наушники и узнать какой sink они используют (pactl list short sinks). В моем случае это bluez_output.F8_4E_17_1E_76_1F.1
  • Создать bash-скрипт, который переключает звук на наушники:
#!/bin/bash

SINK="bluez_output.F8_4E_17_1E_76_1F.1"
pactl set-default-sink $SINK
# Move all audio streams to new sink
pactl list short sink-inputs | while read stream; do
  stream_id=$(echo $stream | cut '-d ' -f1)
  pactl move-sink-input $stream_id $SINK
done
exit 0
  • Делаем исполняемым sudo chmod +x auto-switch.sh
  • Создать udev-правило, которое будет запускать  скрипт как только bluetooth-устройство с указанным mac-адресом будет подключен к компьютеру:
    sudoedit /etc/udev/rules.d/10-bluetooth.rules:
ACTION=="add", SUBSYSTEM=="bluetooth", ATTRS{address}=="f8:4e:17:1e:76:1f", RUN+="/usr/local/bin/auto-swutch.sh"
  • Тестируем что все работает командами:

    sudo udevadm control –reload-rules

    sudo udevadm trigger

Boku dake ga Inai Machi

Начиналось неплохо, но закончилось с мыслью “что, чёрт возьми, я только что посмотрел?”. И в чём вообще мораль этого аниме? В том, что если вернуться в прошлое, то его можно изменить? Очень глубоко и интересно, о да. Вообще большая часть сюжета здесь – это один большой кринж, основанный на излюбленных фантазиях неудачников о том, как бы они изменили будущее, вернувшись в прошлое, при этом не теряя нынешних воспоминаний. Самое забавное, что наш гениальный ГГ не смог поменять прошлое с первого раза, ему понадобилось две попытки. Если бы ГГ возвращался в прошлое, каждый раз безуспешно пытаясь изменить свою судьбу, то в этом был бы какой-то смысл и глубина. А так…

Я наивно надеялся, что здесь будет “битва умов”, хотя бы уровня Лайто vs. L, но увы, ничего такого здесь нет даже близко. Зато здесь есть очень много спорных и просто глупых моментов, и если разбирать каждый из них, то получится внушительная стена текста, поэтому кратко опишу только лишь кульминационный эпизод, который, на мой взгляд, является репрезентативным для всего сериала: ГГ проснулся после 12 лет комы, встретился со своим антагонистом. То, что Яширо не добил нашего глав. героя, который мог бы проснуться из комы и рассказать всё о нём (что он и сделал, собственно), объясняется дефолтными штампами не имеющими никакого смысла: “Я заполнил дыру в твоем сердце и был твоей надеждой, поэтому ты не мог меня добить”. Мотивация убийств у Яширо, кстати, точно такая же: “заполнять дыру в сердце”. Л – логика + Г – глубина (хотя здесь на “г” больше подходит другое слово). Потом наш ГГ на коляске съехал зачем-то с крыши, на батут. Далее плохого парня Яширо наконец-то задержали, за попытку убийства. ГГ внезапно становится успешным мангакой (не, ну а чего бы и нет?) и случайно встречает тяночку из прошлых таймлайнов, которая сразу же чуть ли не на шею ему прыгает (при том что в этом таймлайне он его знать не может). “Рукоплещите, граждане, друзья, комедия окончена”.

5/10. 5 баллов за первые серии, и за атмосферу снежного тёмного почти нуарного Хоккайдо конца 80-х.

Установка nextcloud на домашний сервер через docker с ssh-туннелем до VPS для удалённого доступа.

Задача: установка nextcloud на домашний локальный сервер через docker compose с установкой ssh-туннелем до VPS для доступа к nextcloud из интернета.

Шаги:

1) Создать docker compose файл

2) Установить нужные docker контейнеры

3) Проверить что все работает локально

4) Создать поддомен для удалённого доступа

5) Настроить nginx на удаленном сервере

6) Получаем SSL-сертификат

7) Открыть нужные порты на VPS

8) Создаем ssh-туннель

9) Написать службу systemd которая будет поддерживать постоянный ssh-туннель до сервера

Реализация:

1) Создать docker compose файл

mkdir -p ~/nextcloud && cd ~/nextcloud
vim docker-compose.yml

docker-compose.yml:

version: '3.7' 

services: 
 db: 
   image: mariadb 
   command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW 
   restart: always 
   volumes: 
     - db:/var/lib/mysql 
   environment: 
     - MYSQL_ROOT_PASSWORD=yourRootPassword 
     - MYSQL_PASSWORD=yourUserPassword 
     - MYSQL_DATABASE=nextcloud 
     - MYSQL_USER=nextcloud 

 app: 
   image: nextcloud 
   ports: 
     - 8082:80 
   links: 
     - db 
   volumes: 
     - nextcloud:/var/www/html 
   restart: always 
   environment: 
     - MYSQL_PASSWORD=yourUserPassword 
     - MYSQL_DATABASE=nextcloud 
     - MYSQL_USER=nextcloud 
     - MYSQL_HOST=db 

volumes: 
 db: 
 nextcloud:

Не забыть поменять yourRootPassword, yourUserPassword.

2) Установить нужные docker контейнеры

docker-compose up -d

3) Проверить что все работает локально

Заходим на http://[ip-локального-сервера]:8082 и убеждаемся, что все работает на локально.

4) Создать поддомен для удалённого доступа

Нужно создать DNS-запись у регистратора домена. Пусть это будет nextcloud.bernd32.xyz. В cloudflare это делается так: cloudflare.com -> DNS -> Add record -> name: nextcloud -> ip: [ip_сервера] -> type: A

5) Настроить nginx на удаленном сервере

sudoedit /etc/nginx/sites-available/nextcloud.bernd32.xyz

Файл должен выглядеть примерно так:

server {
       #listen [::]:80;
       server_name nextcloud.bernd32.xyz;
       access_log /var/log/nginx/nextcloud/access.log;

   location / {
       proxy_pass http://localhost:8084;
       proxy_set_header Host $host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
   }

Создаем симлинк конфига:

sudo ln -s /etc/nginx/sites-available/nextcloud.bernd32.xyz /etc/nginx/sites-enabled/

6) Получаем SSL-сертификат

sudo certbot --nginx -d nextcloud.bernd32.xyz
sudo systemctl reload nginx

7) Открыть нужные порты на VPS

sudo ufw allow 8082
sudo ufw allow 8084

8) Создаем ssh-туннель

/usr/bin/ssh -i <путь/до/ssh/ключа> -p 53333 -R 8084:localhost:8082 root@<VPS-IP> -NTC  -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes

Заходим на https://nextcloud.bernd32.xyz и убеждаемся что все работает.

9) Написать службу systemd которая будет поддерживать постоянный ssh-туннель до сервера

sudo vim /etc/systemd/system/nextcloud-ssh-tunnel.service
[Unit]
Description=Persistent SSH Tunnel for nextcloud  
After=network.target
 
[Service]
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/ssh -i <путь/до/ssh/ключа> -p 53333 -R 8084:localhost:8082 root@<VPS-IP> -NTC  -o ServerAliveInterval=60 -o ExitOnForwardFailure=yes
 
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start nextcloud-ssh-tunnel.service
sudo systemctl enable nextcloud-ssh-tunnel.service

В случае возникновения ошибки “Bad Request Your browser sent a request that this server could not understand. Apache/2.4.57 (Debian) Server at 172.19.0.3 Port 80” можно попробовать отредачить конфигурационный файл nextcloud в контейнере:

docker cp id_контейнера:/var/www/html/config/config.php ./config.php
vim ./config.php

Добавляем туда:

'trusted_proxies' => ['172.19.0.3', 'YOUR_VPS_IP'], //  172.19.0.3 внутренний айпи докера
'overwriteprotocol' => 'https',
'overwritehost' => 'nextcloud.bernd32.xyz',
'overwritecondaddr' => '^YOUR_VPS_IP$', // VPS IP

После копируем файл обратно в контейнер:

docker cp ./config.php app:/var/www/html/config/config.php

В случае возникновения каких-то проблемы логи смотреть через команду

docker logs -f айди_контейнера

Boogiepop Phantom

Уникальное аниме, которое отличается от всего остального своей мрачной атмосферой, необычными для аниме художественными приемами (например, виньетирование, выцветшая сепия) и использованием авангардной музыки в стиле нойз и индастриал.

Еще тот очень интересен сюжет. Он довольно замысловат и нелинеен, рассыпан по разным сериям, словно кусочки паззла. Большое количество персонажей сериала раскрывает различные психологические темы, такие как сожаления о прошлом, перемены, эскапизм, отчаяние и другие.

Основная моя претензия к этому сериалу лишь в том, что в сюжете много чего раскрыто очень поверхностно, либо не раскрыто вовсе. Но это и неудивительно, ведь всего за 12 серий авторы пытались хоть как-то раскрыть всех персонажей (которых тут много), показать некоторые сцены по нескольку раз с разных точек зрения, и все это в неспешном ритме, чтобы соответствовать меланхоличной атмосфере сериала. Русские субтитры ужасного качества также не помогают лучше понять сюжет, поэтому лучше смотреть с ансабами (впрочем, они тоже не идеальны).

Несмотря на описанный выше недостаток, сериал получился в прямом смысле слова отличным и заслуживающим высокой оценки. Просто из-за уникальности и необычности. Ничего даже близко похожего на этот сериал нет, увы. Разве что Эксперименты Лейн, да и то только лишь некоторыми художественными приемами.

Установка katrain на (arch) linux с видеокартой AMD

KaTrain — это инструмент для анализа игр Го с обратной связью AI от движка KataGo.

Поэтому для начала нужно получить этот движок. Можно скачать уже скомпилированную версию с гитхаба, но лучше всего скомпилировать самому. Подробнее про это здесь: https://github.com/lightvector/KataGo/blob/master/Compiling.md

В моем случае (с RX5500XT)  это выглядело так:

 

sudo pacman -S opencl-clover-mesa 
sudo pacman -S opencl-icd-loader opencl-headers
git clone https://github.com/lightvector/KataGo.git
cd KataGo/cpp
cmake . -DUSE_BACKEND=OPENCL -DBUILD_DISTRIBUTED=1
make -j 6

Скомпилированный бинарник будет находиться в Katago/cpp под названием katago. Теперь нужно установить и настроить katrain. Это можно сделать через репозиторий AUR, но проще всего установить через pip:

pipx install katrain

Далее в настройках katrain (engine settings) указываем на скомпилированный бинарник katago.

Если в процессе запуска будет ошибка касающаяся opencl, то нужно будет установить opencl-драйвер. В моем случае это:

git clone https://aur.archlinux.org/opencl-amd.git
makepkg -si

Далее перезагрузить компьютер.

Read more

Использование s2ram вместо elogind в gentoo (openRC)

Пытаюсь наладить саспенд (оно же режим “сна”) на ноуте. Проблема в том, что когда я закрываю крышку ноутбука, то Х11-сессия крашится. Как выяснилось, это происходит из-за того, что ноут переключается в режим саспенда, используя elogind (loginctl suspend). Я попробовал установить пакет sys-power/suspend и перейти в режим сна с помощью s2ram,  с таким подходом все работает идеально. Теперь нужно придумать как заставить триггерить s2ram вместо loginctl suspend при закрытии крышки ноута. Вообще, хотелось бы конечно удалить elogind из системы полностью, но тогда х11 не будет запускаться не из-под рута (https://wiki.gentoo.org/wiki/Non_root_Xorg). Записываю сюда, чтобы не забыть:

– заэмержить sys-power/acpid

– создать файл /etc/acpi/events/lid:

event=button[ /]lid.*
action=/etc/acpi/actions/lid.sh "%e"

– создать скипт, который будет вызывать при закрытии крышки ноута:

/etc/acpi/actions/lid.sh:

#!/bin/sh
if grep -q close /proc/acpi/button/lid/LID0/state; then
s2ram
fi

Не забыть сделать скрипт исполняемым.

переключение устройств воспроизведения в pulseaudio

На моем компьютере есть два устройства воспроизведения звука: встроенная в материнскую плату, подключенная к колонкам, и внешняя с подключением по usb, к которой подключены наушники. Задача: настроить переключение между этими двумя устройствами (т.е. в моем случае это переключение между наушники и колонками) по нажатию клавиш Meta-a. В качестве звукового сервера используется pulseaudio.

Для начала нужно вывести список на экран список доступных звуковых потоков воспроизведения (sink’ов):

pactl list short sinks | awk '{print $2}'

В моем случае это:

alsa_output.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo-output
alsa_output.pci-0000_00_1f.3.analog-stereo

То, что надо. Теперь напишем скрипт, который бы переключался между этими sink’ами при выполнении:

vim ~/scripts/sink_toggle.sh:
#!/bin/bash

# названия нужных нам sink'ов берем из  pactl list short sinks | awk '{print $2}'
# внутрення звуковая карта (колонки)
SINK1="alsa_output.pci-0000_00_1f.3.analog-stereo" 
# внешняя звуковая карта (наушники)
SINK2="alsa_output.usb-Burr-Brown_from_TI_USB_Audio_CODEC-00.analog-stereo-output"

# устанавливаем нужный нам sink дефолтным 
CURRENT_SINK=$(pactl get-default-sink)
if [ "$CURRENT_SINK" = "$SINK1" ]; then
pactl set-default-sink $SINK2
NEW_SINK=$SINK2
else
pactl set-default-sink $SINK1
NEW_SINK=$SINK1
fi

# перенаправляем все звуковые потоки на нужный sink
pactl list short sink-inputs | while read stream; do
stream_id=$(echo $stream | cut '-d ' -f1)
pactl move-sink-input $stream_id $NEW_SINK
done

Этот shell-скрипт перенаправляет все текущие аудиопотоки (звуковые входы), воспроизводимые в системе, на новый звуковой выход ($NEW_SINK). Скрипт использует утилиту pactl для управления звуковым сервером PulseAudio.

Делаем скрипт исполняемым:

sudo chmod +x ~/scripts/sink_toggle.sh

Осталось только настроить триггер для выполнения скрипта. В качестве триггера я буду использовать сочетание клавиш Meta+a. В KDE Plasma это настраивается элементарно в системных настройках.

 

Конфигурация goaccess на nginx-сервере.

Итак, стоит задача настроить анализатор логов nginx-сервера goaccess таким образом, чтобы оно отображало статистику в реальном времени (для этого будем использовать веб-сокеты). Статистика должна быть доступна по адресу https://website1.example.com/goaccess

Далее – создать systemd-юниты для автоматизации процесса. Дополнительные задачи: настроить goaccess для второго сайта на том же сервере (https://website2.example.com/goaccess). Два процесса goaccess должны работать параллельно (для этого будем использовать встроенные опции именованных каналов межпроцессного взаимодействия, указание на путь хранения базы данных программой goaccess, а также укажем другой порт). Также установить ограничений по ip-адресам для доступа к панели статистики второго сайта (с помощью конфигурации nginx).

Предположим, что goaccess уже установлен. Нам нужно просматривать статистику по логам /var/log/nginx/website1/access.log по адресу https://website1.example.com/goaccess/main.html. HTML-страница со статистикой для https://website1.example.com будет храниться здесь: /var/www/goaccess/website1. Далее нам потребуется настроить nginx. Для этого в конфиге сайта (/etc/nginx/sites-available/website1) нужно добавить две локации: stats и ws:

location /stats/ {
alias /var/www/goaccess/website1/;
try_files $uri $uri/ =404;
}

вкратце, этот блок конфигурации Nginx настроен на обработку запросов, начинающихся с “/stats/”. Он сопоставляет эти запросы с локальным каталогом на сервере и пытается предоставить запрашиваемый файл или каталог, возвращаясь к ошибке 404, если таковой не существует.

Далее нужно настроить веб-сокет:

location /ws/ {

# порт не должен блокироваться фаерволом
proxy_pass http://localhost:7890/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}

Релоадим конфигурацию nginx:

sudo systemctl reload nginx

этот блок перенаправляет http-реквесты с https://website1.example.com/ws на http://localhost:7890 и устанавливает необходимые заголовки для работы с веб-сокетами. 

Запуск команды для проверки что все работает: 

goaccess /var/log/nginx/website1/access.log -o /var/www/goaccess/website1/main.html --real-time-html --port=7890 --log-format=COMBINED --ws-url=wss://eiensora.bernd32.xyz/ws/:443

Порт 443 предполагает, что у нас настроено https.

Заходим https://website1.example.com/goaccess/main.html и смотрим. Если все ок, то добавим systemd-юнит: 

vim /etc/systemd/system/goaccess_website1.service:

[Unit]
Description=GoAccess Live Log Analyzer for website1


[Service]
Type=simple
ExecStart=goaccess /var/log/nginx/website1/access.log \
-o /var/www/goaccess/website1/main.html \
--real-time-html \
--port=7890 \
--log-format=COMBINED \
--ws-url=wss://website1.example.com/ws/:443
ExecStop=/bin/kill ${MAINPID}
PrivateTmp=false
RestartSec=1800
User=root
Group=root
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start goaccess_website1
sudo systemctl enable goaccess_website1

Для одного сайта всё должно работать ок. Если нужно мониторить несколько разных логов (скажем, от разных сайтов, которые находятся на одном сервере) одновременно на разных адресах. То есть нам нужно запустить каким-то образом запустить два параллельных процесса goaccess. Сделать это можно, если

– запускать каждый процессор goaccess на разных портах –port.

– Различные каналы (FIFO) –fifo-in=/path/in.1 –fifo-out=/path/out.1.

– Если вы используете хранилище на диске, вам понадобится другой путь, по которому хранятся файлы БД –db-path=/path/instance1/.

Нужно изменить предыдущий юнит и добавить новые опции

–fifo-in=/tmp/es.in \
–fifo-out=/tmp/es.out \
–db-path=/var/lib/goaccess/

[Unit]
Description=GoAccess Live Log Analyzer for website1


[Service]
Type=simple
ExecStart=goaccess /var/log/nginx/website1/access.log \
-o /var/www/goaccess/website1/main.html \
--real-time-html \
--port=7890 \
--log-format=COMBINED \
--ws-url=wss://website1.example.com/ws/:443 \

--fifo-in=/tmp/site1.in \
--fifo-out=/tmp/site1.out \
--db-path=/var/lib/goaccess/website1
ExecStop=/bin/kill ${MAINPID}
PrivateTmp=false
RestartSec=1800
User=root
Group=root
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl start goaccess_website1
sudo systemctl enable goaccess_website1

Значения fifo и db-path можно выбрать какие-угодно.

Далее, добавить второй юнит для статистики второго сайта, в котором будет другой порт, другое значение параметров –db-path, –fifo-in и –fifo-out:

vim /etc/systemd/system/goaccess_website2.service:

[Unit]
Description=GoAccess Live Log Analyzer for website2

[Service]
Type=simple
ExecStart=goaccess /var/log/nginx/website2/access.log \
-o /var/www/goaccess/website2/main.html \
--real-time-html --port=7891 \
--log-format=COMBINED \
--ws-url=wss://website1.example.com/ws/:443 \
--fifo-in=/tmp/site2.in \
--fifo-out=/tmp/site2.out \
--db-path=/var/lib/goaccess/website2/
ExecStop=/bin/kill ${MAINPID}
PrivateTmp=false
RestartSec=1800
User=root
Group=root
Restart=always

[Install]
WantedBy=multi-user.target

Также не забыть добавить в конфиг /etc/nginx/sites-available/website2:

location /stats/ {
alias /var/www/goaccess/website2/;
try_files $uri $uri/ =404;

#даем доступ к статистике только локальной подсетке и одному внешнему айпи
allow 44.51.220.3;
allow 192.168.1.0/24;
deny all;
}
location /ws/ {

# порт должен отличаться от созданного первого юнита
proxy_pass http://localhost:7891/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
sudo systemctl daemon-reload
sudo systemctl start goaccess_website2
sudo systemctl enable goaccess_website2

Теперь панели просмотра goaccess разных сайтов будут доступны одновременно по двум адресам:

https://website1.example.com/goaccess/main.html

https://website2.example.com/goaccess/main.html