Как заменить диск в BTRFS-рейде

Допустим встала задача заменить диск в рейде BTRFS. Замена может быть плановой, когда диск начал активно ругаться через SMART, или аварийной, когда диск уже умер. Рассмотрим случай, когда у нас нет свободных портов для подключения еще одного диска к существующим, и даже для плановой замены нам потребуется сначала извлечь заменяемый диск. Тогда оба сценария у нас будут максимально похожи, и будут сопряжены с выключением сервера.

Итак.

  1. Если замена плановая (если сервер уже упал переходим к п.2), то лучше сразу в /etc/fstab добавить опцию монтирования degraded ко всем точкам монтирования, которые будут затронуты при изъятии диска.
     
     
    1. UUID="b8022e27-2df2-404d-a404-1ca03f9c90e9" / btrfs defaults,degraded,subvol=@rootfs,noatime,compress-force=zstd 0 0
    2. UUID="b8022e27-2df2-404d-a404-1ca03f9c90e9" /var/log btrfs defaults,degraded,subvol=@var-log,compress-force=zstd 0 0
    3. UUID="ea4980c5-dee0-49e0-960c-3975a70f77eb" /share btrfs defaults,degraded,noatime,nofail 0 0

    В данном примере физические диски разбиты на разделы, и из разделов составлены RAID1 для «/» и «/var/log» (два сабволюма на общей ФС) и RAID5 для /share (вторая независимая ФС). Таким образом при изъятии диска оба рейда деградируют, и для обоих нужно добавить данную опцию монтирования.

  2. Выключаем сервер и меняем диск на новый
  3. При загрузке нажимаем «e» чтобы отредактировать конфигурацию загрузчика. Находим строчку «linux….» как на скриншоте ниже.
    * Если рутовый раздел монтируется из сабволюма, т.е. как в п.1 в fstab в параметрах монтирования указана опция «subvol=» с именем сабволюма, то и в строке загрузчика  уже будет опция «rootflags=…» в которой эта опция будет повторена — как на скриншоте. В этом случае просто дописываем «,degraded».
    * В том случае, если рутовый раздел монтируется из корня самой файловой системы (в п.1 так монтируется /share — параметр «subvol=» при этом  отсутствует), то скорее всего в загрузчике в принципе будет отсутствовать опция «rootflags» и ее нужно будет добавить в виде «rootflags=degraded»
  4. Нажимаем F10 и загружаемся с указанными опциями загрузчика.
  5. Если мы на первом шаге не исправили /etc/fstab, то наш сервер не загрузится и предложит перейти в maintenance mode. Делаем это, после чего правим  /etc/fstab как в п.1. После этого монтируем разделы командой «mount -a».
    Если все прошло удачно и разделы смонтировались — я рекомендовал бы перезагрузить сервер, снова повторить п.п. 3-4, и тем самым добиться полноценной загрузки сервера на деградированных рейдах. Таким образом дальнейшие шаги по пересборке рейда, которые могут быть довольно протяженными по времени, будут проходить при работающем сервере. С другой стороны если вам важны данные, вы хотите снизить нагрузку на диски, и вам не так важно чтобы сервер продолжал быть в работе, можете перейти к следующему пункту сразу после успешного монтирования ваших разделов.
  6. Выполните команду lsblk и убедитесь что все ваши диски видны (на скриншоте диски sda, sdb и sdc — рабочие, sdd — новый, не размеченный диск того же размера)
  7. Копируем таблицу разделов с одного из рабочих дисков на новый
     
     
    1. sfdisk -d /dev/sda | sfdisk /dev/sdd
  8. Дальше нужно посмотреть конфигурацию btrfs и выяснить какой диск, с ее точки зрения, у нас отсутствует. Выполняем команду
     
     
    1. btrfs fi sh

    В данном случае отсутствует диск 3, а сам рейд составлен из разделов sda2, sdb2 и sdc2

  9. Производим замену: вместо пропавшего диска 3 подставляем раздел нового диска — sdd2
     
     
    1. btrfs replace start 3 /dev/sdd2 /
  10. Для отслеживания прогресса выполняем команду
     
     
    1. btrfs replace status /

    Также можно отметить, что до окончания операции замены в рейде будут видны оба диска — missing и новый

     
     
    1. btrfs fi sh /

  11. После завершения замены обязательно производим мягкий ребаланс, так как часть данных на текущий момент скорее всего не будет соответствовать уровню рейда (иными словами не будет задублирована и защищена избыточностью). Для этого сначала смотрим какие профили используются для данных и для метаданных:
     
     
    1. btrfs fi us /


    После чего выполняем команду:

     
     
    1. btrfs balance start -dconvert=RAID1C4,soft -mconvert=RAID1C4,soft /

    dconvert — профиль для данных (Data)
    mconvert — профиль для медатанных (Metadata)

  12. Повторяем п.п. 8-11 для всех оставшихся отдельных файловых систем (в данном примере: для ФС, монтируемой в /share, и расположенной на разделах sda3, sdb3 и sdc3).
  13. Редактируем /etc/fstab, удаляя добавленные ранее опции dagraded.

После этого останется восстановить загрузчик на новом диске, если он там был, и перезагрузить сервер, чтобы убедиться что все работает как надо без дополнительных опций.

SAMBA: Неправильно отображается информация о размерах папки лежащей на BTRFS

Типичной ситуацией является некорректное отображение общего размера сетевой шары, если она лежит на BTRFS-рейде — вместо действительного размера тома показывается сумма размеров всех дисков в рейде. Для исправления этой ситуации можно воспользоваться опцией «dfree command», которая позволяет указать кастомный исполняемый файл, которые будет подсчитывать и возвращать данные о размерах диска.

Данные опции нужно добавить в конфигурацию шары:

/etc/samba/smb.conf
 
[Public]
    ....
    dfree command = /etc/samba/btrfs-dfree.py
    dfree cache time = 60
    force user = root
    force group = root
    ....

Здесь стоит обратить внимание на опцию «force user = root», которая с одной стороны принудительно сделает рута владельцем новых файлов и папок, что может быть вам не нужно, но также позволит выполняться скрипту с рутовыми правами — это необходимо для получения таких данных из вывода «btrfs filesystem usage» как «ratio» — коэффициент данных на рейде, учитывающий сколько копий данных фактически на рейде расположено, и «free (estimated) min» —  более точное значение свободного места.

Если в ваши планы не входит менять юзера с дефолтного, то свободное место будет браться скриптом из «Free (statfs, df)», а для показа точного общего размера сетевой шары можно вручную в скрипте указать значение «ratio», присвоив его переменной «CUSTOMRATIO».

Итак, создаем скрипт «/etc/samba/btrfs-dfree.py» (спасибо проекту openmediavault, я использовал их скрипт «omv-btrfs-dfree» как основу), не забываем сделать его исполняемым. Скрипт на гитхабе

/etc/samba/btrfs-dfree.py
 
#!/usr/bin/env python3
import os
import re
import subprocess
import sys
from systemd import journal
CUSTOMRATIO = 0 # set ratio of your btrfs volume if samba user is not root (smb.conf: force user = root)
LOGGING = 0 # 0 - off, 1 - on. journalctl -t 'SMBUS'
def main():
    path = os.path.realpath(sys.argv[1] if len(sys.argv) > 0 else '.')
    output = subprocess.run(
        ['btrfs', 'filesystem', 'usage', '--raw', '-T', path],
        capture_output=True
    ).stdout.decode()
    re_matches_for_total = r'.+Device size:\s+(\d+)\n.+'
    matches_for_total = re.match(
        re_matches_for_total,
        output, re.DOTALL
    )
    if os.getuid() == 0: # if samba user is root we can get ratio to calculate total space
        re_matches_for_ratio = r'.+Data ratio:\s+(\d+\.\d+).+'
        matches_for_ratio = re.match(
            re_matches_for_ratio,
            output, re.DOTALL
        )
        ratio = float(matches_for_ratio.group(1))
    else: # else set ratio = 1 but can get wrong total size
        if CUSTOMRATIO == 0:
            ratio = 1
        else:
            ratio = CUSTOMRATIO
    if os.getuid() == 0: # if user is root we can get estimated (minimum) free space
        re_matches_for_available = r'.+Free \(estimated\):\s+\d+\s+\(min: (\d+)\)\n.+'
    else: # otherwise only 'statfs' free
        re_matches_for_available = r'.+Free \(statfs, df\):\s+(\d+)\n.+'
    matches_for_available = re.match(
        re_matches_for_available,
        output, re.DOTALL
    )
    if matches_for_total is not None:
        totalb = matches_for_total.group(1)
        availableb = matches_for_available.group(1)
        if LOGGING == 1:
            journal.stream('SMBUS').write(f'SMB VARS: userid={os.getuid()}, ratio={ratio}, availableb={availableb}, totalb={totalb}')
            for line in output.splitlines():
                journal.stream('SMBUS').write(f'{line}')
        total =     round(int(totalb) // (1024 * ratio))
        available = round(int(availableb) // 1024)
    else:
        output = subprocess.run(
            ['df', '--portability', '--print-type', '--block-size=1K', path],
            capture_output=True
        ).stdout.decode()
        _, _, total, _, available, *_ = output.split('\n')[1].split()
    sys.stdout.write(f'{total} {available} 1024\n')
if __name__ == "__main__":
    sys.exit(main())

Проверить работу скрипта можно выполнив его вручную, указав в качестве аргумента путь к папке на btrfs:

Как отредактировать текстовый файл на 40Gb??

Поимел тут дамп базы данных — текстовик на 40 гигов.

Для понимания проблемы: дамп состоит из двух основных блоков
[блок команд создания таблиц]
[блок команд вставки строк]

Первый блок небольшой, на 150 строк. Второй – все остальные гиги, которые выглядят как

 
 
  1. INSERT INTO tablename VALUES (val1, val2… valN);
  2. INSERT INTO tablename VALUES (val1, val2… valN);
  3. ...
  4. INSERT INTO tablename VALUES (val1, val2… valN);

Импортируется обычно все командой

 
 
cat dump.sql | mysql basename

то есть файл просто читается в пайп и mysql выполняет команды из него.

И в чем подстава.
Во-первых у дампа в начале не хватало пары команд — это выяснилось сразу при попытке импорта и легко выгуглилось. Во-вторых — в блоке импорта строк, ВО ВСЕХ строках отсутствовало начало: «INSERT INTO tablename VALUES»

Я не нашел такой чудо-редактор, который смог бы на редактирование хотя бы открыть этот мегадамп, поэтому к сути.

Сделал два вспомогательных файла:
1.sql – с недостающими командами,
2.sql – с первыми 150 строками, которые про создание таблиц, и первым недостающим «INSERT INTO tablename VALUES» — для начала блока импорта — который я добавил вручную.

Свел задачу к:
— как бы в один поток прочитать сначала эти два файла,
— а потом третий – только в нем пропустить первые строки, а во оставшихся — заменять концы строк с «);» на «); INSERT INTO tablename VALUES», чтобы каждая новая строка начиналась с корректной команды,
— и все это точно также запихать в пайп и отдать mysql.

Оказывается есть такая магия!

 
 
{cat 1.sql 2.sql; sed -n -e 's/);/); INSERT INTO tablename VALUES /g;151,$ p' dump.sql;} | mysql basename
 
 
конструкция команд внутри {} дает общий вывод, который можно направить в пайп и в mysql.
cat 1.sql 2.sql - просто читает два файла подряд
чтение основного файла отдаем седу, с двумя его командами
sed -n -e 's/);/); INSERT INTO tablename VALUES /g;152,$ p' dump.sql;
здесь      ^-- меняем ";)" на "); INSERT..."   --^ ^-- --^ - выводим файл со 151 строки

Nvidia Optimus: включить ускорение для всего сеанса на постоянку

Долгое время на своем ноуте (Dell Vostro 5470) не мог заставить по-человечески работать  видюху NVIDIA  GK208M [GeForce GT 740M], которая по уму должна включаться по запросу приложений, в остальное время уступая работу по отрисовке графики интегрированной интеловской карточке. Все эти Bumblebee нифига не захотели работать, но на вики дебиана (внезапно) нашлась инструкция — как заставить нвидиевский чип работать постоянно (а почему бы, собственно, и нет — энергосбережение мне нафиг не уперлось).

Коротенько как это сделать при использовании SDDM.

Дрова и xorg

Сначала накатываются дрова

 
 
wajig install  nvidia-driver

Выясняются ID шины для обеих видюх

 
 
lspci
 
 
...
00:02.0 VGA compatible controller: Intel Corporation Haswell-ULT Integrated Graphics Controller (rev 09)
...
09:00.0 3D controller: NVIDIA Corporation GK208M [GeForce GT 740M] (rev a1)
...

Теперь создаем файл /etc/X11/xorg.conf (обратите внимание, что запись ID в нем отличается от вывода lspci)

/etc/X11/xorg.conf
 
Section "ServerLayout"
    Identifier "layout"
    Screen 0 "nvidia"
    Inactive "intel"
EndSection
Section "Device"
    Identifier "nvidia"
    Driver "nvidia"
    BusID "PCI:9:0:0"
EndSection
Section "Screen"
    Identifier "nvidia"
    Device "nvidia"
    Option "AllowEmptyInitialConfiguration"
EndSection
Section "Device"
    Identifier "intel"
    Driver "modesetting"
    BusID "PCI:0:2:0"
EndSection
Section "Screen"
    Identifier "intel"
    Device "intel"
EndSection

SDDM

Так как я использую SDDM в качестве дисплей-менеджера, то для него в файл /usr/share/sddm/scripts/Xsetup дописываются строки:

 
 
xrandr --setprovideroutputsource modesetting NVIDIA-0
xrandr --auto
xrandr --dpi 96

Тиринг

Ну и чтобы не было тиринга, в конец файла /etc/modprobe.d/nvidia.conf дописывается строка

 
 
options nvidia-drm modeset=1

после чего выполняется команда

 
 
update-initramfs -u

Теперь после перезагрузки ускорение работает.

Источник: https://wiki.debian.org/NVIDIA%20Optimus#Using_NVIDIA_GPU_as_the_primary_GPU

Отказоустойчивая установка Debian с EFI на зеркало mdadm-рейда

Данный пост возник в результате моей собственной попытки понять, как именно можно добиться отказоустойчивости в конфигурации с EFI-загрузчиком и корнем системы на RAID-массиве. Базовая проблема заключается в том, что разделы с файлами EFI не могут быть расположены на рейде, что приводит к курьезной ситуации, когда сам линукс установлен на рейд, но загрузчик оказывается только на одном диске. Как оказалось, выход конечно есть, но требует дополнительных манипуляций. Я пошел длинным путем и решил описать установку дебиана через Live-CD при помощи debootstrap, что позволяет акцентировать внимание на момент установки загрузчика.

В самом низу будет видео, демонстрирующее все описанные ниже шаги.

Исходная позиция: система с двумя неразмеченными дисками, загруженная с Live-CD

Действия в консоли Live-CD

Размечаем первый диск.
Следующий набор команд создаст на диске GPT-таблицу c двумя разделами: 1 — EFI-раздел на 100 Мб, 2 — раздел под будущее зеркало, размером в 10 Гб

 
 
fdisk /dev/sda
g
n
1
[default]
+100M
t
1
n
2
[default]
+10G
w

Скопируем конфигурацию разделов на второй диск, чтобы они были идентичны

 
 
sfdisk -d /dev/sda | sfdisk /dev/sdb

Отформатируем первые разделы дисков в FAT32

 
 
mkfs.fat -F32 /dev/sda1
mkfs.fat -F32 /dev/sdb1

Создадим зеркало md0 из вторых разделов дисков sda и sdb

 
 
mdadm --create --metadata=0.90 /dev/md0 -l 1 -n 2 /dev/sda2 /dev/sdb2

Форматируем и монтируем рейд

 
 
mkfs.ext4 /dev/md0
mount /dev/md0 /mnt

При помощи утилиты debootstrap скачиваем и разворачиваем на смонтированном рейде основу дебиана

 
 
debootstrap --arch amd64 stable /mnt https://deb.debian.org/debian

Переходим в свежую систему при помощи chroot

 
 
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt

Действия в chroot-окружении

Устанавливаем пароль root

 
 
passwd

Создаем директорию под файлы EFI

 
 
mkdir /boot/efi

Выясняем ID рейда и прописываем содержимое fstab

 
 
blkid /dev/md0 
vi /etc/fstab
 
 
UUID="..."    /           ext4    errors=remount-ro    1 1
/dev/sda1       /boot/efi       vfat    umask=0077           0 1

Важно: рейд указываем через ID, EFI-раздел — по имени.

Монтируем согласно fstab (рейд уже смонтирован, то есть по факту домонтируем EFI)

 
 
mount -a

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

 
 
apt update
apt install mdadm

Опционально настроим локали и часовой пояс

 
 
apt install locales
dpkg-reconfigure locales
dpkg-reconfigure tzdata

Установим ядро

 
 
apt install linux-image-amd64

Установим и настроим загрузчик

 
 
apt install grub-efi
update-grub2

Проинсталлируем GRUB на диски

 
 
grub-install /dev/sda
grub-install /dev/sdb

В момент инсталляции загрузчика на sda каталог /boot/efi/ заполняется файлами. Для отказоустойчивости необходимо скопировать эти файлы с sda1 на sdb1…

 
 
mkdir /boot/efi2
mount /dev/sdb1 /boot/efi2
cp -RT /boot/efi /boot/efi2

… и добавить второй диск в список UEFI, чтобы система знала, что на нем тоже есть все необходимые файлы

 
 
efibootmgr  -c -g -d /dev/sdb -p 1 -L "debian 2" -l '\EFI\debian\shimx64.efi'

Таким образом у нас оба диска будут в списке загрузчика и при смерти любого из них система будет способна загрузиться.
Используя утилиту efibootmgr в дальнейшем можно удалить из списка замененные диски, а для добавленных дисков нужно будет повторить шаги второго диска:
1. скопировать таблицу разделов,
2. отформатировать первый раздел и скопировать на него файлы EFI,
3. добавить второй раздел в существующий рейд,
4. заинсталлировать на диск grub,
5. добавить этот диск в UEFI.

Выходим из chroot

 
 
exit

Действия в консоли Live-CD

Перезагружаемся

 
 
reboot

Вывод

Обеспечить отказоустойчивость системы на рейд-массиве можно путем создания EFI-раздела на каждом диске, копировании на него файлов EFI и добавлении в список загрузчика при помощи утилиты efibootmgr.

Видео, в котором я последовательно показываю весь процесс с момента создания виртуальной машины:

 

Использованные материалы

См. также

Debian 10 Buster + openbox (установка и настройка)

Классный скрипт для конвертации в utf8

Запарило пересохранять субтитры, которые часто выкладывают в вин-кодировке. Нашел клевый скрипт на питоне (а значит и под виндой можно юзать) для конвертации из любой кодировки (исходная автоопределяется) в UTF8. Навесил его как кастомную команду для *.srt в Double Commander, который также юзаю в обеих системах — стало совсем хорошо =)

 
 
#!/usr/bin/env python3
import os
import sys
from chardet import detect
srcfile = sys.argv[1]
tmpfile = sys.argv[1] + '.tmp'
bakfile = sys.argv[1] + '.bak'
# get file encoding type
def get_encoding_type(file):
    with open(file, 'rb') as f:
        rawdata = f.read()
    return detect(rawdata)['encoding']
from_codec = get_encoding_type(srcfile)
# add try: except block for reliability
try: 
    with open(srcfile, 'r', encoding=from_codec) as f, open(tmpfile, 'w', encoding='utf-8') as e:
        text = f.read() # for small files, for big use chunks
        e.write(text)
    os.rename(srcfile, bakfile) # backup old encoding file
    os.rename(tmpfile, srcfile) # rename new encoding
    
except UnicodeDecodeError:
    print('Decode Error')
except UnicodeEncodeError:
    print('Encode Error')

mergerfs: прозрачное объединение дисков (файловых систем)

The Perfect Media Server 2016Сегодня хочу рассказать о достаточно нетипичном решении для объединения дисков в один массив. Начну с юзкейса.

У меня есть домашняя файлопомойка, которая построена на классическим RAID5. Инфа на ней хранится, прямо скажем, не критической важности, но все же я предпочитаю ее иногда бэкапить, чтобы хотя бы копия за прошлый год у меня где-то валялась. Разумеется, мне не хочется тратить большие деньги на бэкапные диски, поэтому, как правило, это  старые, относительно небольшого объема, разнокалиберные харды из серии «что было под рукой».

Понятно, что классическим способом получения большого тома из нескольких дисков, является объединение их через LVM, или сборка RAID0. Однако, учитывая,что диски старые и посыпаться могут, например, на этапе восстановления информации с них, мне бы не хотелось рисковать всем таким массивом. Хотелось бы объединить диски в него так, чтобы каждый отдельный диск нес на себе самостоятельную файловую систему, которую можно было бы смонтировать отдельно. Допустим, в массиве из 3х дисков один умер — я смонтировал два оставшихся диска отдельно и спокойно скопировал с них инфу.

Удивительно, но когда я полез гуглить такую хотелку, оказалось, что решение уже придумано и называется mergerfs.

Работает оно ровно так — вы монтируете ваши диски по отдельности, а потом при помощи утилиты mergerfs объединяете их в виртуальную фс.

 
 
mergerfs -o defaults,allow_other,use_ino,category.create=mfs,moveonenospc=true,minfreespace=1M  /tmp/backups/vol1:/tmp/backups/vol2 /backup

При этом файлы пишутся то на один диск, то на второй, для балансировки свободного места. При этом любой конкретный файл будет лежать только на одном реальном диске и его можно будет с него прочитать.

 
 
df -h | egrep "Filesystem|backup"
 
 
Filesystem                                      Size  Used Avail Use% Mounted on
/dev/mapper/backup-backup                       3.6T  2.6T  858G  76% /tmp/backups/vol1
/dev/mapper/backup2-backup                      916G   12G  858G   2% /tmp/backups/vol2
vol1:vol2                                       4.5T  2.6T  1.7T  61% /backup
 
 
ls /tmp/backups/vol1/Public/Video/Movies/Qatsi_Trilogy/
 
 
'1. Koyaanisqatsi (1982) 1080p.mkv'
 
 
ls /tmp/backups/vol2/Public/Video/Movies/Qatsi_Trilogy/
 
 
'2. Powaqqatsi (1988) 1080p.mkv'
 
 
ls /backup/Public/Video/Movies/Qatsi_Trilogy/
 
 
'1. Koyaanisqatsi (1982) 1080p.mkv' '2. Powaqqatsi (1988) 1080p.mkv'

Как можно видеть: на одном смонтированном томе виден один файл, на втором — второй, а в точке монтирования mergerfs — оба.

Схема из man mergerfs:

 
 
              A                B        =       C
              /disk1           /disk2           /merged
              |                |                |
               -- /dir1         -- /dir1         -- /dir1
              |   |            |   |            |   |
              |    -- file1    |    -- file2    |    -- file1
              |                |    -- file3    |    -- file2
               -- /dir2        |                |    -- file3
              |   |             -- /dir3        |
              |    -- file4        |             -- /dir2
              |                      -- file5   |   |
               -- file6                         |    -- file4
                                                |
                                                 -- /dir3
                                                |   |
                                                |    -- file5
                                                |
                                                 -- file6

Конечно, нельзя рекомендовать это решение там, где вы имеете надежное оборудование и вам важна скорость — mergerfs работает через fuse, так что в любом случае это компромисс и не замена RAID0. Но в случае подобном моем — это однозначно лучший вариант, который можно придумать.

PS: К слову, mergerfs не единственная виртуальная ФС такого типа. Изначально я наткнутся на mhddfs, которая даже есть в репозитории debian. Однако, как я понял, ее разработка завяла, а вот тут пишут, что в ней есть баги и лучше таки использовать mergerfs.

Borg Backup: Cache is newer than repository.

Ошибка:
«Cache is newer than repository — do you have multiple, independently updated repos with same ID?»
может возникнуть, если репозиторий был восстановлен из бэкапа.

Лечится выполнением команды (на стороне клиента)

 
 
rm -rf ~/.cache/borg/
mv ~/.config/borg/security{,_bak}

Заполнение mp3-тегов скриптом

Довелось скачать саундтрек к игре в виде кучи файлов без тегов вообще.

Захотелось на скорую руку заполнить хотя бы названия и номера треков (альбом/год/жанр — одинаковые для всех, с этим все сильно проще).

Для начала из имени каждого файла нужно вычленить название трека. Используем sed в однострочном цикле для разделения имени файла на три блока. Блоки в sed выделяются экранированными скобками: начало — \(, конец — \)

 
 
                                                       вычленяем блок №2
                                                        |             |
 
 
for file in *.mp3; do name=$(sed "s/\(^.*_.\{1,3\}_\)\(.*\)\(\.mp3\)/\2/" <<< $file); echo $name ; done;
 
 
                                          |                     |    
           блок №1: начало строки, любые символы,          блок №3: .mp3
                    подчеркивание, 1-3 любых символа,
                    подчеркивание

Вывод:

 
 
chat_thiscouldbeAWESOME
lab sewers
chat_downthe
...

(да, если вы решаете проблему с помощью регулярных выражений — у вас уже 2 проблемы, но в данном случае это отличное решение).

Убедившись что имена получаются корректные, меняем echo $name на редактор тегов mid3v2

 
 
for file in *.mp3; do name=$(sed "s/\(^.*_.\{1,3\}_\)\(.*\)\(\.mp3\)/\2/" <<< $file); mid3v2 -t "$name" "$file" ; done;

Самое сложное сделано. Теперь номера треков (всего их 46, так что это число я подставляю вручную):

 
 
i=1; for file in *.mp3; do mid3v2 -T  "${i}/46" "$file" ; ((i+=1)); done;

Все одинаковые для треков теги заполняются совсем просто, например год:

 
 
for file in *.mp3; do mid3v2 -y 2010  "$file" ; done;

PS: утилита mid3v2 (рекомендуется как полностью поддерживающая v2/utf8-теги) входит в питоновский пакет mutagen и ставится примерно так (для debian/ubuntu)

 
 
apt install python3-mutagen

или так (установка в пользовательский профиль из репозитория pypi)

 
 
pip3 install --user mutagen

Debian 10 Buster + openbox (установка и настройка)

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

Читать: Debian 10 Buster + openbox (установка и настройка)