diff --git a/05_hash_ciphers_ssh_certs/tasks.md b/05_hash_ciphers_ssh_certs/tasks.md index 46c995e..58ebac9 100644 --- a/05_hash_ciphers_ssh_certs/tasks.md +++ b/05_hash_ciphers_ssh_certs/tasks.md @@ -59,7 +59,6 @@ gpg --output un_encrypted.data --decrypt encrypted.data ### 8. Сгенерируйте сертификат x.509 и ключ с помощью openssl. Посмотрите содержимое сертификата командой `openssl x509`. - # Справка ### Хэш функция diff --git a/10_bash_scripts/solutions.md b/10_bash_scripts/solutions.md new file mode 100644 index 0000000..b262eed --- /dev/null +++ b/10_bash_scripts/solutions.md @@ -0,0 +1,468 @@ +# Решения + +# Задания + +### 1. +Напишите .sh скрипт в котором в переменную date присваивается значение текущей даты, в переменную claim - строка "snow is white". После вызова скрипт должен выводить строку, используя переменные date и claim: +``` +Ср 14 сен 2022 14:50:46 +04: The claim that “snow is white” is true if and only if snow is white. +``` +Сделайте файл исполняемым для владельца и вызовите указанием полного или относительного пути к нему. + +содержимое скрипта 1.sh +``` +date=$(date) +claim='snow is white' +echo "$date: The claim that \"$claim\" is true if and only if $claim." +``` + +### 2. +Напишите функцию в скрипте, которая создает каталог, путь к которому передан в качестве первого аргумента и переходит в него. Проверьте работу функции в этом же файле. Работает ли функция за пределами контекста скрипта? +``` +$ cat 2.sh +mkdir_cd () { + mkdir -p $1 + cd $1 + echo current dir: $(pwd) +} + +mkdir_cd $1 +stud@stud15:~$ ./2.sh /tmp/1/2/3/4/5 +current dir: /tmp/1/2/3/4/5 +stud@stud15:~$ +``` +После выполнения скрипта текущая директория не изменилась. +``` +$ mkdir_cd () { + mkdir -p $1 + cd $1 + echo current dir: $(pwd) +} +stud@stud15:~$ mkdir_cd /tmp/a/b/c/d +current dir: /tmp/a/b/c/d +stud@stud15:/tmp/a/b/c/d$ +``` +После определения функции и вызова в оболочке изменилась. + + +### 3. +Менее известной, но полезной может быть подстановка дескриптора файла с результатом выполнения команды. `<( CMD )` выполнит `CMD` и поместит вывод во временный файл и заменит `<()` именем этого файла. Это полезно, когда команды ожидают, что значения будут переданы через файл, а не STDIN. Например, `diff <(ls foo) <(ls bar)` покажет различия между файлами в каталогах foo и bar. +``` +$ diff <(cat buylist) <(cat bought) +1,3c1,5 +< salad +< milk +< bread +--- +> icecream +> cheese +> cake +> lays +> beer +``` + +### 4. +Попробуйте условные выражения в скрипте в if конструкции: +``` +$ cat 4.sh +if [[ true && true ]] +then + echo "True" +fi + +if [[ true || false ]] +then + echo "True" +fi +stud@stud15:~$ ./4.sh +True +True +``` + +### 5. +Напишите скрипт, который проходит по всем файлам, переданным в качестве аргументов, и ищет в них строку hello. Перенаправьте grep `STDOUT` и `STDERR` в специальный файл `/dev/null`. Для каждого файла в if создайте файл с содержимым `hello`, если `grep` завершился с ошибкой. +``` +$ cat 5.sh +for f in $@; do + grep hello $f 2> /dev/null 1> /dev/null + if [[ $? -ne 0 ]] + then + echo "hello" > $f + fi +$ ./5.sh /tmp/one /tmp/two /tmp/three +/tmp/one has no hello in it. correcting. +/tmp/two has no hello in it. correcting. +/tmp/three has no hello in it. correcting. +$ grep hello /tmp/* 2> /dev/null +/tmp/one:hello +/tmp/three:hello +/tmp/two:hello +``` + +### 6. +Установите пакет shellcheck и проверьте написанный вами ранее скрипт одноименной командой. +``` +$ shellcheck 5.sh + +In 5.sh line 1: +for f in $@; do +^-- SC2148 (error): Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive. + ^-- SC2068 (error): Double quote array expansions to avoid re-splitting elements. + + +In 5.sh line 2: + grep hello $f 2> /dev/null 1> /dev/null + ^-- SC2086 (info): Double quote to prevent globbing and word splitting. + +Did you mean: + grep hello "$f" 2> /dev/null 1> /dev/null + + +In 5.sh line 3: + if [[ $? -ne 0 ]] + ^-- SC2181 (style): Check exit code directly with e.g. 'if ! mycmd;', not indirectly with $?. + + +In 5.sh line 5: + echo $f has no hello in it. correcting. + ^-- SC2086 (info): Double quote to prevent globbing and word splitting. + +Did you mean: + echo "$f" has no hello in it. correcting. + + +In 5.sh line 6: + echo "hello" > $f + ^-- SC2086 (info): Double quote to prevent globbing and word splitting. + +Did you mean: + echo "hello" > "$f" + +For more information: + https://www.shellcheck.net/wiki/SC2068 -- Double quote array expansions to ... + https://www.shellcheck.net/wiki/SC2148 -- Tips depend on target shell and y... + https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ... +``` + +### 7. +Напишите скрипт, который выполняет следующий код: +``` +$ cat ./7.sh +#!/usr/bin/env python +import sys +for arg in reversed(sys.argv[1:]): + print(arg) +$ ./7.sh 1 2 3 4 5 +5 +4 +3 +2 +1 +``` + +### 8. +Функции выполняются в текущей среде оболочке, тогда как скрипты выполняются в своем собственном процессе. + +Проверьте, что функции могут изменять переменные среды, например, изменить текущий каталог, тогда как скрипт не может. Напишите скрипт, в котором инициализируются две переменные `A` и `B`. Перед одной из них указывается `export `. Выполните скрипт и посмотрите на выдачу команды `env`. Выполните файл командой source (source --help). Какие переменные экспортировались в оболочку? +``` +$ cat 8.sh +#!/bin/bash +A=1 +export B=2 +stud@stud15:~$ ./8.sh +stud@stud15:~$ env | grep -E "^A|B" +stud@stud15:~$ source ./8.sh +stud@stud15:~$ env | grep -E "^A|B" +B=2 +``` + +### 9. +Напишите сценарий bash, который запускает следующий сценарий до тех пор, пока он не завершится аварийно, записывает стандартный вывод и потоки ошибок в файлы и печатает все в конце. +``` +stud@stud15:~$ cat random_bug_script.sh +#!/usr/bin/env bash + +n=$(( RANDOM % 100 )) +echo $n +if [[ n -eq 42 ]]; then + echo "Something went wrong" + >&2 echo "The error was using magic numbers" + exit 1 +fi + +echo "Everything went according to plan" + +stud@stud15:~$ cat repeat_until_error.sh +#!/bin/bash +echo "" > output.log +echo "" > error.log +i=0 +while true; do + bash $1 2>> error.log 1>> output.log + if [[ $? -ne 0 ]]; then + echo Took "$i" iterations to get an error. + echo "\noutput.log" + cat output.log + echo "\nerror.log" + cat error.log + break + fi + i=$((i+1)) +done + +stud@stud15:~$ ./repeat_until_error.sh ./random_bug_script.sh +Took 37 iterations to get an error. + +output.log + +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Everything went according to plan +Something went wrong + +error.log + +The error was using magic numbers +``` + +Бонусный балл, за то, что вы можете сообщить, сколько запусков потребовалось для сбоя сценария. +``` +stud@stud15:~$ cat mean.sh +#!/bin/bash +script=$1 +iters=$2 +sum=0 +for i in $(seq $iters) +do + failedoniter=$(bash $script | grep 'Took' | awk '{ print $2; }') + sum=$((sum+failedoniter)) +done + +echo Done $iters trials. +echo Mean number of steps until error: $(( sum / iters )) + +$ time ./mean.sh "./repeat_until_error.sh ./random_bug_script.sh" 1000 +Done 1000 trials. +Mean number of steps until error: 99 + +real 2m6,924s +user 1m36,964s +sys 0m29,409s +``` + +### 10. +Напишите скрипт, который: +- создаёт пользователя на двух машинах, +- кроме домашней директории заводит папку для пользователя в `/ceph/` с нужными правами, +- создаёт ссылку в домашней директории на директорию в `/ceph/`, +- ограничивает доступ к домашней папке всем, кроме владельца, +- генерирует пользователям ключи ed25519, рассылает по машинам и регистрирует ключи для беспарольного перемещения пользователя между машинами. + +Настройка беспарольного перехода для суперпользователя между машинами +``` +root@stud15:~# cat .ssh/config +Host w001 + HostName 10.160.179.25 + +Host w002 + HostName 10.160.179.55 + +root@stud15:~# hostname -i +10.160.179.25 +root@stud15-v1:~# hostname -i +10.160.179.55 + +root@stud15-v1:~# cat /etc/ssh/sshd_config | grep PermitRootLogin +PermitRootLogin yes + +root@stud15-v1:~# systemctl restart sshd + +root@stud15:~# ssh-copy-id w002 +/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" +/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed +/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys +root@10.160.179.55's password: + +Number of key(s) added: 1 + +Now try logging into the machine, with: "ssh 'w002'" +and check to make sure that only the key(s) you wanted were added. + +root@stud15-v1:~# cat /etc/ssh/sshd_config | grep PermitRootLogin +PermitRootLogin prohibit-password + +root@stud15-v1:~# systemctl restart sshd + +root@stud15:~# ssh-copy-id w001 +/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" +The authenticity of host '10.160.179.25 (10.160.179.25)' can't be established. +ECDSA key fingerprint is SHA256:3K1vZ3p2zlZpJabnqm3ZqwUPkmxxnIHiqYplqRLEku8. +Are you sure you want to continue connecting (yes/no/[fingerprint])? yes +/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed + +/usr/bin/ssh-copy-id: WARNING: All keys were skipped because they already exist on the remote system. + (if you think this is a mistake, you may want to use -f option) +``` + +``` +root@stud15:~# cat create_user.sh +#!/bin/bash + +help() { + echo "Usage: ./create_user.sh file_with_node_ip_addresses user_name" +} + +if [[ $# < 2 ]] +then + help + exit +fi + + +nodes=$(cat $1) +user=$2 +create_user_and_link_command="useradd $user --create-home --shell=/bin/bash --key HOME_MODE=0700; \ +mkdir -p /ceph/$user -m 0700; \ +chown $user:$user /ceph/$user; \ +ln -s /ceph/$user /home/$user/ceph; \ +chown $user:$user --no-dereference /home/$user/ceph" + +mkdir -p /root/users.ssh/$user/ +ssh-keygen -t ed25519 -N "" -f "/root/users.ssh/$user/id_ed25519" +sed --in-place "s/root/user/" "/root/users.ssh/$user/id_ed25519.pub" +cat /root/users.ssh/$user/id_ed25519.pub > /root/users.ssh/$user/authorized_keys + +echo "" > /root/users.ssh/$user/known_hosts +for node in $nodes; do + ssh-keyscan -H "$node" >> /root/users.ssh/$user/known_hosts +done + +for node in $nodes; do + echo "$node" "$create_user_and_link_command" + ssh "$node" "$create_user_and_link_command" + scp -r /root/users.ssh/$user/ $node:/home/$user/.ssh + ssh "$node" "chown -R $user:$user /home/$user/.ssh && chmod 0700 /home/$user/.ssh/" +done + +root@stud15:~# cat nodes +10.160.179.25 +10.160.179.55 + +root@stud15:~# ./create_user.sh nodes user6 +Generating public/private ed25519 key pair. +Your identification has been saved in /root/users.ssh/user6/id_ed25519 +Your public key has been saved in /root/users.ssh/user6/id_ed25519.pub +The key fingerprint is: +SHA256:FdusRTajDoM/7us/Tyf3VCmu/8kAWjWoYkerUGKggzg root@stud15 +The key's randomart image is: ++--[ED25519 256]--+ +| . . = | +|o . . . O.o | +|Eo o..o.+.+o | +| .. . o..=oo. . .| +| . oS+oo . ..| +| o.+.o o . .| +| ... ooo .| +| . ...+oo.| +| .+o.+o..+.| ++----[SHA256]-----+ +# 10.160.179.25:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.25:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.25:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.25:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.25:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.55:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.55:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.55:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.55:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +# 10.160.179.55:22 SSH-2.0-OpenSSH_8.4p1 Debian-5+deb11u1 +10.160.179.25 useradd user6 --create-home --shell=/bin/bash --key HOME_MODE=0700; mkdir -p /ceph/user6 -m 0700; chown user6:user6 /ceph/user6; ln -s /ceph/user6 /home/user6/ceph; chown user6:user6 --no-dereference /home/user6/ceph +id_ed25519.pub 100% 93 484.7KB/s 00:00 +id_ed25519 100% 399 2.8MB/s 00:00 +authorized_keys 100% 93 746.1KB/s 00:00 +known_hosts 100% 1957 12.5MB/s 00:00 +10.160.179.55 useradd user6 --create-home --shell=/bin/bash --key HOME_MODE=0700; mkdir -p /ceph/user6 -m 0700; chown user6:user6 /ceph/user6; ln -s /ceph/user6 /home/user6/ceph; chown user6:user6 --no-dereference /home/user6/ceph +id_ed25519.pub 100% 93 434.1KB/s 00:00 +id_ed25519 100% 399 2.4MB/s 00:00 +authorized_keys 100% 93 625.8KB/s 00:00 +known_hosts 100% 1957 10.4MB/s 00:00 +root@stud15:~# + + +user6@stud15:~$ ssh 10.160.179.55 +Linux stud15-1v15 5.10.0-17-amd64 #1 SMP Debian 5.10.136-1 (2022-08-13) x86_64 + +The programs included with the Debian GNU/Linux system are free software; +the exact distribution terms for each program are described in the +individual files in /usr/share/doc/*/copyright. + +Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent +permitted by applicable law. +user6@stud15-1v15:~$ ssh 10.160.179.25 +Linux stud15 5.10.0-16-amd64 #1 SMP Debian 5.10.127-1 (2022-06-30) x86_64 + +The programs included with the Debian GNU/Linux system are free software; +the exact distribution terms for each program are described in the +individual files in /usr/share/doc/*/copyright. + +Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent +permitted by applicable law. +user6@stud15:~$ + + +root@stud15:~# ls -la /home/user6/ +total 28 +drwx------ 3 user6 user6 4096 сен 15 11:49 . +drwxr-xr-x 13 root root 4096 сен 15 11:47 .. +-rw------- 1 user6 user6 18 сен 15 11:49 .bash_history +-rw-r--r-- 1 user6 user6 220 мар 27 22:40 .bash_logout +-rw-r--r-- 1 user6 user6 3526 мар 27 22:40 .bashrc +lrwxrwxrwx 1 user6 user6 11 сен 15 11:47 ceph -> /ceph/user6 +-rw-r--r-- 1 user6 user6 807 мар 27 22:40 .profile +drwx------ 2 user6 user6 4096 сен 15 11:47 .ssh +root@stud15:~# ls -la /ceph +total 32 +drwxr-xr-x 8 root root 4096 сен 15 11:47 . +drwxr-xr-x 21 root root 4096 сен 15 11:12 .. +drwx------ 2 user1 user1 4096 сен 15 11:14 user1 +drwx------ 2 user2 user2 4096 сен 15 11:25 user2 +drwx------ 2 user3 user3 4096 сен 15 11:38 user3 +drwx------ 2 user4 user4 4096 сен 15 11:42 user4 +drwx------ 2 user5 user5 4096 сен 15 11:44 user5 +drwx------ 2 user6 user6 4096 сен 15 11:47 user6 +``` + diff --git a/10_bash_scripts/tasks.md b/10_bash_scripts/tasks.md index 28ba5f6..dc0d0b3 100644 --- a/10_bash_scripts/tasks.md +++ b/10_bash_scripts/tasks.md @@ -23,18 +23,17 @@ echo_arguments () { ``` В отличие от других языков сценариев, bash использует множество специальных переменных для ссылки на аргументы, коды ошибок и другие важные переменные. Ниже приведен список некоторых из них. Более полный список можно найти здесь (https://tldp.org/LDP/abs/html/special-chars.html или https://www.opennet.ru/docs/RUS/bash_scripting_guide/c301.html. -$0 - имя скрипта, $1 до $9 - аргументы скрипта, $@ - все аргументы, $# - количество аргументов $? - возвращаемый код предыдущей команды, $$ - идентификатор процесса текущего скрипта, !! - вся команда, включая аргументы (попробуйте sudo !!, если забыли, что команде требуются права суперпользователя), $_ - последний аргумент последней команды (в терминале попробуйте нажать Esc . или Alt+). +`$0` - имя скрипта, `$1` до `$9` - аргументы скрипта, `$@` - все аргументы, `$#` - количество аргументов,`$?` - возвращаемый код предыдущей команды, `$$` - идентификатор процесса текущего скрипта, `!!` - вся команда, включая аргументы (попробуйте `sudo !!`, если забыли, что команде требуются права суперпользователя), `$_` - последний аргумент последней команды (в терминале попробуйте нажать `Esc .` или `Alt+`). Напишите функцию в скрипте, которая создает каталог, путь к которому передан в качестве первого аргумента и переходит в него. Проверьте работу функции в этом же файле. Работает ли функция за пределами контекста скрипта? ### 3. Менее известной, но полезной может быть подстановка дескриптора файла с результатом выполнения команды. `<( CMD )` выполнит `CMD` и поместит вывод во временный файл и заменит `<()` именем этого файла. Это полезно, когда команды ожидают, что значения будут переданы через файл, а не STDIN. Например, `diff <(ls foo) <(ls bar)` покажет различия между файлами в каталогах foo и bar. - ### 4. -Команды часто возвращают выходные данные, используя STDOUT, ошибки — через STDERR и код возврата, чтобы сообщать об ошибках более удобным для сценариев способом. Код возврата или статус выхода — это то, как скрипты/команды должны сообщать о том, как прошло выполнение. Значение 0 обычно означает, что все прошло нормально; все, что отличается от 0, означает, что произошла ошибка. +Команды часто возвращают выходные данные, используя `STDOUT`, ошибки — через `STDERR` и код возврата, чтобы сообщать об ошибках более удобным для сценариев способом. Код возврата или статус выхода — это то, как скрипты/команды должны сообщать о том, как прошло выполнение. Значение 0 обычно означает, что все прошло нормально; все, что отличается от 0, означает, что произошла ошибка. -Коды выхода можно использовать для условного выполнения команд с использованием && (и оператора) и || (или оператор), оба из которых являются операторами . Команды также можно разделять в пределах одной строки с помощью точки с запятой ;. Истинная программа всегда будет иметь код возврата 0, а ложная команда всегда будет иметь код возврата 1. +Коды выхода можно использовать для условного выполнения команд с использованием `&&` (и оператора) и `||` (или оператор), оба из которых являются операторами. Команды также можно разделять в пределах одной строки с помощью точки с запятой `;`. Истинная программа всегда будет иметь код возврата `0`, а ложная команда всегда будет иметь код возврата `1`. Попробуйте выполнить следующие примеры: ``` @@ -65,13 +64,13 @@ fi ``` ### 5. -Напишите скрипт, который проходит по всем файлам, переданным в качестве аргументов, и ищет в них строку hello. Перенаправьте grep STDOUT и STDERR в специальный файл /dev/null. Для каждого файла в if создайте файл с содержимым hello, если grep завершился с ошибкой. +Напишите скрипт, который проходит по всем файлам, переданным в качестве аргументов, и ищет в них строку hello. Перенаправьте grep `STDOUT` и `STDERR` в специальный файл `/dev/null`. Для каждого файла в if создайте файл с содержимым `hello`, если `grep` завершился с ошибкой. ### 6. Установите пакет shellcheck и проверьте написанный вами ранее скрипт одноименной командой. ### 7. -Cкрипты не обязательно должны быть написаны на bash для вызова из терминала. Ядро определяет, что сценарий нужно выполнять с помощью другого интерпретатора вместо командой оболочки, если в начало скрипта включена строка shebang. Хорошей практикой является написание строк shebang с помощью команды env, которая будет разрешаться везде, где эта команда находится в системе, что повышает переносимость ваших сценариев. Например, чтобы определить местоположение python, env будет использовать переменную среды PATH при записи `#!/usr/bin/env python`. +Cкрипты не обязательно должны быть написаны на bash для вызова из терминала. Ядро определяет, что сценарий нужно выполнять с помощью другого интерпретатора вместо командой оболочки, если в начало скрипта включена строка shebang. Хорошей практикой является написание строк shebang с помощью команды env, которая будет разрешаться везде, где эта команда находится в системе, что повышает переносимость ваших сценариев. Например, чтобы определить местоположение python, env будет использовать переменную среды `PATH` при записи `#!/usr/bin/env python`. Напишите скрипт, который выполняет следующий код: ``` @@ -83,7 +82,7 @@ for arg in reversed(sys.argv[1:]): ### 8. Функции выполняются в текущей среде оболочке, тогда как скрипты выполняются в своем собственном процессе. -Проверьте, что функции могут изменять переменные среды, например, изменить текущий каталог, тогда как скрипт не может. Напишите скрипт, в котором инициализируются две переменные A и B. Перед одной из них указывается `export `. Выполните скрипт и посмотрите на выдачу команды `env`. Выполните файл командой source (source --help). Какие переменные экспортировались в оболочку? +Проверьте, что функции могут изменять переменные среды, например, изменить текущий каталог, тогда как скрипт не может. Напишите скрипт, в котором инициализируются две переменные `A` и `B`. Перед одной из них указывается `export `. Выполните скрипт и посмотрите на выдачу команды `env`. Выполните файл командой source (source --help). Какие переменные экспортировались в оболочку? ### 9. Скажем, у вас есть команда, которая редко дает сбой. Чтобы отладить её, вам нужно зафиксировать её выходные данные, но это может занять много времени, чтобы поймать неудачный запуск. Напишите сценарий bash, который запускает следующий сценарий до тех пор, пока он не завершится аварийно, записывает стандартный вывод и потоки ошибок в файлы и печатает все в конце. Бонусный балл, за то, что вы можете сообщить, сколько запусков потребовалось для сбоя сценария. @@ -104,7 +103,8 @@ echo "Everything went according to plan" ### 10. Напишите скрипт, который: - создаёт пользователя на двух машинах, -- кроме домашней директории заводит папку для пользователя в /ceph/ с нужными правами, -- создаёт ссылку в домашней директории на директорию в /ceph/, +- кроме домашней директории заводит папку для пользователя в `/ceph/` с нужными правами, +- создаёт ссылку в домашней директории на директорию в `/ceph/`, - ограничивает доступ к домашней папке всем, кроме владельца, -- генерирует пользователям ключи ed25519, рассылает по машинам и регистрирует ключи для беспарольного перемещения пользователя между машинами. \ No newline at end of file +- генерирует пользователям ключи ed25519, рассылает по машинам и регистрирует ключи для беспарольного перемещения пользователя между машинами. +