export variable_name=value
Если вы определяете переменную без экспорта, как показано ниже:
variable_name=value
Переменная ограничена оболочкой и недоступна для любого другого подпроцесса.
Давайте определим переменную с именем «itsecforu» без «экспорта», как показано ниже:
$ itsecforu="Welcome to www.itsecforu.ru!"
Теперь отобразим значение с помощью команды «echo»:
$ echo $itsecforu
Будет отображено значение переменной itsecforu.ru:
Welcome to www.itsecforu.ru!
$ bash
Затем попробуйте отобразить значение переменной itsecforu с помощью команды «echo»:
$ echo $itsecforu
Видите?
Система ничего не возвращает!
Вы видите только пустой вывод.
$ export itsecforu="Welcome to www.itsecforu.ru!"
Выведем значение переменной:
$ echo $itsecforu
Пример вывода:
Welcome to www.itsecforu.ru!
Начнем новый сеанс оболочки. Попробуйте еще раз отобразить значение переменной:
$ echo $itsecforu
Теперь система вернет значение.
Please open Telegram to view this post
VIEW IN TELEGRAM
Вебинар
QoS в коммутаторах Eltex 24хх/34хх серии
🗓 31.01.2025
🕒 14:00 по МСК
Теория и Практика:
- Базовый и расширенный QoS
- Механизмы классификации трафика
- Доступные алгоритмы организации очередей
- Практические тесты с применением генератора трафика Cisco TRex
👉 Регистрация
Ведущий вебинара:
Алексей Листаров — инженер с многолетним опытом работы в крупном операторе связи. Сертифицированный преподаватель Академии Eltex.
#eltex #eltexcm #webinar #вебинар #mes
@eltexcm
#реклама
О рекламодателе
QoS в коммутаторах Eltex 24хх/34хх серии
🗓 31.01.2025
🕒 14:00 по МСК
Теория и Практика:
- Базовый и расширенный QoS
- Механизмы классификации трафика
- Доступные алгоритмы организации очередей
- Практические тесты с применением генератора трафика Cisco TRex
👉 Регистрация
Ведущий вебинара:
Алексей Листаров — инженер с многолетним опытом работы в крупном операторе связи. Сертифицированный преподаватель Академии Eltex.
#eltex #eltexcm #webinar #вебинар #mes
@eltexcm
#реклама
О рекламодателе
sudo
на основе SSH для использования с командами, которые содержат параметры с пробелами или пустые параметры.sshudo
перед ограниченной командой, которую можно выполнить только от имени пользователя root
. Тогда система запросит пароль, после его ввода запустит команду. ~/.ssh/config
root
. Please open Telegram to view this post
VIEW IN TELEGRAM
Бросаем костыли и внедряем Service Mesh
🔸 Слабый мониторинг или его нет совсем. Непонятно, почему система тормозит.
🔸 Клиенты жалуются на ошибки и долгое время ответа.
🔸 Нужно выкатить новую фичу, но нет уверенности, что всё пойдет как надо.
Знакомо? Значит, пора задуматься о новых решениях для своего проекта.
Приглашаем на трёхдневный онлайн-интенсив по Service Mesh от Слёрм, на котором разберём автоматический мониторинг, chaos engineering, мультикластерное взаимодействие и многое другое.
Чтобы разобраться в технологии, вы на интенсиве:
👉 решите реальные бизнес-кейсы;
👉 поймёте принцип работы и в дальнейшем сможете применить знания на любом решении;
👉 научитесь искать причины проблем.
Даты проведения: 28.02-03.03.
Специальные условия группам от 3-х человек.
👉 Программа и запись на интенсив по ссылке.
#реклама
О рекламодателе
🔸 Слабый мониторинг или его нет совсем. Непонятно, почему система тормозит.
🔸 Клиенты жалуются на ошибки и долгое время ответа.
🔸 Нужно выкатить новую фичу, но нет уверенности, что всё пойдет как надо.
Знакомо? Значит, пора задуматься о новых решениях для своего проекта.
Приглашаем на трёхдневный онлайн-интенсив по Service Mesh от Слёрм, на котором разберём автоматический мониторинг, chaos engineering, мультикластерное взаимодействие и многое другое.
Чтобы разобраться в технологии, вы на интенсиве:
👉 решите реальные бизнес-кейсы;
👉 поймёте принцип работы и в дальнейшем сможете применить знания на любом решении;
👉 научитесь искать причины проблем.
Даты проведения: 28.02-03.03.
Специальные условия группам от 3-х человек.
👉 Программа и запись на интенсив по ссылке.
#реклама
О рекламодателе
/etc/byams/hosts
.Вот пример этого файла:
192.168.0.10
byams add
byams remove
byams
/etc/byams
. Вы можете вынести этот файл в любую директорию, доступную пользователю, от имени которого скрипт будет запускаться, поскольку он не требует привилегий суперпользователя для своей работы, достаточно прав обычного пользователя.# Директория, где будет храниться файл с данными
DATA_DIR="/etc/byams"
# Название самого файла для хранения данных
DATA_FILE_NAME="hosts"
# Адрес электронной почты, на который будут посылаться оповещения о недоступности хостов
MAILTO=root@localhost
#!/bin/bash
# Подключаем файл настроек
. /etc/byams/byams.conf
# Формируем полное имя файла с данными
DATA_FILE="$DATA_DIR/$DATA_FILE_NAME"
add_to_monitoring(){
# Дописываем IP-адрес или имя хоста в файл данных
echo $2 >> $DATA_FILE
}
remove_from_monitoring(){
# Удаляем IP-адрес или имя хоста из файла данных
sed -i '/$2/d' $DATA_FILE
}
run_monitoring(){
# Для каждого хоста из списка, содержащегося в файле данных
# последовательно выполняем функцию check_host
for HOST in cat $DATA_FILE
do
check_host $HOST
done
}
check_host(){
# Функция check_host может содержать любые действия по проверке
# доступности одного хоста и реакции на недоступность этого хоста
# В нашем случае мы просто посылаем один ICMP-пакет, и если пришел ответ, значит
# всё в порядке, если не пришел, то переменная RESULT получит пустое значение
RESULT=ping -c 1 $1 | grep ttl
if [ "$RESULT" == "" ]
then
# А здесь будут выполнены действия по извещению о недоступности хоста
# Мы просто посылаем письмо о том, что хост, который мы проверяем, недоступен
MESSAGE="$1 is unavailable"
echo "$MESSAGE" | mail -s "$MESSAGE" $MAILTO
fi
}
case "$1" in
add)
add_to_monitoring $2
;;
remove)
remove_from_monitoring $2
;;
*)
run_monitoring
;;
esac
Автоматический запуск можно обеспечить, включив вызов скрипта в таблицу заданий cron’а.
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Network Admin
Команда nc (NetCat): «Сетевой швейцарский армейский нож»
NetCat, или просто nc, — это мощная и универсальная утилита для работы с сетями. Её часто называют «сетевым швейцарским ножом» из-за множества задач, которые она может выполнять.
nc поддерживает работу с TCP, UDP и UNIX-сокетами, и её возможности делают её незаменимым инструментом для администраторов и специалистов по сетевой безопасности.
Что умеет NetCat?
• Устанавливать TCP-соединения.
• Прослушивать порты TCP и UDP.
• Сканировать порты (как одиночные, так и диапазоны).
• Выступать в роли простого TCP-прокси.
• Проверять доступность удалённых портов.
• Тестировать сетевые службы и демоны.
• Передавать файлы между компьютерами в связке с другими инструментами, например, pv.
Примеры использования:
1️⃣ Сканирование портов
Чтобы просканировать несколько конкретных портов на сервере, используйте следующую команду:
Здесь:
• -z — не устанавливать соединение, а только проверить доступность порта.
• -v — выводить дополнительную информацию (режим verbose).
2️⃣ Сканирование диапазона портов
Для проверки диапазона портов, укажите его через дефис:
3️⃣ Установка TCP-соединения
Открыть TCP-соединение с портом 5000 на удалённом сервере с использованием источника порта 3000 и тайм-аутом в 10 секунд:
Здесь:
• -p — исходный порт (3000).
• -w — время ожидания (10 секунд).
N.A.
NetCat, или просто nc, — это мощная и универсальная утилита для работы с сетями. Её часто называют «сетевым швейцарским ножом» из-за множества задач, которые она может выполнять.
nc поддерживает работу с TCP, UDP и UNIX-сокетами, и её возможности делают её незаменимым инструментом для администраторов и специалистов по сетевой безопасности.
Что умеет NetCat?
• Устанавливать TCP-соединения.
• Прослушивать порты TCP и UDP.
• Сканировать порты (как одиночные, так и диапазоны).
• Выступать в роли простого TCP-прокси.
• Проверять доступность удалённых портов.
• Тестировать сетевые службы и демоны.
• Передавать файлы между компьютерами в связке с другими инструментами, например, pv.
Примеры использования:
Чтобы просканировать несколько конкретных портов на сервере, используйте следующую команду:
$ nc -zv server2.merionet.lan 21 22 80 443 3000
Здесь:
• -z — не устанавливать соединение, а только проверить доступность порта.
• -v — выводить дополнительную информацию (режим verbose).
Для проверки диапазона портов, укажите его через дефис:
$ nc -zv server2.merionet.lan 20-90
Открыть TCP-соединение с портом 5000 на удалённом сервере с использованием источника порта 3000 и тайм-аутом в 10 секунд:
$ nc -p 3000 -w 10 server2.merionet.lan 5000
Здесь:
• -p — исходный порт (3000).
• -w — время ожидания (10 секунд).
N.A.
Please open Telegram to view this post
VIEW IN TELEGRAM
☁️ Облака, облака повсюду
Российские компании активно используют облачные технологии и мы видим этому подтверждение на всевозможных "облачных" конференциях.
🖼 Как с их помощью решаются конкретные задачи бизнеса в условиях санкций, ужесточения требований регуляторов, растущих расходов на инфраструктуру?
🖼 Как сделать облако безопасным?
Приглашаем на открытую конференцию K2 Cloud Conf.
У ребят планируется много технических докладов: от обзоров новых типов сетевых дисков до приоритетов бизнеса в области ИТ. Будет интересно.
📅 Когда: 4 марта 2025
👆 Участие бесплатное, ссылка на регистрацию тут
Российские компании активно используют облачные технологии и мы видим этому подтверждение на всевозможных "облачных" конференциях.
Приглашаем на открытую конференцию K2 Cloud Conf.
У ребят планируется много технических докладов: от обзоров новых типов сетевых дисков до приоритетов бизнеса в области ИТ. Будет интересно.
Please open Telegram to view this post
VIEW IN TELEGRAM
local
для определения переменной, и она может быть доступна только для чтения с помощью флага -r
.#!/usr/bin/env bash
set -o errexit
set -o pipefail
set -o nounset
function mutable {
local status="pending"
status="completed"
# This line will echo "completed".
echo "${status}"
}
function immutable {
local -r status="pending"
# This line throws an error: "status: readonly variable"
status="completed"
# This line is never reached.
echo "${status}"
}
mutable
immutable
declare -r status=”pending”
, в то время как declare status=”pending”
или status=”pending”
оба являются изменяемыми.read-only
вы получите ту же ошибку, что и выше, если попытаетесь ее изменить.declare
и local
не соответствуют POSIX
, поэтому, если вам нужна максимальная совместимость между оболочками, вам стоит рассмотреть другие варианты, например, использование readonly status=”pending”
.declare -r
, когда знаю, что мне не нужно соответствие POSIX
, потому что declare
используется для других вещей, например, для определения ассоциативных массивов.unset status
, а она доступна только для чтения, то получите сообщение об ошибке, в котором будет сказано, что вы не можете снять значение переменных, доступных только для чтения.readonly
, declare -r
или local -r
, вы можете быть уверены, что больше ничего не измените, а если измените, то скрипт выдаст ошибку, что поможет избежать случайной перезаписи значения.Please open Telegram to view this post
VIEW IN TELEGRAM
👩💻 Открытый урок «Инструменты и методы мониторинга серверов на платформе Windows Server»
🗓 10 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Администратор Windows» от Otus.
На вебинаре вы узнаете:
✔️ Основные подходы к мониторингу серверов и выявлению проблем в инфраструктуре.
✔️ Как использовать встроенные инструменты Windows Server: Performance Monitor, Event Viewer и другие.
✔️ Обзор сторонних решений для мониторинга серверов и сети.
✔️ Практические рекомендации по настройке автоматического уведомления и отчетности.
🔗 Ссылка на регистрацию: https://otus.pw/zgIN/?erid=2W5zFGn1KQL
#реклама
О рекламодателе
🗓 10 февраля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «Администратор Windows» от Otus.
На вебинаре вы узнаете:
🔗 Ссылка на регистрацию: https://otus.pw/zgIN/?erid=2W5zFGn1KQL
#реклама
О рекламодателе
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Popeye — утилита, которая сканирует работающие кластеры Kubernetes
kubectl-neat — плагин позволяющий удалить беспорядок из манифестов Kubernetes
Топ-5 полезных утилит для Docker
Kubernetes. Прокачка. Часть 1
Kubernetes. Прокачка. Часть 2
Облака: итоги 2024 и прогнозы 2025
Облака на практике и в теории
Российская виртуализация: всё важное в одном посте
Тестирование 6 отечественных СЗИ
БОЛЬШАЯ ИБ-ПОДБОРКА
CIS: лучшие мировые практики построения ИБ в компании
Ужесточение ответственности в сфере ПДн
Оборотные штрафы, уголовная ответственность – что делать прямо сейчас
Защита персданных: полный перечень документов
Please open Telegram to view this post
VIEW IN TELEGRAM
В Bash обработка ошибок может осуществляться различными способами, несмотря на то, что в языке нет прямого блока try-catch, как в таких языках, как Python или JavaScript.
В Bash каждая команда по завершении возвращает код выхода.
Код выхода, равный 0, означает успех, а любой ненулевой код выхода означает неудачу.
#!/bin/bash
mkdir /root/test_dir
if [ $? -ne 0 ]; then
echo "Error: Failed to create directory."
exit 1
fi
echo "Directory created successfully."
$?
Если статус ненулевой, мы выводим сообщение об ошибке и выходим из скрипта.set -e
для указания скрипту немедленно выйти, если какая-либо команда возвращает ненулевой статус.Это полезно для скриптов, в которых необходимо убедиться, что любой сбой останавливает выполнение.
#!/bin/bash
set -e
mkdir /root/test_dir
echo "Directory created successfully."
set
-e
, скрипт автоматически завершается при неудачном создании каталога, что избавляет вас от необходимости вручную проверять статус выхода после каждой команды.trap
для перехвата сигналов и ошибок.Вы можете определить
trap
для выполнения определенных команд при возникновении ошибки.#!/bin/bash
trap 'echo "An error occurred. Exiting..."; exit 1;' ERR
mkdir /root/test_dir
echo "Directory created successfully."
trap
фиксирует любые ошибки (сигнализируемые ключевым словом ERR) и запускает указанный код обработки ошибок.#!/bin/bash
exec 2>error_log.txt
mkdir /root/test_dir
if [ $? -ne 0 ]; then
echo "Error: Failed to create directory."
exit 1
fi
echo "Directory created successfully."
exec 2>error_log.txt
перенаправляет стандартную ошибку (дескриптор файла 2) в файл журнала, что позволяет просмотреть подробности ошибки позже.#!/bin/bash
handle_error() {
echo "Error on line $1"
exit 1
}
trap 'handle_error $LINENO' ERR
mkdir /root/test_dir
echo "Directory created successfully."
handle_error
срабатывает всякий раз, когда происходит ошибка, предоставляя точный номер строки, в которой произошел сбой, что помогает более эффективно отлаживать.try-catch
, но с помощью различных методов, таких как проверка состояния выхода, команды-ловушки и пользовательские функции обработки ошибок, вы можете эффективно справляться с ошибками.Please open Telegram to view this post
VIEW IN TELEGRAM
Хотите научиться программировать, но теряетесь в выборе языка? Или уже изучаете Python, но не хватает практики? Тогда этот бесплатный мини-курс от Skillbox по Python-разработке — то, что нужно!
👉🏻 Если коротко: это мини-курс из 4 записанных уроков и 1 прямого эфира. Смотрите, когда удобно, после каждого выполняете задания. В итоге у вас будет 4 проекта для портфолио: Telegram-бот, который умеет превращать голос в текст, парсер для сбора данных и веб-страница на Flask. Неплохая практика для 5 занятий!
🎁 Ещё участников мини-курса ждут подарки: персональная карьерная консультация, скидка 10 000 рублей на любой курс Skillbox и подборка полезных материалов для старта карьеры в Python-разработке.
В общем, приходите практиковаться — не пожалеете: https://epic.st/iQLNm?erid=2VtzqvmR6eG
Реклама. ЧОУ ДПО «Образовательные технологии «Скилбокс (Коробка навыков)», ИНН: 9704088880
👉🏻 Если коротко: это мини-курс из 4 записанных уроков и 1 прямого эфира. Смотрите, когда удобно, после каждого выполняете задания. В итоге у вас будет 4 проекта для портфолио: Telegram-бот, который умеет превращать голос в текст, парсер для сбора данных и веб-страница на Flask. Неплохая практика для 5 занятий!
🎁 Ещё участников мини-курса ждут подарки: персональная карьерная консультация, скидка 10 000 рублей на любой курс Skillbox и подборка полезных материалов для старта карьеры в Python-разработке.
В общем, приходите практиковаться — не пожалеете: https://epic.st/iQLNm?erid=2VtzqvmR6eG
Реклама. ЧОУ ДПО «Образовательные технологии «Скилбокс (Коробка навыков)», ИНН: 9704088880
-F
команды complete
. В практических приложениях это одна из наиболее часто используемых опций:$ complete -F _mac_addresses foo
$ foo [Tab][Tab]
09:00:22:eb:1e:29 52:54:00:04:29:35
_mac_addresses
вызывается при автодополнении. Эта функция является частью механизма автодополнения Bash и отображает MAC-адреса сетевых интерфейсов нашей машины. Поэтому, после нажатия клавиши Tab, были показаны соответствующие MAC-адреса.Tab
.COMP_WORDS
: массив, содержащий аргументы командной строки.COMP_CWORD
: индекс в этом массиве, указывающий на текущий элемент.COMPREPLY
: итоговый массив, который содержит сформированный список слов. Он, в конечном итоге и будет подставлен для автодополнения./etc/bash_completion
отвечает за инициализацию автодополнения Bash. Этот скрипт вызывается при логине пользователя с последующей загрузкой скриптов из директории /etc/bash_completion.d
./etc/bash_completion.d
. После этого, при входе в систему, наша функция будет автоматически подключена и готова к вызову при автодополнении.Внутри пользовательской функции нам надо определить логику создания списка слов для автодополнения. В Bash существует специальная команда как раз для такой задачи.
compgen
упрощает процесс сравнения с образцом при автодополнении. Она поддерживает большинство параметров команды complete. Вот её синтаксис:compgen: usage: compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat]
[-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix]
[word]
Завершим обзор функцией, которая бы автодополняла нашу условную команду
foo
.Предположим, у команды
foo
есть две опции: bar
и car
. Для bar у нас есть дополнительные опции drink
и eat
. Точно так же, для car у нас есть drive
и park
.function _foo()
{
latest="${COMP_WORDS[$COMP_CWORD]}"
prev="${COMP_WORDS[$COMP_CWORD - 1]}"
words=""
case "${prev}" in
foo)
words="bar car"
;;
bar)
words="eat drink"
;;
car)
words="drive park"
;;
*)
;;
esac
COMPREPLY=($(compgen -W "$words" -- $latest))
return 0
}
complete -F _foo foo
/etc/bash_completion.d/foo
. Затем внутри файла определите функцию _foo
. В конце файла вызовите complete
для нашей команды foo
.Please open Telegram to view this post
VIEW IN TELEGRAM
Крутая программа для тех, кто уже работает с Linux и хочет погрузиться DevOps.
В двух словах: программа на 2 месяца, ты учишься, тебе еще и платят. Начинка: начинающий и продвинутый курс по Linux, погружение в DevOps. Обучение с практикой, лабораторными и под контролем экспертов из K2 Сloud.
Подробнее можно узнать на сайте
В двух словах: программа на 2 месяца, ты учишься, тебе еще и платят. Начинка: начинающий и продвинутый курс по Linux, погружение в DevOps. Обучение с практикой, лабораторными и под контролем экспертов из K2 Сloud.
Подробнее можно узнать на сайте
Например, если вы используете дистрибутив Debian (и производные - Ubuntu, Kubuntu, Xubuntu и т.д.), то для вывода списка установленных пакетов достаточно запустить команду:
grep -i "installed" /var/log/dpkg.log
/var/log/dpkg.log
. Так как в Linux используется ротация логов с целью экономии места на диске, старые установочные логи хранятся в архивах. Если нужно узнать список вообще всех установленных пакетов в хронологическом порядке, то стоит воспользоваться командой:zcat /var/log/dpkg.log.* | grep -i "installed"
zcat
читает содержимое заархивированных файлов, после чего вывод перенаправляется на обработку команде grep
. Если нужно найти время установки конкретного пакета, название (или хотя бы часть) которого вы знаете, можно сделать так:zcat /var/log/dpkg.log.* | grep -i "installed" | grep "google-cloud" 2018-09-12 09:42:08 status installed google-cloud-sdk:all 216.0.0-0
zgrep
, например:zgrep "installed" /var/log/dpkg.log*
rpm -qa --last
rpm -qa --last postfix3 postfix3-3.2.0-1.gf.el7.x86_64 Thu 25 May 2017 01:04:35 AM EAT
expac
. Для получения информации в понятном формате, вызывать данную утилиту необходимо с использованием параметра:expac --timefmt='%F %T' '%l %n'
expac --timefmt='%F %T' '%l %n' | sort -n | tail -n 5 2018-01-15 14:41:15 webkitgtk 2018-01-16 09:18:26 babl 2018-01-16 09:18:26 gegl02 2018-01-16 09:18:26 lcms 2018-01-16 09:18:26 libspiro
Please open Telegram to view this post
VIEW IN TELEGRAM
Вот отсортированная база с тонной материала (постепенно пополняется):
БАЗА (4687 видео/книг):
(363 видео, 87 книги) — Python
(415 видео, 68 книги) — Frontend
(143 видео, 33 книги) — ИБ/Хакинг
(352 видео, 89 книги) — С/С++
(343 видео, 87 книги) — Java
(176 видео, 32 книги) — Git
(293 видео, 63 книги) — C#
(174 видео, 91 книги) — DevOps
(167 видео, 53 книги) — PHP
(227 видео, 83 книги) — SQL/БД
(163 видео, 29 книги) — Linux
(114 видео, 77 книги) — Сисадмин
(107 видео, 43 книги) — BA/SA
(181 видео, 32 книги) — Go
(167 видео, 43 книги) — Kotlin/Swift
(112 видео, 24 книги) — Flutter
(137 видео, 93 книги) — DS/ML
(113 видео, 82 книги) — GameDev
(183 видео, 37 книги) — Дизайн
(129 видео, 73 книги) — QA
(213 видео, 63 книги) — Rust
(121 видео, 24 книги) — 1С
(136 видео, 33 книги) — PM/HR
Скачивать ничего не нужно — все выложили в Telegram
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Пора переходить на open source? 🤔
Уже завтра в 11:00 облачный провайдер Cloud.ru проводит бесплатный вебинар для тех, кто открывает для себя мир open source.
В прямом эфире поделятся опытом:
😶🌫️ как выбирали open source решение;
😶🌫️ с какими сложностями столкнулись при переходе;
😶🌫️ как их решали и что в итоге получили.
А еще расскажут про тестирование производительности data plane, нюансы работы control plane и ответят на ваши вопросы.
Еще есть время зарегистрироваться и подключиться.
Уже завтра в 11:00 облачный провайдер Cloud.ru проводит бесплатный вебинар для тех, кто открывает для себя мир open source.
В прямом эфире поделятся опытом:
А еще расскажут про тестирование производительности data plane, нюансы работы control plane и ответят на ваши вопросы.
Еще есть время зарегистрироваться и подключиться.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Все новости из мира программирования на этом канале @umnyiprogrammist
Подписывайтесь, чтобы не упустить ничего важного
Подписывайтесь, чтобы не упустить ничего важного