🐧
Linux для QA-инженера

От основ архитектуры до анализа логов

1 / 38

Обо мне

[Фото]

Григорий Звягинцев

QA Engineer

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

2 / 38

О чем эта презентация?

Мы совершим полное погружение в мир Linux с точки зрения тестировщика: начнем с фундаментальных теоретических концепций и закончим практическими навыками, необходимыми для эффективной ежедневной работы.

Теория

Разберемся, что такое Linux, чем он отличается от Windows, какова его архитектура и какие бывают дистрибутивы.

Практика

Освоим командную строку для навигации, работы с файлами, управления процессами и правами доступа.

Инструменты QA

Сфокусируемся на главном: научимся анализировать логи, работать с сетью и использовать утилиты, которые упростят поиск багов.

3 / 38

Для кого эта презентация?

Начинающие QA-инженеры

Вы получите прочный фундамент для работы с серверными приложениями и тестовыми стендами на Linux.

Специалисты с опытом

Сможете систематизировать знания и открыть для себя новые, более эффективные инструменты и подходы.

Все, кто хочет уверенности

Вы перестанете бояться черного экрана консоли и начнете использовать его как мощный рабочий инструмент.

Что она даст?

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

4 / 38

Что такое Linux?

Linux — это семейство операционных систем, основанных на ядре Linux. Это свободное программное обеспечение с открытым исходным кодом, что является его ключевой особенностью.

Открытый код

Любой желающий может посмотреть, изменить и распространять исходный код. Это способствует быстрому развитию и поиску уязвимостей.

Многозадачность

Система спроектирована для одновременного выполнения множества задач и работы многих пользователей.

Надежность

Linux славится своей стабильностью и является стандартом де-факто для серверного оборудования по всему миру.

Гибкость

От суперкомпьютеров и МКС до вашего смартфона (Android) и роутера — Linux работает везде.

5 / 38

Принципиальные отличия от Windows

Понимание этих различий — ключ к эффективной работе.

АспектLinuxWindows
Файловая системаЕдиная иерархия, корень /. Нет дисков C: или D:.Логические диски с буквами (C:, D:).
Установка ПОЦентрализованно через пакетный менеджер (apt, yum).Скачивание и запуск .exe/.msi файлов.
НастройкиТекстовые файлы в директории /etc и домашних папках.Централизованный Реестр (Registry).
Права доступаЧеткое разделение. Обычный пользователь не может навредить системе.Пользователи часто работают с правами администратора.
Командная строкаОсновной и самый мощный инструмент для управления.Вспомогательный инструмент (хотя PowerShell очень мощный).
6 / 38

Что такое дистрибутив?

Так как ядро Linux свободно, разные компании и сообщества создают на его основе свои операционные системы — дистрибутивы. Дистрибутив — это ядро Linux + набор программ и утилит + графическая оболочка.

Выбор дистрибутива зависит от ваших задач. Для тестирования серверного ПО чаще всего используются дистрибутивы, основанные на Debian (например, Ubuntu) или Red Hat (CentOS, Fedora).

7 / 38

Дистрибутивы: Для новичков

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

Ubuntu

Самый популярный и дружелюбный дистрибутив. Огромное сообщество, простая установка и хорошая поддержка оборудования "из коробки".

Linux Mint

Основан на Ubuntu. Его интерфейс Cinnamon очень похож на Windows, что облегчает переход. Считается очень стабильным и нетребовательным к ресурсам.

Manjaro

Более продвинутый вариант, основанный на Arch Linux, но с простым установщиком. Предоставляет доступ к самому свежему ПО.

8 / 38

Дистрибутивы: Для серверов

На тестовых и продуктовых серверах вы, скорее всего, встретите один из этих дистрибутивов. Главный критерий для них — стабильность.

Debian

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

Ubuntu Server

Серверная версия самого популярного дистрибутива. Сочетает стабильность с доступом к более новому ПО и коммерческой поддержкой от Canonical.

CentOS / AlmaLinux

Бесплатные аналоги коммерческого Red Hat Enterprise Linux (RHEL). Стандарт для многих корпоративных сред, где важна совместимость с RHEL.

9 / 38

WSL: Linux внутри Windows

Windows Subsystem for Linux — это официальный инструмент от Microsoft, который позволяет запускать полноценную командную строку Linux прямо в Windows без виртуальных машин.

Зачем это QA-инженеру?

Это идеальный способ практиковаться в командах Linux, писать и отлаживать скрипты на своем рабочем Windows-компьютере, не устанавливая вторую ОС. Вы можете установить Ubuntu из Microsoft Store и сразу начать работать.

10 / 38

Архитектура: Файловая система

Ключевое отличие от Windows: в Linux всё является файлом. Жесткие диски, клавиатура, принтеры — для системы все это файлы, расположенные в единой древовидной структуре.

Корень /

Вся файловая система начинается с корневого каталога /. Все пути к файлам и папкам отсчитываются от него. Например: /home/grigory/documents/report.txt.

11 / 38

Структура каталогов

Файлы в Linux организованы по назначению. Вот самые важные каталоги, которые нужно знать:

КаталогНазначение
/binОсновные команды и утилиты системы.
/etcФайлы конфигурации всех программ и системы.
/homeДомашние директории пользователей (/home/grigory).
/var/logСамая важная папка для QA! Здесь хранятся лог-файлы.
/tmpВременные файлы.
/rootДомашняя директория суперпользователя (администратора).
12 / 38

Архитектура: Уровни выполнения

Runlevel (уровень выполнения) определяет, какие службы и процессы запущены в системе в данный момент. Это похоже на "Режимы загрузки" в Windows (обычный, безопасный).

УровеньНазначениеКогда используется?
0ВыключениеКоманда shutdown.
1ОднопользовательскийДля восстановления системы, когда что-то сломалось.
3Многопользовательский, консольСтандартный режим для серверов.
5Многопользовательский, графикаСтандартный режим для настольных ПК.
6ПерезагрузкаКоманда reboot.
13 / 38

Архитектура: Процессы и Демоны

Любая запущенная программа в Linux — это процесс. У каждого процесса есть уникальный номер (PID).

Демоны (Службы)

Это особенные процессы, которые работают в фоновом режиме и выполняют системные задачи. Например, веб-сервер (httpd, nginx) или служба удаленного доступа (sshd). Именно их работу мы чаще всего и тестируем.

14 / 38

Переходим к практике

Философия: «Одна утилита — одна функция»

В Linux множество маленьких, но очень мощных программ (утилит). Наша цель — не выучить их все, а научиться комбинировать их для решения конкретных задач. Мы будем рассматривать каждую команду в связке "теория + практический пример".

Структура изучения

  • Что делает команда? - Краткое и понятное описание.
  • Зачем это QA? - Конкретный пример из практики тестировщика.
  • Как это выглядит? - Демонстрация в эмуляторе терминала.
# Пример: ищем ошибки в логе и считаем их количество qa-user@server:~$ grep "ERROR" /var/log/app.log | wc -l 15
15 / 38

Навигация и работа с директориями

Первый шаг — научиться перемещаться по файловой системе и управлять её структурой.

Ключевые команды

  • pwd — Показывает, где вы сейчас находитесь.
  • ls -la — Показывает детальное содержимое директории.
  • cd <путь> — Перемещает вас в другую директорию.
  • cd .. — Вернуться на уровень выше.
  • mkdir <имя> — Создает новую директорию.
# Где я? grigory@test-stand:~$ pwd /home/grigory # Создадим папку для логов и перейдем в нее grigory@test-stand:~$ mkdir test-logs grigory@test-stand:~$ cd test-logs # Проверим, что мы в нужной папке grigory@test-stand:~/test-logs$ pwd /home/grigory/test-logs
16 / 38

Работа с файлами

Создание, копирование, перемещение и удаление файлов — базовые операции для подготовки тестовых данных.

Ключевые команды

  • touch — Создает пустой файл.
  • cp — Копирует файл или директорию.
  • mv — Перемещает или переименовывает.
  • rm — Удаляет файл. **Безвозвратно!**
  • rm -rf <папка> — Удаляет папку со всем содержимым.
# Создадим файл конфигурации grigory@test-stand:~/test-logs$ touch config.xml # Сделаем его резервную копию grigory@test-stand:~/test-logs$ cp config.xml config.xml.bak # Переименуем оригинальный файл grigory@test-stand:~/test-logs$ mv config.xml settings.xml # Удалим ненужную копию grigory@test-stand:~/test-logs$ rm config.xml.bak
17 / 38

Просмотр содержимого файлов

Читать логи и конфигурационные файлы — ежедневная задача. Для этого есть несколько удобных инструментов.

Ключевые команды

  • cat — Выводит всё содержимое файла.
  • less — Постраничный просмотр для больших файлов.
  • head — Показывает первые 10 строк.
  • tail — Показывает последние 10 строк.
  • tail -f — **Must-have!** Следит за файлом в реальном времени.
# Смотрим конец лога grigory@test-stand:~$ tail /var/log/syslog ... Oct 8 13:05:46 server systemd[1]: session-c2.scope: Succeeded. # Следим за логом в реальном времени grigory@test-stand:~$ tail -f /var/log/syslog Oct 8 13:05:46 server systemd[1]: session-c2.scope: Succeeded. # (здесь будут появляться новые строки)
18 / 38

Символьные и жесткие ссылки

Ссылки позволяют одному файлу или директории быть доступными по разным путям. Это аналог "ярлыков" в Windows.

Команда `ln`

  • Символьная ссылка (Symbolic): ln -s /путь/к/файлу /путь/к/ссылке. Это просто указатель. Если удалить оригинал, ссылка "сломается".
  • Жесткая ссылка (Hard): ln /путь/к/файлу /путь/к/ссылке. Это второе имя для того же файла. Файл будет удален с диска, только когда будет удалена последняя жесткая ссылка на него.
  • Зачем это QA? Для быстрой организации доступа к логам или конфигурациям, которые лежат глубоко в файловой системе.
# Создадим символьную ссылку на лог-файл Nginx grigory@test-stand:~$ ln -s /var/log/nginx/error.log nginx_error.log # Теперь мы можем смотреть лог прямо из домашней папки grigory@test-stand:~$ tail -f nginx_error.log
19 / 38

Перенаправление ввода-вывода (I/O)

По умолчанию, команды выводят результат в консоль. Но мы можем "перенаправить" этот вывод в файл.

Операторы > и >>

  • > (Перезаписать): ls -l > file_list.txt. Сохранит список файлов в file_list.txt, полностью **перезаписав** его содержимое.
  • >> (Добавить): echo "Test completed" >> report.log. **Добавит** строку в конец файла report.log, не удаляя старое содержимое.
  • Зачем это QA? Для сохранения результатов выполнения команд, создания отчетов или тестовых данных.
# Сохраним список процессов в файл grigory@test-stand:~$ ps aux > running_processes.txt # Добавим в этот же файл информацию о памяти grigory@test-stand:~$ free -h >> running_processes.txt # Посмотрим, что получилось grigory@test-stand:~$ cat running_processes.txt USER PID %CPU %MEM... ... total used free Mem: 7.7Gi 3.4Gi 4.3Gi
20 / 38

Конвейеры (Pipelines)

Конвейер (|, "пайп") — это сердце философии Linux. Он передает вывод одной команды напрямую на ввод другой, создавая мощные цепочки обработки данных.

Оператор |

команда1 | команда2 | команда3

  • Пример для QA: Найти в логе все строки с "ERROR", из них выбрать только те, что связаны с "Payment", отсортировать и сохранить в файл.
  • Это позволяет обрабатывать огромные объемы данных "на лету", не создавая промежуточных файлов.
# Найти все запущенные процессы # Отфильтровать только те, что содержат "java" # Посчитать количество таких строк grigory@test-stand:~$ ps aux | grep "java" | wc -l 3
21 / 38

Управляющие операторы

Эти операторы позволяют объединять несколько команд в одну строку, управляя логикой их выполнения.

Операторы &&, ||, ;

  • && (И): команда1 && команда2. Вторая команда выполнится **только если** первая завершилась успешно.
  • || (ИЛИ): команда1 || команда2. Вторая команда выполнится **только если** первая завершилась с ошибкой.
  • ; (Точка с запятой): команда1 ; команда2. Вторая команда выполнится **в любом случае**, независимо от результата первой.
# Обновить список пакетов И если успешно, обновить их $ sudo apt update && sudo apt upgrade -y # Попытаться создать папку ИЛИ если не вышло (уже есть), # вывести сообщение $ mkdir logs || echo "Папка уже существует" # Перейти в папку; затем показать ее содержимое $ cd /var/log ; ls -l
22 / 38

Права доступа: Теория

Каждый файл и директория в Linux имеют владельца, группу и набор прав для трёх категорий пользователей.

-rwx-r--r--

  • Первый символ: - (файл), d (директория), l (ссылка).
  • Символы 2-4: Права для владельца (user).
  • Символы 5-7: Права для группы (group).
  • Символы 8-10: Права для всех остальных (others).
grigory@test-stand:~$ ls -l /bin/bash -rwxr-xr-x 1 root root 1183448 мая 17 2021 /bin/bash # r (read) - Чтение # w (write) - Запись # x (execute) - Выполнение
23 / 38

Права доступа: `chmod`

Команда chmod (change mode) изменяет права доступа. Часто для теста нужно сделать скрипт исполняемым.

Способы изменения

Числовой: r=4, w=2, x=1. Суммируем для каждой категории.

  • chmod 755 script.sh: 7(rwx) для владельца, 5(r-x) для группы и остальных. Стандарт для скриптов.
  • chmod 644 config.txt: 6(rw-) для владельца, 4(r--) для остальных. Стандарт для текстовых файлов.

Символьный: u, g, o, a (user, group, others, all) и +, -, =.

  • chmod u+x script.sh: Добавить (+) право на выполнение (x) для пользователя (u).
# Создали скрипт, но он не запускается grigory@test-stand:~$ ls -l deploy.sh -rw-r--r-- 1 grigory grigory 128 окт 8 13:15 deploy.sh # Делаем его исполняемым grigory@test-stand:~$ chmod 755 deploy.sh # Проверяем снова grigory@test-stand:~$ ls -l deploy.sh -rwxr-xr-x 1 grigory grigory 128 окт 8 13:15 deploy.sh
24 / 38

Смена владельца: `chown`

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

Команда `chown` (change owner)

  • chown user file.txt: Сменить владельца файла.
  • chown user:group file.txt: Сменить и владельца, и группу.
  • chown -R user:group /path/to/dir: Рекурсивно сменить владельца для всей директории и ее содержимого.
  • Важно: Эту команду может выполнять только суперпользователь (`sudo`).
# Мы загрузили конфиг, но он принадлежит нам grigory@test-stand:~$ ls -l /var/www/config.json -rw-r--r-- 1 grigory grigory 512 окт 8 14:00 /var/www/config.json # Отдадим его веб-серверу (пользователь www-data) grigory@test-stand:~$ sudo chown www-data:www-data /var/www/config.json # Проверяем grigory@test-stand:~$ ls -l /var/www/config.json -rw-r--r-- 1 www-data www-data 512 окт 8 14:00 /var/www/config.json
25 / 38

Управление пакетами: `apt`

Для установки, обновления и удаления программ в Debian/Ubuntu используется пакетный менеджер APT. Он автоматически скачивает программы из надежных источников (репозиториев).

Основные команды `apt`

  • sudo apt update: Обновить список доступных пакетов. **Всегда выполняйте перед установкой!**
  • sudo apt install <пакет>: Установить программу (например, htop).
  • sudo apt upgrade: Обновить все установленные программы.
  • sudo apt remove <пакет>: Удалить программу.
  • apt search <название>: Поиск пакета.
# Обновляем информацию о пакетах grigory@test-stand:~$ sudo apt update ... # Установим Midnight Commander - удобный файловый менеджер grigory@test-stand:~$ sudo apt install mc Reading package lists... Done ... The following NEW packages will be installed: mc
26 / 38

Управление процессами: Мониторинг

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

Ключевые команды

  • `ps aux`: Показывает статический список всех запущенных процессов.
  • `top` / `htop`: Динамический "Диспетчер задач" в консоли. Показывает нагрузку на CPU, память и список процессов в реальном времени. `htop` более наглядный и удобный (если не установлен, sudo apt install htop).
  • `ps aux | grep <имя>`: Найти конкретный процесс.
# Проверим, запущено ли наше java-приложение grigory@test-stand:~$ ps aux | grep my-app.jar grigory 12345 0.5 10.2 2516480 812345 pts/0 Sl 13:20 0:42 java -jar my-app.jar
27 / 38

Управление процессами: Завершение

Приложение зависло или работает некорректно? Его нужно остановить.

Команда `kill`

Использует PID процесса из вывода `ps`.

  • `kill <PID>`: "Мягко" просит процесс завершиться (сигнал SIGTERM 15). Процесс может сохранить данные перед выходом.
  • `kill -9 <PID>`: Принудительно "убивает" процесс (сигнал SIGKILL 9). Используйте, если обычный `kill` не помогает. Данные могут быть потеряны.
# Приложение с PID 12345 зависло, попробуем его остановить grigory@test-stand:~$ kill 12345 # (ждем несколько секунд... процесс не завершился) # Принудительно завершаем процесс grigory@test-stand:~$ kill -9 12345
28 / 38

Управление службами: `systemctl`

Для управления фоновыми службами (демонами) используется команда `systemctl`.

Основные команды `systemctl`

Требуют `sudo`.

  • `systemctl status <служба>`: Проверить статус (работает, остановлена, ошибка).
  • `systemctl start <служба>`: Запустить.
  • `systemctl stop <служба>`: Остановить.
  • `systemctl restart <служба>`: Перезапустить. Часто нужно после изменения конфигов.
  • `systemctl enable <служба>`: Включить автозапуск при старте системы.
# Проверим статус веб-сервера grigory@test-stand:~$ sudo systemctl status nginx ● nginx.service - A high performance web server Active: active (running) since Wed 2025-10-08 13:00:00 # Перезапустим его после обновления конфига grigory@test-stand:~$ sudo systemctl restart nginx
29 / 38

Анализ логов: Важность для QA

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

Что мы ищем в логах?

Ошибки

Явные сообщения об ошибках: ERROR, Exception, FATAL, panic.

Аномалии

Неожиданное поведение, резкое увеличение количества сообщений, таймауты.

Последовательность

Восстановление шагов, которые привели к сбою. Что делал пользователь перед ошибкой?

Подтверждение

Убедиться, что действие (например, сохранение данных) действительно было выполнено и залогировано.

30 / 38

Анализ логов: Инструменты

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

ИнструментНазначение
grepОсновной инструмент. Ищет строки по шаблону.
lessУдобный просмотр больших файлов с поиском.
tail -fМониторинг логов в реальном времени.
journalctlПросмотр системных логов в дистрибутивах с `systemd`.
zgrep, zcatРабота с архивированными логами (.gz).
31 / 38

Анализ логов: `grep` + `tail`

Соединение `tail -f` и `grep` через пайп — один из самых мощных приемов для QA. Вы можете следить за логом в реальном времени, отфильтровывая только нужные вам события.

Возможности `grep`

  • Без учета регистра: grep -i "error".
  • Контекст: grep -C 5 "Exception" покажет 5 строк до и 5 после ошибки.
  • Инверсия: grep -v "DEBUG" покажет все строки, КРОМЕ отладочных.
  • Количество: grep -c "SUCCESS" просто посчитает количество успешных операций.
# Следим за логом, но показываем ТОЛЬКО ошибки $ tail -f /var/log/app.log | grep -i "error" # (терминал будет ждать и выводить только новые ошибки) # Следим за действиями конкретного пользователя $ tail -f /var/log/app.log | grep "user_id=555"
32 / 38

Продвинутый `grep`: Цепочки и Regex

Для сложных поисковых задач можно объединять `grep` в цепочки или использовать регулярные выражения.

Сложная фильтрация

  • `grep | grep`: Позволяет сужать поиск. Сначала находим все строки по одному критерию, а потом из них выбираем строки по второму.
  • Регулярные выражения (`-E`): Позволяют искать не точное слово, а шаблон. Например, найти все IP-адреса или ошибки с определенным форматом кода.
# Найти все ошибки, связанные с пользователем user-123 $ grep -i "error" app.log | grep "user-123" # Найти все IP-адреса в логе Nginx # (Пример регулярного выражения) $ grep -E -o "([0-9]{1,3}\.){3}[0-9]{1,3}" /var/log/nginx/access.log 8.8.8.8 192.168.1.1
33 / 38

Работа с сетью: Диагностика

Простые утилиты для быстрой проверки сетевой доступности.

Ключевые команды

  • `ping <host>`: Проверяет, "виден" ли сервер в сети и есть ли задержки.
  • `ip address` или ifconfig: Показывает IP-адреса сетевых интерфейсов сервера.
  • `curl <url>`: Делает HTTP-запросы из консоли. Удобно для быстрой проверки API. curl -I покажет только заголовки.
  • `traceroute <host>`: Показывает маршрут пакетов до целевого хоста.
# Проверим, отвечает ли наш веб-сервис $ curl http://localhost:8080/api/status {"status": "OK", "version": "1.2.3"} # Проверим только HTTP статус $ curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/status 200
34 / 38

Удаленное подключение: SSH и SCP

Тестовые стенды почти всегда находятся на удаленных серверах. `SSH` и `SCP` — ваши главные инструменты для работы с ними.

Ключевые команды

  • `ssh user@host` (Secure Shell): Безопасное подключение к командной строке удаленного сервера.
  • `scp file.txt user@host:~/` (Secure Copy): Безопасное копирование локального файла в домашнюю директорию (`~/`) на сервере.
  • `scp -r user@host:~/logs/ .`: Рекурсивное копирование папки `logs` с сервера в текущую (`.`) локальную директорию.
# Подключаемся к тестовому стенду my-laptop:~$ ssh grigory@192.168.1.100 Welcome to Ubuntu 22.04 LTS grigory@test-stand:~$ # Копируем локальный лог на сервер для анализа my-laptop:~$ scp my_log.txt grigory@192.168.1.100:~/ my_log.txt 100% 256KB 12.8MB/s 00:00
35 / 38

Основы Bash-скриптов

Bash-скрипт — это просто текстовый файл с последовательностью команд. Он позволяет автоматизировать рутинные задачи.

Создание скрипта

  1. Создайте файл: touch my_script.sh.
  2. Откройте файл в текстовом редакторе, например: nano my_script.sh.
  3. Первая строка #!/bin/bash (шебанг). Не обязательна, но крайне рекомендуется, чтобы система знала, каким интерпретатором выполнять скрипт.
  4. Напишите команды, каждая с новой строки.
  5. Сделайте файл исполняемым: chmod +x my_script.sh.
  6. Запустите: ./my_script.sh.
# Содержимое файла check_service.sh: #!/bin/bash echo "Проверяю статус сервиса..." systemctl status nginx # Запускаем скрипт grigory@test-stand:~$ ./check_service.sh Проверяю статус сервиса... ● nginx.service - A high performance web server...
36 / 38

Полезные утилиты

Несколько команд, которые сильно облегчают жизнь.

УтилитаНазначение
df -hПоказывает свободное место на дисках в удобном формате.
du -sh *Показывает размер каждого файла и папки в текущей директории.
free -hПоказывает использование оперативной памяти.
historyПоказывает историю введенных вами команд.
mcMidnight Commander. Двухпанельный файловый менеджер в стиле Norton Commander. Очень удобен для новичков.
37 / 38

Заключение

Командная строка Linux — это не страшно, а невероятно эффективно. Мы рассмотрели ключевые концепции и команды, которых достаточно для решения 90% повседневных задач QA-инженера на сервере.

Главное — практика!

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

Спасибо за внимание!

Вопросы?

38 / 38