LINUX.ORG.RU

Избранные сообщения Imker

Настраиваем и используем ZSH вместо Bash, или превращаем терминал в раскраску

Статьи — Администрирование
Настраиваем и используем ZSH вместо Bash, или превращаем терминал в раскраску

Я не буду расписывать преимущества ZSH над Bash, отмечу лишь то, что ZSH используется по дефолту во многих дистрибутивах Linux, а также с недавних пор и в macOS (тут должна быть шутка про Торвальдса и его макбук). Главной причиной повсеместной замены bash на zsh является встроенный механизм модулей, поверх которого было навалено такое великолепие, как Oh My Zsh.

( читать дальше... )

 , ,

rtxtxtrx
()

M3U плейлисты на вашем ПеКа

Форум — Talks

Сидел свою коллекцию ссылок разбирал, в том числе на видео по разной тематике, оно разбросано по разным плейлистам и хуже того по разным площадкам, вопщем проще было тематические плейлисты из разных мест объединить в один M3U файлик, выкинуть ненужное и смотреть уже на локальном плеере, а не прыгать в браузере туда сюда. Для этой специфической хотелки вот утилитка, может кому надо , это просто обёртка над yt-dlp.

Пример

m3u-tube 'https://youtube.com/playlist?list=PL4FxkpKzI-TpB2seZeP4IZ8_NSad7G9hm&feature=shared' 

Вывод

#EXTM3U
#EXTINF:-1,'Bill Gates - Deposition Part 4 of 12:'
https://www.youtube.com/watch?v=HhdDZk45HDI
#EXTINF:-1,'Bill Gates - Deposition Part 5 of 12:'
https://www.youtube.com/watch?v=n_yI27mVHc4
#EXTINF:-1,'Bill Gates - Deposition Part 6 of 12:'
https://www.youtube.com/watch?v=GDjAYvnKL8c
#EXTINF:-1,'Bill Gates - Deposition Part 7 of 12:'
https://www.youtube.com/watch?v=aqNE7qGHiLQ
#EXTINF:-1,'Bill Gates - Deposition Part 8 of 12:'
https://www.youtube.com/watch?v=v8QbaOvFHyk
#EXTINF:-1,'Bill Gates   Deposition Part 9 of 12:'
https://www.youtube.com/watch?v=odJNphz9GPg
#EXTINF:-1,'Bill Gates   Deposition Part 11 of 12:'
https://www.youtube.com/watch?v=YBPITEcCYb0
#EXTINF:-1,'Bill Gates   Deposition Part 12 of 12:'
https://www.youtube.com/watch?v=is0LVBlYPsM

Справка

[Usage: m3u-tube -u [URL] -o [FILENAME]

This simple util generate M3U playlist from
youtube, rutube playlists or maybe other web sites.
Multiple playlists can be combined into one M3U playlist.
yt-dlp does all the work, m3u-tube just generates the output.

Argsuments:

    -                       Read one or more URL from pipe
    -h --help               This help message
    -u --url     [URL]      One or more playlist URL links
    -i --input   [FILENAME] Filename for read URL links
    -o --output  [FILENAME] Falename for save M3U playlist
    -v --verbose            Show processing log, and enable yt-dlp warnings
    [URL]                   One or more playlist URL links, divide space

    If use multiple URL links, they combine in single M3U playlist.
    Multiple links are separated by a space or new line. Bad links or
    links without playlists ignored with information message.

Examples:

    m3u-tube -i urls.txt -o play.m3u    # create M3U from file with URL links
    m3u-tube 'url' -v > out.m3u         # create M3U from link, show processing
    m3u-tube 'url1' 'url2' 'url3'       # concat three playlists to one M3U
    cat urls.txt | m3u-tube -           # create M3U from pipe data
    cat urls.txt | m3u-tube url1 - url2 # combine pipe and argumens

Notice:

    If playlists not collected... Well, sometimes websites broken,
    You need update yt-dlp to latest or add changes in yt-dlp for support.
    For check what is broken try run it:

    yt-dlp --flat-playlist --print url 'your_url_playlist'

See also:

    yt-dlp(1)


Исходники

git clone https://gitflic.ru/project/blogdron/m3u-tube.git

Всё я спать. В 5 утра огород копать :(
Досвиданья

 , ,

LINUX-ORG-RU
()

Шрифты с отличающейся кириллицей

Форум — Development

Лет 5 ждал, пока кто-то сделает, и в итоге сам сделал. Задача состояла в том, чтобы сделать шрифт, в котором визуально отличаются пары букв, которые обычно выглядят одинаково, например, „с“ и „c“. Тогда при любой работе с двуязычными текстами в программировании можно будет избегать ошибок, связанных с перепутыванием этих букв.

https://tvoygit.ru/budden/dr_cyr

Сделан необходимый минимум, один моноширинный шрифт - модифицированный Ubuntu Mono, и один пропорциональный - модифицированный Golos Text, одно начертание для каждого. Проигнорировано всё, кроме русской кириллицы и основной латиницы, возможны косяки. Идея, заложенная в шрифты, немного отличается.

Художники обругали, простой народ похвалил, на данный момент порядка 4 внедрений.

 , ,

den73
()

oculante — просмотрщик изображений с аппаратным ускорением

Форум — Talks

Быстрый, кроссплатформенный (Win, Mac, Linux и NetBSD).

Есть базовое редактирование: обрезка, изменение размера, раскрашивание, контрастность, HSV, поворот, размытие, шум и т. д.

Плюс немного рисование.

https://github.com/woelper/oculante

Всё приложение — один бинарный файл

 ls -l /usr/bin/oculante 
-rwxr-xr-x 1 root root 34059824 мая 27 14:40 /usr/bin/oculante

(у lazpaint аналогично, один бинарник, но размер файла в несколько раз меньше…)

$ ls -l /usr/bin/lazpaint 
-rwxr-xr-x 1 root root 10701336 авг 24  2022 /usr/bin/lazpaint

 , oculante, ,

greenman
()

Делаем машину времени с Btrfs

Статьи — Администрирование
Делаем машину времени с Btrfs

Btrfs – это файловая система с легковесными снапшотами, которая позволяет создать самую настоящую машину времени, делая снимки состояния файловой системы (снапшоты) и монтировать их на лету. Этой файловой системе скоро стукнет 16, а значит уже можно ее попробовать.

( читать дальше... )

 , ,

rtxtxtrx
()

Включаем шифрование для DNS-запросов

Статьи — Администрирование
Включаем шифрование для DNS-запросов

Рассмотренные ниже приемы будут полезны для пользователей прокси-серверов/VPN и позволяют скрывать запрашиваемые по DNS имена доменов.
Время на чтение: ~5 минут.
Сложность: Middle AnyKey Developer (нужно уметь запустить терминал).

( читать дальше... )

 , , ,

rtxtxtrx
()

Игра «Бездна света» на свободном движке INSTEAD

Новости — Игры
Игра «Бездна света» на свободном движке INSTEAD
Группа Игры

Василий Воронков, автор игр «Переход» и «Лидия», а так же нескольких книг, выпустил новую игру «Бездна света».

Экипаж ГКМ «Грозный» отправляется к орбитальной станции «Кабирия», последнему рубежу исследованного человеком космоса, где ему предстоит столкнуться с чем-то нечеловеческим.

( читать дальше... )

>>> Скачать игру

 , , , ,

gloomy
()

Рабочий стол юриста v2

Галерея — Скриншоты

Решил запостить и свой рабочий стол. Предыдущий скриншот тут Рабочий стол юриста.

( читать дальше... )

 ,

mshewzov
()

Настройка Boot logo (Кастомизация)

Форум — General

У многих Boot logo (пингвины, показывающие количество потоков или ядер) не работает из коробки. В связи с этим небольшая памятка.

  1. В /boot/grub/grub.cfg в стоке linux предлагается убрать слово quiet (рядом со splash).
  2. В ядре (.config) отключить (закомментировать) #CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y Поставить is not set
  3. Включить boot logo в ядре: Device Drivers->Graphics->Boot logo (то, которое 224)
  4. Включить в ядре поддержку Framebuffer (вариативно, от системы)
  5. Поставить в grub.cfg нужный режим, например, vga=0x317 для 1024х768 (можно разными способами сделать).

Кастомизация (создание своего) Boot logo

  1. Заходим в /usr/src/linux/drivers/video/logo
  2. Удалим файлы: logo_linux_clut224.c и logo_linux_clut224.o (они генерируются при компиляции ядра)
  3. Отредактируем файл logo_linux_clut224.ppm в редакторе gimp по своему вкусу.
  4. Установим пакет netpbm
  5. Отредактируем количество цветов программой: ppmquant

ppmquant 224 logo_linux_clut224.ppm > logo_linux_clut224.ppm

  1. Переведем в ASCII формат Лого: pnmnoraw logo_linux_clut224.ppm > logo_linux_clut224.ppm

Для конвертации можно использовать промежуточный файл, предварительно переименовав logo_linux_clut224.ppm.

Логотип готов. Осталось перекомпилировать ядро.

P.S. Кстомизированное мной Boot Logo: https://disk.yandex.ru/i/jauzt48_ydk1zg

Пример: https://ibb.co/PcfVgD7

 ,

AnonymUser
()

Нейросети в Firefox, а-ля Яндекс.Браузер

Форум — General

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

Но оказывается, уже давно (с 2021 года) можно прикрутить данную фишку и на firefox. Суть проста:

  • Установка расширения Tampermonkey
  • Установка скрипта с github (форк)
  • При воспроизведении, нажать на всплывающий значок вверху-середине видео

Возможно понадобится дать разрешение на автовоспроизведение «аудио и видео» (значок в адресной строке).


Проверил на ютубе с BBC News, ok.
Источник с 4pda

p.s. Специально не упомянул Chrome, ‘конкуренты’ пусть горят синим пламенем. :)


Обновление:
Добавлена консольная vot-cli.

 , ,

krasnh
()

Правильные ключи для команды 'cp'

Форум — Admin

Hi, All!

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

Когда-то копировал каталоги с одного диска на другой на удаленной машине с использованием команды cp в фоне, т.е. подключался к машине по SSH, запускал команду копирования и отключался, а команда продолжала отрабатывать. К сожалению, забыл с помощью каких опций/ключей мне это удавалось сделать, весь man перерыл…

Заранее большое спасибо за помощь!

 ,

Zer0Mesh
()

Концепция автоматической настройки автономных ПК

Форум — Security

Всем привет!

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

Ситуация следующая - у меня большое число автономных компьютеров на Debian, которые нельзя подключить к интернету или локальной сети.

Я администратор безопасности и системный администратор в одном лице и я устал по каждой мелочи совершать обход всех ПК.

Одна смена пароля может затянуться на два дня, пока всех обойдёшь.

У меня работает система обновления баз антивируса с определённой флешкой (флешки кроме разрешённых блокированы).

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

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

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

Человек подключает флешку, компьютер выполняет скрипт (например смены пароля) и все счастливы.

Единственное «но» в безопасности такой реализации.

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

Второй скрипт, размещён на всех автономных ПК. Он предназначен для расшифровки скриптов с настройками и их выполнения. На автономных ПЭВМ так же размещается приватный ключ для расшифровки.

Первый скрипт (шифрование):

#!/bin/bash

file_path_to_encrypt=$1
dir_path_to_result=./task

rm -Rf ./task && mkdir $dir_path_to_result

openssl rand 214 > ./key_to_work.key # Генерируем случайный ключ (он же пароль)

openssl enc -aes-256-ctr -pbkdf2 -in $file_path_to_encrypt -out $dir_path_to_result/encrypt_shell.sh -pass file:./key_to_work.key # Используя симметричное шифрование шифрую файл используя этот ключ (пароль)

openssl rsautl -encrypt -pubin -inkey public.pem -in ./key_to_work.key -out $dir_path_to_result/auth_key.pem # Используя публичный ключ шифрую пароль

rm ./key_to_work.key # Удаляю пароль в открытом виде

Второй скрипт (расшифровка и выполнение):

#!/bin/bash

file_path_to_decrypt="$1"

openssl rsautl -decrypt -inkey private.pem -in ./task/auth_key.pem -out ./key_to_work.key # Расшифрую пароль используя приватный ключ (асимментричное шифрование)

if [[ $? == "0" ]] # Если расшифровка прошла успешно
  then
    : # Значит скрипт зашифровал я, продолжаем работу
  else
    echo 'Скрипт не подтверждён. Завершаю работу.' # Иначе вывожу сообщение, удаляю открытый файл ключа, завершаю работу
    rm -f ./key_to_work.key
    exit 1
fi

openssl enc -d -aes-256-ctr -pbkdf2 -in $file_path_to_decrypt -out ./script.sh -pass file:./key_to_work.key # Расшифрую файл используя полученный пароль (симметричное шифрование)

/bin/bash ./script.sh # Запускаю расшифрованный скрипт

rm -f ./{key_to_work.key,script.sh} # Удаляю файлы пароля и скрипта

На «красоту» и оптимизацию кода прошу внимание не обращать. Это черновой вариант, просто чтобы посмотреть на концепцию.

Безопасно ли это? Какие тонкие места Вы видите в такой реализации (например, возможность замены инструкций скрипта настроек)?

Заранее спасибо!

 

Sandro331k
()

Найти случайно затёртый с диска исходник

Форум — Development

В очередной (третий-четвёртый за несколько последних лет) раз затерев по неаккуратности файл с кодом (cp не в ту сторону), на который был потрачен предыдущий час или больше, и который ещё не был закоммичен, решил что искать его с помощью dd и grep - занятие утомительное. Слышал тут про binwalk, но, посмотрев описание, то ли не осилил найти способ её для этой цели использовать, то ли она и правда для другого.

Написал свою прогу в итоге: исходник.

Компилировать: gcc -o rawsearch rawsearch.c

Синтаксис: ./rawsearch if=/dev/sda8 str=some_string_from_file

Прога найдёт на диске все текстовые блоки (внимание: если файл фрагментирован то он будет не одним блоком а несколькими, прога их сцеплять не будет), что содержат эту строку и создаст пачку файлов с названиями found-NNN (NNN - байт где начинается) с этими текстами. Границы текстовых блоков определяются так:

static int is_binchar(char c) { return (c==127 || c>=0 && c<=6 || c>=14 && c!=27 && c<=31); }

(это символы которые по мнению проги в текстовых файлах не встречаются).

Возможно кому-то будет полезно.

Исходник максимально простой (всего 300 строк и 12кб), можно легко патчить под какие-то потребности по месту.

 , , ,

firkax
()

Как менять регистр при разорхивации?

Форум — Games

С наступающим, линукс-геймеры. После установки модов на Morrowind, всё превратилось в розовое месево. Посмотрев на это, я понял, что это из-за того, что оригинальные файлы игры названы капсом, а модифицированные нет. В Windows файловая система не чувствительна к регистру, поэтому при распаковке файлов, они автоматически заменяются. А я не могу выискивать три сотни конфликтующих файлов. Может есть архиваторы с нужной функцией или утилиты?

 , ,

kllk
()

У Вас маленький экран? Диалоги не влазят? РЕШЕНИЕ ПРОСТО! Как 1,2,3...

Форум — Desktop

Начнем с 1,2,3.
Окрываем эмулятор терминала и запускаем:

$xrandr --output LVDS1 --scale 1.25x1.25
(Вместо LVDS1 возможно придется указать другое значение, не знаю как его узнать кошерно, я подсмотрел в диалоге MATE: Система->Параметры->Оборудование->Экраны. У меня там картинка экрана: Ноутбук: LVDS1)

ВСЁ! Это работает на уровне системы, решение подсказали на LOR, когда я расхваливал Xfce с таким же решением в пункте меню.

Далее идем в Система->Параметры->Персональные->Запускаемые приложения и добавляем скажем: screenresize с параметрами: $xrandr --output LVDS1 --scale 1.25x1.25

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

Я являюсь владельцем древнего 10" нетбука который тут все рекомендуют выкинуть... Но впрочем он вполне работает, и с собой брать не так тяжело как толстую машинку....
Но всегда мучала проблема... Открываешь в Линуксовом десктопе какое нибудь модальное окно и оно больше чем 1024x600, кнопочки: «Применить», «Сохранить», «Идинафик» - находятся где то за нижней границей экрана.
Играясь с Manjaro Linux (Я его назвал Мажориком, хотя тут ходит Ник: Бомжара) я столкнулся с оконным менеджером Xfce, у которого прямо в меню настроек можно выставить масштаб 1.2 и всё стало вмещаться на УРА!
Расписал это здесь на форуме, и анонимус подсказал мне решение, ссылкой на: https://wiki.archlinux.org/title/HiDPI.

Теперь я знаю об этом рабочем решении и хочу поделиться им с другими!

 , ,

n0mad
()

Бекапилка вашего ПекА

Форум — Talks
- АХТУНГ, ВАХТУНГ, БАХТУНГ, ДРЯХТУНГ, АЛЯРМ, ВНИМАНИЕ
- ЭТОТ СКРИПТ ПРЕДОСТАВЛЯЕТСЯ КАК ЕСТЬ, Я НЕ НЕСУ НИКАКОЙ
- ОТВЕТСТВЕННОСТИ ЯВНОЙ ИЛИ КОСВЕННОЙ, ВАМ ЛИБО КОМУ ТО ЕЩЁ
- ПО ПРИЧИНЕ, ПОРЧИ И/ИЛИ УНИЧТОЖЕНИИ ВАШИХ ДАННЫХ 
- ЕСЛИ ВЫ НЕСОГЛАСНЫ, Я ЗАПРЕЩАЮ ВАМ ЗАПУСКАТЬ ЭТОТ КОД
- ДЕЙСТВУЙТЕ НА СВОЙ СТРАХ И РИСК, ВАШИ ЛЮБЫЕ СОМНЕНИЯ 
- КАСАТЕЛЬНО СКРИПТА ДОЛЖНЫ ВЕСТИ К ОТКАЗУ ОТ ЕГО ИСПОЛЬЗОВАНИЯ

Всё, теперь если у вас что-то пойдёт не так, то я чист.
И меня никто не будет ругать, гы :) Просто будте внимательный с тем,
какой каталог указывается для сохранения бекапов. А то ведь так и затереть чего важного можно случайно.
Вопщем решил поделится прост. Пусть будет.

Простой скрипт ручного бекапа наиболее важных файлов, использует
rsync и zip Настройка производится внутри стрипта. Описание
настройки бекапа тоже распологается внутри скрипта.
Типичное использование это ручной запуск в конце дня или по
завершению какой либо важной работы или перед сном :)
Используйте для бекапа, отдельный диск где нет ничего кроме бекапа!
Просто иначе, в бекапе нет никакого смысла.
Лично я просто на панельку кнопочку сделал, и перед отплытием в люльку тыкаю кнопочку.
Комп я не выключаю обычно, а если выключаю до явно дожидаюсь окончания бекапа, не проверял что будет если увести в сон во время бекапа, так что, лучше дождаться окончания.

Зависимости

mkdir zip rsync notify-send lua

Использование

Настроить скрипт, после чего просто его запускать. Так как вам удобно.

  • Обязательные параметры
    • source каталог или файл источник
    • dest каталог приёмник
  • Дополнительные параметры
    • secure применить пароль (требуется zip=true)
    • zip сжать в архив
    • mirror сделать точную копию и обновить им текущий каталог бекапа( или архив если zip=true)
    • versions сделать точную копию и пометить датой в отдельном каталоге (или архиве если zip=true)

Пример поля конфигурации:

  • {secure=true, zip=true, versions=true, source='~/.ssh/', dest='ssh'};

Значит что нужно сделать рекурсивный бекап каталога с ключами ssh и расположить бекап в каталоге с именем ssh. secure=true означает что данные будут запаролены, а zip что будут сжаты, versions=true означает что каждый новый бекап будет создавать новую копию ~/.ssh помеченную датой. Описание того какие есть ключи и как они работают друг с другом есть внутри скрипта, вместе с примерами уже готовой настройки.

Ключи можно опускать (не указывать) обязательными являются только source и dest Не указанные ключи считаются заданными как false так что вот такая запись валидна

  • {source='~/Изображения/', dest='картинки'}

И означает сделать копию каталога ~/Изображения в каталоге картинки внутри общего каталога бекапа backup_path=... при этом если это второй или последующий бекап и в каталоге ~/Изображения/ была удалена картинка, она не будет удалена в каталоге картинки это сделано специально, дабы максимизировать сохраняемые данные. Если нужна точная копия с удалением того чего уже нет в каталоге источнике то нужно дополнительно явно указать опцию mirror=true это же правило работает если включить флаг zip=true будет всё тоже самое, но уже в виде архива.

На заметку

В каталоге относительно котрого исполняется скрипт будет лог бекапа, на рабочий стол будут приходить уведомление о текущем статусе выполнения, в случае ошибки будет показaн код возврата В лог попадает информация о том какая именно команда потерпела неудачу, пароль присутцвующий в команде заменяется на звёздочки. В зависимости от типа настроенного бекапа(первый бекап будет всегда долгим), а вот последующие при отсуцтвии изменений будут быстрыми исключение это mirror и versions оба создают точную копию с нуля, а не пытаются обновить текущее содержимое бекапа. В случае если любая программа вернёт код возврата отличный от 0 выполнение всего бекапа прерывается, и повторно он не запустится пока не будет удалён lock файл, это сделано специально, чтобы выяснить причину, исправить её и в ручном режиме удалить lock файл название котрого есть в срипте, в логах и уведомлении на рабочий стол.:

Если вы бекапите например ~./vimrc в dest каталог myvimrc то он будет там лежать как есть, с точкой. Так что так же чтобы его увидеть в каталоге бекапа нужно нажимать ctrl+h. Ну, я так. На всякий случай.

Удалять из бекапов лишнее, и вообще контролировать влезет ли всё, это ваша забота =)
Нет опции отключения уведомлений. Предпочитаю явно знать что всё прошло гладко.
Логи бекапа тоже руками удалять.

Дадада, пароль на zip для ssh и gpg ключей хахахаха, но хоть что-то.
Сам внешний накопитель держите шифрованным если туда важное сохраняется.

Сам сриптик. Взял его как есть.

#!/usr/env lua
local backup_rule =
{
    --каталог куда будут размещаться все бекапы
    backup_path = '/media/$USER/STORAGE_SSD/backup';
    --пароль если используется secure=true, лучше использовать файл с паролем
    backup_pass = nil;
    --пароль для важныйх файлов, можно записать в файл дабы не светить
    backup_pass_file = "/home/$USER/Документы/backup_pass";
    ---------------------------------------------------------------------------
    backup_list =
    {
    -- backup critical --
    {secure=true, zip=true, versions=true, source='~/.ssh/',     dest='ssh'    };
    {secure=true, zip=true, versions=true, source='~/.gnupg/',   dest='gpg'    };
    {secure=true, zip=true, mirror=true,   source='~/.config/',  dest='cfg'    };
    {secure=true, zip=true, mirror=true,   source='~/.mozilla/', dest='firefox'};
    {secure=true, zip=true, mirror=true,   source='~/Документы/',dest='doc'    };

    -- diffrerent media --
    {secure=false,zip=true, mirror=true, source='~/Книги/', dest='book'};
    {secure=false,zip=true, mirror=true, source='~/Музыка/',dest='music'};

    -- backup multimedia --
    {secure=false, zip=false, versions=false, source='~/FAMILY_ARCHIVE/', dest='family'};

    -- backup dev stuff  --
    {secure=false, zip=false, versions=true, source='~/.gitconfig',dest='gitconfig'};
    {secure=false, zip=false, versions=true, source='~/.vimrc',    dest='vimrc'};
    {secure=false, zip=false, versions=true, source='~/.bashrc',   dest='bashrc'};
    {secure=false, zip=true,  versions=true, source='~/.vim/',     dest='vim'};

    -- backups source code --
    {secure=false, zip=true, mirror=true, source='/mnt/STORAGE/', dest='code'};

    };
};
-------------------------------------------------------------------------------
-- :secure=true   - шифровать ли сжатый бекап с паролем.
--                  создать архив и запаролить, zip должен быть zip=true
--                  явное указание zip=false или отсуцтвие ключа создаст ошибку
-- ----------------------------------------------------------------------------
-- :secure=false  - тоже самое поведение что и при zip=false
-- ----------------------------------------------------------------------------
-- :zip=true      - создать архив и добавить в него файлы если их нет в архиве
--                  если version=false то обновлять архив, добавляя новые
--                  файлы и обновля существующие, не удаляет отсуцтвующие
-------------------------------------------------------------------------------
-- :zip=false     - создавать бекап в каталоге dest если versions=false
--                  то клонировать source в dest, при повторном бекапе добавлять
--                  новые файлы и обновлять текущие, не удалять отсуцтвующие
--                  если versions=true создавать отдельный бекап в новом
--                  каталоге с датой бекапа, полностью отельный бекап.
-------------------------------------------------------------------------------
-- :versions=true - если zip=false то создать новый каталог с датой бекапа
--                  если zip=true  то создать новый архив с датой бекапа
-------------------------------------------------------------------------------
-- :mirror=true   - если zip=true то создаётся точная сжатая копия источника
--                  если при этом versions=false то текущий архив удаляет из
--                  себя файлы которых больше нет в источнике
--                  если zip=false то вместо архива создаётся точная копия
--                  источника с удалением файлов из каталога бекапа если их
--                  нет в источнике, тоже самое зеркалирование/клонирование
-------------------------------------------------------------------------------
-- :source        - файл или каталог который нужно бекапить, каталоги
--                  обрабатываются рекурсивно бекапя всё что есть
-------------------------------------------------------------------------------
-- :dest          - каталог внутри носителя для бекапа, оно же префикс
--                  добавляющийся к каталогам и/или архивам при versions=true
--                  отражает то бекап чего делается ОБЯЗАН БЫТЬ УНИКАЛЬНЫМ!!!!
-------------------------------------------------------------------------------
--        Если какого либо ключа нет то он считается равным false
-------------------------------------------------------------------------------
-- В случае если zip mkdir или rsync завершаться с кодом отличным от нуля
-- бекап тут же прекращается с уведомлением на рабочий стол и в лог ошибок
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
---- исполняет все команды, в случае ошибки прерывает всю работу
-------------------------------------------------------------------------------
local function execute(rule,command,exit_if_fail)
    local success, meta, code = os.execute(command..' >> backup-info.log');
    if (not success) then
       -- hide pass from output
       -- info log and messages
       if rule.backup_pass then
          command = command:gsub(rule.backup_pass,"********");
       end
       local msg = string.format('BACKUP ERROR %s %s %s',command,meta,code);
       io.stderr:write(msg..'\n');
       io.open('backup-error.log','a+'):write(msg);
       execute({},'notify-send  "'..msg..'" -u critical',false);
       if (exit_if_fail == true) then
          os.exit(127);
       end
       return success;
    end
    return success;
end
-------------------------------------------------------------------------------
--- информирует об ошибке и прерывает всю работу
-------------------------------------------------------------------------------
local function backup_fail(msg)
      io.stderr:write(msg..'\n');
      io.open('backup-error.log','a+'):write('\n'..msg..'\n');
      execute({},'notify-send -u critical "'..msg..'"',false);
      os.exit(127);
end
-------------------------------------------------------------------------------
--- просто информирует
-------------------------------------------------------------------------------
local function backup_info(msg)
      io.stdout:write(msg..'\n');
      local log = io.open('backup-info.log','a+');
      log:write('\n'..msg..'\n');
      log:close();
      execute({},'notify-send -u normal "'..msg..'"',false);
end
-------------------------------------------------------------------------------
--- проверяет используется ли в конфигурации пароль
-------------------------------------------------------------------------------
function check_need_pass(rule)
    for name,val in pairs(rule.backup_list) do
        if val.secure and val.secure == true then
           return true;
        end
    end
    return false;
end
-------------------------------------------------------------------------------
--- делает бекап K.O. :)
-------------------------------------------------------------------------------
local function make_backup(rule)
    if (rule.backup_path) then
       -- replaice $USER in path if we have ite
       rule.backup_path = rule.backup_path:gsub('$USER',os.getenv('USER'));
    else
       backup_fail('BACKUP ERROR backup_path not set, no place to save backup',true);
    end
    -- we use password?
    if (check_need_pass(rule) == true) then
        -- check pass contained in configuration
        if not rule.backup_pass and not rule.backup_pass_file then
           backup_fail('BACKUP ERROR you use secure option but backup_pass or backup_pass_file no set!',true);
        end
        -- if pass_file set read the password
        -- and override/write rule.backup_pass
        if (rule.backup_pass_file) then
           -- replaice $USER in path if we have ite
           rule.backup_pass_file = rule.backup_pass_file:gsub('$USER',os.getenv('USER'));
           local pass_file = io.open(rule.backup_pass_file);
           if (pass_file) then
              if rule.backup_pass then
                 backup_info('BACKUP WARNING rewrite backup_pass from backup_pass_file');
              end
              rule.backup_pass = pass_file:read('*l');
           else
              backup_fail('BACKUP ERROR '..rule.backup_pass_file..' no readable!',true);
           end
           pass_file:close();
        end
        -- maybe pass use only numbers force to string
        rule.backup_pass = tostring(rule.backup_pass);
        -- check small pass, no need but jut be
        if not rule.backup_pass or #rule.backup_pass <= 4 then -- kek cheburek 
           backup_info('BACKUP WARNING you backup_pass small, less or equal 4 symbols');
        end
    end
    -- info about starting
    backup_info("BACKUP START "..os.date());
    --first check, we have storage and access?
    execute(rule,'mkdir -p '..rule.backup_path, true);
    -- lockfile + uuid for exclude collisions
    local lockfile = '.lock-938448fc-1742-43e9-bff8-e2acf6d29710';
    -- check/create lock file
    -- if backup failed you self
    -- delete lock file your hands
    if not io.open(rule.backup_path..'/'..lockfile,'r') then
       io.open(rule.backup_path..'/'..lockfile,'w'):write('lock');
    else
       backup_fail("OTHER BACKUP PROCESS IS WORKING, SKIPPING THIS PROCESS\n"..
                   "IF YOU SURE DELETE LOCK FILE "..rule.backup_path..'/'..lockfile..'\n',true);
       ----------------------------------------------------------------------
       -- uncomment if after backup error no need locked backup for fix error
       ----------------------------------------------------------------------
       -- os.remove(rule.backup_path..'/'..lockfile);
    end
    for id,item in pairs(rule.backup_list) do
        local date = os.date("%Y-%m-%d_%X");
        local path = rule.backup_path;
        local pass = rule.backup_pass;
        local dest = item.dest;
        local source = item.source;

        if (not source) then
           backup_fail('BACKUP ERROR source path not set, what files backup?',true)
        end

        if (not dest) then
           backup_fail('BACKUP ERROR dest path not set, wheare dir name to save?',true)
        end

        execute(rule,'mkdir -p '..path..'/'..dest,true);
        backup_info('BACKUP: '..source);

        ------------------- secure: versionize backup data ---------------------
        ------------------------------------------------------------------------
        if (item.secure and item.zip and item.versions) then
            local target = string.format('%s/%s/%s-%s.zip',path,dest,dest,date);
            execute(rule,'zip -r9P '..pass..' '..target..' '..source,true);
            goto next_item;
        end
        ---------------- secure: update and append backup data -----------------
        ------------------------------------------------------------------------
        if (item.secure and item.zip and not item.versions) then
            local target = string.format('%s/%s/%s.zip',path,dest,dest);
            local opts = item.mirror and ' -rFS9P ' or ' -ru9P ';
            execute(rule,'zip '..opts..' '..pass..' '..target..' '..source,true);
            goto next_item;
        end
        ----------- no secure: zipped update and append backup data ------------
        ------------------------------------------------------------------------
        if (not item.secure and item.zip and not item.versions) then
           local target = string.format('%s/%s/%s.zip',path,dest,dest);
           local opts = item.mirror and ' -rFS9 ' or ' -ru9 ';
           execute(rule,'zip '..opts..' '..target..' '..source,true);
           goto next_item;
        end
        ----- no secure: zipped, versionize update and append backup data ------
        ------------------------------------------------------------------------
        if (not item.secure and item.zip and item.versions ) then
           local target = string.format('%s/%s/%s-%s.zip',path,dest,dest,date);
           execute(rule,'zip -r9 '..target..' '..source,true);
           goto next_item;
        end
        --------- no secure: versionize update and append, no delete -----------
        ------------------------------------------------------------------------
        if (not item.secure and not item.zip and item.versions ) then
           local target = string.format('%s/%s/%s-%s/',path,dest,dest,date);
           execute(rule,'mkdir -p '..target);
           execute(rule,'rsync -arv '..source..' '..target,true);
           goto next_item;
        end
        ----------------- no secure: update and append, no delete --------------
        ------------------------------------------------------------------------
        if (not item.secure and not item.zip and not item.versions) then
           local target = string.format('%s/%s/',path,dest);
           execute(rule,'mkdir -p '..target);
           local opts = item.mirror and ' -arv --delete ' or ' -arv ';
           execute(rule,'rsync '..opts..' '..source..' '..target,true);
           goto next_item;
        end
        ------------------------------------------------------------------------
        if (item.secure and not item.zip) then
            backup_fail('BACKUP ERROR UNSUPPORT SECURE WITCHOUT ZIP ARCHIVE :(');
        end
        ::next_item::
    end
    backup_info("BACKUP END "..os.date());
    os.remove(rule.backup_path..'/'..lockfile);
end

-- check depends
execute({},"zip --version",true);
execute({},"rsync --version",true);
--execute({},"mkdir --version",true);
execute({},"notify-send --version",true);
-- start backup now
make_backup(backup_rule)

Всё. Досвиданья.

 , , , ,

LINUX-ORG-RU
()

Почему Go это плохо, и он вам, на самом деле, не нужен.

Форум — Development

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

Дело в том, что Go это, на самом деле, «решение» внутренних гугловских проблем. Но отнюдь не проблем горизонтального масштабирования серверного ПО, как многие почему-то думают. Он приспособлен специально для использования в гугле вот в каком контексте.

Гугл нанимает большое количество тупых студентов, только-только после вуза или ПТУ, и заставлять их писать хоть какой-то простой код. И делать минимум ошибок, при этом. Для этого Go сделан таким тупым и упрощенным. И выкинут в паблик он только для того, чтобы вероятность, что у такого студента, только пришедшего в гугл, было хоть какое-то знание Go, была выше нуля.

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

Из гугла же идет маразматическая система управления зависимостями Го, которая заточена на монорепы.

Тут возникает вопрос - а почему этому тимлиду не дать в руки кодогенератор, вместо всей этой accidental complexity, возникающей из-за огромного количества строк кода, и из-за затрат на коммуникацию?

А тут надо понимать, как внутри устроены огромные корпорации типа гугла.

Их давно пожрал рак бюрократии. Там у менеджерских и околоменеджерских должностей один из главных критериев промоушнов, или вообще даже ассесмента(усидения на должности), это количество людей у тебя в подчинении. И количество говнокода в вакууме которая твоя команда написала. И вот все эти люди, сидящие на более-менее средне-высоких должностях, постоянно бодаются за эти промоушны и ассесменты. Это их главная и единственная цель. Поэтому, ни о какой эффективности тут речи не идет вообще от слова совсем. Тут главное - корпоративные игры, количество голов в твоем стаде и количество и размер высеров, которые это твое стадо произвело(причем буквально, важны SLOC).

Естественно, это все отражается на качестве продуктов, и это видно как по полному прекращению инноваций в гугле, так и по постоянно мелькающим и закрывающимся высерам этой компании - hangouts, duo, google plus, google wave, и прочее и прочее, можете еще вспомнить много чего.

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

Никакой мифической простоты в отладке и в понимании кода Go не приносит. Да и сложность программных систем растет совершенно не из-за понятности/непонятности какой-то отдельной взятой строчки кода или функции. Потому, что, во-первых, понятность это понятие субъективное, во-вторых потому, что, отдельно взятая фунцкия на 5 строк понятна любому опытному программисту, будь она написана хоть на Rust, хоть на Common Lisp.

Сложность программных систем возникает из-за их размера. И Go эту проблему значительно ухудшает. Человек не может удерживать в голове слишком много вещей, даже если каждая отдельная вещь - очень простая. Количество RAM в голове ограничено.

В случае если вы не хотите выкидывать кучу денег просто так, и скорее предпочли бы нанять немного, но более-менее опытных программистов, Go будет только вреден, потому что все вменяемые люди от него, на самом деле, плюются. Он реально отталкивает опытных людей, которые способны понять сложные требования и написать, и поддерживать, более-менее сложные системы уровнем хотя бы нескольких сервисов плюс БД и MQ.

 ,

lovesan
()

Firefox не может восстановить сессию

Форум — Desktop

Закрыл фаерфокс. Как обычно — с сохранением сессии. 4 окна, каждое — с кучей вкладок. Попробовал запустить — не вышло, закрывается с ошибкой. Попробовал другой профиль — запустилось нормально. Попробовал Safe Mode — предложило почистить профиль или просто запустить без плагинов. Выбрал второе — снова упало. Повторил Safe Mode, почистил профиль, запустил сохранённые вкладки — опять упало.

Проапдейтил фаерфокс со 102 до 115. Запустил — пишет «Нам не удалось восстановить вашу последнюю сессию. Выберите «Восстановить сессию», чтобы попробовать снова.»

Кнопка «Восстановить сессию» неактивна, список «Предыдущие вкладки» пуст, в меню «Журнал» тоже ничего интересного: «Восстановить предыдущую сессию» и «Недавно закрытые окна» серые, в «Недавно закрытые вкладки» — только вкладки о новшествах в новой версии Фаерфокса.

Как восстановить вкладки?

Ответ: https://support.mozilla.org/ru/kb/kak-vosstanovit-sessiyu-prosmotra-iz-rezervnoj-kop

В моём случае помогло по-быстрому скопировать все файлы из ~/.mozilla/firefox/<имя профиля>/sessionstore-backups/ а затем перед запуском Фаерфокса заменить ~/.mozilla/firefox/<имя профиля>/sessionstore.jsonlz4 на самый большой из них. Там было 2 одинаковых файла: previous.jsonlz4 и upgrade.jsonlz4-20230916112848. Возможно, 2-й сохранился потому, что я закрывал браузер по Ctrl-c в терминале.

 

question4
()

Написал статью «Как жить если у вас юникод»

Форум — Development

Собственно, сабж. Статья про то самое, что мы с Eddy_Em не могли осилить в прежние времена. В этом году я это, внезапно, осилил. Ну и написал статью.

https://saahriktu.ru/pdf/kak_jit_esli_u_vas_yunikod.pdf

 ,

saahriktu
()

Посчитать количество дней рождений за период. Как?

Форум — General

Посчитать количество дней рождений за период. PHP

Я с изумлением не вижу простого решения.

  1. Переберать весь период в цикле?

  2. Считать количество лет. Приводить к одному году и добовля или не добавлять единицу?

Спасибо.

 

kompospec
()