Файлы, пакеты, SSH
Зачем это нужно
На чемпионате тебе выдадут чистую машину с Ubuntu — и почти сразу окажется, что «просто написать код» мало. Скрипт, который ты скачал или написал сам, откажется запускаться, пока ты не дашь ему право на выполнение. Нужной программы на машине не будет — её придётся установить, а для этого нужны права администратора, которых у обычного пользователя по умолчанию нет. Файл на сервере придётся поправить прямо в терминале, без графического редактора. А иногда и сама машина, с которой нужно работать, будет вообще не перед тобой: сервер стоит в другой комнате или в другом городе, и подключаться к нему нужно по сети.
Эта глава закрывает все эти ситуации по очереди: что такое права доступа (permission) и как их читать и менять командой chmod, что такое sudo и когда без него не обойтись, чем apt update отличается от apt upgrade и apt install, как поправить файл прямо в терминале редактором nano, и как командой ssh оказаться внутри чужого компьютера, не вставая со стула — сначала по паролю, а потом и вовсе без него, по ключу. В конце — scp, которая копирует файлы между машинами тем же защищённым каналом. Ничего не считаем очевидным: если символ есть в команде, у него есть причина там быть, и мы её найдём.
- Зачем это нужно
- Права доступа: три буквы rwx
- chmod: меняем права
- sudo: временный суперпользователь
- apt: пакетный менеджер Ubuntu
- nano: редактор в терминале
- SSH: подключение к чужому компьютеру
- scp: скопировать файл на другую машину
- Практикум: от прав до подключения
- Типичные ошибки
- Слова главы
- Потренируйся печатать
- Команды и флаги главы
- Куда дальше: проверенные ресурсы
- Челлендж ⭐
- Что должен уметь
Права доступа: три буквы rwx
У каждого файла и каталога в Linux есть права доступа (permission) — отметка, кому и что с ним можно делать. Прав ровно три вида: читать (r, read), писать (w, write) и выполнять (x, execute). Для файла «выполнять» значит «запускать как программу»; для каталога — значит «заходить внутрь» (об этом коротко упоминалось в прошлой главе про ls -l, здесь разберём подробно).
Прав не одна тройка, а сразу три — они назначаются отдельно трём разным «кому»: владельцу файла (owner, тот, кто его создал), его группе (group, обычно и есть сам владелец плюс, возможно, коллеги) и всем остальным (other, все прочие пользователи системы). Ровно это и показывает ls -l. Создадим настоящий скрипт и посмотрим на него:
cat > hello.sh <<EOF
#!/bin/bash
echo Hello, chempionat!
EOF
ls -l hello.sh
-rw-r--r-- 1 student student 36 Aug 31 19:06 hello.sh
Строка -rw-r--r-- — это ровно десять символов, и в них зашифрован весь ответ на вопрос «кто и что может». Разберём каждый:
Обрати внимание: нигде нет буквы x. Значит, файл нельзя запустить как программу — только прочитать или изменить. Проверим:
./hello.sh
bash: ./hello.sh: Permission denied
Перевод: «в доступе отказано». Linux не считает файл программой просто потому, что в нём лежит код на bash с правильным первым символом (#!) — он программа только тогда, когда у неё явно стоит бит x. Это осознанная защита: если бы любой скачанный текстовый файл можно было запустить одним движением, вредоносный скрипт под видом текстового документа выполнялся бы сам собой.
Разница между r и x у каталога — отдельная тонкость, которую стоит запомнить сразу: r на каталоге разрешает посмотреть список имён внутри (ls), а x — зайти внутрь и работать с содержимым конкретных файлов (cd, открыть файл по полному пути). Можно иметь r без x — тогда видно, что внутри лежит, но реально прочитать эти файлы по одному не получится; а можно иметь x без r — тогда список файлов ls не покажет, но если знаешь точное имя файла внутри, до него можно достучаться. На практике для своих каталогов почти всегда ставят либо оба бита разом, либо ни одного.
Как это было
ls, cd, mkdir и сама идея «всё есть файл». Чтобы переписать UNIX с ассемблера на что-то переносимое, Ритчи создал язык C — и обе эти вещи, UNIX и C, до сих пор фундамент почти всего, чем ты пользуешься.chmod: меняем права
chmod (change mode) — единственная команда, которая меняет права доступа. У неё есть два независимых способа задать новые права: буквенный (символьный) и числовой. Оба означают одно и то же — просто записаны по-разному, и чемпионатные задания используют оба вперемешку, так что нужны оба.
Буквенная запись: кому, что, как
Проверим на живом файле — запустим ту же команду, что уже видели во введении к главе, но теперь построчно, с проверкой после каждого шага:
chmod u+x hello.sh
ls -l hello.sh
-rwxr--r-- 1 student student 36 Aug 31 19:06 hello.sh
Смотри внимательно: было rw-r--r--, стало rwxr--r-- — x появился ровно в одной тройке, у владельца, потому что мы написали букву u. А вот если перед +/-/= не указать вообще никакой буквы u/g/o/a, chmod применит изменение сразу ко всем трём тройкам, как если бы ты написал a+x. Буква u в нашей команде как раз и ограничила добавление только владельцем — без неё, командой просто chmod +x hello.sh, x появился бы у всех троих. Проверим это прямо здесь на том же файле:
chmod 644 hello.sh
chmod +x hello.sh
ls -l hello.sh
-rwxr-xr-x 1 student student 36 Aug 31 19:06 hello.sh
Видишь разницу с предыдущим примером? С u+x группа и остальные права x не получили (rwxr--r--), а с голым +x — получили все трое (rwxr-xr-x). Разница между «с буквой-целью» и «без неё» — та самая деталь, которую легко упустить, читая чужую команду по диагонали.
Буквы можно комбинировать через запятую в одной команде — это задаёт сразу несколько троек за один вызов:
chmod 644 hello.sh
chmod u=rwx,g=rx,o=rx hello.sh
ls -l hello.sh
-rwxr-xr-x 1 student student 36 Aug 31 19:06 hello.sh
Здесь использован = вместо +: он не добавляет права к тому, что уже было, а задаёт их заново, целиком — «у владельца теперь ровно rwx, у группы ровно r-x, у остальных ровно r-x», независимо от того, что стояло раньше. А отнять право у всех сразу можно буквой a:
chmod a-x hello.sh
ls -l hello.sh
-rw-r--r-- 1 student student 36 Aug 31 19:06 hello.sh
Типичная ошибка — опечатка в имени файла или файл ещё не создан:
chmod: cannot access 'nope.sh': No such file or directory
Числовая запись и таблица 755/644
У числовой записи та же логика, просто без букв. Каждому из трёх прав присвоено число: r = 4, w = 2, x = 1. Права одной тройки складываются в одну цифру от 0 до 7 — а поскольку сумма любого набора из 1 без повторов всегда получается уникальной, по одной цифре однозначно восстанавливается, какие именно буквы в неё входили:
| Цифра | Из чего сложена | Буквы | Значение |
|---|---|---|---|
| 0 | — | --- | ничего нельзя |
| 1 | 1 | --x | только выполнение |
| 2 | 2 | -w- | только запись |
| 3 | 2+1 | -wx | запись и выполнение |
| 4 | 4 | r-- | только чтение |
| 5 | 4+1 | r-x | чтение и выполнение |
| 6 | 4+2 | rw- | чтение и запись |
| 7 | 4+2+1 | rwx | всё сразу |
Полная команда — три такие цифры подряд, по одной на каждую тройку: владелец, группа, остальные. Разберём ровно ту команду, которая чаще всего звучит на чемпионате, — сделать свежескачанный или свежесозданный скрипт исполняемым и одновременно ограничить права для чужих:
Две связки чисел встречаются почти в каждом задании — 755 для программ и скриптов, 644 для обычных файлов вроде конфигов и текста. Вот их полная расшифровка бок о бок:
| Позиция | Кому | Цифра в 755 | Права | Цифра в 644 | Права |
|---|---|---|---|---|---|
| 1-я | владелец (owner) | 7 | rwx | 6 | rw- |
| 2-я | группа (group) | 5 | r-x | 4 | r-- |
| 3-я | остальные (other) | 5 | r-x | 4 | r-- |
755 = rwxr-xr-x — владелец может всё, включая запуск; группа и все остальные могут только читать и запускать, но не менять. Это стандартные права для исполняемого скрипта или программы. 644 = rw-r--r-- — владелец читает и пишет, все остальные только читают; это стандартные права для обычного файла без исполняемого кода — текста, конфига, разметки. Проверим оба на нашем файле:
chmod 644 hello.sh
ls -l hello.sh
chmod 755 hello.sh
ls -l hello.sh
-rw-r--r-- 1 student student 36 Aug 31 19:06 hello.sh
-rwxr-xr-x 1 student student 36 Aug 31 19:06 hello.sh
Ровно та же строка прав, что мы уже видели после u=rwx,g=rx,o=rx — буквенная и числовая запись всегда приводят к одному и тому же результату, просто это два разных языка для одной идеи.
rw-r--r--Углубиться
Почему по умолчанию не 777. Когда ты создаёшь новый файл, у него уже есть какие-то права — их назначает не сама программа, а значение umask, которое вычитается из «максимума» 666 для файлов (rw без x — новые файлы никогда не создаются сразу исполняемыми, из соображений безопасности) и 777 для каталогов. Типичный umask — 022, поэтому свежесозданный файл почти всегда получается именно 644, а каталог — 755: и то, и другое мы видели выше как «стандартные» права не просто так.
chmod -R. У chmod, как у cp и rm, есть флаг -R (recursive, заглавная буква, не строчная, как у cp/rm) — применить изменение сразу ко всему каталогу вместе со всем содержимым: chmod -R 755 project/.
Дальше по теме:
- man chmod — официальная man-страница: полное описание символьного и числового режимов, включая биты
sиt, которых в этой главе не было - Академия Selectel — команда chmod в Linux — тот же материал другими словами, с дополнительными примерами вроде
chmod 700
sudo: временный суперпользователь
Установка программ, правка системных файлов, перезапуск служб — всё это меняет систему целиком, а не только файлы конкретного пользователя. Такие действия разрешены не всем: их может делать только суперпользователь (superuser) — учётная запись root, у которой прав ровно 777 на всё в системе без исключений. Работать под root постоянно опасно: одна опечатка в команде удаления способна снести систему целиком, без единого лишнего вопроса.
sudo (substitute user do — «выполнить от имени другого пользователя») — компромисс: обычный пользователь на секунду становится root только для одной конкретной команды, подтвердив это своим же паролем. Дальше всё возвращается как было. Разберём на живом примере — что будет, если попросить sudo пользователя, которому админ прав не выдавал:
sudo whoami
[sudo] password for student: student is not in the sudoers file.
Перевод: «student отсутствует в файле sudoers». /etc/sudoers — список тех, кому вообще разрешено пользоваться sudo; не любой пользователь системы туда попадает автоматически. Добавим пользователя в группу sudo (это отдельная операция самого администратора машины, через usermod -aG sudo student) и повторим:
sudo whoami
[sudo] password for student: root
Пароль спрашивается собственный, пользователя student, а не пароль root — sudo проверяет, что ты действительно тот, за кого себя выдаёшь, а уже потом на секунду одалживает тебе права root. При вводе пароль не отображается на экране вообще, ни звёздочками, ни точками — это нормально, так задумано, чтобы длину пароля не подглядели через плечо. Команда whoami («кто я») после успешного sudo ответила root — доказательство, что права действительно временно повышены.
Если пароль введён неверно:
[sudo] password for student: Sorry, try again.
Перевод: «извините, попробуйте снова». После нескольких неверных попыток подряд sudo временно блокирует дальнейшие попытки — это защита от подбора пароля перебором.
Практическое правило: sudo ставят перед командой ровно тогда, когда она меняет что-то общесистемное — устанавливает программу, правит файл в /etc, перезапускает службу. Открыть свой собственный файл в nano или посмотреть свой каталог sudo не нужен вовсе.
apt: пакетный менеджер Ubuntu
В Ubuntu программы не скачивают со случайных сайтов по одной. Есть пакетный менеджер (package manager) — программа, которая сама находит нужный софт, скачивает его вместе со всем, что ему требуется для работы, и ставит одной командой. В Ubuntu он называется apt. Единица установки — пакет (package): архив с программой и служебной информацией о ней. Хранятся пакеты в репозитории (repository) — заранее проверенном каталоге софта в интернете, адрес которого уже прописан в системе.
У apt три разных команды, которые новички путают между собой чаще всего, — и путать их дорого: update, upgrade, install. Разберём по одной, на реальных выводах.
apt update — обновить список, не софт
sudo apt update
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Hit:2 http://archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:3 http://archive.ubuntu.com/ubuntu noble-backports InRelease
Hit:4 http://archive.ubuntu.com/ubuntu noble-security InRelease
Reading package lists...
update не ставит и не обновляет ни одной программы — самая частая путаница новичков ровно здесь. Он идёт в репозиторий и обновляет только локальный список того, что там вообще есть и в каких версиях — как будто сверяет оглавление магазина перед покупкой, ничего не покупая. Строки Hit:N адрес InRelease значат «список для этого репозитория уже свежий, качать не нужно»; если список устарел, вместо Hit появится Get с реальной загрузкой. Именно поэтому apt update всегда идёт первым шагом — иначе install будет смотреть на устаревший список и может не найти свежую версию пакета или новый пакет вовсе.
Без sudo эта команда вообще не сработает — попробуем:
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
Перевод: «невозможно открыть файл блокировки: в доступе отказано (13)» и «невозможно заблокировать каталог». Список пакетов — общесистемный файл, писать в него может только root; apt использует lock-файл, чтобы два запуска apt не сталкивались одновременно, и обычный пользователь до этого файла попросту не дотягивается.
apt upgrade — обновить уже установленное
upgrade смотрит на список, который только что освежил update, сравнивает его с тем, что реально стоит на машине, и предлагает обновить всё устаревшее до новых версий. Сначала можно посмотреть список кандидатов, ничего не меняя:
apt list --upgradable
Listing...
bsdutils/noble-updates,noble-security 1:2.39.3-9ubuntu6.6 arm64 [upgradable from: 1:2.39.3-9ubuntu6.5]
diffutils/noble-updates,noble-security 1:3.10-1ubuntu0.1 arm64 [upgradable from: 1:3.10-1build1]
dpkg/noble-updates,noble-security 1.22.6ubuntu6.6 arm64 [upgradable from: 1.22.6ubuntu6.5]
А сама команда sudo apt upgrade покажет итог одной строкой и список пакетов, которые собирается тронуть:
The following packages will be upgraded:
diffutils dpkg gzip libc-bin libc6 sed tar zlib1g
21 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
update без upgrade — список свежий, а сами программы старые. upgrade без свежего update — команда сравнивает с устаревшим списком и может ничего не найти, хотя обновления давно вышли. На практике их почти всегда пишут парой: sudo apt update && sudo apt upgrade.
apt install — поставить новое
Установим маленький и полезный пакет tree, который рисует дерево каталогов, — и увидим сразу важную тонкость поведения apt, которую легко упустить:
sudo apt install tree
The following NEW packages will be installed:
tree
0 upgraded, 1 newly installed, 0 to remove and 21 not upgraded.
Need to get 46.2 kB of archives.
After this operation, 160 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble-updates/universe tree 2.1.1-2ubuntu3.24.04.2 [46.2 kB]
Fetched 46.2 kB in 0s (121 kB/s)
Selecting previously unselected package tree.
Preparing to unpack .../tree_2.1.1-2ubuntu3.24.04.2_amd64.deb ...
Unpacking tree (2.1.1-2ubuntu3.24.04.2) ...
Setting up tree (2.1.1-2ubuntu3.24.04.2) ...
Здесь apt не спросил подтверждения — сразу перешёл к скачиванию и установке, хотя ты ничего не отвечал. А вот при удалении того же пакета команда останавливается и ждёт ответа:
sudo apt remove tree
The following packages will be REMOVED:
tree
0 upgraded, 0 newly installed, 1 to remove and 21 not upgraded.
After this operation, 160 kB disk space will be freed.
Do you want to continue? [Y/n]
Вывод: apt не всегда переспрашивает — для простой установки новых пакетов без удаления чего-либо он, как правило, действует сразу; а вот когда операция что-то убирает с диска, он останавливается и явно спрашивает [Y/n], ожидая Enter (по умолчанию Y, заглавная буква — вариант по умолчанию) или n для отмены. Правило простое: раз команда спрашивает подтверждения — значит, она собирается что-то удалить, стоит на секунду прочитать список выше, прежде чем нажимать Enter.
Проверить, что установка удалась, можно флагом --version, который есть почти у любой программы:
tree --version
tree v2.1.1 (c) 1996 - 2023 by Steve Baker, Thomas Moore, Francesc Rocher, Florian Sesser, Kyosuke Tokoro
Повторная установка уже стоящего пакета не ломается, а просто сообщает об этом:
tree is already the newest version (2.1.1-2ubuntu3.24.04.2).
0 upgraded, 0 newly installed, 0 to remove and 21 not upgraded.
А если ошибиться в названии пакета:
sudo apt install nonexistent-pkg-xyz123
E: Unable to locate package nonexistent-pkg-xyz123
Перевод: «не удалось найти пакет». Либо опечатка в имени, либо пакета с таким названием правда не существует в подключённых репозиториях.
Углубиться
apt — не единственный инструмент. Под капотом apt работает поверх более низкоуровневой утилиты dpkg, которая устанавливает и удаляет отдельные .deb-файлы, но сама не умеет искать пакеты в интернете и разрешать зависимости — этим и занимается apt поверх неё. Раньше вместо apt использовали apt-get/apt-cache — они существуют до сих пор и делают то же самое чуть более многословным синтаксисом; apt появился позже как удобная объединённая обёртка для человека, а не для скриптов (это явно написано в предупреждении apt does not have a stable CLI interface, которое иногда мелькает в выводе).
Куда пишется история установок. Всё, что apt/dpkg делали с системой, записывается в журнал /var/log/dpkg.log — можно посмотреть, что и когда ставилось, даже спустя месяцы.
Дальше по теме:
- Ubuntu Server — Package management — официальная документация: update, upgrade, install, remove и альтернативные инструменты вроде aptitude
nano: редактор в терминале
Полноценную IDE nano не заменит, но поправить одну строку в конфиге на сервере, где нет вообще никакой графики, — ровно его работа. Открывается командой nano имя_файла; если файла с таким именем не было, nano создаст его при первом сохранении.
Внизу экрана nano всегда держит подсказку по горячим клавишам — вот как она выглядит в открытом файле на самом деле:
^G Help ^O Write Out ^W Where Is ^K Cut ^T Execute ^C Location M-U Undo
^X Exit ^R Read File ^\ Replace ^U Paste ^J Justify ^/ Go To Line M-E Redo
Значок ^ здесь значит Ctrl, а M- — Alt (Meta). Из всей этой панели новичку критично запомнить ровно две клавиши — сохранение и выход, — но обе неочевидны, поэтому разберём с реальным экраном.
| Клавиши | Действие | Что произойдёт |
|---|---|---|
Ctrl+O | Write Out — записать | сохранить файл на диск, не закрывая nano; спросит имя файла (можно просто нажать Enter, если менять не нужно) |
Ctrl+X | Exit — выйти | закрыть nano; если были несохранённые изменения — сначала спросит, сохранить их или нет |
В nano начиная с версии 4.0 (а значит, и в Ubuntu 22.04, и в 24.04) работает ещё и привычный Ctrl+S — он сохраняет молча, вообще ничего не переспрашивая. В нижней панели его нет, и на старых сборках он может не сработать, поэтому основной клавишей запоминаем всё-таки Ctrl+O.
Наберём текст и сохраним через Ctrl+O:
File Name to Write: notes.txt
nano переспрашивает имя файла для сохранения — по умолчанию то же, что было открыто; менять не нужно, просто нажми Enter. После этого внизу мелькнёт подтверждение:
[ Wrote 1 line ]
Если после этого сразу нажать Ctrl+X, не меняя больше ничего, nano закроется молча — сохранять уже нечего. А если после сохранения дописать ещё текст и снова нажать Ctrl+X, не сохранившись через Ctrl+O, экран покажет предупреждение:
Save modified buffer?
Y Yes
N No ^C Cancel
Три варианта: Y — сохранить и выйти, N — выйти, отбросив несохранённые изменения, Ctrl+C — вообще передумать и вернуться в редактор.
Здесь легко потерять текст по невнимательности, нажав N вместо Y на автомате, — так что стоит на секунду прочитать вопрос, а не бить N рефлекторно.
Обе связки — «сохранить и выйти» и «выйти, отбросив правки» — проще один раз прожать руками, чем запоминать по таблице:
port=2222 user=student
Кликни в окно nano, затем нажимай настоящие сочетания клавиш (подсвечены в панели). Если браузер перехватил сочетание — нажми его кнопкой прямо в панели.
SSH: подключение к чужому компьютеру
Сервер — это компьютер без экрана и клавиатуры, часто вообще в другом здании. Управляют им по сети, через SSH (Secure Shell) — протокол, который открывает терминал удалённой машины прямо в твоём терминале, шифруя всё, что летает между вами. Набираешь команду у себя — выполняется там, а результат прилетает обратно.
Подключение по паролю
Если адрес неверный или машина не отвечает на этом порту, ssh откажется сразу, без долгого ожидания:
ssh -p 2222 student@localhost
ssh: connect to host localhost port 2222: Connection refused
Перевод: «в соединении отказано». Порт закрыт или на нём вообще ничего не слушает — либо ошибка в номере порта, либо SSH-сервер там не запущен. А если ошибка в самом адресе — опечатка в имени машины:
ssh nosuchhost.invalid
ssh: Could not resolve hostname nosuchhost.invalid: Name or service not known
Перевод: «не удалось разрешить имя хоста: имя или служба не известны». Это не «сервер не отвечает», а раньше: DNS вообще не нашёл, по какому IP-адресу искать машину с таким именем — обычно означает опечатку в адресе.
Когда всё указано верно и сервер отвечает, при первом подключении к конкретной машине ssh остановится с неожиданным на вид вопросом:
The authenticity of host 'localhost (::1)' can't be established.
ED25519 key fingerprint is SHA256:ABqQ+3oxmaU6fkkoqfJTjOpuQ3A8KiGxeX79BJEMwEg.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Перевод: «подлинность хоста не может быть установлена... ты уверен, что хочешь продолжить подключение?». У каждого SSH-сервера есть собственный ключ (host key), которым он подтверждает: «это точно я, а не кто-то, притворяющийся мной посередине». В первый раз проверить его нечем — твой компьютер ещё не видел эту машину, поэтому и спрашивает напрямую тебя. Печатаешь yes — и ssh запоминает этот ключ у себя навсегда, в файле ~/.ssh/known_hosts:
Warning: Permanently added 'localhost' (ED25519) to the list of known hosts.
student@localhost's password:
Дальше — обычный пароль пользователя на удалённой машине. После успешного входа приглашение в терминале сменится на приглашение удалённой машины, и все команды (ls, cat, apt…) с этого момента выполняются уже там, а не у тебя. Вернуться обратно к себе — команда exit.
Если то же самое подключение повторить ещё раз, вопроса про authenticity уже не будет — ключ уже знаком, ssh сверит его молча и сразу перейдёт к паролю. А если пароль ввести неверно:
Permission denied, please try again.
После нескольких неудачных попыток подряд ssh разрывает соединение вовсе:
student@localhost: Permission denied (publickey,password).
Ключи вместо пароля: ssh-keygen
Пароль каждый раз набирать неудобно, а главное — его теоретически можно подобрать перебором. Реальная практика — заменить пароль парой ключей (key pair): закрытым (private key), который никогда никуда не покидает твой компьютер, и открытым (public key), который можно свободно отдавать хоть всем — из публичного ключа восстановить закрытый вычислительно нереально. Сервер, у которого в списке разрешённых лежит твой публичный ключ, пускает без единого вопроса о пароле — доказательством служит то, что у тебя на руках есть парный закрытый ключ, а его не подделать.
Генерирует такую пару команда ssh-keygen:
ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/student/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/student/.ssh/id_ed25519
Your public key has been saved in /home/student/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:SZMt2OlfwKzF1kXp9D7Ylduw1XJfBnlh+UMa1CcorXU student@laptop
-t ed25519 — какой именно математический алгоритм используем для пары (ed25519 — современный и короткий стандарт по умолчанию в свежих версиях OpenSSH). Дальше три вопроса подряд: где сохранить (Enter — оставить путь по умолчанию), и дважды — кодовую фразу (passphrase), дополнительный пароль именно на сам закрытый ключ. Пустая passphrase (просто Enter дважды) означает «входить будем совсем без вопросов»; непустая — «ключ работает, но при каждом использовании спросит ещё и эту фразу», компромисс между удобством и защитой на случай кражи самого файла ключа.
Результат — два файла:
ls -la ~/.ssh
-rw------- 1 student student 411 Aug 31 18:58 id_ed25519
-rw-r--r-- 1 student student 102 Aug 31 18:58 id_ed25519.pub
Обрати внимание на права: у закрытого ключа id_ed25519 — 600 (rw-------, только владелец, вообще никому больше даже читать нельзя), у публичного id_ed25519.pub — обычные 644. Это не случайность, а первое, что проверяет сам ssh, — разберём отдельно чуть ниже, потому что это прямая связка с самым началом этой главы.
Публичный ключ нужно один раз доставить на сервер, в файл ~/.ssh/authorized_keys того пользователя, под которым будешь заходить. Вручную это cat ~/.ssh/id_ed25519.pub и вставка строки на сервере, а есть готовая утилита, которая делает это одной командой:
ssh-copy-id student@localhost
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'localhost'"
and check to make sure that only the key(s) you wanted were added.
С этого момента вход происходит без единого вопроса о пароле:
ssh localhost whoami
student
Почему право доступа к ключу — не мелочь
Вернёмся к правам 600 на закрытый ключ — это не просто аккуратность, а требование, которое ssh реально проверяет перед каждым подключением. Испортим права специально и посмотрим на настоящий ответ:
chmod 644 ~/.ssh/id_ed25519
ssh -i ~/.ssh/id_ed25519 localhost whoami
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/student/.ssh/id_ed25519' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/student/.ssh/id_ed25519": bad permissions
student@localhost: Permission denied (publickey,password).
Полностью сообщение переводится так: «предупреждение: незащищённый файл закрытого ключа! Права 0644 для файла слишком открыты. Требуется, чтобы файлы закрытых ключей были недоступны другим. Этот ключ будет проигнорирован». SSH рассуждает предельно логично: если файл закрытого ключа мог прочитать кто угодно в системе, то и защита, которую он даёт, ничего не стоит — поэтому он просто отказывается им пользоваться, вообще не пробуя. Чинится ровно той же командой, с которой началась эта глава:
chmod 600 ~/.ssh/id_ed25519
ssh -i ~/.ssh/id_ed25519 localhost whoami
student
Права снова 600 — и ключ снова принят без единого возражения.
755 · rwxr-xr-xdeploy.sh — владелец student, группа studentscp: скопировать файл на другую машину
scp (secure copy) копирует файлы между машинами тем же зашифрованным каналом, что и ssh, — фактически та же команда cp, только один (или оба) из путей находится не локально, а на удалённом хосте.
Флаг регистра — реальный источник путаницы: ssh -p 2222 и scp -P 2222 задают один и тот же порт, но регистр буквы разный. Перепутать легко, а scp на маленькую -p не пожалуется ошибкой — просто молча применит другое поведение (сохранение времени и прав), что для порта совершенно не то, что нужно.
Копирование одного файла:
scp report.txt localhost:/home/student/report_copy.txt
report.txt 100% 23 12.4KB/s 00:00
Если исходного файла не существует:
scp ghost.txt localhost:/home/student/
scp: stat local "ghost.txt": No such file or directory
Перевод: «не удалось получить сведения о локальном файле ghost.txt: нет такого файла или каталога» — опечатка в имени или файл не в том каталоге.
Каталог одним scp, как и cp, без специального флага не скопировать:
scp mydir localhost:/home/student/
scp: local "mydir" is not a regular file
scp: failed to upload file mydir to /home/student/
Перевод: «mydir — не обычный файл» и «не удалось загрузить файл mydir». Нужен тот же по смыслу флаг, что у cp и rm, — рекурсивный:
scp -r mydir localhost:/home/student/mydir_copy
a.txt 100% 0 0.0KB/s 00:00
Направление копирования можно развернуть — переставить местами локальный и удалённый путь: scp localhost:/home/student/report.txt . скачает файл с сервера на локальную машину, в текущий каталог (.). scp не различает «загрузить» и «скачать» как разные команды — направление задаётся исключительно порядком: что откуда, что куда.
Практикум: от прав до подключения
Собери всю главу в одну связку — пройди путь только терминалом, без единого клика мышью.
Шаг 1. Создай скрипт и проверь его права по умолчанию:
cat > deploy.sh <<EOF
#!/bin/bash
echo "Деплой запущен"
EOF
ls -l deploy.sh
Шаг 2. Попробуй запустить — получи Permission denied — и почини правом на выполнение:
./deploy.sh
chmod +x deploy.sh
./deploy.sh
Шаг 3. Обнови список пакетов и поставь tree:
sudo apt update
sudo apt install tree
tree --version
Шаг 4. Заведи конфиг через nano, впиши одну строку, сохрани (Ctrl+O, Enter) и выйди (Ctrl+X):
nano deploy.conf
Шаг 5. Сгенерируй пару SSH-ключей и проверь права на закрытый ключ — они должны быть 600 сразу после генерации:
ssh-keygen -t ed25519
ls -l ~/.ssh/id_ed25519
Шаг 6. Подключись к серверу (первый раз ответь yes на вопрос про authenticity, дальше — своим паролем):
ssh student@192.168.1.10
Шаг 7. Скопируй конфиг на сервер тем же каналом:
scp deploy.conf student@192.168.1.10:/home/student/
Шаг 8. Финальная проверка: зайди на сервер и убедись, что файл на месте:
ssh student@192.168.1.10 'ls -l deploy.conf'
Типичные ошибки
Шесть сообщений, каждое — с воспроизводящим примером, точным текстом (проверено вживую в реальной Ubuntu), переводом, причиной и починкой.
1. Скрипт без права на выполнение
./hello.sh
bash: ./hello.sh: Permission denied
Перевод: «в доступе отказано». Причина: у файла не установлен бит x — Linux не считает его программой, каким бы правильным ни был код внутри. Как починить: chmod +x hello.sh.
2. chmod на несуществующий файл
chmod +x nope.sh
chmod: cannot access 'nope.sh': No such file or directory
Перевод: «невозможно получить доступ к nope.sh: нет такого файла или каталога». Причина: опечатка в имени или файл ещё не создан. Как починить: проверить точное имя через ls, при необходимости — создать файл.
3. apt без sudo
apt update
E: Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
E: Unable to lock directory /var/lib/apt/lists/
Перевод: «невозможно открыть файл блокировки: в доступе отказано» и «невозможно заблокировать каталог». Причина: список пакетов — общесистемный файл, писать в него может только root. Как починить: добавить sudo — sudo apt update.
4. Пользователь не в sudoers
sudo whoami
student is not in the sudoers file.
Перевод: «student отсутствует в файле sudoers». Причина: этому пользователю администратор машины ещё не выдал право пользоваться sudo. Как починить: попросить администратора добавить пользователя в группу sudo — самостоятельно, без уже имеющихся прав, это не сделать (иначе защита не имела бы смысла).
5. SSH: соединение отклонено
ssh -p 2222 student@localhost
ssh: connect to host localhost port 2222: Connection refused
Перевод: «в соединении отказано». Причина: на указанном порту никто не слушает — неверный номер порта или SSH-сервер там не запущен. Как починить: проверить правильный порт у администратора сервера или запустить SSH-сервер на нужной машине.
6. scp: файл-источник не найден
scp ghost.txt localhost:/home/student/
scp: stat local "ghost.txt": No such file or directory
Перевод: «не удалось получить сведения о локальном файле ghost.txt: нет такого файла или каталога». Причина: опечатка в имени или запуск не из того каталога, где лежит файл. Как починить: проверить ls в текущем каталоге и точное имя файла.
Слова главы
Потренируйся печатать
Числовая запись прав — набирается быстрее буквенной, стоит довести до автоматизма:
Цель: скорость ≥ 120 зн/мин, точность ≥ 90%
chmod +x deploy.sh && ./deploy.sh
Подключение по нестандартному порту:
Цель: скорость ≥ 130 зн/мин, точность ≥ 90%
ssh -p 2222 student@192.168.1.10
Команды и флаги главы
Шпаргалка по всему, что встретилось в этой главе.
| Команда | Флаг / форма | Что делает | Пример |
|---|---|---|---|
chmod | буквенная (u/g/o/a + +/-/= + rwx) | изменить права конкретной тройке | chmod u+x hello.sh |
chmod | числовая (0–7 на тройку) | изменить права все три тройки сразу | chmod 755 script.sh |
chmod | -R | применить рекурсивно ко всему каталогу | chmod -R 755 project/ |
sudo | — | выполнить одну команду от имени root, подтвердив своим паролем | sudo apt update |
apt | update | обновить локальный список пакетов, не устанавливая ничего | sudo apt update |
apt | upgrade | обновить уже установленные пакеты до новых версий | sudo apt upgrade |
apt | install | поставить новый пакет | sudo apt install tree |
apt | -y | сразу отвечать «да» на вопросы подтверждения | sudo apt install -y tree |
nano | Ctrl+O | Write Out — сохранить файл, не закрывая редактор | — |
nano | Ctrl+X | Exit — выйти (спросит про сохранение, если есть изменения) | — |
ssh | -p | подключиться на нестандартный порт (строчная p) | ssh -p 2222 student@host |
ssh | -i | использовать конкретный файл закрытого ключа | ssh -i ~/.ssh/id_ed25519 host |
ssh-keygen | -t | сгенерировать пару ключей заданного типа | ssh-keygen -t ed25519 |
ssh-copy-id | — | скопировать публичный ключ в authorized_keys на сервере | ssh-copy-id student@host |
scp | -P | нестандартный порт (заглавная P, не путать с ssh -p) | scp -P 2222 f.txt host: |
scp | -r | скопировать каталог рекурсивно | scp -r mydir host:~/mydir |
Углубиться
umask — откуда берутся права по умолчанию. Когда файл только создаётся, ему сразу назначаются какие-то права — их вычисляет значение umask, которое вычитается из «потолка» 666 для файлов и 777 для каталогов. Типичный umask 022 даёт именно те 644 и 755, что мы разбирали как «стандартные» права в этой главе, — это не совпадение, а прямое следствие настройки по умолчанию.
visudo — как правильно редактировать sudoers. Файл /etc/sudoers напрямую редактировать опасно — одна синтаксическая ошибка может заблокировать sudo для всех сразу, включая самого администратора. Для этого есть специальная команда visudo, которая проверяет синтаксис перед сохранением и не даст выйти с битым файлом.
Файл ~/.ssh/config. Чтобы не помнить каждый раз длинную команду с портом, пользователем и адресом, можно один раз прописать алиас в ~/.ssh/config — и дальше просто ssh champserver вместо ssh -p 2222 student@192.168.1.10.
Дальше по теме:
- OpenSSH manual pages — официальные man-страницы ssh, ssh-keygen, scp и всей семьи инструментов OpenSSH
- nano — официальная документация — полный список горячих клавиш, не только те две, что разобраны в этой главе
→ Отдельная тема: SSH-ключи глубоко — пара ключей изнутри, ssh-agent, файл ~/.ssh/config и несколько ключей на одной машине.
Куда дальше: проверенные ресурсы
-
Академия Selectel — команда chmod в Linux — открывай, чтобы увидеть числовую и буквенную запись прав ещё раз другими словами, с разбором
chmod 700и других сочетаний, которых не было в этой главе. -
Яндекс.Образование — nano: базовые команды, сохранение, выход — открывай, чтобы увидеть полный список команд nano за пределами Ctrl+O/Ctrl+X: поиск, замену, вырезание строк.
-
cloud.ru — SSH для начинающих — открывай для цельной картины: установка SSH-клиента и сервера, настройка безопасности, команды scp и sftp в одном месте.
-
cloud.ru — пошаговая инструкция по настройке SSH-ключей — открывай, если нужен более подробный разбор именно
ssh-keygenи переноса ключа на сервер, чем уместилось в этой главе. -
Подключение к серверу через SSH — видео (UnixHost) — открывай, если проще воспринимать на слух и глазами: тот же процесс подключения, но с живым терминалом на экране.
-
man-страница chmod — официальное руководство: полное описание обоих режимов записи прав, включая биты, которых не было в этой главе.
-
OpenSSH manual pages — официальные man-страницы ssh, ssh-keygen и scp: первоисточник, который пересказывают все остальные статьи.
-
Ubuntu Server — Package management — официальная документация Canonical по apt, dpkg и репозиториям.
-
Видео и материалы сообщества — ниже — ролики по теме и ссылки от студентов и преподавателей смотри в самом низу страницы.
Челлендж ⭐
Ступень 1. На свежей Ubuntu-машине без пакета tree: установи его через apt (не забудь освежить список пакетов первой командой), выведи версию, чтобы доказать, что установка удалась, и запусти tree в своей домашней папке. Затем создай скрипт check.sh с любым содержимым, попробуй его запустить (получишь Permission denied) и почини правами так, чтобы владелец мог всё, а группа и все остальные — только читать и запускать, не редактировать.
Ступень 2 ⭐. Товарищ по команде скинул тебе на флешке файл id_ed25519 — свой закрытый SSH-ключ, чтобы ты подключился к общему тренировочному серверу под его учёткой. Флешка отформатирована так, что все файлы на ней получают права 644. Команда ssh -i id_ed25519 teammate@192.168.1.20 отказывается работать. Разберись, что покажет ssh, и почини — используя ровно то, что разобрано в этой главе.
Решение (сначала попробуй сам)
Ступень 1:
sudo apt update
sudo apt install tree
tree --version
tree ~
cat > check.sh <<EOF
#!/bin/bash
echo "Проверка окружения"
EOF
./check.sh # Permission denied
chmod 755 check.sh # владелец: rwx, группа и остальные: r-x
./check.sh
Ступень 2 ⭐:
ls -l id_ed25519
# -rw-r--r-- 1 student student ... id_ed25519 — права 0644, слишком открытые
chmod 600 id_ed25519
ssh -i id_ed25519 teammate@192.168.1.20
ssh откажется использовать ключ с правами 0644 и явно напишет об этом: Permissions 0644 for 'id_ed25519' are too open. ... This private key will be ignored. Причина — SSH требует, чтобы закрытый ключ был читаем только владельцем, иначе доверять ему нельзя, ведь прочитать его теоретически мог кто угодно на этой машине. chmod 600 id_ed25519 возвращает права ровно к тем, что ssh-keygen устанавливает по умолчанию сам, — и ключ снова принимается без вопросов.
Сводная проверка по всей главе: 8 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.
Что должен уметь
- Читать строку прав из
ls -l(-rwxr-xr-x) и объяснять, что означает каждая из трёх троек — владелец, группа, остальные. - Менять права и буквенной записью (
chmod u+x,chmod a-x,chmod u=rwx,g=rx,o=rx), и числовой (chmod 755,chmod 644), понимая, чем755отличается от644. - Объяснять, что такое
sudo, зачем он нужен и что значит сообщениеis not in the sudoers file. - Различать
apt update,apt upgradeиapt installи объяснять, почемуupdateне ставит и не обновляет ни одной программы. - Сохранять и выходить из
nanoклавишамиCtrl+OиCtrl+X, понимая, что означает вопросSave modified buffer?. - Подключаться по SSH и паролем, и ключом: генерировать пару
ssh-keygen, переносить публичный ключ черезssh-copy-id, и объяснять, зачем закрытый ключ должен иметь права600. - Копировать файлы и каталоги между машинами через
scp, не путая заглавную-Pс ssh-шной строчной-p. - Узнавать по точному тексту сообщения шесть типичных ошибок этой главы — от
Permission deniedдоConnection refused— и знать, как каждую починить.
Комментарии
Комментарии появятся после настройки. Нужен аккаунт GitHub — вход прямо в виджете выше.