From 3b7242f3d6ffcc469741a5ba9f82285f83d4a1b2 Mon Sep 17 00:00:00 2001 From: Qandra Si Date: Tue, 12 Mar 2024 19:33:55 +0300 Subject: [PATCH 1/4] docs: Add advanced SSH article (SSH keys) (#503) --------- Co-authored-by: Oleg Kalachev --- .../ssh-keys-known_hosts-fingerprint.png | Bin 0 -> 34562 bytes docs/en/SUMMARY.md | 1 + docs/en/cli.md | 10 + docs/en/ssh.md | 4 +- docs/en/ssh_keys.md | 180 +++++++++++++++++ docs/ru/SUMMARY.md | 1 + docs/ru/cli.md | 10 + docs/ru/ssh.md | 4 +- docs/ru/ssh_keys.md | 184 ++++++++++++++++++ redirects.json | 1 + 10 files changed, 392 insertions(+), 3 deletions(-) create mode 100644 docs/assets/ssh-keys-known_hosts-fingerprint.png create mode 100644 docs/en/ssh_keys.md create mode 100644 docs/ru/ssh_keys.md diff --git a/docs/assets/ssh-keys-known_hosts-fingerprint.png b/docs/assets/ssh-keys-known_hosts-fingerprint.png new file mode 100644 index 0000000000000000000000000000000000000000..3485d40aa6db84a40898a55b0574eecec37942a0 GIT binary patch literal 34562 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 literal 0 HcmV?d00001 diff --git a/docs/en/SUMMARY.md b/docs/en/SUMMARY.md index d0fc7ce7e..ace075994 100644 --- a/docs/en/SUMMARY.md +++ b/docs/en/SUMMARY.md @@ -57,6 +57,7 @@ * [COEX Pix](coex_pix.md) * [COEX PDB](coex_pdb.md) * [COEX GPS](coex_gps.md) + * [Using SSH keys](ssh_keys.md) * [Guide on autonomous flight](auto_setup.md) * [Hostname](hostname.md) * [PX4 Simulation](sitl.md) diff --git a/docs/en/cli.md b/docs/en/cli.md index 3db1fc1e7..c2d44984d 100644 --- a/docs/en/cli.md +++ b/docs/en/cli.md @@ -30,6 +30,16 @@ Print path to the current directory: pwd ``` +Go to the user's home directory: + +```bash +# all three commands are equivalent, where the tilde character (~) is an abbreviated +# path entry to the home directory, and the $HOME variable stores this path +cd +cd ~ +cd $HOME +``` + Print contents of the `file.py` file: ```bash diff --git a/docs/en/ssh.md b/docs/en/ssh.md index c4104113c..96f64e129 100644 --- a/docs/en/ssh.md +++ b/docs/en/ssh.md @@ -13,9 +13,9 @@ ssh pi@192.168.11.1 Password: `raspberry`. -For SSH access from Windows, you may use [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html). +For SSH access from Windows, you may use [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html). You can also gain SSH access from your smartphone using the [Termius](https://www.termius.com) app. -You can also gain SSH access from your smart-phone using the [Termius](https://www.termius.com) app. +> **Hint** To avoid entering the password each time you connect via SSH, see [the article on using SSH keys](ssh_keys.md). Read more: https://www.raspberrypi.org/documentation/remote-access/ssh/README.md diff --git a/docs/en/ssh_keys.md b/docs/en/ssh_keys.md new file mode 100644 index 000000000..9d42c1e57 --- /dev/null +++ b/docs/en/ssh_keys.md @@ -0,0 +1,180 @@ +# Connecting to Raspberry Pi using SSH keys + +*This instruction will allow you to quickly connect to the Raspberry Pi. In just one second. Without entering a password.* + +Basic information on working with SSH can be found in the section [SSH access to Raspberry Pi](ssh.md). In this section you will find advanced information on using SSH, as well as a number of recommendations on using SSH when working with Clover. + +## General information + +SSH (*secure shell*) is a network protocol that allows you to remotely control the operating system on the computer you are connected to. It is similar to a protocol such as *telnet*, but allows you to encrypt network traffic during interaction. Thus, the transfer of passwords and other secret information is hidden. The Raspberry Pi operating system supports SSH communication, like many other common Linux-based systems. + +SSH allows you not only to organize work in the command shell, but also to transfer files, as well as tunnel transmitted data from other protocols, such as information from a video camera or telemetry. In addition, SSH supports several authentication modes (that is, verification of the connecting user), with its help it is possible to connect to the Clover not only using a password, but also password-free access (authentication by a key pair, i.e. SSH keys). + +## Password authentication + +Authentication [by password](ssh.md) on the image of RPi for Clover is enabled by default and the password can be used to enter into the command shell of the minicomputer. On computers with Linux operating systems (and primarily on servers connected to the Internet), the ability to login with a password is usually disabled, since there is a more secure authentication method. + +> **Hint** It is not recommended to disable logging into Clover by password, since you can completely lose access to the command shell over the network. + +When connecting to RPi for the first time, you will see the notification with a suggestion to save a unique *fingerprint*. The stored information is accumulated on computers from which SSH login to RPi is performed, and is checked for sudden substitution. + +On Linux and Unix (Mac OS) the first SSH-connection to the RPi looks like this: + +```bash +ssh pi@192.168.11.1 +# The authenticity of host '192.168.11.1 (192.168.11.1)' can't be established. +# ED25519 key fingerprint is SHA256:4w/7MqTgrtsqPwKnVAMISpouaOJNqzUew2NkJjldMWI. +# This key is not known by any other names +# Are you sure you want to continue connecting (yes/no/[fingerprint])? yes +# Warning: Permanently added '192.168.11.1' (ED25519) to the list of known hosts. +# pi@192.168.11.1's password: ********* +# Linux clover-3270 5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021 armv7l + +whoami +# pi + +exit +``` + +In graphical programs in Windows, you will periodically see window with similar warnings. + +Сохранение отпечатка в Windows + +> **Hint** Windows 10 has a built-in SSH client that can be run from the command line, see the Microsoft usage guide [at this link](https://learn.microsoft.com/ru-ru/windows-server/administration/openssh/openssh_install_firstuse). + +## Authentication using SSH keys + +SSH keys are a convenient, fast alternative way to connect to the Raspberry Pi, which does not require entering a password. In particular, when operating with Clover, this method is convenient because it saves time, and therefore battery power, and the time limit allocated for events in flight zones. In addition, using SSH keys opens up opportunities for convenient use of other programs that you would hardly use if you needed to type a password every time. + +The SSH key is divided into two parts: the pair consists of a so-called *private* and *public* key. The key is generated once. One part of the key (open) is transferred once to the remote computer to which the connection will be made, the second part of the key (private) is stored on the computer that will connect, the private part of the key is not transferred anywhere. + +> **Hint** The public key is copied once to the Raspberry Pi, and the private key is stored in the laptop as a file. + +### Preparation + +In order for a key pair to appear, it must be generated. In Linux and Unix (Mac OS), there is a program `ssh-keygen` with which we will get the key pair we need (**attention!** commands are executed not in Raspberry Pi, and not in the virtual machine of the Gazebo simulator, but in the command shell of the laptop from which you will connect to the Clover): + +Before using the keys, you need to perform a number of actions to configure access rights *on the laptop*: + +```bash +# one-time setting of access rights to user directories +chmod o-rwx $HOME +mkdir ~/.ssh +chmod g-rwx,o-rwx ~/.ssh +touch ~/.ssh/config ~/.ssh/known_hosts +chmod 600 ~/.ssh/config ~/.ssh/known_hosts +``` + +> **Hint** The `.ssh` directory in the user's home folder is the standard storage location for both key pairs and SSH connection settings, so we prohibit access to it by the Others group (*outsiders*). Modern Linux distributions check access rights to files in the `.ssh` directory and may refuse authentication by key pairs. + +### Generating an SSH key pair + +Generating a pair of SSH keys in the `~/.ssh` directory on the laptop: + +```bash +ssh-keygen -f ~/.ssh/id_clover -C "SSH key for Clover" -N "" +# Your identification has been saved in /home/galina/.ssh/id_clover +# Your public key has been saved in /home/galina/.ssh/id_clover.pub + +chmod 400 ~/.ssh/id_clover* +``` + +### Copying SSH key to Raspberry Pi + +After that [connect to Raspberry Pi via WiFi](wi fi.md) and continue to enter commands *on the laptop* to copy the key to the minicomputer: + +```bash +ssh-copy-id -i ~/.ssh/id_clover.pub pi@192.168.11.1 +# pi@192.168.11.1's password: ********* +``` + +As a result, the so-called *public* part of the key will be copied from the laptop to the RPi microcomputer, and the *private* part will remain on the laptop. To verify the connection without entering a password, use the command indicating the path where the SSH key is located: + +```bash +ssh -i ~/.ssh/id_clover pi@192.168.11.1 +``` + +If the terminal does not require you to enter a password to connect to the RPi, then you did everything correctly and the SSH key pair works. Now you can type the exit command from the SSH terminal to continue configuring the laptop: + +```bash +pi@clover-3270:~ $ exit +# logout +# Connection to 192.168.11.1 closed. + +galina@Thinkpad-X1:~/.ssh$ +``` + +## Configuring SSH connection to Clover + +Now let's set up the SSH terminal in such a way that you don't have to enter the path to the private key every time. This is done by editing the `~/.ssh/config` file *on a laptop*. Open the file in a text editor and add the following lines to the file (if there is already some information there, then put them at the end of the file): + +```txt +Host 192.168.11.1 + User pi + IdentityFile ~/.ssh/id_clover + PreferredAuthentications publickey,password + PubkeyAuthentication yes + PasswordAuthentication yes + ConnectTimeout 1 + TCPKeepAlive yes + ServerAliveInterval 2 + ServerAliveCountMax 3 + StrictHostKeyChecking no +``` + +This setting: + +* affects the operation of the SSH terminal when connected to a computer with the IP address `192.168.11.1`; +* if the user name is not specified, the name `pi` will be used automatically; +* the private key `~/.ssh/id_clover` will be used automatically; +* if the key does not fit for some reason (it was replaced on one laptop, but forgot to replace it on another), then the SSH terminal will switch to password authentication (settings `PreferredAuthentications`, `PubkeyAuthentication`, `PasswordAuthentication`); +* if communication with RPi cannot be established (WiFi is not yet connected), then the SSH connection will not hang, but will be completed quickly (setting `ConnectTimeout`); +* if the connection with RPi is suddenly severed, the SSH connection will not hang, but will be completed quickly (settings `TCPKeepAlive`, `ServerAliveInterval`, `ServerAliveCountMax`); +* the unique SSH *fingerprints* of the RPi microcomputers mentioned above will no longer be checked (the settings `StrictHostKeyChecking`). + +This will solve a lot of inconveniences associated with using SSH connections. + +> **Hint** If you have several Raspberry Pi-based drones in your laboratory, and several laptops, then you can **generate SSH keys once**, copy them to all drones and spread them across all laptops, then you can quickly access any of the drones from any laptop. + +Now, to connect to RPi from a Linux terminal, you just need to type `ssh 1[TAB][TAB][ENTER]` and the ip address `192.168.11.1` will be automatically updated on the command line, because the command shell uses addresses from the file `~/.ssh/config` and is able to "guess" your intentions to connect to the Clover. By pressing enter, you will instantly find yourself in the RPi terminal. + +> **Hint** Graphical programs for Windows that support working with SSH keys, which you can use: [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) and [MobaXterm](https://mobaxterm.mobatek.net/). + +## Copying files using SSH + +To copy a file `circle_flight.py` from the laptop to the RPi to the user's home folder `pi`, you can also use SSH. To do this, type the command in the command shell: + +```bash +# first we specify 'what' we copy, and then 'where' +scp circle_flight.py 192.168.11.1 +``` + +To copy `output.avi` file from the `examples` RPi' folder to the laptop, use a similar command: + +```bash +# after the ':' character (colon), you can specify the path on the remote computer +# the path specified as './' means the current folder where the file will be copied +scp 192.168.11.1:examples/output.avi ./ +``` + +## Remote command launch via SSH + +To run a command at laptop on the RPi (that is, remotely), you can also use SSH. + +Raspberry shutdown command: + +```bash +ssh 192.168.11.1 'sudo shutdown now' +``` + +Example of a Python script' startup command: + +```bash +ssh -t 192.168.11.1 'ROS_HOSTNAME=`hostname`.local && . /opt/ros/noetic/setup.bash && . /home/pi/catkin_ws/devel/setup.bash && python3 examples/get_telemetry.py' +``` + +In order to remotely start video recording, you can run the command: + +```bash +ssh -t 192.168.11.1 'ROS_HOSTNAME=`hostname`.local && . /opt/ros/noetic/setup.bash && . /home/pi/catkin_ws/devel/setup.bash && rosrun image_view video_recorder image:=/main_camera/image_raw' +``` diff --git a/docs/ru/SUMMARY.md b/docs/ru/SUMMARY.md index 580e31a2a..fd8568b81 100644 --- a/docs/ru/SUMMARY.md +++ b/docs/ru/SUMMARY.md @@ -58,6 +58,7 @@ * [COEX Pix](coex_pix.md) * [COEX PDB](coex_pdb.md) * [COEX GPS](coex_gps.md) + * [Использование SSH-ключей](ssh_keys.md) * [Радио-телеметрия](radio_telemetry.md) * [Камера Hawk Eye](hawk_eye.md) * [Гид по автономному полету](auto_setup.md) diff --git a/docs/ru/cli.md b/docs/ru/cli.md index 35ed33df4..781921ec2 100644 --- a/docs/ru/cli.md +++ b/docs/ru/cli.md @@ -30,6 +30,16 @@ cd .. pwd ``` +Перейти в домашнюю директорию пользователя: + +```bash +# все три команды равнозначны, где символ тильда (~) это сокращённая запись пути +# к домашней директории, а переменная $HOME хранит этот путь +cd +cd ~ +cd $HOME +``` + Вывести содержимое файла `file.py`: ```bash diff --git a/docs/ru/ssh.md b/docs/ru/ssh.md index 14e18d58b..5f47eefc7 100644 --- a/docs/ru/ssh.md +++ b/docs/ru/ssh.md @@ -10,10 +10,12 @@ ssh pi@192.168.11.1 ``` -Пароль: ``raspberry``. +Пароль: `raspberry`. Для доступа по SSH из Windows можно использовать [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) или веб-доступ (см. далее). Также можно получить доступ по SSH со смартфона с помощью приложения [Termius](https://www.termius.com). +> **Hint** Для того, чтобы не вводить пароль при каждом подключении по SSH, см. [статью об использовании SSH-ключей](ssh_keys.md). + Подробнее: https://www.raspberrypi.org/documentation/remote-access/ssh/README.md. ## Веб-доступ diff --git a/docs/ru/ssh_keys.md b/docs/ru/ssh_keys.md new file mode 100644 index 000000000..1baaa9b57 --- /dev/null +++ b/docs/ru/ssh_keys.md @@ -0,0 +1,184 @@ +# Подключение к Raspberry Pi с использованием SSH-ключей + +*Эта инструкция позволит вам быстро подключаться к Raspberry Pi. Всего за одну секунду. Без ввода пароля.* + +Базовые сведения по работе с SSH вы можете найти в разделе [Доступ по SSH к Raspberry Pi](ssh.md). А в этом разделе вы найдёте расширенную информацию по использованию SSH, а также ряд рекомендаций по использованию SSH при работе с Клевером. + +## Общая информация + +SSH (англ. *secure shell* — "безопасная оболочка") - сетевой протокол, позволяющий удалённо управлять операционной системой на компьютере, к которому вы подключились. Аналогичен такому протоколу, как *telnet*, но позволяет выполнять шифрование сетевого трафика по время взаимодействия. Таким образом передача паролей и другой секретной информации оказываются скрыты. Операционная система Raspberry Pi поддерживает взаимодействие по SSH, как и многие другие распространённые системы на базе Linux. + +SSH позволяет не только организовывать работу в командной оболочке, но и передавать файлы, а также туннелировать передаваемые данные других протоколов, например информацию с видеокамеры или телеметрию. Кроме того, SSH поддерживает несколько режимов аутентификации (то есть проверки подключающегося пользователя), с его помощью возможно подключение к Клеверу не только с использованием пароля, но и беспарольный доступ (аутентификация по ключевой паре, т.е. SSH-ключи). + +## Аутентификация по паролю + +Аутентификация [по паролю](ssh.md) на образе RPi для Клевера включена и пароль может быть использован для входа в командную оболочку мини-компьютера. На ЭВМ с операционными системами Linux (и в первую очередь на серверах, подключенных к интернету) возможность входа по паролю обычно отключают, поскольку есть более безопасный способ аутентификации. + +> **Hint** Вход в Клевер по паролю отключать не рекомендуется, поскольку можно совсем утратить доступ к командной оболочке по сети. + +При первом подключении к RPi пользователю показывается уведомление с предложением сохранить уникальный отпечаток *fingerprint*. Сохранённая информация накапливается на компьютерах с которых выполняется вход по SSH на RPi, и проверяется на внезапную подмену. + +В ОС Linux и Unix (Mac OS) в текстовом SSH-клиенте первое подключение к RPi выглядит таким образом: + +```bash +ssh pi@192.168.11.1 +# The authenticity of host '192.168.11.1 (192.168.11.1)' can't be established. +# ED25519 key fingerprint is SHA256:4w/7MqTgrtsqPwKnVAMISpouaOJNqzUew2NkJjldMWI. +# This key is not known by any other names +# Are you sure you want to continue connecting (yes/no/[fingerprint])? yes +# Warning: Permanently added '192.168.11.1' (ED25519) to the list of known hosts. +# pi@192.168.11.1's password: ********* +# Linux clover-3270 5.10.17-v7l+ #1414 SMP Fri Apr 30 13:20:47 BST 2021 armv7l + +whoami +# pi + +exit +``` + +В графических программах в Windows у вас будут периодически возникать окошки с похожими предупреждениями. + +Сохранение отпечатка в Windows + +> **Hint** В Windows 10 появился встроенный SSH-клиент, который можно запускать из командной строки, см. руководство по использованию от Microsoft [по этой ссылке](https://learn.microsoft.com/ru-ru/windows-server/administration/openssh/openssh_install_firstuse). + +## Аутентификация с использованием SSH-ключей + +SSH-ключи - это удобный, быстрый альтернативный способ подключения к Raspberry Pi, для которого не требуется ввод пароля. В частности, при эксплуатации Клевера такой способ удобен потому, что экономит время, а значит и заряд аккумулятора, и лимит времени отведённого на мероприятия в полётных зонах. Кроме того, использование SSH-ключей открывает возможности по удобному использованию других программ, которыми бы вы вряд-ли воспользовались бы при необходимости всякий раз набирать пароль. + +SSH-ключ делится на две части: пара состоит из т.н. *закрытого* и *открытого* ключа. Ключ однократно генерируется. Одна часть ключа (открытая) однократно передаётся на удалённый компьютер к которому будет выполняться подключение, вторая часть ключа (закрытая) хранится на компьютере, который будет подключаться, закрытая часть ключа никуда не передаётся. + +> **Hint** Открытый ключ однократно копируется на Raspberry Pi, а закрытый ключ сохраняется в ноутбуке в виде файла. + +### Подготовка + +Для того, чтобы пара ключей появилась, её необходимо сгенерировать. В ОС Linux и Unix (Mac OS) есть программа `ssh-keygen` с помощью которой мы и получим нужную нам пару ключей (**внимание!** команды выполняются не в Raspberry Pi, и не в виртуальной машине симулятора Gazebo, а в командной оболочке ноутбука с которого вы будете подключаться к Клеверу): + +Прежде чем пользоваться ключами, необходимо выполнить ряд действий для настройки прав доступа *на ноутбуке*: + +```bash +# однократная настойка прав доступа к пользовательским директориям +chmod o-rwx $HOME +mkdir ~/.ssh +chmod g-rwx,o-rwx ~/.ssh +touch ~/.ssh/config ~/.ssh/known_hosts +chmod 600 ~/.ssh/config ~/.ssh/known_hosts +``` + +> **Hint** Директория `.ssh` в домашней папке пользователя - это стандартное место хранения и ключевых пар, и настроек подключения с использованием SSH, поэтому доступ к ней запрещаем группе Others (*посторонние*). Современные дистрибутивы Linux проверяют права доступа к файлам в директории `.ssh` и могут отказать в аутентификации по ключевым парам. + +### Генерация пары SSH-ключей + +Генерируем пару SSH-ключей в директории `~/.ssh` на ноутбуке: + + + +```bash +ssh-keygen -f ~/.ssh/id_clover -C "SSH key for Clover" -N "" +# Your identification has been saved in /home/galina/.ssh/id_clover +# Your public key has been saved in /home/galina/.ssh/id_clover.pub + +chmod 400 ~/.ssh/id_clover* +``` + +### Копирование SSH-ключа на Raspberry Pi + +После чего [подключаемся к Raspberry Pi по Wi-Fi](wifi.md) и продолжаем вводить команды *на ноутбуке* для копирования ключа на мини-компьютер: + +```bash +ssh-copy-id -i ~/.ssh/id_clover.pub pi@192.168.11.1 +# pi@192.168.11.1's password: ********* +``` + +В результате с ноутбука на микрокомпьютер RPi будет скопирована т.н. *открытая* часть ключа, а *закрытая* останется на ноутбуке. Для проверки подключения без ввода пароля используем команду с указанием пути где находится SSH-ключ: + +```bash +ssh -i ~/.ssh/id_clover pi@192.168.11.1 +``` + +Если терминал не потребует ввода пароля для подключения к RPi, то вы всё сделали правильно и пара SSH-ключей работает. Теперь можно набрать команду выхода из SSH-терминала, чтобы продолжить настройку ноутбука: + +```bash +pi@clover-3270:~ $ exit +# logout +# Connection to 192.168.11.1 closed. + +galina@Thinkpad-X1:~/.ssh$ +``` + +## Настройка SSH-подключения к Клеверу + +Теперь давайте настроим SSH-терминал таким образом, чтобы не приходилось всякий раз вписывать путь к закрытому ключу. Это делается с помощью редактирования файла `~/.ssh/config` *на ноутбуке*. Откройте файл в текстовом редакторе и добавьте в файл следующие строки (если там уже есть какая-то информация, то поместите их в конец файла): + +```txt +Host 192.168.11.1 + User pi + IdentityFile ~/.ssh/id_clover + PreferredAuthentications publickey,password + PubkeyAuthentication yes + PasswordAuthentication yes + ConnectTimeout 1 + TCPKeepAlive yes + ServerAliveInterval 2 + ServerAliveCountMax 3 + StrictHostKeyChecking no +``` + +Эта настройка: + +* влияет на работу SSH-терминала при подключении к компьютеру с ip-адресом `192.168.11.1`; +* если имя пользователя не указано, то автоматически будет использоваться имя `pi`; +* будет автоматически использоваться приватный ключ `~/.ssh/id_clover`; +* если ключ по каким-то причинам не подойдёт (был заменён на одном ноутбуке, но забыт заменить на другом), то SSH-терминал перейдёт к аутентификации по паролю (настройки `PreferredAuthentications`, `PubkeyAuthentication`, `PasswordAuthentication`); +* если связь с RPi не может установиться (WiFi ещё не включился), то SSH-подключение не зависнет, а быстро завершится (настройка `ConnectTimeout`); +* если связь с RPi будет внезапно разорвана, то SSH-подключение не зависнет, а быстро завершится (настройки `TCPKeepAlive`, `ServerAliveInterval`, `ServerAliveCountMax`); +* уникальные SSH-отпечатки RPi-микрокомпьютеров (*fingerprints*) о которых упоминалось выше, проверяться больше не будут (настройка `StrictHostKeyChecking`). + +Таким образом будет решено множество неудобств, связанных с использованием SSH-подключений. + +> **Hint** Если у вас в лаборатории несколько дронов на базе Raspberry Pi, и несколько ноутбуков, то можно **однократно** сгенерировать SSH-ключи, скопировать их на все дроны и разложить по всем ноутбукам, тогда с любого ноутбука можно будет быстро зайти на любой из дронов. + +Теперь, чтобы подключиться к RPi из терминала Linux вам достаточно набрать `ssh 1[TAB][TAB][ENTER]` и ip-адрес `192.168.11.1` автоматически дополнится в командной строке, т.к. командная оболочка использует адреса из файла `~/.ssh/config` и способна "угадать" ваши намерения для подключения к Клеверу. Нажав ввод вы мгновенно окажетесь в терминале RPi. + +> **Hint** Графические программы для Windows, которые поддерживают работу с SSH-ключами, которыми вы можете воспользоваться: [PuTTY](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html) и [MobaXterm](https://mobaxterm.mobatek.net/). + +## Копирование файлов при помощи SSH + +Чтобы скопировать файл `circle_flight.py` с ноутбука на RPi в домашнюю папку пользователя `pi` можно также воспользоваться SSH. Для этого наберите в командной оболочке команду: + +```bash +# сначала указываем 'что' копируем, а потом 'куда' +scp circle_flight.py 192.168.11.1 +``` + +Для того, чтобы скопировать файл `output.avi` c RPi из папки `examples` на ноутбук используем похожую команду: + +```bash +# после символа ':' (двоеточие) можно указать путь на удалённом компьютере +# путь указанный как './' означает текущую папку, куда будет скопирован файл +scp 192.168.11.1:examples/output.avi ./ +``` + +## Удалённый запуск команд по SSH + +Чтобы запустить команду с ноутбука на RPi (то есть удалённо) можно также воспользоваться SSH. + +Команда выключения Raspberry: + +```bash +ssh 192.168.11.1 'sudo shutdown now' +``` + +Пример команды запуска Python-скрипта: + + + +```bash +ssh -t 192.168.11.1 'ROS_HOSTNAME=`hostname`.local && . /opt/ros/noetic/setup.bash && . /home/pi/catkin_ws/devel/setup.bash && python3 examples/get_telemetry.py' +``` + +Для того, чтобы удалённо запустить запись видео можно выполнить команду: + +```bash +ssh -t 192.168.11.1 'ROS_HOSTNAME=`hostname`.local && . /opt/ros/noetic/setup.bash && . /home/pi/catkin_ws/devel/setup.bash && rosrun image_view video_recorder image:=/main_camera/image_raw' +``` diff --git a/redirects.json b/redirects.json index a851c75e7..2fa8d8347 100644 --- a/redirects.json +++ b/redirects.json @@ -21,6 +21,7 @@ { "from": "connection.html", "to": "en/connection.html" }, { "from": "wifi.html", "to": "ru/wifi.html" }, { "from": "ssh.html", "to": "ru/ssh.html" }, + { "from": "ssh_keys.html", "to": "ru/ssh_keys.html" }, { "from": "network.html", "to": "ru/network.html" }, { "from": "gcs_bridge.html", "to": "ru/gcs_bridge.html" }, { "from": "rc.html", "to": "ru/rc.html" }, From b8344dbb842a4ebd91b3b124063654c118d5c751 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Sat, 13 Apr 2024 16:57:02 +0300 Subject: [PATCH 2/4] Add dictionary parameter to aruco.launch --- clover/launch/aruco.launch | 1 + 1 file changed, 1 insertion(+) diff --git a/clover/launch/aruco.launch b/clover/launch/aruco.launch index 0a540645d..d0bd86d9c 100644 --- a/clover/launch/aruco.launch +++ b/clover/launch/aruco.launch @@ -16,6 +16,7 @@ + From c55e0cb7e17474e486dcff6f1decd4a3ec2995a7 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Sat, 13 Apr 2024 19:06:44 +0300 Subject: [PATCH 3/4] Fix geographiclib dependency --- builder/assets/noetic-rosdep-clover.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/builder/assets/noetic-rosdep-clover.yaml b/builder/assets/noetic-rosdep-clover.yaml index 93aa3508b..d76c037b0 100644 --- a/builder/assets/noetic-rosdep-clover.yaml +++ b/builder/assets/noetic-rosdep-clover.yaml @@ -736,3 +736,6 @@ realsense2_camera: realsense2_description: debian: buster: [ros-noetic-realsense2-description] +geographiclib: + debian: + buster: [libgeographic-dev] From 936efa985dffb06be5ea8b12e950590d86660300 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Sat, 13 Apr 2024 21:32:55 +0300 Subject: [PATCH 4/4] Make clover rosdep file more priority to fix build --- builder/image-ros.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/image-ros.sh b/builder/image-ros.sh index 30c7df7ff..02dfdecc6 100755 --- a/builder/image-ros.sh +++ b/builder/image-ros.sh @@ -72,7 +72,7 @@ my_travis_retry() { echo_stamp "Init rosdep" my_travis_retry rosdep init # FIXME: Re-add this after missing packages are built -echo "yaml file:///etc/ros/rosdep/${ROS_DISTRO}-rosdep-clover.yaml" >> /etc/ros/rosdep/sources.list.d/20-default.list +echo "yaml file:///etc/ros/rosdep/${ROS_DISTRO}-rosdep-clover.yaml" >> /etc/ros/rosdep/sources.list.d/10-clover.list my_travis_retry rosdep update echo_stamp "Populate rosdep for ROS user"