Архив метки: Утилиты командной строки

Команда chown Linux

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




При создании файла ему тот пользователь, от имени которого он был создан становится его владельцем, а группой устанавливается основная группа владельца. Но владельца файла и группу можно менять, для этого используются команды chown и chgrp. В этой статье будет рассмотрена команда chown linux, а также основные примеры её использования.




Команда chown Linux




1. Синтаксис и опции




Синтаксис chown, как и других подобных команд linux очень прост:




$ chown пользователь опции /путь/к/файлу




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




  • -c, —changes — подробный вывод всех выполняемых изменений;



  • -f, —silent, —quiet — минимум информации, скрыть сообщения об ошибках;



  • —dereference — изменять права для файла к которому ведет символическая ссылка вместо самой ссылки (поведение по умолчанию);



  • -h, —no-dereference — изменять права символических ссылок и не трогать файлы, к которым они ведут;



  • —from — изменять пользователя только для тех файлов, владельцем которых является указанный пользователь и группа;



  • -R, —recursive — рекурсивная обработка всех подкаталогов;



  • -H — если передана символическая ссылка на директорию — перейти по ней;



  • -L — переходить по всем символическим ссылкам на директории;



  • -P — не переходить по символическим ссылкам на директории (по умолчанию).




Утилита имеет ещё несколько опций, но это самые основные и то большинство из них вам не понадобится. А теперь давайте посмотрим как пользоваться chown.




2. Использование chown




Например, у нас есть несколько папок dir и их владелец пользователь sergiy:




ls





Давайте изменим владельца папки dir1 на root:




chown root ./dir1





Если вы хотите поменять сразу владельца и группу каталога или файла запишите их через двоеточие, например, изменим пользователя и группу для каталога dir2 на root:




chown root:root ./dir2





Если вы хотите чтобы изменения применялись не только к этому каталогу, но и ко всем его подкаталогам, добавьте опцию -R:




chown -R root:root ./dir3





Дальше давайте изменим группу и владельца на www-data только для тех каталогов и файлов, у которых владелец и группа root в каталоге /dir3:




chown --from=root:root www-data:www-data -cR ./





Для обращения к текущему каталогу используйте путь ./. Мы его использовали и выше. Далее указываем нужную группу с помощью опции —from и просим утилиту выводить изменения, которые она делает в файловой системе с помощью опции -c.




Источник: https://losst.pro/komanda-chown-linux



2023-06-20T01:05:42
Утилиты командной строки

Шпарагалка по Mysqldump

Утилита mysqldump позволяет получить дамп содержимого базы данных или совокупности баз для создания резервной копии или пересылки данных на другой SQL-сервер (не обязательно MySQL-сервер). Дамп будет содержать набор команд SQL для создания и/или заполнения таблиц.




Так же mysqldump имеет возможность развертывания баз данных из созданного sql-файла.




Создание дампа




Разберем пример простейшее использования, задампим базу данных “database” при помощи перенаправления потока в файл “database.sql”:




mysqldump -u root -h 82.82.82.82 -p database > database.sql




  • -u или —user=… – имя пользователя



  • -h или —host=… – удаленный хост (для локального хоста можно опустить этот параметр)



  • -p или —password – запросить пароль



  • database – имя базы данных



  • database.sql – файл для дампа




Развертывание дампа




Перенаправляем поток в обратную сторону и развертываем базу данных:




mysql -uroot -h 82.82.82.82 -p database < database.sql




Или через mysql console:




mysql> use database; 
mysql> source database.sql




Пример использование некоторых параметров




Например, нам нужны данные с “продакшен версии базы” для “версии разработчика”, то есть нам нужна “песочница”. Выбираем не более 100 записей:




mysqldump - uroot -h 82.82.82.82 -p --where="true limit 100" database > database.sql




Или нам нужна только структура, без данных:




mysqldump -u root -h 82.82.82.82 -p --no-data database > database.sql




Делаем дамп в архив:




mysqldump -u root -p database | gzip > ~/database.sql.gz




Шпаргалка по параметрам




Приведу некоторые параметры, которые могут понадобится при работе с утилитой mysqldump.




  • —add-drop-database Добавляет оператор DROP DATABASE перед каждым оператором CREATE DATABASE.



  • —add-drop-table Добавляет оператор DROP TABLE перед каждым оператором CREATE TABLE.



  • —add-locks Добавляет оператор LOCK TABLES перед выполнением и UNLOCK TABLE после выполнения каждого дампа таблицы (для ускорения доступа к MySQL).



  • —all-databases, -A Сохраняет все таблицы из всех баз данных, которые находятся под управлением текущего сервера.



  • —allow-keywords Разрешить создавать имена столбцов, которые совпадают с ключевыми словами. Отсутствие конфликтов обеспечивается прибавлением имени таблицы в качестве префикса к имени каждого столбца.



  • —comments, -i Данный параметр позволяет добавить в дамп дополнительную информацию, такую, как версия mysqldump, версия MySQL, имя хоста, на котором расположен сервер MySQL.



  • —compact Данный параметр требует от mysqldump создать дамп, используя как можно более компактный формат. Параметр является противоположным —comments.



  • —compatible=name Параметр генерирует вывод, который совместим с другими СУБД или более старыми версиями MySQL. Вместо ключевого слова name можно использовать: “ansi”, “mysql323”, “mysql40”, “postgresql”, “oracle”, “mssql”, “db2”, “maxdb”, “no_key_options”, “no_table_options”, “no_field_options”. Можно использовать несколько значений, разделив их запятыми.



  • —complete-insert, -c Используется полная форма оператора INSERT (с именами столбцов).



  • —create-options Добавляет дополнительную информацию в операторы CREATE TABLE. Это может быть тип таблицы, начальное значение AUTO_INCREMENT и другие параметры.



  • —databases, -B Параметр позволяет указать имена нескольких баз данных, для которых необходимо создать дамп.



  • —delayed Использовать команду INSERT DELAYED при вставке строк.



  • —delete-master-logs На главном сервере репликации автоматически удаляются бинарные логи (logbin) после того, как дамп был успешно создан при помощи mysqldump. Этот параметр автоматически включает параметр “—master-data”.



  • —disable-keys, -K Для каждой таблицы, окружает оператор INSERT выражениями /!40000 ALTER TABLE tbl_name DISABLE KEYS /; и /!40000 ALTER TABLE tbl_name ENABLE KEYS /; в выводе результата дампа. Это ускорит загрузку данных на сервер для таблиц типа MyISAM, так как индексы создаются после внесения всех данных.



  • —extended-insert, -e Использовать команду INSERT с новым многострочным синтаксисом (повышает компактность и быстродействие операторов ввода).



  • —flush-logs, -F Записать на диск данные системного журнала из буфера MySQL-сервера перед началом выполнения дампа.



  • —force, -f Продолжать даже если в процессе создания дампа произошла ошибка.



  • —hex-blob Параметр позволяет представить бинарные данные в полях типа BINARY, VARBINARY, BLOB и BIT в шестнадцатеричном формате. Так последовательность “abc” будет заменена на 0x616263.



  • —ignore-table=db_name.tbl_name Позволяет игнорировать таблицу tbl_name базы данных db_name при создании дампа. Если из дампа необходимо исключить несколько таблиц, необходимо использовать несколько параметров “—ignore-table”, указывая по одной таблице в каждом из параметров.



  • —insert-ignore Добавляет ключевое слово IGNORE в оператор INSERT.



  • —lock-all-tables, -x Указание этого параметра приводит к блокировке всех таблиц во всех базах данных на время создания полного дампа всех баз данных.



  • —lock-tables, -l Указание этого параметра приводит к блокировке таблиц базы данных, для которой создается дамп.



  • **—no-autocommit Включает все операторы INSERT, относящиеся к одной таблице, в одну транзакцию, что приводит к увеличению скорости загрузки данных.



  • —no-create-db, -n Подавляет создание в дампе операторов CREATE DATABASE, которые автоматически добавляются при использовании параметров —databases и —all-databases.



  • —no-data, -d Подавляет создание операторов INSERT в дампе, что может быть полезно при создании дампа структуры базы данных без самих данных.



  • —opt Параметр предназначен для оптимизации скорости резервирования данных и является сокращением, включающим следующие опции: —quick —add-drop-table —add-locks —create-options —disable-keys —extended-insert —lock-tables —set-charset. Начиная с MySQL 4.1, параметр —opt используется по умолчанию, т.е. все вышеперечисленные параметры включаются по умолчанию, даже если они не указываются. Для того чтобы исключить такое поведение, необходимо воспользоваться параметров —skip-opt



  • —order-by-primary Указание параметра приводит к тому. что каждая таблица сортируется по первичному ключу или первому уникальному индексу.



  • —port, -P Номер TCP порта, используемого для подключения к хосту.



  • —protocol={TCP|SOCKET|PIPE|MEMORY} Параметр позволяет задать протокол подключения к серверу.



  • —quick, -q Позволяет начать формирование дампа, не дожидаясь полной загрузки данных с сервера и экономя тем самым память.



  • —quote-names, -Q Помещает имена баз данных, таблиц и столбцов в обратные апострофы `. Начиная с MySQL 4.1, данный параметр включен по умолчанию.



  • —replace Добавляет ключевое слово REPLACE в оператор INSERT. Данный параметр впервые появился в MySQL 5.1.3.



  • —result-file=/path/to/file, -r /path/to/file Параметр направляет дамп в файл file. Этот параметр особенно удобен в Windows, без использования командной строки. когда можно перенаправить результат в файл при помощи последовательностей > и >>.



  • —routines, -R Данный параметр создает дамп хранимых процедур и функций. Доступен с MySQL 5.1.2.



  • —single-transaction Параметр создает дамп в виде одной транзакции.



  • —skip-comments Данный параметр позволяет подавить вывод в дамп дополнительной информации.



  • —socket=/path/to/socket, -S /path/to/socket Файл сокета для подсоединения к localhost.



  • —tab=/path/, -T /path/ При использовании этого параметра в каталоге path для каждой таблицы создаются два отдельных файла: tbl_name.sql, содержащий оператор CREATE TABLE, и tbl_name.txt, который содержит данные таблиц, разделенные символом табуляции. Формат данных может быть переопределен явно с помощью параметров —fields-xxx и —lines-xxx.



  • —tables Перекрывает действия параметра —databases (-B). Все аргументы, следующие за этим параметром, трактуются как имена таблиц.



  • —triggers Создается дамп триггеров. Этот параметр включен по умолчанию. для его отключения следует использовать параметр —skip-triggers.



  • —events, -E Создается дамп событий. Смотрите MySQL Event Scheduler или встроенный диспетчер событий в MySQL.



  • —tz-utc при использовании данного параметра в дамп будет добавлен оператор вида SET TIME_ZONE=‘+00:00’, который позволит обмениваться дампа в различных временных зонах.



  • —verbose, -v Расширенный режим вывода. Вывод более детальной информации о работе программы.



  • —version, -V Вывести информацию о версии программы.



  • —where=‘where-condition’, -w ‘where-condition’ Выполнить дамп только выбранных записей. Обратите внимание, что кавычки обязательны.



  • —xml, -X Представляет дамп базы данных в виде XML.



  • —first-slave, -x Блокирует все таблицы во всех базах данных.



  • —debug=…, –# Отслеживать прохождение программы (для отладки).



  • —help Вывести справочную информацию и выйти из программы.




Источник: http://ajaxblog.ru/mysql/cheatsheet-on-mysqldump/



2023-02-21T16:17:44
Утилиты командной строки

Taskset — привязка процесса к ядрам CPU

По умолчанию процессы используют все ядра процессора, но иногда необходимо освободить 0 ядро, которое обычно больше всего загружено или назначить некоторые процессы только на второй CPU и т.д., в этом случае поможет taskset.




Переключимся на root пользователя:




sudo -i




Просмотр краткой справки по taskset:




taskset -h




Узнаем ID процесса bird или любого другого нужного процесса:




pidof bird




Посмотрим каким ядрам назначен этот процесс:




taskset -pc 744

taskset -p -c 744




Можно указать все в одной команде:




taskset -cp `pidof bird`




Например у меня отобразилось, что на все ядра:




pid 744’s current affinity list: 0-27




Посмотрим сколько ядер имеет процессор и сколько есть процессоров:




lscpu | grep -i numa




Например у меня отобразилось:




NUMA node(s): 2
NUMA node0 CPU(s): 0-13
NUMA node1 CPU(s): 14-27




В моем случае второй процессор загружен на 10% меньше чем первый, поэтому я привязал процесс к ядрам второго процессора:




taskset -pc 14-27 `pidof bird`




Или укажем на все кроме 0:




taskset -pc 1-27 `pidof bird`




В ответ у меня отобразилось:




pid 17092’s current affinity list: 0-27
pid 17092’s new affinity list: 14-27




Проверим:




taskset -pc `pidof bird`




Если с указанным именем запущено несколько процессов, то можно использовать скрипт (на примере процесс ixnfo_com):




(for thread in $(ps -T -C ixnfo_com | awk '{print $2}' | grep -E '[0-9]'); do /usr/bin/taskset -pc $thread; done)




Например у меня отобразилось:




pid 2455's current affinity list: 0-27

pid 2458's current affinity list: 0-27

pid 2459's current affinity list: 0-27

pid 2460's current affinity list: 0-27

pid 2461's current affinity list: 0-27

pid 2463's current affinity list: 0-27




Теперь привяжем все эти процессы к нужным ядрам:




(for thread in $(ps -T -C ixnfo_com | awk '{print $2}' | grep -E '[0-9]'); do /usr/bin/taskset -pc 14-27 $thread; done)




Чтобы изменения не сбросились после перезапуска операционной системы, укажем команду например в файле /etc/rc.local.




Источник: https://ixnfo.com/taskset.html



2023-02-16T01:55:10
Утилиты командной строки

nice и ionice. Приоритеты процессов

nice — позволяет указывать приоритет выполнения процессором различных задач, диапазон приоритетов -20 до 19, где 19 наименьший, если не указать, то будет стандартный приоритет 0. Удобен например при упаковке данных в архивы, чтобы эта задача не грузила сервер или когда нужно запустить много процессов, распределив нагрузку, которые занимают все процессорное время.




Пример выполнения команды с самым низким приоритетом:




nice -n 19 КОМАНДА




Посмотреть таблицу процессов и их приоритетов можно так (колонка NI):




ps axlps -l




Если таблица большая, можно перенаправить вывод команды в Less и смотреть постранично:




ps axl | less




Чтобы изменить приоритет:




renice -n 19 ПРОЦЕСС(PID)




Проверка значения приоритета по умолчанию (стандартно 0):




nice




ionice — позволяет указать приоритет при операциях ввода/вывода, например чтобы снизить нагрузку на диск. Первым указывается класс от 1 до 3, потом приоритет от 0 до 7, где 7 наименьший.
Классы есть трех видов:
1) Real time — Преимущественный без обращения внимания на другие процессы с указанием приоритетов от 0 до 7.
2) Best Effort — Стандартный с указанием приоритетов от 0 до 7.
3) Idle — При простое без указания приоритетов.




Пример выполнения команды с самым низким приоритетом ввода/вывода:




ionice -c2 -n7 КОМАНДА




Для изменения приоритета:




ionice -c2 -n7 -p ПРОЦЕСС(PID)




Для просмотра установленного приоритета:




ionice -p ПРОЦЕСС(PID)




Можно указать одновременно приоритеты через nice и ionice:




ionice -p ПРОЦЕСС(PID)




Для указания высоких приоритетов например могут понадобится root права, по этому команды нужно выполнять от имени root пользователя либо добавив перед командой sudo.




Источник: https://ixnfo.com/nice-ionice.html



2023-02-16T01:48:36
Утилиты командной строки

Визуальное руководство по туннелям SSH

Визуальное руководство по туннелям SSH: Локальная и удаленная переадресация портов.




SSH – это еще один пример древней технологии, которая широко используется и сегодня. Вполне возможно, что освоение пары трюков с SSH в долгосрочной перспективе более выгодно, чем освоение дюжины инструментов Cloud Native, которым суждено устареть в следующем квартале.




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




  • Доступ к внутренним конечным точкам VPC через публичный экземпляр EC2.



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



  • Открыть любой локальный сервер из домашней/частной сети внешнему миру.




И многое другое




Но несмотря на то, что я ежедневно использую SSH-туннели, мне всегда требуется время, чтобы найти нужную команду. Должен ли это быть локальный или удаленный туннель? Какие должны быть флаги? Должен ли это быть локальный_порт:удаленный_порт или наоборот? Итак, я решил наконец разобраться с этим, и в результате получилась серия лабораторных работ и наглядная шпаргалка.





Необходимые условия




Туннели SSH – это соединение хостов по сети, поэтому в каждой из приведенных ниже лабораторных работ, как ожидается, будет задействовано несколько “машин”. Однако мне лень создавать полноценные экземпляры, особенно когда вместо них можно использовать контейнеры. Поэтому в итоге я использовал только одну виртуальную машину vagrant с установленным на ней Docker.




Теоретически, подойдет любая Linux-машина с установленным на ней Docker Engine. Однако запустить приведенные ниже примеры как есть с помощью Docker Desktop не удастся, поскольку предполагается возможность доступа к контейнерам машин по их IP-адресам.




В качестве альтернативы, лабораторные работы можно выполнить с помощью Lima (QEMU + nerdctl + containerd + BuildKit), но не забудьте сначала выполнить limactl shell bash.




Каждый пример требует наличия на хосте действующей пары ключей без парольной фразы, которая затем монтируется в контейнеры для упрощения управления доступом. Если у вас нет такой пары, сгенерировать ее можно просто с помощью ssh-keygenна хосте.




Важно: демоны SSH в контейнерах здесь предназначены исключительно для образовательных целей — контейнеры в этом посте предназначены для представления полноценных «машин» с SSH-клиентами и серверами на них. Имейте в виду, что использование SSH в реальных контейнерах редко бывает хорошей идеей!




Переадресация локального порта




Начнем с того, что я использую чаще всего. Часто бывает, что есть служба, прослушивающая localhost или частный интерфейс машины, к которому я могу подключиться только по SSH через его публичный IP. И мне крайне необходимо получить доступ к этому порту извне. Несколько типичных примеров:




  • Доступ к базе данных (MySQL, Postgres, Redis и т.д.) с помощью причудливого пользовательского интерфейса с вашего ноутбука.



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



  • Доступ к порту контейнера с вашего ноутбука без публикации его на публичном интерфейсе сервера.




Все вышеперечисленные случаи использования могут быть решены с помощью одной команды  ssh:




ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr




Флаг  -L  указывает на то, что мы запускаем локальную проброску портов. На самом деле это означает следующее:




  • На вашей машине клиент SSH начнет слушать local_port (скорее всего, на localhost, но это зависит от ситуации – проверьте настройки GatewayPorts).



  • Любой трафик на этот порт будет перенаправлен на remote_private_addr:remote_port на машине, к которой вы подключились по SSH.




Вот как это выглядит на схеме:





Профессиональный совет: Используйте  ssh -f -N -L  для запуска сеанса переадресации портов в фоновом режиме.




Лабораторная работа 1: Использование туннелей SSH для локальной переадресации портов




Лабораторная работа воспроизводит настройку из приведенной выше схемы. Во-первых, нам нужно подготовить сервер – машину с демоном SSH и простым веб-сервисом, прослушивающим 127.0.0.1:80:




$ docker buildx build -t server:latest -<<'EOD'

# syntax=docker/dockerfile:1

FROM alpine:3



# Install the dependencies:

RUN apk add --no-cache openssh-server curl python3

RUN mkdir /root/.ssh && chmod 0700 /root/.ssh && ssh-keygen -A



# Prepare the entrypoint that starts the daemons:

COPY --chmod=755 <<'EOF' /entrypoint.sh

#!/bin/sh

set -euo pipefail



for file in /tmp/ssh/*.pub; do

  cat ${file} >> /root/.ssh/authorized_keys

done

chmod 600 /root/.ssh/authorized_keys



# Minimal config for the SSH server:

sed -i '/AllowTcpForwarding/d' /etc/ssh/sshd_config

sed -i '/PermitOpen/d' /etc/ssh/sshd_config

/usr/sbin/sshd -e -D &



python3 -m http.server --bind 127.0.0.1 ${PORT} &



sleep infinity

EOF



# Run it:

CMD ["/entrypoint.sh"]

EOD




Запускаем сервер и записываем его IP-адрес:




$ docker run -d --rm 

   -e PORT=80 

   -v $HOME/.ssh:/tmp/ssh 

   --name server 

   server:latest



SERVER_IP=$(

  docker inspect 

    -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 

  server

)




Поскольку веб-служба прослушивает localhost, она не будет доступна извне (т.е. из хост-системы в данном конкретном случае):




$ curl ${SERVER_IP}

curl: (7) Failed to connect to 172.17.0.2 port 80: Connection refused




Но изнутри “сервера” работает просто отлично:




$ ssh -o StrictHostKeyChecking=no root@${SERVER_IP}

7b3e49181769:$# curl localhost

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>

...




И вот в чем хитрость: привяжите localhost:80 сервера к  localhost:8080 хоста, используя локальную переадресацию портов:




$ ssh -o StrictHostKeyChecking=no -f -N -L 8080:localhost:80 root@${SERVER_IP}




Теперь вы должны иметь возможность получить доступ к веб-службе на локальном порту хост-системы:




$ curl localhost:8080

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>

...




Несколько более многословный (но более явный и гибкий) способ достижения той же цели – использование формыlocal_addr:local_port:remote_addr:remote_port form:




$ ssh -o StrictHostKeyChecking=no -f -N -L 

  localhost:8080:localhost:80 

  root@${SERVER_IP}




Локальная переадресация портов с хостом Bastion




Это может быть неочевидно на первый взгляд, но команда  ssh -L позволяет перенаправить локальный порт на удаленный порт на любой машине, а не только на самом SSH-сервере. Обратите внимание, что remote_addr  и  sshd_addr могут иметь одинаковое значение, а могут и не иметь:




ssh -L [local_addr:]local_port:remote_addr:remote_port [user@]sshd_addr




Не уверен, насколько правомерно здесь использование термина bastion host , но именно так я представляю себе этот сценарий:





Я часто использую этот трюк для вызова конечных точек, которые доступны с хоста bastion, но не с моего ноутбука (например, использование экземпляра EC2 с частным и публичным интерфейсами для подключения к кластеру OpenSearch, развернутому полностью в VPC).




Лаборатория 2: Локальная переадресация портов с хостом Bastion




И снова лабораторная работа воспроизводит установку из приведенной выше схемы. Сначала нам нужно подготовить хост бастиона – машину, на которой установлен только демон SSH:




$ docker buildx build -t bastion:latest -<<'EOD'

# syntax=docker/dockerfile:1

FROM alpine:3



# Install the dependencies:

RUN apk add --no-cache openssh-server

RUN mkdir /root/.ssh && chmod 0700 /root/.ssh && ssh-keygen -A



# Prepare the entrypoint that starts the SSH daemon:

COPY --chmod=755 <<'EOF' /entrypoint.sh

#!/bin/sh

set -euo pipefail



for file in /tmp/ssh/*.pub; do

  cat ${file} >> /root/.ssh/authorized_keys

done

chmod 600 /root/.ssh/authorized_keys



# Minimal config for the SSH server:

sed -i '/AllowTcpForwarding/d' /etc/ssh/sshd_config

sed -i '/PermitOpen/d' /etc/ssh/sshd_config

/usr/sbin/sshd -e -D &



sleep infinity

EOF



# Run it:

CMD ["/entrypoint.sh"]

EOD




Запускаем бастионный хост и записываем его IP:




$ docker run -d --rm 

    -v $HOME/.ssh:/tmp/ssh 

    --name bastion 

    bastion:latest



BASTION_IP=$(

  docker inspect 

    -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 

  bastion

)




Теперь запускаем целевую веб-службу на отдельной “машине”:




$ docker run -d --rm 

    --name server 

    python:3-alpine 

    python3 -m http.server 80



SERVER_IP=$(

  docker inspect 

    -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 

  server

)




Представим, что вызов  curl ${SERVER_IP}  непосредственно с хоста по какой-то причине невозможен (например, как если бы не было маршрута от хоста к этому IP-адресу). Значит, нам нужно запустить переадресацию портов:




$ ssh -o StrictHostKeyChecking=no -f -N -L 8080:${SERVER_IP}:80 root@${BASTION_IP}




Обратите внимание, что переменные SERVER_IP и BASTION_IP имеют разные значения в приведенной выше команде.




Проверяем, что все работает:




$ curl localhost:8080

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>

...




Удаленная переадресация портов




Другой популярный (но скорее обратный) сценарий – когда вы хотите на время открыть локальную службу для внешнего мира. Разумеется, для этого вам понадобится публичный сервер входящего шлюза. Но не бойтесь! В качестве такого шлюза можно использовать любой сервер с публичным доступом, на котором установлен демон SSH:




ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr




Приведенная выше команда выглядит не сложнее, чем ее аналог  ssh -L. Но есть один подводный камень…




По умолчанию вышеуказанный SSH-туннель позволяет использовать в качестве удаленного адреса только localhost шлюза. Другими словами, ваш локальный порт станет доступным только изнутри самого сервера шлюза, и, скорее всего, это не то, что вам действительно нужно. Например, я обычно хочу использовать публичный адрес шлюза в качестве удаленного адреса, чтобы открыть доступ к моим локальным службам в публичный интернет. Для этого SSH-сервер должен быть настроен с параметром GatewayPorts yes.




Вот для чего можно использовать удаленное перенаправление портов:




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



  • Хм… Я могу придумать несколько эзотерических примеров, но сомневаюсь, что стоит делиться ими здесь. Любопытно услышать, для чего другие люди могут использовать удаленное перенаправление портов!




Вот как удаленное перенаправление портов выглядит на схеме:





Профессиональный совет: Используйте ssh -f -N -R для запуска сеанса переадресации портов в фоновом режиме.




Лабораторная работа 3: Использование туннелей SSH для удаленной переадресации портов




Лабораторная работа воспроизводит установку, показанную на схеме выше. Сначала нам нужно подготовить “dev machine” – компьютер с SSH-клиентом и локальным веб-сервером:




$ docker buildx build -t devel:latest -<<'EOD'

# syntax=docker/dockerfile:1

FROM alpine:3



# Install dependencies:

RUN apk add --no-cache openssh-client curl python3

RUN mkdir /root/.ssh && chmod 0700 /root/.ssh



# Prepare the entrypoint that starts the web service:

COPY --chmod=755 <<'EOF' /entrypoint.sh

#!/bin/sh

set -euo pipefail



cp /tmp/ssh/* /root/.ssh

chmod 600 /root/.ssh/*



python3 -m http.server --bind 127.0.0.1 ${PORT} &



sleep infinity

EOF



# Run it:

CMD ["/entrypoint.sh"]

EOD




Запуск виртуальной машины:




$ docker run -d --rm 

    -e PORT=80 

    -v $HOME/.ssh:/tmp/ssh 

    --name devel 

    devel:latest




Подготовка сервера шлюза – простой SSH-сервер с GatewayPorts, установленным на yes  в  sshd_config:




$ docker buildx build -t gateway:latest -<<'EOD'

# syntax=docker/dockerfile:1

FROM alpine:3



# Install the dependencies:

RUN apk add --no-cache openssh-server

RUN mkdir /root/.ssh && chmod 0700 /root/.ssh && ssh-keygen -A



# Prepare the entrypoint that starts the SSH server:

COPY --chmod=755 <<'EOF' /entrypoint.sh

#!/bin/sh

set -euo pipefail



for file in /tmp/ssh/*.pub; do

  cat ${file} >> /root/.ssh/authorized_keys

done

chmod 600 /root/.ssh/authorized_keys



sed -i '/AllowTcpForwarding/d' /etc/ssh/sshd_config

sed -i '/PermitOpen/d' /etc/ssh/sshd_config

sed -i '/GatewayPorts/d' /etc/ssh/sshd_config

echo 'GatewayPorts yes' >> /etc/ssh/sshd_config



/usr/sbin/sshd -e -D &



sleep infinity

EOF



# Run it:

CMD ["/entrypoint.sh"]

EOD




Запуск сервера шлюза и запись его IP-адреса:




$ docker run -d --rm 

    -v $HOME/.ssh:/tmp/ssh 

    --name gateway 

    gateway:latest



GATEWAY_IP=$(

  docker inspect 

    -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 

  gateway

)




Теперь изнутри dev-машины запустите удаленное перенаправление портов:




$ docker exec -it -e GATEWAY_IP=${GATEWAY_IP} devel sh

/ $# ssh -o StrictHostKeyChecking=no -f -N -R 0.0.0.0:8080:localhost:80 root@${GATEWAY_IP}

/ $# exit  # or detach with ctrl-p, ctrl-q




И проверьте, что локальный порт машины dev стал открытым на публичном интерфейсе шлюза (с хост-системы):




$ curl ${GATEWAY_IP}:8080

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>

...




Удаленная переадресация портов из домашней/частной сети




Подобно локальной переадресации портов, удаленная переадресация портов имеет свой собственный режим бастионного хоста. Но на этот раз в роли бастиона выступает машина с SSH-клиентом (например, ваш ноутбук dev). В частности, он позволяет открывать порты из домашней (или частной) сети, к которой имеет доступ ваш ноутбук, во внешний мир через входящий шлюз:




ssh -R [remote_addr:]remote_port:local_addr:local_port [user@]gateway_addr




Выглядит почти так же, как и простой удаленный SSH-туннель, но пара  local_addr:local_port  становится адресом устройства в домашней сети. Вот как это можно изобразить на схеме:





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




Лаборатория 4: Удаленная переадресация портов из домашней/частной сети




Как обычно, лаборатория воспроизводит установку из приведенной выше схемы. Сначала нам нужно подготовить “машину dev”:




$ docker buildx build -t devel:latest -<<'EOD'

# syntax=docker/dockerfile:1

FROM alpine:3



# Install the dependencies:

RUN apk add --no-cache openssh-client

RUN mkdir /root/.ssh && chmod 0700 /root/.ssh



# This time we run nothing (at first):

COPY --chmod=755 <<'EOF' /entrypoint.sh

#!/bin/sh

set -euo pipefail



cp /tmp/ssh/* /root/.ssh

chmod 600 /root/.ssh/*



sleep infinity

EOF



# Run it:

CMD ["/entrypoint.sh"]

EOD




Запуск “dev machine”:




$ docker run -d --rm 

    -v $HOME/.ssh:/tmp/ssh 

    --name devel 

    devel:latest




Запуск частного dev-сервера с использованием отдельной “машины” и указанием ее IP-адреса:




$ docker run -d --rm 

    --name server 

    python:3-alpine 

    python3 -m http.server 80



SERVER_IP=$(

  docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 

  server

)




Подготовка сервера входящего шлюза:




$ docker buildx build -t gateway:latest -<<'EOD'

# syntax=docker/dockerfile:1

FROM alpine:3



# Install the dependencies:

RUN apk add --no-cache openssh-server

RUN mkdir /root/.ssh && chmod 0700 /root/.ssh && ssh-keygen -A



# Prepare the entrypoint that starts the SSH daemon:

COPY --chmod=755 <<'EOF' /entrypoint.sh

#!/bin/sh

set -euo pipefail



for file in /tmp/ssh/*.pub; do

  cat ${file} >> /root/.ssh/authorized_keys

done

chmod 600 /root/.ssh/authorized_keys



sed -i '/AllowTcpForwarding/d' /etc/ssh/sshd_config

sed -i '/PermitOpen/d' /etc/ssh/sshd_config

sed -i '/GatewayPorts/d' /etc/ssh/sshd_config

echo 'GatewayPorts yes' >> /etc/ssh/sshd_config



/usr/sbin/sshd -e -D &



sleep infinity

EOF



# Run it:

CMD ["/entrypoint.sh"]

EOD




И запустить его:




$ docker run -d --rm 

    -v $HOME/.ssh:/tmp/ssh 

    --name gateway 

    gateway:latest



GATEWAY_IP=$(

  docker inspect 

    -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 

  gateway

)




Теперь, находясь внутри ” dev machine”, запустите удаленный проброс портов SERVER-GATEWAY:




$ docker exec -it -e GATEWAY_IP=${GATEWAY_IP} -e SERVER_IP=${SERVER_IP} devel sh

/ $# ssh -o StrictHostKeyChecking=no -f -N -R 0.0.0.0:8080:${SERVER_IP}:80 root@${GATEWAY_IP}

/ $# exit  # or detach with ctrl-p, ctrl-q




Наконец, проверьте, что сервер dev стал доступен на публичном интерфейсе шлюза (из хост-системы):




$ curl ${GATEWAY_IP}:8080

<!DOCTYPE HTML>

<html lang="en">

<head>

...




Подведение итогов




После выполнения всех этих лабораторных работ и рисунков я заметил следующее:




  • Слово “local” может означать как машину клиента SSH, так и хост, доступный с этой машины.



  • Слово “remote” может означать как машину сервера SSH (sshd), так и доступный с нее хост.



  • Локальная проброска портов (ssh -L) подразумевает, что именно клиент  sshначинает прослушивать новый порт.



  • Удаленное перенаправление портов  (ssh -R)  подразумевает, что именно сервер  sshd начинает прослушивать дополнительный порт.




Источник: https://itmozg.ru/vizualnoe-rukovodstvo-po-tunneljam-ssh/



2023-01-17T19:03:58
Утилиты командной строки

Команда test

Предназначена для проверки типа файла и сравнения чисел и строк. Возвращает код возврата 0 (истина) или 1 (ложь) в зависимости от вычисления выражения. Выражения могут быть как унарными, так и бинарными.




test выражение




Для сокращения кода сценария используют парный оператор [ как синоним test. Парный оператор требует пробела между скобками потому, что [ (скобка) является командой оболочки.




Проверка типа файла




  • -d file — истина, если file существует и является каталогом



  • -e file — истина, если file существует



  • -f file — истина, если file существует и является обычным файлом



  • -r file — истина, если file существует и доступен для чтения



  • -s file — истина, если file существует и имеет размер больше, чем ноль



  • -w file — истина, если file существует и доступен для записи



  • -x file — истина, если file существует и доступен для выполнения



  • -L file — истина, если file существует и является символьной ссылкой



  • file1 -nt file2 — истина, если file1 новее (дата модификации), чем file2



  • file1 -ot file2 — истина, если file1 старее, чем file2




#!/bin/bash
if [ -f "$HOME/.bashrc" ]; then
    echo "Файл существует!"
else
    echo "Файл не существует!"
fi




Сравнение строк




  • -z string — истина, если длина string равна нулю



  • -n string — истина, если длина string не ноль



  • string1 = string2 — истина, если строки равны



  • string1 != string2 — истина, если строки не равны




Сравнение целых чисел




  • число1 -eq число2 — истина, если число1 равно число2



  • число1 -gt число2 — истина, если число1 больше число2



  • число1 -ge число2 — истина, если число1 больше или равно число2



  • число1 -lt число2 — истина, если число1 меньше число2



  • число1 -le число2 — истина, если число1 меньше или равно число2



  • число1 -ne число2 — истина, если число1 не равно число2




#!/bin/bash
if [ 3 -lt 6 ]; then
    echo "Истина"
else
    echo "Ложь"
fi




Операции AND и OR




  • expr1 -a expr2 — истина, если оба выражения expr1 и expr2 истина (операция AND)



  • expr1 -o expr2 — истина, если хотя бы одно из выражений expr1 или expr2 истина (операция OR)



  • ! expr — истина, если выражение expr ложно




В условном выражении команды test можно использовать круглые скобки, чтобы изменить порядок вычисления, но их нужно экранировать:




$ [ ( "$count" -ge 0 ) -a ( "$count" -lt 10 ) ]




«[[…]]» — расширенный вариант от «[…]», оболочка выполняет его как один элемент с кодом возврата. Внутри «[[…]]» разрешается выполнение операторов &&|| которые приводят к ошибке в обычных скобках «[…]».




#!/bin/bash
if [[ -f "$HOME/.bashrc" && -f "/usr/bin/nano" ]]; then
    echo "Все в порядке, можно редактировать!"
else
    echo "Ошибка!"
fi



2022-11-10T13:34:12
Утилиты командной строки