GoAT diagrams (ASCII)

Всегда восхищали таблицы в markdown:

| Column 1      | Column 2      |
| ------------- | ------------- |
| Cell 1, Row 1 | Cell 2, Row 1 |
| Cell 1, Row 2 | Cell 1, Row 2 |

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

Можно сделать некрасиво и тоже будет работать, но это же некрасиво!

Но таблицы это что-то очень для слабеньких и богопослушных.

Люди восстали и решили гневать богов полностью и придумали GoAT diagrams:

Восхитительно травмирующе. Бесконечно проклято.

  o o o o o  * * * * *  * * o o *    o o o      * * *      o o o     · * · · ·     · · ·
  o o o o o  * * * * *  o o o o *   o o o o    * * * *    * o * *    · * * · ·    · · · ·
  o o o o o  * * * * *  o * o o o  o o o o o  * * * * *  o o o o o   · o · · o   · · * * ·
  o o o o o  * * * * *  o * o o o   o o o o    * * * *    o * o o    · · · · o    · · * ·
  o o o o o  * * * * *  * * * * o    o o o      * * *      o * o     · · · · ·     · · *

+-------------------+                           ^                      .---.
|    A Box          |__.--.__    __.-->         |      .-.             |   |
|                   |        '--'               v     | * |<---        |   |
+-------------------+                                  '-'             |   |
                       Round                                       *---(-. |
  .-----------------.  .-------.    .----------.         .-------.     | | |
 |   Mixed Rounded  | |         |  / Diagonals  \        |   |   |     | | |
 | & Square Corners |  '--. .--'  /              \       |---+---|     '-)-'       .--------.
 '--+------------+-'  .--. |     '-------+--------'      |   |   |       |        / Search /
    |            |   |    | '---.        |               '-------'       |       '-+------'
    |<---------->|   |    |      |       v                Interior                 |     ^
    '           <---'      '----'   .-----------.              ---.     .---       v     |
 .------------------.  Diag line    | .-------. +---.              \   /           .     |
 |   if (a > b)     +---.      .--->| |       | |    | Curved line  \ /           / \    |
 |   obj->fcn()     |    \    /     | '-------' |<--'                +           /   \   |
 '------------------'     '--'      '--+--------'      .--. .--.     |  .-.     +Done?+-'
    .---+-----.                        |   ^           |\ | | /|  .--+ |   |     \   /
    |   |     | Join        \|/        |   | Curved    | \| |/ | |    \    |      \ /
    |   |     +---->  o    --o--        '-'  Vertical  '--' '--'  '--  '--'        +  .---.
 <--+---+-----'       |     /|\                                                    |  | 3 |
                      v                             not:line    'quotes'        .-'   '---'
  .-.             .---+--------.            /            A || B   *bold*       |        ^
 |   |           |   Not a dot  |      <---+---<--    A dash--is not a line    v        |
  '-'             '---------+--'          /           Nor/is this.            ---

#cursed #godslayer #gods_layer


telegram english version

2025.12.13 00:48

Следящая Собака и Крон

Вы уже знаете что я презираю systemd, сильно больше чем wayland, но будущее когда-нибудь будет в будущем, а прошлое всё ещё будет в прошлом.

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

Это всего один сервер и больше серверов никогда не будет (но меньше будет) поэтому не надо меня критиковать пожалуйста.

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

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

И они работали. Час. А потом нет. Руками запускаешь — работают. А сами потом не работают.

Было удивительно ведь крон никто не трогал, память перестала пропадать, а воркеры не хотят оживать.

Книга жизни (/var/log/syslog | grep -i cron) сказала что крон работал нормально, но очень давно в последний раз, а потом перестал.

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

Первый раз в моей жизни сторожевая собака убила крон! Невероятно!

А выжили бы systemd timers? Попали ли бы они под лапу смерти сторожевой собаки?

Загадка. Можно было бы конечно провести эксперимент, но не нет. Императивные знания нужны только людям со слабой верой!

#linux #cron #oom #outofmemory #memory #memoryleak #loopofdeath #systemd #systemdtimers


telegram english version

2025.12.09 20:43

Кое-кто испортил интернет! (x)

Все мы знаем что email@example.com — это имейл. Но что значит имейл? А значит оно что на сервере который находится по адресу example.com есть аккаунт с именем email. Ещё мы знаем что это имейл поэтому мы знаем на какой порт обращаться и какой протокол использовать (уточним детали в dns).

Точно так же каждый *nix аккаунт можно записать как user1@computer1 что значит что на computer1 есть аккаунт user1.

Символ @ буквально называется at:

  • user1-at-computer1
  • email-at-example.com

Удобно. Униформатично.

И тут приходит глупый твиттер и решает что теперь все будут @user2 и сломал интернет. ТВИТТЕР ДОЛЖЕН БЫЛ ИСПОЛЬЗОВАТЬ user2@!!!111

Всё потеряно. Дальше только хуже.

#deep #blasphemy


telegram english version

2025.11.28 17:53

WP actions hooks and filter hooks

There are two types of hooks: Actions and Filters.

Actions allow you to add data or change how WordPress operates.

Filters give you the ability to change data during the execution of WordPress Core, plugins, and themes.

function add_action( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
    return add_filter( $hook_name, $callback, $priority, $accepted_args );
}

function has_action( $hook_name, $callback = false ) {
	return has_filter( $hook_name, $callback );
}
public function has_filters() {
    foreach ($this->callbacks as $callbacks) {
        if ($callbacks) {
            return true;
        }
    }

    return false;
}

#php #wordpress #why


telegram english version

2025.11.27 12:17

Google OS Aluminum

Google развивает ОС Aluminium для ноутбуков и планшетов

А будет форк OS Aluminum?

#deep


telegram english version

2025.11.25 13:00

.ssh/unknown_hosts

Когда ssh подключается к неизвестному хосту она зачем-то просит человека написать "yes". Никто не знает зачем это нужно делать, но без этого ssh не подключается.

Но этого можно избежать этими двумя способами:

# 1. Отключить опцией (небезопасно)
$ ssh -o "StrictHostKeyChecking no" user@example.com
# 2. Автоматически сделать так чтобы хост был известным
$ ssh-keyscan -t rsa example.com >> ~/.ssh/known_hosts
$ ssh user@example.com

Во втором случае не будет предупреждения! Но не потому что мы просто отключаем проверку, а мы делаем хост нам известным!

Теперь вы понимаете что профессионала отличает то какие способы он выбирает! Будьте профессионалами, выбирайте безопасность!

#linux #ssh #safety


telegram english version

2025.11.22 23:39

OTP регистрация

А что если мы посмотрим на OPIE и OTPW и решим что это нам не нужно.

Но сделаем регистрацию на сайте через генерацию OTP. Однофакторную. Пока есть доступ к секретному ключу — есть доступ к сайту.

Не нужно ни помнить паролей, ни использовать ни имейлов, ни имён.

Свежо! Тупо и свежо!

#whatif #hearmeout #otp #idea


telegram english version

2025.11.18 22:10

Zola SSG: история успеха

Много сгоревших свечей пришлось сжечь чтобы разобраться как работает генератор статических сайтов zola.

Оно использует .md файлы и это должен быть максимально безопасный вариант.

Оказалось, что оно не может рендерить ``` и зачем-то внутри всё оборачивает слоями <code> и <p> даже если выключена подсветка.

Это печально — упасть на тексте который не надо трогать (потрогайте картинки).

(иногда фантазирую как конвертирую вордпресс в золу и при этом меняю структуру урлов и мне очень тепло)

#zola #web #ssg #markdown #wtf


telegram english version

2025.11.16 15:23

meme.jpg & ai

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

Теперь вместо meme.jpg надо ai_picture.jpg

#deep

2025.11.12 22:59

apache@docker

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

То есть как бы апач, а как бы и внутри докера.

То есть вот вас вроде бы и тошнит, а вроде бы и в пакет.

#linux #apache


telegram

2025.11.12 21:24

Шорткаты терминала

В терминале можно неплохо удалять. Например, если у вас есть строка и курсор в центре:

xxx xxx █ xxx xxx

То вы можете:
CTRL+W чтобы удалить слово слева
ALT+D чтобы удалить слово справа

Почему?

#linux #why #wtf #cursed


telegram english version

2025.11.10 23:17

Деплой статического блога через ssh и git --bare

Эпиграф

Когда у меня будет депрессивная фаза я никому не скажу, но будут признаки.

Начало

Вы уже прочитали первый пост и второй пост про как и зачем мы git --bare и всё ещё не понимаете зачем.

Давайте представим что у нас есть статический сайт и мы хотим его деплоить с локального устройство на серверное устройство. Мы всё тоже самое можем сделать через гитхаб, но мы можем и без!

Я вам расскажу как без, но это вряд ли оптимальный способ жить:
+ весело
+ независимо
– если у вас много картинок, то блог будет занимать x2 или даже сильно хуже
– гитхаб даст третью точку для бекапа

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

Подготавливаемся

1. делаем ssh

Допустим у нас есть блог hshhhhh.name, на сервере пользователь тоже hshhhhh.name и мы уже можем подключиться к нему по ssh.

Теперь мы добавим в ~/ssh/config:

Host hshhhhh.name
    HostName 159.223.250.0
    IdentityFile ~/.ssh/keys/hshhhhh.name
    User hshhhhh.name

Теперь работает так:

$ ssh hshhhhh.name

2. подготавливаем сервер

Мы будем направлять nginx на директорию /home/hshhhhh.name/public_html/ потому что мы чтим традиции и уважаем чтение традиций. Поэтому мы создадим на сервере один git --bare и один нормальный, нормальный будет получать апдейты из git --bare, а потом нгинкс через симлинк будет ходить в нормальный.

Или на локальном устройстве, или на удалённом устройстве:

$ ssh hshhhhh.name "git init --bare ~/.git--bare"
$ ssh hshhhhh.name "mkdir ~/git/"

3. делаем блог

Внутри нашего репозитория тоже будет /public_html/ директория куда мы будем складывать результат. Всякое остальное на ваш выбор.

На локальном устройстве:

$ mkdir -p /tmp/hshhhhh.name/public_html/
$ cd /tmp/hshhhhh.name/
$ date > public_html/index.html
$ git init .
$ git config --local user.name "hshhhhh"
$ git config --local user.email "email"
$ git add public_html/
$ git commit -m "initial commit"

И посылаем это на удалённое устройство (если в урле есть : то это относительный путь, а если нет — абсолютный (но тогда должно начинаться с ssh://)):

$ git remote add hosting "hshhhhh.name:.git--bare/"
$ git push hosting

4. деплоим

Сначала мы git pull в локальный нормальный репозиторий, потом мы симлинкаем и как-нибудь там перезапускаем nginx если он вдруг не оценит подмену директории на симлинк.

Или на локальном устройстве, или на удалённом устройстве:

$ ssh hshhhhh.name "git clone ~/.git--bare ~/git/"
$ ssh hshhhhh.name "git -C ~/git/ pull"
$ ssh hshhhhh.name "cat ~/git/public_html/index.html"

Делаем симлинк и проверяем в браузере (при создании симлинка в конце не должно быть слеша):

$ ssh hshhhhh.name "mv ~/public_html/ ~/public_html_backup/"
$ ssh hshhhhh.name "ln -s ~/git/public_html/ ~/public_html"
$ curl --location https://hshhhhh.name/

4. деплоим обновление

На локальном устройстве:

$ cd /tmp/hshhhhh.name/
$ date >> public_html/index.html
$ git add public_html/index.html
$ git commit -m "second commit"
$ git push hosting
$ ssh hshhhhh.name "git -C ~/git/ pull"
$ curl --location https://hshhhhh.name/

Конец

Потрясающе, вы прямо хакер такие чудеса делаете может быть вам бы уже завести себе бложик и делиться вашими исследованиями?

#linux #howto #man #git #deploy

2025.11.10 04:05

Как точка файлы

Начало

В прошлом посте вы узнали про git --bare, а в этом вы узнаете зачем вы про это узнали.

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

В посте на реддите люди называют три способа.

1. gnu stow + git

Этот stow просто хранит всё в какой-то дирректории, а потом указывает туда симлинками, например:

 ~/.config/nvim/ > ~/.stow/.config/nvim/

Мне просто не нравится.

2. yadm: Yet Another Dotfiles Manager

Сложно!

3. git --blame

Можно случайно добавить самого себя, но можно и не добавлять.

Делаем ~/.dotfiles/

В том же посте рассказывают как всё делать и есть даже ссылка на блог (в котором нет rss!).

Я делаю всё так же как в этом блоге, но кладу гит на +1 уровень вложенности в ~/.dotfiles/git--bare/ и это даёт мне возможность добавить файл ~/.dotfiles/readme.md в котором я напишу как этим пользоваться.

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

0. далёкий репозиторий

Создайте у себя в гитхабе приватный dotfiles репозиторий и найстройте ssh чтобы всё работало.

1. первый коммит

Создаём репозиторий, можете переименовывать всё как угодно

$ cd ~
$ mkdir -p ~/.dotfiles/git--blame/
$ git init --bare ~/.dotfiles/git--bare/
$ echo 'hello world' > ~/.dotfiles/readme.md

Делаем первый коммит, проверяем что всё работает

$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" add ~/.dotfiles/readme.md
$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" config set --local user.name "hello"
$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" config set --local user.name "mail@example.com"
$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" commit -m 'initial commit'
$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" log

Если коммит случился — мы радуемся.

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

  
$ cat ~/.config/fish/functions/dotfiles.fish

function dotfiles
    command git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" $argv
end

Теперь у нас есть функция, её мы проверяем:

$ dotfiles status

Если вам стало неприятно от моего совета, то это хорошо! Теперь вызывая dotfiles мы как бы вызываем git, но со странными параметрами.

Теперь мы можем отключить показ недобавленных файлов:

$ dotfiles status
$ dotfiles config --local status.showUntrackedFiles not  
$ dotfiles status

2. синхронизация

$ dotfiles remote add github <url>
$ dotfiles push

3. безумие время

$ dotfiles add ~/.config/fish/
$ dotfiles commit -m '`~/.config/fish/`'
$ dotfiles push

Эмулируем второе устройство

Что выполнять на настоящем втором устройстве вы найдёте ниже, а тут мы проверим что всё работает на этом же устройстве. И убедимся что мы понимаем как это работает,
потому что если мы не понимаем мы могли бы пользоваться yadm например.

$ mkdir /tmp/dotfiles-sandbox/
$ cd /tmp/dotfiles-sandbox/
$ git clone --bare <url> /tmp/dotfiles-sandbox/.dotfiles/git--bare/
$ git --git-dir="/tmp/dotfiles-sandbox/.dotfiles/git--bare/" --work-tree="/tmp/dotfiles-sandbox/" reset --hard
$ ls

Если файлы внезапно появились, то мы всё сделали правильно. Теперь делаем коммит:

$ git --git-dir="/tmp/dotfiles-sandbox/.dotfiles/git--bare/" --work-tree="/tmp/dotfiles-sandbox/" config --local status.showUntrackedFiles no;
$ git --git-dir="/tmp/dotfiles-sandbox/.dotfiles/git--bare/" --work-tree="/tmp/dotfiles-sandbox/" config set user.name "temp"
$ git --git-dir="/tmp/dotfiles-sandbox/.dotfiles/git--bare/" --work-tree="/tmp/dotfiles-sandbox/" config set user.email "temp"

$ date >> /tmp/dotfiles-sandbox/.dotfiles/readme.md
$ git --git-dir="/tmp/dotfiles-sandbox/.dotfiles/git--bare/" --work-tree="/tmp/dotfiles-sandbox/" add /tmp/dotfiles-sandbox/.dotfiles/readme.md
$ git --git-dir="/tmp/dotfiles-sandbox/.dotfiles/git--bare/" --work-tree="/tmp/dotfiles-sandbox/" commit -m '`.dotfiles/readme.md`'  
$ git --git-dir="/tmp/dotfiles-sandbox/.dotfiles/git--bare/" --work-tree="/tmp/dotfiles-sandbox/" push

Если всё работает то всё работает.

$ rm -Rf /tmp/dotfiles-sandbox/

мы завтрашние

Вам может быть непонятно зачем это если на втором устройстве ничего не настроено, но:
1. вы можете посмотреть это файл прямо в гитхабе
2. вы всё равно должны как-то передать урл на второе устройство и настроить там ssh

А если у вас там всё это работает, то вы всегда можете сделать:

$ git clone <url> /tmp/dotfiles-temp/
$ cat /tmp/dotfiles-temp/.dotfiles/readme.md
$ rm -Rf /tmp/dotfiles-temp/

Вот вам содержимое ~/.dotfiles/readme.md, вы его поменяйте, поменяйте, сохраните и запушьте сами.

```
### init, first machine

$ mkdir -p ~/.dotfiles/git--blame/
$ git init --bare ~/./dotfiles/git--bare/
$ echo 'hello world' > ~/.dotfiles/readme.md

$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" add ~/.dotfiles/readme.md
$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" config set --local user.name "hello"
$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" config set --local user.name "mail@example.com"
$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" commit -m 'initial commit'
$ git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" log

# fish function / alias

$ cat ~/.config/fish/functions/dotfiles.fish

function dotfiles
    command git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" $argv
end

# check function / alias and hide new files notifications

$ dotfiles status
$ dotfiles config --local status.showUntrackedFiles not
$ dotfiles status

# add remote

$ dotfiles remote add github <url>
$ dotfiles push

# add first config

$ dotfiles add ~/.config/fish/
$ dotfiles commit -m '`~/.config/fish/`'
$ dotfiles push
```

```
### second machine

# be smart, create fish function / alias first

$ cat ~/.config/fish/functions/dotfiles.fish

function dotfiles
    command git --git-dir="$HOME/.dotfiles/git--bare/" --work-tree="$HOME" $argv
end


# deploy, but be careful: you can ruin existing files. Handle it somehow, I won't fight your internal coflicts!

$ git clone --bare <url> ~/.dotfiles/git--bare/
$ dotfiles status
$ dotfiles config --local status.showUntrackedFiles not
$ dotfiles status
$ dotfiles config set --local user.name "hello 2nd machine"
$ dotfiles config set --local user.name "mail@example.com"
```

Конец

Поздравляшки, теперь вы нерд!

#linux #howto #man #dotfiles #git

2025.11.10 00:31

git vs git --bare

Ваш гит репозиторий может существовать в двух вариантах: обычный и --bare. Обычный это ~гит-клиент, а необычный это ~гит-сервер. Ну то есть как бы нет, но --bare существует чтобы его как remote использовали обычные репозитории. И в нём ещё нет файлов.

Вы можете на своём впс создать --bare репозиторий и через ssh в него синхронизироваться не используя никаких сервисов вроде гитхаба. И каждый у кого будет ssh доступ тоже сможет его использовать как remote.

Почему-то когда создаёшь обычный, то он для себя создаёт отдельную директорию /.git, а когда --bare то он указанный путь использует как .git.

> git init  ./git-normal/
    Initialized empty Git repository in /tmp/.dotfiles/git-normal/.git/
> git init --bare ./git-bare/
    Initialized empty Git repository in /tmp/.dotfiles/git-bare/

> ls -lah git-normal/
    .git/
> ls -lah git-bare/
    hooks/
    info/
    objects/
    refs/
    HEAD
    config
    description

Смешная шутка: если вы положите --bare в ./.git/, то оно будет выглядеть как будто бы ./ тут есть гит, и он даже есть, но его нет!

fatal: this operation must be run in a work tree

#linux #howto #man #git


telegram english version

2025.11.09 20:36