Метка: Linux

  • Обновите свои SSH-ключи до Ed25519

    closeup photo of Yale 19 key against black background
    Photo by Matt Artz on Unsplash

    Привет. Это мой самостоятельный перевод некогда случайно найденной мной оригинальной статьи Upgrade Your SSH Key to Ed25519, автор — Risan Bagja, ныне веб-разработчик из Швеции.

    Благодаря ей я когда-то чуть скорректировал свой взгляд на SSH и стал использовать именно такие ключи. В современном мире они без проблем генерируются и принимаются буквально где угодно, без каких-либо настроек. Читатель моего блога, должно быть, заметил, что я использовал этот алгоритм при настройке Termux.

    В статье идёт речь о том, как сгенерировать и использовать ключи с алгоритмом, отличным от набившего оскомину RSA, почему следует отказываться от RSA и что даёт этот ваш Ed25519.

    Следует обратить внимание на дату оригинальной статьи — ноябрь 2017. За прошедшие до сего момента 5 лет что-то могло существенно измениться.

    Далее — текст перевода.

    (далее…)
  • Настройка среды php-разработки с нуля на NetBeans + php + docker + xdebug3

    Привет. Это здоровенный мануал-шпаргалка по настройке этой IDE для php-разработки. Здесь будет много текста и картинок.

    Полагаю, он больше сгодится для российских и белоруских разработчиков, переходящих c PhpStorm, ибо есть повод. В этом контексте было решено построить себе запасной инструментарий. А ещё я всё-таки закрыл гештальт и познакомился с Netbeans, как давно хотел.

    На деле эта IDE во многих отношениях проще шторма, но местами и переусложнена. Будь готов многого лишиться. Постараюсь раскрыть здесь это поподробнее. Поэтому статья иногда будет дополняться и корректироваться.

    Версия Netbeans на сию секунду — 24.

    В этой статье я установлю NB, настрою его, разверну тестовый проект с php8.3 и xdebug3 на контейнерах и настрою отладку php-скриптов в разных позах.

    Я обкатал стек на двух ПК, так что сетап проверен.

    (далее…)
  • Немного про графические оболочки на Linux и за что я в итоге полюбил KDE

    Photo by Nayam on Unsplash

    Пост про поиски и вкусовщину.

    Я уже упомянул, что перелез на KDE на обоих своих компах, и дома, и на работе. Но этому предшествовал долгий поиск того самого, единственного.

    Впервые я погрузился в Linux, когда отдал маме свой старый Hasee, сидеть в одноквасниках. На тот момент у него уже был удалён экран: в корпусе разломались все крепления и матрица с уже нерабочей подсветкой отправилась в утиль. Ноут цеплялся к внешнему монитору и продолжал сносно работать по мере сил.

    А силёнок у него было немного, зато ALT Linux 6 (а может и 7, не помню) с иксфейсом (xfce) вполне годно вытягивал огнелиса с мультимедией. Большего от него не требовалось.

    Тогда я пробовал чем-то заменить xfce, но это было зря — ноут не вытягивал. Это всё, что я помню.

    (далее…)
  • DavFS2. Куда утекает свободное место? Got error 28 from storage engine

    DavFS2. Куда утекает свободное место? Got error 28 from storage engine

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

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

    Однажды утром, после свежего бекапа, MySQL стал падать с ошибкой:

    Got error 28 from storage engine

    Эта ошибка возникает во время выборки записей из БД. Поскольку выборка хранится в кеше на диске и в этот момент возникает ошибка, значит что-то с ним не так. Самое банальное — закончилось место. По факту так и оказалось. СУБД просто негде было хранить файлы кеша.

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

    Начал поиски обжоры.

    (далее…)
  • Резервное копирование базы данных на Cron с выгрузкой в облако на примере Яндекс.Диск. Версия 1.

    Резервное копирование базы данных на Cron с выгрузкой в облако на примере Яндекс.Диск. Версия 1.

    Привет.

    Тут я расскажу о самом простом способе создания бекапов БД на сервере, о выгрузке их в Яндекс.Диск. Я написал скрипт, который всё это выполняет.

    Он приведён поэтапно, можешь скопировать пункты 4.1-4.5, убрав оттуда заголовки, и получишь готовый скрипт. Или можешь скачать, ссылка будет в конце. А лучше прочитать пост и вникнуть в суть происходящего.

    ОС на сервере — CentOS 6.7
    Версия СУБД — MySQL 5.5 (да, знаю, старая)

    Скрипт будет вертеться на сron, конечно же. Это чтобы само всё. Но это в конце.

    Монтирование Я.Диска в систему.

    1.1 Ставим davfs2 систему:

    yum install davfs2

    1.2 Создаём папку, в которую у нас будет монтироваться удалённое хранилище:

    mkdir /mnt/yadisk

    1.3 В файл /etc/davfs2/secrets пишем:

    /mnt/yadisk полныйадресemail@yandex.ru пароль

    1.4 В файле /etc/fstab указываем настройки монтирования хранилища (в одну строку, конечно):

    https://webdav.yandex.ru/ /mnt/yadisk davfs user,rw,_netdev,file_mode=600,dir_mode=700 0 1

    В конце файла должна быть пустая строка.

    Разгадку этого заклинания можно разобрать вот тут: rus-linux.net (отлично всё расписано)

    1.5 Тестируем:

    mount /mnt/yadisk # монтирование
    df -h /mnt/yadisk # проверка свободного места

    В результате должно отобразиться свободное место на Яндекс.Диске, типа того:

    [root@server ~]# mount /mnt/yadisk
    [root@server ~]# df -h /mnt/yadisk
    Filesystem            Size  Used Avail Use% Mounted on
    https://webdav.yandex.ru/
                           10G  1,8G  8,3G  18% /mnt/yadisk

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

    umount /mnt/yadisk # Размонтируем диск

    Три-четыре. Закончили упражнение.

    Делаем дампы базы данных

    Дамп базы данных создаётся штатной утилитой mysqldump, которая идёт в комплекте с MySQL. Подробнее о ней можно прочесть здесь: MySQL.ru. Я же покажу здесь только необходимое мне самому.

    Синтаксис всей команды, например, таков:

    mysqldump --host=localhost --user=root --password=1234 -q --default-character-set=utf8 mybigdatabase > /home/mybigdatabase.sql

    Разберёмся с этой командой:

    —user — Имя пользователя БД
    —password — Его пароль
    —host — Адрес базы данных (скорее всего это localhost)
    —default-character-set — Кодировка текста дампа (скорее всего, это будет utf8)
    -q — Вывод текста дампа непосредственно на стандартный вывод stdout без буферизации запроса. Вообще, этот ключик нам необязателен, ибо у нас будет прямая запись вывода в файл. Но без него оно нафиг не надо, а с ним пусть будет.
    mybigdatabase — Имя базы данных
    > — Перенаправление вывода с перезаписью
    /home/mybigdatabase.sql — …например, в этот файл

    Можешь поиграться, чего-нибудь подампить, если есть чего.

    Упаковка дампа

    Используем команду gzip таким простым образом:

    gzip /home/mybigdatabase.sql

    В этой же папке образуется файл mybigdatabase.sql.gz, который меньше исходного на порядки.

    Можно использовать tar, но придётся вносить правки в скрипт. Если хочешь заморочиться — пожалуйста, но особой разницы не будет.

    tar -czf mybigdatabase.tar.gz /home/mybigdatabase.sql

    Всё.

    Объединение вышеописанного

    Теперь определяемся что и зачем будет делать наш скрипт. Всё очень просто:

    1. Инициализация — готовим переменные, параметры, пути, адреса;
    2. Создание дампа — собственно, бекапа БД;
    3. Упаковка дампа — для экономии места;
    4. Отправка бэкапа в облака — на случай смерти локального файла:
      1. Монтирование хранилища;
      2. Копирование файла в хранилище;
      3. Размонтирование хранилища;
    5. Завершение — выводим сообщения с результатами и итогами работы скрипта.

    Дальше я буду описывать это уже самими командами.

    Создаём файл db_backup.sh там, где душе угодно. Мне угодно в домашней папке рута.
    Пишем в него нижеследующее.

    4.1 Инициализация:

    #!/bin/bash
    
    # Данные для работы с БД
    DBHOST=localhost # Адрес БД
    DBUSER=root # Имя пользователя базы данных
    DBPASSWD=1234 # Пароль от базы данных
    DBNAME=mybigdatabase # Имя базы данных для резервного копирования
    DBCHARSET=utf8 # Кодировка базы данных (utf8)
    
    # Даты
    DATE=`date +%F` # Префикс для структурирования бекапов (формат: 2017-05-22)
    DATETIME=`date +%F-%H-%M-%S` # Полная текущая дата и время (формат: 2017-05-22-12-23-34)
    
    # Локальное хранилище
    LOCALDIR=/root/db_backup # Полный путь к каталогу, где будут храниться резервные копии
    LOCALPATH=$LOCALDIR/$DATE # Полный путь к папке за сегодня
    LOCALFILE=$LOCALPATH/$DBNAME-$DATETIME.sql # Полный путь к файлу дампа
    LOCALFILEGZ=$LOCALFILE.gz # Полный путь к архиву дампа
    # Путь к бекапу будет выглядеть так:
    # /root/db_backup/2017-05-22/mybigdatabase-2017-01-01-12-23-34.sql.gz
    
    # Облачное хранилище
    CLOUDUSE=1 # Копировать ли в облако? Закомментировать строку, если не надо
    CLOUDMNT=/mnt/yadisk # Точка монтирования облака относительно корня
    CLOUDDIR=db_backup # Папка в облаке, куда будут лететь файлы (внутри папки CLOUDMNT, т.е. без / в начале)
    CLOUDPATH=$CLOUDMNT/$CLOUDDIR/$DATE # Полный путь к папке текущей даты в облаке относительно корня
    CLOUDFILE=$CLOUDPATH/$DBNAME-$DATETIME.sql # Полный путь к файлу дампа в облаке
    CLOUDFILEGZ=$CLOUDFILE.gz # Полный путь к архиву в облаке
    
    # Путь к бекапу на примонтированном хранилище будет выглядеть так:
    # /mnt/yadisk/db_backup/2017-05-22/mybigdatabase-2017-01-01-12-23-34.sql.gz
    
    # Начало процесса
    echo "[-----------------------------[`date +%F-%H-%M-%S`]-----------------------------]"
    echo "[`date +%F-%H-%M-%S`] Starting backup"

    4.2 Создание дампа:

    if ! [[ -d $LOCALPATH ]]; then # Если нет папки за сегодня
     mkdir $LOCALPATH 2> /dev/null # создаём её, ошибки игнорируем
    fi
    echo "[`date +%F-%H-%M-%S`] Generate a database dump: '$DBNAME'..."
    mysqldump --user=$DBUSER --host=$DBHOST --password=$DBPASSWD -q --default-character-set=$DBCHARSET $DBNAME > $LOCALFILE
    if [[ $? -gt 0 ]]; then
     # если дамп сделать не удалось (код завершения предыдущей команды больше нуля) - прерываем весь скрипт
     echo "[`date +%F-%H-%M-%S`] Dumping failed! Script aborted."
     exit 1

    4.3 Упаковка дампа:

    else # иначе - упаковываем его
     echo "[`date +%F-%H-%M-%S`] Dumping successfull! Packing in GZIP..."
     gzip $LOCALFILE # Упаковка
     if [[ $? -ne 0 ]]; then # Если не удалась
      echo "[`date +%F-%H-%M-%S`] GZipping failed! SQL-file will be uploaded."
      GZIP_FAILED=1 # Создаём флажок, что упаковка сорвалась
     else
      echo "[`date +%F-%H-%M-%S`] Result file: $LOCALFILEGZ"
     fi

    4.4 Отправка в облака:

    if [[ $CLOUDUSE -eq 1 ]]; then # Если задано копирование в облако - делаем всякое такое 
     mount | grep "$CLOUDMNT" > /dev/null # Проверяем примонтировано ли уже у нас облако (вывод не важен) 
     if [[ $? -ne 0 ]]; then # Если нет 
      mount $CLOUDMNT # значит монтируем 
     fi 
     if [[ $? -eq 0 ]]; then # если монтирование успешно - копируем туда файл 
      echo "[`date +%F-%H-%M-%S`] Cloud: successfully mounted at $CLOUDMNT" 
      echo "[`date +%F-%H-%M-%S`] Cloud: copying started => $CLOUDFILEGZ" 
      if ! [[ -d $CLOUDPATH ]]; then # Если в облаке нет папки за сегодня 
       mkdir $CLOUDPATH 2> /dev/null # создаём её, ошибки игнорируем 
      fi 
      if [[ -f $LOCALFILEGZ && GZIP_FAILED -ne 1 ]]; then # Если у нас архивирование выше не сорвалось 
       cp -R $LOCALFILEGZ $CLOUDFILEGZ # Копируем архив 
      else 
       cp -R $LOCALFILE $CLOUDFILE # Иначе - копируем большой тяжёлый дамп 
      fi 
      if [[ $? -gt 0 ]]; then # Если не скопировался - просто сообщаем 
       echo "[`date +%F-%H-%M-%S`] Cloud: copy failed." 
      else # Если скопировался - сообщаем и размонтируем 
       echo "[`date +%F-%H-%M-%S`] Cloud: file successfully uploaded!" 
       umount $CLOUDMNT # Размонтирование облака 
       if [[ $? -gt 0 ]]; then # Сообщаем результат размонтирования (если необходимо)
        echo "[`date +%F-%H-%M-%S`] Cloud: umount - failed!" 
       fi # Конец проверки успешного РАЗмонтирования 
      fi # Конец проверки успешного копирования 
     else # если монтирование НЕуспешно - сообщаем 
      echo "[`date +%F-%H-%M-%S`] Cloud: failed to mount cloud at $CLOUDMNT" 
     fi # Конец проверки успешного монтирования 
    fi # Конец проверки необходимости выгрузки в облако

    4.5 Завершение

    fi # Конец проверки успешного выполнения mysqldump
    echo "[`date +%F-%H-%M-%S`] Stat datadir space (USED): `du -h $LOCALPATH | tail -n1`" # вывод размера папки с бэкапами за текущий день
    echo "[`date +%F-%H-%M-%S`] Free HDD space: `df -h /home|tail -n1|awk '{print $4}'`" # вывод свободного места на локальном диске
    echo "[`date +%F-%H-%M-%S`] All operations completed!"
    exit 0 # Успешное завершение скрипта

    5. Устанавливаем задачу в cron

    Из под root запускаем crontab -e. Подробности по работе с crontab можно найти здесь: Codenet.ru | Ubuntu.ru

    В окне запустившегося редактора пишем нижеследующее:

    # в качестве командного интерпретатора использовать /bin/sh
    SHELL=/bin/sh
    # результаты работы отправлять по этому адресу
    MAILTO=example@site.com
    # Запуск скрипта дампа боевой БД и запись в лог
    0 8,20 * * * bash ~/db_backup.sh >> ~/db_backup/db_backup.log

    Важна последняя команда:

    • 0 — в ноль минут 8,20 — в 8 часов утра и 20 часов вечера (без пробела) * — каждый день — каждой недели * — каждого месяца;
    • запускается интерпретатор bash;
    • который получает путь к скрипту ~/db_backup.sh (а равно /root/db_backup.sh, если всё происходит под рутом);
    • выполняет его;
    • а вывод дописывается (>>) в файл лога ~/db_backup/db_backup.log

    Сразу разъясню простой момент с угловыми скобками:

    • > (равносильно 1> ) — перенаправление всего вывода в указанное место с перезаписью. Существующий файл перезаписывается полностью, отсутствующий — создаётся.
    • 2> — перенаправление вывода ошибок stderr в указанное место. Если отправить в /dev/null, то сообщений об ошибках в выводе на экране не окажется.
    • >> — перенаправление вывода без перезаписи. Если файла нет — он создаётся, если файл есть — результат дописывается в его конец. Подробнее о перенаправлениях выводов можно прочесть здесь: OpenNET.ru. Там очень богатый функционал и синтаксис.

    Пример конечного лога

    [-----------------------------[2017-01-01-17-40-50]-----------------------------]
    [2017-01-01-17-40-50] Run the backup script...
    [2017-01-01-17-40-50] Generate a database backup: 'mybigdatabase'...
    [2017-01-01-17-44-17] Dumping successfull! Packing in GZIP...
    [2017-01-01-17-47-36] Result file: /root/db_backup/2017-01-01/mybigdatabase-2017-01-01-17-40-50.sql.gz
    [2017-01-01-17-47-38] Cloud: successfully mounted at /mnt/yadisk.
    [2017-01-01-17-47-38] Cloud: copying started => /mnt/yadisk/db_backup/2017-01-01/mybigdatabase-2017-01-01-17-40-50.sql.gz
    [2017-01-01-17-48-58] Cloud: file successfully uploaded!
    [2017-01-01-17-48-58] Stat datadir space (USED): 666M   /root/db_backup/2017-01-01
    [2017-01-01-17-48-58] Free HDD space: 100500G
    [2017-01-01-17-48-58] All operations completed!

    Заключение

    На этом пока всё.

    В планах сделать лимиты на объём папок с бекапами. При превышении заданного лимита — удалять старые бекапы.

    Это будет во второй версии. Когда-нибудь.

    Принимаю инфу об ошибках, критику и предложения.