Ищем и убираем дубликаты строк в терминале!
Частая задача: есть файл с логами, списком ID, email-адресами или любыми строками, где встречаются повторы. Нужно быстро привести данные в порядок прямо в консоли.
Базовый инструмент —
Самый простой вариант:
Что здесь происходит:
Если нужны только строки, которые встретились ровно один раз:
Если нужно посчитать, сколько раз встречается каждая строка:
Если нужно сразу увидеть самые частые значения сверху:
Практический пример для логов — топ IP по количеству запросов:
Если нужно записать результат обратно в тот же файл:
Если важно игнорировать регистр:
Это эквивалентно связке с
Важно:
🔥 Такого набора хватает для большинства задач: быстро почистить данные, посмотреть частоты, выявить лишние записи в логах.
🚪 Linux Ready | #практика
Частая задача: есть файл с логами, списком ID, email-адресами или любыми строками, где встречаются повторы. Нужно быстро привести данные в порядок прямо в консоли.
Базовый инструмент —
uniq. Важно понимать: он удаляет только соседние одинаковые строки. Поэтому в большинстве случаев перед ним нужна сортировка.Самый простой вариант:
sort data.txt | uniq
Что здесь происходит:
sort сортирует строки, чтобы одинаковые значения оказались рядом, uniq убирает повторяющиеся соседние строки.Если нужны только строки, которые встретились ровно один раз:
sort data.txt | uniq -u
Если нужно посчитать, сколько раз встречается каждая строка:
sort data.txt | uniq -c
Если нужно сразу увидеть самые частые значения сверху:
sort data.txt | uniq -c | sort -nr
Практический пример для логов — топ IP по количеству запросов:
awk '{print $1}' access.log | sort | uniq -c | sort -nr | head
Если нужно записать результат обратно в тот же файл:
sort -u -o data.txt data.txt
Если важно игнорировать регистр:
sort -fu data.txt
Это эквивалентно связке с
uniq, но короче.Важно:
uniq не ищет все дубликаты по всему файлу — он работает только с соседними строками. Без sort он уберет только те повторы, которые уже идут подряд.Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🤝8❤7
This media is not supported in your browser
VIEW IN TELEGRAM
От базовых понятий и структуры системы до понимания дистрибутивов и принципов работы ОС. Материал построен последовательно и помогает сформировать целостное представление о Linux. Уроки ориентированы на системное понимание: объясняется не только работа команд, но и логика самой системы.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🔥9🤝8
This media is not supported in your browser
VIEW IN TELEGRAM
Это структурированный конспект по системе: от базовых вещей вроде файловой иерархии, работы с файлами и regex до более управления дисками, LVM и стримов ввода/вывода. Всё собрано в одном месте и разбито по логичным блокам. Открываешь нужный раздел и сразу получаешь информацию.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🤝9🔥6
Знали, что файл в Linux можно удалить и продолжать в него писать?
В Linux файл — это inode, а имя в файловой системе лишь ссылка на него.
Открываешь файл через файловый дескриптор:
Удаляешь файл из файловой системы:
Файла как бы нет, но дескриптор остаётся открыт.
Продолжаешь писать в уже удалённый файл:
Данные реально записываются, просто файл больше не имеет имени в файловой системе.
Поэтому иногда диск заполнен, но du “ничего не показывает”.
🔥 Это механизм, на котором держится лог-ротация и поведение демонов. Если процесс держит удалённый файл, он продолжает занимать место на диске, пока не закроет дескриптор.
🚪 Linux Ready | #совет
В Linux файл — это inode, а имя в файловой системе лишь ссылка на него.
Открываешь файл через файловый дескриптор:
$ exec 3<>file.txt
$ ls -li file.txt
Удаляешь файл из файловой системы:
$ rm file.txt
$ ls file.txt
Файла как бы нет, но дескриптор остаётся открыт.
Продолжаешь писать в уже удалённый файл:
$ echo "hello" >&3
$ sync
Данные реально записываются, просто файл больше не имеет имени в файловой системе.
Поэтому иногда диск заполнен, но du “ничего не показывает”.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍9❤7🤝4
Например, traceroute показывает маршрут пакетов от компьютера до сервера, а за счёт TTL позволяет определить каждый промежуточный узел (hop) и задержку до него.
На картинке — наглядно разобран принцип работы traceroute: как увеличивается TTL, как роутеры отвечают через ICMP и как по шагам строится маршрут до конечного сервера.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥8🤝6❤2
Знали, что можно корректно записывать в привилегированные файлы без запуска редактора от root?
Частая ошибка заключается в использовании
tee решает эту проблему, так как сама утилита запускается с правами
Флаг -a обеспечивает корректное добавление в файл без его перезаписи.
Можно применять шаблоны или генерируемые конфигурации напрямую:
При этом сохраняется корректная модель прав доступа, отсутствуют временные файлы и исключаются ошибки, связанные с перенаправлением в shell.
🔥 Этот подход широко используется при автоматизации, конфигурации систем и в CI/CD сценариях.
🚪 Linux Ready | #совет
Частая ошибка заключается в использовании
sudo echo ... > file, что не работает ожидаемым образом, поскольку перенаправление выполняется текущим shell без привилегий.tee решает эту проблему, так как сама утилита запускается с правами
sudo и выполняет запись:$ echo "option=1" | sudo tee /etc/app.conf
$ echo "option=2" | sudo tee -a /etc/app.conf
Флаг -a обеспечивает корректное добавление в файл без его перезаписи.
Можно применять шаблоны или генерируемые конфигурации напрямую:
$ generate_config | sudo tee /etc/app.conf
$ sudo tee /etc/app.conf < config.new
При этом сохраняется корректная модель прав доступа, отсутствуют временные файлы и исключаются ошибки, связанные с перенаправлением в shell.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤8🔥7
This media is not supported in your browser
VIEW IN TELEGRAM
Этот репозиторий добавляет в bash автодополнение, полезные алиасы, плагины и готовые команды, которые сильно упрощают работу в терминале. Особенно полезно, когда постоянно работаешь с git, docker, ssh, системными утилитами и сервером.
Оставляю ссылочку: GitHub📱
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝15❤7👍6🔥2
Смотрим, какие capability выданы бинарнику!
Иногда программа запускается без root, но всё равно умеет открывать
Посмотреть
Часто увидишь что-то вроде:
Это значит, что бинарник может работать с
Проверить
Так можно быстро найти потенциально опасные или нестандартные разрешения.
Выдать
Теперь приложение сможет слушать порты ниже 1024 без root.
Например, запускать HTTP сервер сразу на 80:
Удалить
Посмотреть
🔥 Linux
🚪 Linux Ready | #практика
Иногда программа запускается без root, но всё равно умеет открывать
raw sockets, bind low ports или менять network stack. Обычно причина заключается в Linux capabilities.Посмотреть
capability бинарника:getcap /usr/bin/ping
Часто увидишь что-то вроде:
cap_net_raw=ep
Это значит, что бинарник может работать с
raw sockets без полного root-доступа.Проверить
capabilities всех бинарников в системе:sudo getcap -r / 2>/dev/null
Так можно быстро найти потенциально опасные или нестандартные разрешения.
Выдать
capability бинарнику:sudo setcap cap_net_bind_service=+ep ./app
Теперь приложение сможет слушать порты ниже 1024 без root.
Например, запускать HTTP сервер сразу на 80:
./app
Удалить
capability:sudo setcap -r ./app
Посмотреть
capabilities процесса:grep Cap /proc/1234/status
capabilities позволяют выдавать процессам точечные привилегии без полного root-доступа.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍9🤝6
Например, Forward Proxy скрывает клиента и помогает обходить ограничения, а Reverse Proxy принимает запросы от пользователей и распределяет их между серверами.
На картинке — наглядное сравнение Forward Proxy и Reverse Proxy: где они располагаются, как работают и для каких задач используются.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤7🔥7
Знали, что Bash умеет редактировать предыдущие команды как полноценный текстовый объект?
Большинство используют history только через ↑, хотя Bash поддерживает полноценные history expansion и inline-редактирование команд без перепечатывания.
Повторяет предыдущую команду, заменяя все совпадения прямо перед выполнением:
Если последняя команда была:
Shell выполнит:
Без ручного редактирования и без запуска редактора.
Можно вывести результат expansion без выполнения:
Флаг
Для быстрых исправлений опечаток существует встроенная подстановка:
Shell заменит первое совпадение в предыдущей команде и выполнит исправленный вариант в текущей сессии.
🔥 History expansion выполняется самим интерактивным Bash до парсинга команды. Поэтому итоговая строка видит текущие alias, functions, переменные и окружение так же, как если бы вы набрали её вручную.
🚪 Linux Ready | #совет
Большинство используют history только через ↑, хотя Bash поддерживает полноценные history expansion и inline-редактирование команд без перепечатывания.
Повторяет предыдущую команду, заменяя все совпадения прямо перед выполнением:
$ sudo !!:gs/8080/80/
Если последняя команда была:
$ docker run -p 8080:8080 app
Shell выполнит:
$ sudo docker run -p 80:80 app
Без ручного редактирования и без запуска редактора.
Можно вывести результат expansion без выполнения:
$ !-2:p
Флаг
:p показывает итоговую команду после expansion и не запускает её. Это безопасный способ проверить подстановку перед выполнением.Для быстрых исправлений опечаток существует встроенная подстановка:
$ ^sttaus^status
Shell заменит первое совпадение в предыдущей команде и выполнит исправленный вариант в текущей сессии.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13❤9👍8🤝1
Например, когда устройство хочет отправить данные на IP-адрес внутри локальной сети, ему сначала нужно узнать MAC-адрес получателя. Для этого используется ARP — Address Resolution Protocol.
На картинке показано, как хост отправляет ARP Request в broadcast, коммутатор рассылает запрос всем устройствам, а нужный хост отвечает своим MAC-адресом через ARP Reply.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18❤6👍5
Настройка coredump в Linux — диагностика падений процессов!
Когда Linux-процесс аварийно завершается (например, SIGSEGV / Segmentation fault, SIGABRT и др.), система может сохранить снимок памяти процесса — core dump.
Без dump-файла обычно остаётся только сам факт падения и запись в логах. Core dump позволяет открыть состояние процесса в
Проверка текущего лимита на создание dump:
Если вывод 0 — сохранение core dump отключено для текущей shell/session.
Временное включение:
Это работает только для процессов, запущенных из текущей shell-сессии. После logout или reboot настройка пропадёт.
Для systemd-сервисов одного ulimit недостаточно — лимит нужно задавать в unit-файле:
После изменения unit-файла:
Теперь проверяем, как именно система сохраняет dump-файлы:
Параметр
Пример прямого сохранения dump в файл:
Где:
Создадим каталог для dump-файлов и настроим сохранение:
Чтобы настройка сохранилась после reboot:
Добавляем:
Применяем конфигурацию:
Пример аварийного завершения процесса:
После падения появится dump-файл:
Теперь можно открыть dump через
Посмотреть стек вызовов:
Для полноценного анализа бинарь желательно собирать с debug symbols (
На большинстве современных systemd-дистрибутивов dump часто обрабатывается через systemd-coredump, а не сохраняется напрямую через
Посмотреть список crash:
Получить информацию по dump:
Открыть dump сразу в
Вместо
Это особенно важно в проде, где dump может занимать гигабайты и быстро заполнять диск.
🔥 Core dump — один из базовых механизмов low-level диагностики Linux-приложений, backend-сервисов и анализа падений в продакшен.
🚪 Linux Ready | #практика
Когда Linux-процесс аварийно завершается (например, SIGSEGV / Segmentation fault, SIGABRT и др.), система может сохранить снимок памяти процесса — core dump.
Без dump-файла обычно остаётся только сам факт падения и запись в логах. Core dump позволяет открыть состояние процесса в
gdb, получить stack trace, посмотреть память, регистры, потоки и локализовать причину уже после завершения процесса.Проверка текущего лимита на создание dump:
ulimit -c
Если вывод 0 — сохранение core dump отключено для текущей shell/session.
Временное включение:
ulimit -c unlimited
Это работает только для процессов, запущенных из текущей shell-сессии. После logout или reboot настройка пропадёт.
Для systemd-сервисов одного ulimit недостаточно — лимит нужно задавать в unit-файле:
[Service]
LimitCORE=infinity
После изменения unit-файла:
sudo systemctl daemon-reload
sudo systemctl restart app.service
Теперь проверяем, как именно система сохраняет dump-файлы:
cat /proc/sys/kernel/core_pattern
Параметр
core_pattern определяет обработчик и путь сохранения dump. Если значение начинается с |, dump передаётся внешнему обработчику, например systemd-coredump.Пример прямого сохранения dump в файл:
/core.%e.%p.%t
Где:
%e — имя процесса; %p — PID процесса; %t — UNIX timestampСоздадим каталог для dump-файлов и настроим сохранение:
sudo mkdir -p /var/crash
sudo chmod 1777 /var/crash
sudo sysctl -w kernel.core_pattern=/var/crash/core.%e.%p.%t
1777 используется как простой демо вариант для тестов и локальной диагностики. В продакшен обычно делают более жёсткие права доступа и отдельно контролируют доступ к dump-файлам, поскольку они могут содержать чувствительные данные процесса.Чтобы настройка сохранилась после reboot:
sudo nano /etc/sysctl.d/99-coredump.conf
Добавляем:
kernel.core_pattern=/var/crash/core.%e.%p.%t
Применяем конфигурацию:
sudo sysctl --system
Пример аварийного завершения процесса:
./app
Segmentation fault (core dumped)
После падения появится dump-файл:
/var/crash/core.app.18422.1715962012
Теперь можно открыть dump через
gdb:gdb ./app /var/crash/core.app.18422.1715962012
Посмотреть стек вызовов:
(gdb) bt
Для полноценного анализа бинарь желательно собирать с debug symbols (
-g) без stripping.На большинстве современных systemd-дистрибутивов dump часто обрабатывается через systemd-coredump, а не сохраняется напрямую через
core_pattern.Посмотреть список crash:
coredumpctl list
Получить информацию по dump:
coredumpctl info PID
Открыть dump сразу в
gdb:coredumpctl debug PID
Вместо
PID можно использовать имя процесса, путь к бинарю и другие фильтры coredumpctl. Также важно помнить, что systemd-coredump отдельно управляет хранением dump-файлов через coredump.conf: Storage, ProcessSizeMax, ExternalSizeMax, MaxUse, KeepFree.Это особенно важно в проде, где dump может занимать гигабайты и быстро заполнять диск.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15🔥7👍6
This media is not supported in your browser
VIEW IN TELEGRAM
На сайте собраны статьи и гайды по Linux, системному администрированию, hardening и безопасности серверов. Здесь можно найти разбор команд, настройку сервисов, аудит системы, советы по защите инфраструктуры и практические рекомендации для админов и backend-разработчиков.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍7❤5
В этой статье:
• Разбираются ключевые обновления far2l 2.8.0;
• Показывается, как far2l постепенно превращается из простого порта Far Manager в мощный нативный инструмент для Linux и macOS;
• Объясняются практические улучшения для разработчиков и администраторов: перенос слов, номера строк, кликабельные ссылки, улучшенная работа с терминалами и поддержка kitty graphics protocol.🔊 Продолжайте читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥8🤝6❤1
Знали, что tar умеет потоково передавать файлы через pipe без создания архива на диске?
Большинство используют
Команда создаёт
Файлы копируются напрямую на удалённую машину без временного
Можно сразу включить сжатие:
Такой способ часто оказывается быстрее и надёжнее
Этот же приём удобно использовать локально:
🔥 Фактически это полноценное копирование дерева файлов через pipe без
🚪 Linux Ready | #совет
Большинство используют
tar только для архивов, хотя в Linux его часто применяют как быстрый способ потоковой передачи файлов между системами и директориями.Команда создаёт
tar-поток в stdout и сразу передаёт его в другой процесс:$ tar cf - project | ssh server "tar xf -"
Файлы копируются напрямую на удалённую машину без временного
.tar файла и без промежуточной записи на диск.Можно сразу включить сжатие:
$ tar czf - logs | ssh server "tar xzf -"
Такой способ часто оказывается быстрее и надёжнее
scp при большом количестве мелких файлов, потому что сохраняется единый поток передачи и корректно переносятся права и структура директорий.Этот же приём удобно использовать локально:
$ tar cf - . | (cd /backup && tar xf -)
rsync, cp -a и создания временных архивов.Please open Telegram to view this post
VIEW IN TELEGRAM
👍23🔥11🤝5
Например, NAT позволяет нескольким устройствам внутри локальной сети использовать один публичный IP-адрес для выхода в интернет, а обратный NAT возвращает ответы именно тому устройству, которое отправило запрос.
На картинке — наглядная схема того, как работает трансляция адресов: как роутер меняет private IP на public IP, зачем нужны порты и тд.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥7❤5
Перехватываем вывод процесса через tee — лог и консоль одновременно!
Частый кейс: запускаешь задачу (деплой, миграция, билд) и хочешь одновременно видеть вывод в терминале и сохранять его в файл. Обычный редирект
Команда:
Что происходит:
Добавление в файл (
Без потери кода возврата (важно для скриптов):
Без
Альтернатива:
Важно:
Пример: деплой
Лог сохраняется, при этом видно всё в реальном времени.
Пример: долгий билд
Разделение потоков с сохранением,
Используется process substitution (bash).
Пример: отладка пайплайна
Сохраняешь и исходные данные, и результат фильтрации.
Что это даёт: полный контроль над логами без потери интерактивности; удобно для CI, деплоя, отладки; прозрачная диагностика.
🔥 Ограничения и нюансы:
🚪 Linux Ready | #практика
Частый кейс: запускаешь задачу (деплой, миграция, билд) и хочешь одновременно видеть вывод в терминале и сохранять его в файл. Обычный редирект
> убирает вывод из консоли. Решается через tee.Команда:
command 2>&1 | tee output.log
Что происходит:
2>&1 объединяет stderr и stdout; tee дублирует поток — пишет в файл и выводит в терминал.Добавление в файл (
append):command 2>&1 | tee -a output.log
Без потери кода возврата (важно для скриптов):
set -o pipefail
command 2>&1 | tee output.log
echo $?
Без
pipefail код возврата будет от tee, а не от command. echo $? нужно вызывать сразу после пайплайна, иначе значение перезапишется.Альтернатива:
command 2>&1 | tee output.log
exit ${PIPESTATUS[0]}
Важно:
PIPESTATUS нужно читать сразу после пайплайна, иначе он перезапишется.Пример: деплой
set -o pipefail
./deploy.sh 2>&1 | tee deploy.log
Лог сохраняется, при этом видно всё в реальном времени.
Пример: долгий билд
make -j4 2>&1 | tee build.log
stderr не теряется, но порядок строк может перемешиваться (из-за параллельности и буферизации).Разделение потоков с сохранением,
stdout в файл, stderr отдельно:command > >(tee out.log) 2> >(tee err.log >&2)
Используется process substitution (bash).
stdout/stderr остаются в консоли, но порядок между потоками не гарантируется.Пример: отладка пайплайна
tee raw.log < data.txt | grep error | tee filtered.log
Сохраняешь и исходные данные, и результат фильтрации.
Что это даёт: полный контроль над логами без потери интерактивности; удобно для CI, деплоя, отладки; прозрачная диагностика.
pipe меняет код возврата (решается pipefail или PIPESTATUS); pipefail не POSIX (bash/zsh/ksh); некоторые программы буферизуют вывод; при больших потоках — нагрузка на диск.Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥7❤4🤝1
В этой статье:
• Разбираются ключевые обновления far2l 2.8.0;
• Показывается, как far2l постепенно превращается из простого порта Far Manager в мощный нативный инструмент для Linux и macOS;
• Объясняются практические улучшения для разработчиков и администраторов: перенос слов, номера строк, кликабельные ссылки, улучшенная работа с терминалами и поддержка kitty graphics protocol.🔊 Продолжайте читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝12👍8🔥6
Знали, что можно добавлять timestamp к любому выводу terminal pipeline без изменения приложения и логгера?
Во многих CLI-утилитах, shell-скриптах и legacy-сервисах отсутствуют временные метки, из-за чего сложно анализировать задержки, интервалы выполнения и последовательность событий.
Утилита
Теперь каждая строка получает точное время:
Это особенно полезно при отладке конвейеров команд, shell-автоматизации, CI-логов, docker-контейнеров и
Можно использовать свой формат времени:
Или измерять интервалы между событиями:
Иногда программы буферизуют вывод — тогда поможет:
🔥 Приём кажется небольшим, но на практике сильно упрощает анализ поведения систем и CLI-инструментов без внедрения полноценного логгирования.
🚪 Linux Ready | #совет
Во многих CLI-утилитах, shell-скриптах и legacy-сервисах отсутствуют временные метки, из-за чего сложно анализировать задержки, интервалы выполнения и последовательность событий.
Утилита
ts из пакета moreutils добавляет timestamp к каждой строке stdin в реальном времени:$ tail -f app.log | ts '%Y-%m-%d %H:%M:%S'
Теперь каждая строка получает точное время:
2026-05-22 18:41:03 request started
2026-05-22 18:41:07 request finished
Это особенно полезно при отладке конвейеров команд, shell-автоматизации, CI-логов, docker-контейнеров и
long-running процессов, где нельзя быстро изменить сам источник логов.Можно использовать свой формат времени:
$ tail -f app.log | ts '[%H:%M:%S]'
Или измерять интервалы между событиями:
$ ping 1.1.1.1 | ts -i
Иногда программы буферизуют вывод — тогда поможет:
$ stdbuf -oL -eL some-command | ts
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👍10🤝5
This media is not supported in your browser
VIEW IN TELEGRAM
На сайте собрана большая коллекция материалов по Linux, системному администрированию и серверной инфраструктуре. Здесь можно найти шпаргалки по командам, настройку сервисов, работу с сетью, Bash, Docker, SSH, Nginx и другие практические темы, с которыми регулярно сталкиваются админы и backend-разработчики.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍8🔥6
Знали, что Bash умеет потоково обрабатывать stdout и stderr через process substitution?
Когда нужно одновременно сохранить вывод в файл, показать его в терминале и отдельно обработать ошибки — многие делают временные файлы или запускают команду несколько раз.
В Bash это решается напрямую:
Теперь
Можно сразу передавать поток в другие команды:
Или обрабатывать и логировать вывод без временных файлов:
При раздельной обработке
🔥 Крутой механизм Bash для отладки, логирования и построения сложных shell-конвейеров.
🚪 Linux Ready | #совет
Когда нужно одновременно сохранить вывод в файл, показать его в терминале и отдельно обработать ошибки — многие делают временные файлы или запускают команду несколько раз.
В Bash это решается напрямую:
command > >(tee output.log)
stdout команды одновременно выводится в терминал и записывается в output.log.stderr можно обработать отдельно:command > >(tee out.log) 2> >(tee err.log >&2)
Теперь
stdout и stderr разделены по разным log-файлам, но продолжают отображаться в терминале в реальном времени.Можно сразу передавать поток в другие команды:
make 2> >(grep error >&2)
Или обрабатывать и логировать вывод без временных файлов:
docker logs app > >(ts > app.log)
ts обычно входит в пакет moreutilsProcess substitution подключает pipe/FIFO или /dev/fd/* как обычный файл, поэтому данные обрабатываются потоково без временных файлов и без повторного запуска команды.При раздельной обработке
stdout/stderr порядок строк между потоками может отличаться от оригинального.Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤6🔥5