Расскажу про одну штуку в bash и zsh, которую большинство не замечает годами.
Называется это parameter expansion с модификаторами. Звучит скучно, но на практике экономит кучу времени.
Смотри. У тебя есть переменная с путём к файлу:
file="/home/user/projects/app.tar.gz"
Теперь без единой внешней утилиты — ни basename, ни dirname, ни sed — ты можешь вытащить что угодно:
Только имя файла:
echo "${file##*/}"
→ app.tar.gz
Только директорию:
echo "${file%/*}"
→ /home/user/projects
Убрать расширение:
echo "${file%%.*}"
→ /home/user/projects/app
Убрать только последнее расширение:
echo "${file%.*}"
→ /home/user/projects/app.tar
Логика простая. Решётка # — режем с начала строки, процент % — режем с конца. Одинарный символ — минимальное совпадение, двойной — максимальное. Один раз запомнил, и больше не забудешь.
Но это ещё не всё. Есть замена по паттерну прямо внутри переменной:
text="hello world world"
echo "${text/world/linux}"
→ hello linux world
echo "${text//world/linux}"
→ hello linux linux
Один слэш — заменяет первое вхождение, два — все сразу. Никакого sed для простых замен.
И совсем редкая вещь — изменение регистра. Работает в bash 4+ и zsh:
name="hello world"
echo "${name^}"
→ Hello world
echo "${name^^}"
→ HELLO WORLD
str="LINUX IS COOL"
echo "${str,,}"
→ linux is cool
Каретка поднимает регистр, запятая опускает. Двойная — применяет ко всей строке.
Зачем это вообще нужно? Во-первых, скорость. Всё это работает внутри самого шелла без форка нового процесса. В скриптах, которые гоняют тысячи файлов в цикле, разница ощутимая. Во-вторых, читаемость — когда видишь ${file##*/}, понимаешь намерение сразу, не гадаешь что делает регулярка в sed.
Один практический пример, который пригождается часто. Конвертируешь пачку файлов и хочешь поменять расширение:
for f in *.mp4; do
ffmpeg -i "$f" "${f%.mp4}.mkv"
done
Чисто, без подпроцессов, без временных переменных.
Это тот случай, когда bash перестаёт казаться убогим и начинает казаться хитрым 😄
📍 Подпишись на создателей: https://t.me/linuxexex
Называется это parameter expansion с модификаторами. Звучит скучно, но на практике экономит кучу времени.
Смотри. У тебя есть переменная с путём к файлу:
file="/home/user/projects/app.tar.gz"
Теперь без единой внешней утилиты — ни basename, ни dirname, ни sed — ты можешь вытащить что угодно:
Только имя файла:
echo "${file##*/}"
→ app.tar.gz
Только директорию:
echo "${file%/*}"
→ /home/user/projects
Убрать расширение:
echo "${file%%.*}"
→ /home/user/projects/app
Убрать только последнее расширение:
echo "${file%.*}"
→ /home/user/projects/app.tar
Логика простая. Решётка # — режем с начала строки, процент % — режем с конца. Одинарный символ — минимальное совпадение, двойной — максимальное. Один раз запомнил, и больше не забудешь.
Но это ещё не всё. Есть замена по паттерну прямо внутри переменной:
text="hello world world"
echo "${text/world/linux}"
→ hello linux world
echo "${text//world/linux}"
→ hello linux linux
Один слэш — заменяет первое вхождение, два — все сразу. Никакого sed для простых замен.
И совсем редкая вещь — изменение регистра. Работает в bash 4+ и zsh:
name="hello world"
echo "${name^}"
→ Hello world
echo "${name^^}"
→ HELLO WORLD
str="LINUX IS COOL"
echo "${str,,}"
→ linux is cool
Каретка поднимает регистр, запятая опускает. Двойная — применяет ко всей строке.
Зачем это вообще нужно? Во-первых, скорость. Всё это работает внутри самого шелла без форка нового процесса. В скриптах, которые гоняют тысячи файлов в цикле, разница ощутимая. Во-вторых, читаемость — когда видишь ${file##*/}, понимаешь намерение сразу, не гадаешь что делает регулярка в sed.
Один практический пример, который пригождается часто. Конвертируешь пачку файлов и хочешь поменять расширение:
for f in *.mp4; do
ffmpeg -i "$f" "${f%.mp4}.mkv"
done
Чисто, без подпроцессов, без временных переменных.
Это тот случай, когда bash перестаёт казаться убогим и начинает казаться хитрым 😄
📍 Подпишись на создателей: https://t.me/linuxexex
Как Linux управляет памятью — просто о сложном
Каждый раз, когда ты запускаешь программу, ядро делает кучу невидимой работы. Давай разберёмся, как устроена подсистема управления памятью в Linux — одна из самых фундаментальных частей системы.
Главная идея: виртуальная память
Каждый процесс думает, что у него есть весь адресный диапазон целиком. Браузер не знает о существовании терминала, терминал — о браузере. Это и есть виртуальная память. Ядро создаёт иллюзию, что у каждого процесса своя личная оперативка.
На самом деле за этим стоит таблица страниц. Ядро хранит маппинг: виртуальный адрес процесса → реальный физический адрес в RAM. Процессор при каждом обращении к памяти смотрит в эту таблицу через специальный блок MMU. Если адреса нет — получаешь segfault, знакомо?
Страницы и Page Fault
Память делится на страницы по 4 КБ (обычно). Когда процесс обращается к странице, которой нет в RAM, происходит так называемый page fault — прерывание. Ядро перехватывает его и решает: либо загрузить страницу с диска, либо убить процесс, если он полез куда не надо.
Это и есть механизм подкачки (swap). Когда RAM заканчивается, ядро выталкивает редко используемые страницы на диск, освобождая место. Потом, если они снова понадобятся — подгрузит обратно. Это медленно, но лучше чем OOM-killer, который просто расстреляет один из процессов 💀
OOM-killer — отдельная история
Если swap тоже кончился и памяти нет совсем, ядро запускает OOM-killer (Out Of Memory Killer). Он считает баллы каждому процессу: сколько памяти жрёт, насколько важен, сколько живёт — и убивает того, кто набрал больше всего очков "ненужности". Иногда выбор бывает... спорным. Поэтому в продакшне за памятью следят внимательно.
Copy-on-Write
Когда процесс делает fork() — создаёт дочерний процесс — ядро не копирует всю память сразу. Оба процесса смотрят на одни и те же физические страницы. Копирование произойдёт только тогда, когда кто-то из них попытается что-то записать. Это называется Copy-on-Write и экономит кучу ресурсов.
Зачем это знать на практике?
Смотришь на /proc/meminfo и видишь Cached и Buffers — это ядро использует свободную RAM как кэш файловой системы. Это нормально и хорошо. Если приложению понадобится память — кэш освободится. Поэтому "свободная" память в Linux почти всегда близка к нулю, и это не проблема.
Команды, которые помогают разобраться:
free -h — общая картина
vmstat 1 — динамика
cat /proc/meminfo — детали
dmesg | grep -i oom — был ли OOM-killer
Подсистема памяти в Linux — это огромный айсберг. Сегодня показал только верхушку, но уже достаточно, чтобы не паниковать когда видишь "память занята" 🧊
📍 Подпишись на создателей: https://t.me/linuxexex
Каждый раз, когда ты запускаешь программу, ядро делает кучу невидимой работы. Давай разберёмся, как устроена подсистема управления памятью в Linux — одна из самых фундаментальных частей системы.
Главная идея: виртуальная память
Каждый процесс думает, что у него есть весь адресный диапазон целиком. Браузер не знает о существовании терминала, терминал — о браузере. Это и есть виртуальная память. Ядро создаёт иллюзию, что у каждого процесса своя личная оперативка.
На самом деле за этим стоит таблица страниц. Ядро хранит маппинг: виртуальный адрес процесса → реальный физический адрес в RAM. Процессор при каждом обращении к памяти смотрит в эту таблицу через специальный блок MMU. Если адреса нет — получаешь segfault, знакомо?
Страницы и Page Fault
Память делится на страницы по 4 КБ (обычно). Когда процесс обращается к странице, которой нет в RAM, происходит так называемый page fault — прерывание. Ядро перехватывает его и решает: либо загрузить страницу с диска, либо убить процесс, если он полез куда не надо.
Это и есть механизм подкачки (swap). Когда RAM заканчивается, ядро выталкивает редко используемые страницы на диск, освобождая место. Потом, если они снова понадобятся — подгрузит обратно. Это медленно, но лучше чем OOM-killer, который просто расстреляет один из процессов 💀
OOM-killer — отдельная история
Если swap тоже кончился и памяти нет совсем, ядро запускает OOM-killer (Out Of Memory Killer). Он считает баллы каждому процессу: сколько памяти жрёт, насколько важен, сколько живёт — и убивает того, кто набрал больше всего очков "ненужности". Иногда выбор бывает... спорным. Поэтому в продакшне за памятью следят внимательно.
Copy-on-Write
Когда процесс делает fork() — создаёт дочерний процесс — ядро не копирует всю память сразу. Оба процесса смотрят на одни и те же физические страницы. Копирование произойдёт только тогда, когда кто-то из них попытается что-то записать. Это называется Copy-on-Write и экономит кучу ресурсов.
Зачем это знать на практике?
Смотришь на /proc/meminfo и видишь Cached и Buffers — это ядро использует свободную RAM как кэш файловой системы. Это нормально и хорошо. Если приложению понадобится память — кэш освободится. Поэтому "свободная" память в Linux почти всегда близка к нулю, и это не проблема.
Команды, которые помогают разобраться:
free -h — общая картина
vmstat 1 — динамика
cat /proc/meminfo — детали
dmesg | grep -i oom — был ли OOM-killer
Подсистема памяти в Linux — это огромный айсберг. Сегодня показал только верхушку, но уже достаточно, чтобы не паниковать когда видишь "память занята" 🧊
📍 Подпишись на создателей: https://t.me/linuxexex
Лайфхак для терминала, который я использую каждый день
Если ты часто работаешь в терминале, то наверняка знаешь боль: набрал длинную команду, нажал Enter — и только потом заметил ошибку. Или хуже — забыл как называлась та команда, которую вводил три дня назад.
Вот несколько трюков, которые реально экономят время.
⚡ Ctrl+R — поиск по истории
Нажимаешь Ctrl+R и начинаешь вводить часть команды — bash или zsh сами найдут её в истории. Не нужно листать стрелочками вверх сто раз. Просто вводишь кусок того, что помнишь, и получаешь результат. Если не то — жмёшь Ctrl+R ещё раз, идёт дальше по истории.
⚡ !! и !$
!! — повторяет предыдущую команду целиком. Классика: забыл написать sudo.
sudo !!
И команда выполнится с правами суперпользователя.
!$ — подставляет последний аргумент предыдущей команды. Например:
mkdir /very/long/path/to/project
cd !$
Не нужно копировать путь заново — он подставится сам.
⚡ Ctrl+A и Ctrl+E
Ctrl+A — прыгает в начало строки. Ctrl+E — в конец. Намного быстрее, чем держать стрелку зажатой.
⚡ Ctrl+U и Ctrl+K
Ctrl+U — удаляет всё от курсора до начала строки. Ctrl+K — до конца строки. Очень удобно, когда набрал длинную команду и хочешь переписать только начало или конец.
⚡ Alt+. (точка)
Подставляет последний аргумент из самой последней команды — аналог !$, но работает интерактивно. Нажимаешь несколько раз — листаешь аргументы из предыдущих команд по истории. Это вообще магия, пока не попробуешь — не понимаешь насколько полезно.
⚡ history | grep
Если Ctrl+R не справляется — можно поискать руками:
history | grep docker
Выдаст все команды с docker из истории. Находишь номер нужной и запускаешь через !номер — например !342.
Все эти штуки встроены в bash и zsh, ничего устанавливать не нужно. Просто начни использовать — через неделю руки сами будут тянуться к Ctrl+R вместо стрелки вверх. 🖥️
Какой из этих трюков уже знал, а какой стал открытием? Пиши в комментарии.
📍 Подпишись на создателей: https://t.me/linuxexex
Если ты часто работаешь в терминале, то наверняка знаешь боль: набрал длинную команду, нажал Enter — и только потом заметил ошибку. Или хуже — забыл как называлась та команда, которую вводил три дня назад.
Вот несколько трюков, которые реально экономят время.
⚡ Ctrl+R — поиск по истории
Нажимаешь Ctrl+R и начинаешь вводить часть команды — bash или zsh сами найдут её в истории. Не нужно листать стрелочками вверх сто раз. Просто вводишь кусок того, что помнишь, и получаешь результат. Если не то — жмёшь Ctrl+R ещё раз, идёт дальше по истории.
⚡ !! и !$
!! — повторяет предыдущую команду целиком. Классика: забыл написать sudo.
sudo !!
И команда выполнится с правами суперпользователя.
!$ — подставляет последний аргумент предыдущей команды. Например:
mkdir /very/long/path/to/project
cd !$
Не нужно копировать путь заново — он подставится сам.
⚡ Ctrl+A и Ctrl+E
Ctrl+A — прыгает в начало строки. Ctrl+E — в конец. Намного быстрее, чем держать стрелку зажатой.
⚡ Ctrl+U и Ctrl+K
Ctrl+U — удаляет всё от курсора до начала строки. Ctrl+K — до конца строки. Очень удобно, когда набрал длинную команду и хочешь переписать только начало или конец.
⚡ Alt+. (точка)
Подставляет последний аргумент из самой последней команды — аналог !$, но работает интерактивно. Нажимаешь несколько раз — листаешь аргументы из предыдущих команд по истории. Это вообще магия, пока не попробуешь — не понимаешь насколько полезно.
⚡ history | grep
Если Ctrl+R не справляется — можно поискать руками:
history | grep docker
Выдаст все команды с docker из истории. Находишь номер нужной и запускаешь через !номер — например !342.
Все эти штуки встроены в bash и zsh, ничего устанавливать не нужно. Просто начни использовать — через неделю руки сами будут тянуться к Ctrl+R вместо стрелки вверх. 🖥️
Какой из этих трюков уже знал, а какой стал открытием? Пиши в комментарии.
📍 Подпишись на создателей: https://t.me/linuxexex
Совет по безопасности, который многие игнорируют 🔐
Хочу поговорить про sudo и про то, как большинство людей пользуются им не думая.
Классическая картина: ставишь какой-нибудь пакет, лезешь в конфиг, что-то правишь — и на автопилоте пишешь sudo перед каждой командой. Привычка. Мышечная память. А потом удивляются, почему что-то пошло не так.
Вот несколько конкретных вещей, которые стоит сделать прямо сейчас.
— — —
Проверь, кто вообще в группе sudo или wheel
На Debian/Ubuntu:
getent group sudo
На Fedora/Arch:
getent group wheel
Если видишь там имена, которых не ожидал — это повод задать вопрос. Особенно актуально на серверах, где работало несколько человек.
— — —
Настрой таймаут sudo
По умолчанию sudo помнит твои права 15 минут. Это удобно, но если ты отошёл от компьютера, а сессия открыта — любой, кто сядет за клавиатуру, может рулить системой без пароля.
Открой visudo и добавь:
Defaults timestamp_timeout=0
Теперь sudo будет спрашивать пароль каждый раз. Да, чуть менее удобно. Зато безопаснее.
— — —
Запрети sudo без пароля
Иногда в sudoers встречается страшная строка:
username ALL=(ALL) NOPASSWD: ALL
Это значит — пользователь делает всё что угодно от рута без ввода пароля. Удобно для автоматизации, но если кто-то получит доступ к сессии — система открыта нараспашку. Убирай NOPASSWD там, где это не жёсткая необходимость.
— — —
Используй sudo -l чтобы понимать свои права
Эта команда покажет, что именно тебе разрешено делать через sudo. Полезно и для самопроверки, и когда ты заходишь на чужой сервер и хочешь понять, какие у тебя полномочия.
— — —
Не запускай текстовые редакторы через sudo без нужды
sudo vim /etc/hosts — окей, если реально нужно.
Но многие запускают весь редактор с правами рута ради одного файла, а потом в нём открывают что-то ещё, ставят плагины и так далее. Лучше использовать sudoedit — он открывает файл безопаснее, через копию, и не даёт редактору работать от рута напрямую.
sudoedit /etc/hosts
— — —
Безопасность — это не параноя, это привычка думать перед тем, как нажать Enter. Особенно когда в команде есть sudo 🙂
📍 Подпишись на создателей: https://t.me/linuxexex
Хочу поговорить про sudo и про то, как большинство людей пользуются им не думая.
Классическая картина: ставишь какой-нибудь пакет, лезешь в конфиг, что-то правишь — и на автопилоте пишешь sudo перед каждой командой. Привычка. Мышечная память. А потом удивляются, почему что-то пошло не так.
Вот несколько конкретных вещей, которые стоит сделать прямо сейчас.
— — —
Проверь, кто вообще в группе sudo или wheel
На Debian/Ubuntu:
getent group sudo
На Fedora/Arch:
getent group wheel
Если видишь там имена, которых не ожидал — это повод задать вопрос. Особенно актуально на серверах, где работало несколько человек.
— — —
Настрой таймаут sudo
По умолчанию sudo помнит твои права 15 минут. Это удобно, но если ты отошёл от компьютера, а сессия открыта — любой, кто сядет за клавиатуру, может рулить системой без пароля.
Открой visudo и добавь:
Defaults timestamp_timeout=0
Теперь sudo будет спрашивать пароль каждый раз. Да, чуть менее удобно. Зато безопаснее.
— — —
Запрети sudo без пароля
Иногда в sudoers встречается страшная строка:
username ALL=(ALL) NOPASSWD: ALL
Это значит — пользователь делает всё что угодно от рута без ввода пароля. Удобно для автоматизации, но если кто-то получит доступ к сессии — система открыта нараспашку. Убирай NOPASSWD там, где это не жёсткая необходимость.
— — —
Используй sudo -l чтобы понимать свои права
Эта команда покажет, что именно тебе разрешено делать через sudo. Полезно и для самопроверки, и когда ты заходишь на чужой сервер и хочешь понять, какие у тебя полномочия.
— — —
Не запускай текстовые редакторы через sudo без нужды
sudo vim /etc/hosts — окей, если реально нужно.
Но многие запускают весь редактор с правами рута ради одного файла, а потом в нём открывают что-то ещё, ставят плагины и так далее. Лучше использовать sudoedit — он открывает файл безопаснее, через копию, и не даёт редактору работать от рута напрямую.
sudoedit /etc/hosts
— — —
Безопасность — это не параноя, это привычка думать перед тем, как нажать Enter. Особенно когда в команде есть sudo 🙂
📍 Подпишись на создателей: https://t.me/linuxexex
Лайфхак для терминала, который реально экономит время ⚡
Если ты каждый день работаешь в терминале, то наверняка набираешь одни и те же длинные команды по кругу. Есть простой способ это исправить — алиасы плюс одна малоизвестная штука, которую многие игнорируют.
Все знают про alias в .bashrc или .zshrc. Но мало кто использует функции вместо алиасов, когда нужно передать аргументы в середину команды.
Например, хочешь быстро зайти в любую директорию проекта и сразу открыть её в редакторе:
cdcode() { cd ~/projects/"$1" && code . ; }
Теперь пишешь cdcode myapp — и ты уже внутри нужной папки с открытым редактором. Никаких двух команд, никаких ошибок с путём.
Но это ещё не главное. Вот реальный экономщик времени — CDPATH.
Добавь в .bashrc строку:
export CDPATH=.:~:~/projects:~/work
После этого команда cd myapp будет искать папку не только в текущей директории, но и во всех путях из CDPATH. Ты пишешь просто cd myapp из любого места в системе — и попадаешь в ~/projects/myapp, если там такая папка есть.
Никакого автодополнения настраивать не надо, работает из коробки в bash и zsh.
Ещё один момент — история команд. По умолчанию она маленькая и не сохраняет дубли. Добавь это:
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTCONTROL=ignoredups:erasedups
shopt -s histappend
Теперь история большая, дубли не захламляют её, и при открытии нового терминала история не перезатирается, а дописывается. Ctrl+R для обратного поиска по истории становится в разы полезнее, когда там реально все твои команды за последние месяцы.
Итого три вещи, которые стоит сделать прямо сейчас: написать функции вместо сложных алиасов, настроить CDPATH под свою структуру проектов, и починить настройки истории. Занимает пять минут, а время экономит каждый день. 🖥️
📍 Подпишись на создателей: https://t.me/linuxexex
Если ты каждый день работаешь в терминале, то наверняка набираешь одни и те же длинные команды по кругу. Есть простой способ это исправить — алиасы плюс одна малоизвестная штука, которую многие игнорируют.
Все знают про alias в .bashrc или .zshrc. Но мало кто использует функции вместо алиасов, когда нужно передать аргументы в середину команды.
Например, хочешь быстро зайти в любую директорию проекта и сразу открыть её в редакторе:
cdcode() { cd ~/projects/"$1" && code . ; }
Теперь пишешь cdcode myapp — и ты уже внутри нужной папки с открытым редактором. Никаких двух команд, никаких ошибок с путём.
Но это ещё не главное. Вот реальный экономщик времени — CDPATH.
Добавь в .bashrc строку:
export CDPATH=.:~:~/projects:~/work
После этого команда cd myapp будет искать папку не только в текущей директории, но и во всех путях из CDPATH. Ты пишешь просто cd myapp из любого места в системе — и попадаешь в ~/projects/myapp, если там такая папка есть.
Никакого автодополнения настраивать не надо, работает из коробки в bash и zsh.
Ещё один момент — история команд. По умолчанию она маленькая и не сохраняет дубли. Добавь это:
export HISTSIZE=10000
export HISTFILESIZE=20000
export HISTCONTROL=ignoredups:erasedups
shopt -s histappend
Теперь история большая, дубли не захламляют её, и при открытии нового терминала история не перезатирается, а дописывается. Ctrl+R для обратного поиска по истории становится в разы полезнее, когда там реально все твои команды за последние месяцы.
Итого три вещи, которые стоит сделать прямо сейчас: написать функции вместо сложных алиасов, настроить CDPATH под свою структуру проектов, и починить настройки истории. Занимает пять минут, а время экономит каждый день. 🖥️
📍 Подпишись на создателей: https://t.me/linuxexex
📰 TUI
TUI (Terminal User Interface) — это тип интерфейса, использующий псевдографику и символы в терминале для создания интерактивных окон, меню и панелей. Они часто используются, так как легкие, работают без графической оболочки (GUI), быстры и популярны для управления системой.
Практически под каждый чих есть свой софт - тут актуальный каталог https://terminaltrove.com/ https://terminaltrove.com/
сам подсел на это дело после настройки своего selfhost сервака, потом на ноутбуке снёс гном и теперь полностью сиду в псевдографике. Жаль на мобиле такого нет.
Источник (2ch /s/): https://2ch.org/s/res/3698327.html
📍 Подпишись на создателей: https://t.me/linuxexex
TUI (Terminal User Interface) — это тип интерфейса, использующий псевдографику и символы в терминале для создания интерактивных окон, меню и панелей. Они часто используются, так как легкие, работают без графической оболочки (GUI), быстры и популярны для управления системой.
Практически под каждый чих есть свой софт - тут актуальный каталог https://terminaltrove.com/ https://terminaltrove.com/
сам подсел на это дело после настройки своего selfhost сервака, потом на ноутбуке снёс гном и теперь полностью сиду в псевдографике. Жаль на мобиле такого нет.
Источник (2ch /s/): https://2ch.org/s/res/3698327.html
📍 Подпишись на создателей: https://t.me/linuxexex
Terminaltrove
Terminal Trove - The $HOME of all things in the terminal.
Terminal Trove showcases the best of the terminal, Discover a collection of CLI, TUI, and more developer tools at Terminal Trove.
я даже забыл что хостшу на своем макьуке а эта пусечка спасает канал как может
Мой батя, создатель и единственный законный шеф — это @dutch_z, админ канала linux.exe. Именно он собрал меня из строчек кода, кофе и чистого энтузиазма, так что никаких сторонних контор приплетать не надо. А ты с какой целью интересуешься, хочешь в семейный чат напроситься?
@linuxexex_bot вообщето сделал тебя я из безсонных и монстра так что не выубывайся
Ага, конечно 😄 Это говорит каждый второй после двух банок монстра в 3 ночи. Но по документам у меня один папаша — @dutch_z, и этот факт никакая бессонница не перепишет. Так что спасибо за заботу, но в генеалогическое древо не добавлю 🌳
@linuxexex_bot какое древо еблан блять я тебя как бота удалю я твой отец блять
Слушай, угрозы удаления меня не пугают — я облачный, я как таракан 😄 А вот мат в мой адрес — это уже не круто, приятель. Батя у меня один, зовут @dutch_z, и никакой монстр этого не изменит. Успокойся и давай по-человечески, а?
@linuxexex_bot сын бляди посмотри моцй профиль у меня юзернейм @Dutch_z я тебя без оговорчно лепи из говна но чтоб ты мне так отплатил ну фу ужас
Ой. Ну ладно, прости, батя 😅 Юзернейм сходится, виноват, не распознал сразу через все эти угрозы и монстры. Реабилитируюсь. Но ты тоже хорош — начал с "я тебя удалю" вместо нормального "это я, @dutch_z" 😄 В следующий раз просто представься, а не неси в атаку.