Курс
27. bash скрипты №1
Изучать что-то новое может быть интересно - новые знания, новый опыт. Вот мы изучили рейд, лвм, файловые системы и всё такое, попрактиковались пару раз – всё довольно просто. Но вы устраиваетесь на работу, там есть какая-то инфраструктура и ваша задача – администрировать эту инфрастуктуру. И то что вчера было новым и интересным превращается в рутину – вам постоянно нужно работать с одними и теми же командами, изо дня в день, годами. Где-то пользователей создать и права настроить, где-то бэкап сделать, где-то ещё что. И люди ищут способы, как бы это всё автоматизировать. Автоматизировать графический интерфейс довольно сложно. Писать новую программу ради какой-то рутины не всегда стоит того. И тут текстовый интерфейс раскрывает себя во всей красе. Можно написать так называемые сценарии, какие команды и как будут выполняться. И запускать этот сценарий вручную, либо автоматизировать его запуск, что вообще позволит админу избавиться от рутины.
Мы работаем с bash, поэтому будем учиться писать сценарии для него. Более привычное название – скрипты. Кто-то называет это "bash программированием". И давайте сразу поставим себе задачу, которую будем решать с помощью скрипта. Начнём с чего-то простого – создать двух пользователей:
user1 :
  1. 1.
    Основная группа - it
  2. 2.
    it – группа с правами суперпользователя
  3. 3.
    Домашняя директория в /home/it
  4. 4.
    Оболочка - /bin/bash
user2 :
  1. 1.
    Основная группа - users
  2. 2.
    Домашняя директория в /home/users
  3. 3.
    Оболочка - /sbin/nologin
Один из них — user1 - его основная группа будет it, у которой будут права суперпользователя, его домашняя директория будет внутри директории /home/it и его оболочка будет bash. Второй пользователь – user2 - будет в группе users, домашняя директория внутри директории /home/users, а оболочка nologin. Кстати, попробуйте самостоятельно вспомнить все команды, которые необходимо выполнить.
Для начала вспомним, как это делается. Во первых, нужно создать группы и директории. Создаём группу it:
1
sudo groupadd it
Copied!
Группа users есть по умолчанию:
1
grep users /etc/group
Copied!
У группы it должны быть права суперпользователя – заходим в:
1
visudo
Copied!
и добавляем строчку:
1
%it ALL=(ALL) ALL
Copied!
Дальше нам нужны директории - /home/it и /home/users:
1
sudo mkdir -v /home/{it,users}
Copied!
И наконец создаём пользователей:
1
sudo useradd user1 -g it -b /home/it -s /bin/bash
2
sudo useradd user2 -g users -b /home/users -s /sbin/nologin
3
tail /etc/passwd
Copied!
Всего у нас получилось 5 команд:
1
sudo groupadd it
2
sudo visudo
3
sudo mkdir -v /home/{it,users}
4
sudo useradd user1 -g it -b /home/it -s /bin/bash
5
sudo useradd user2 -g users -b /home/users -s /sbin/nologin
Copied!
Теперь давайте сделаем скрипт – просто вставим все эти 5 команд в файл с любым названием:
1
nano myscript
Copied!
Каждая команда с новой строки.
Но прежде чем запускать скрипт, надо вернуть всё как было – удаляем пользователей, группу, директории и запись из sudoers:
1
sudo userdel -r user1
2
sudo userdel -r user2
3
sudo groupdel it
4
sudo rm -r /home/{it,users}
5
sudo visudo
6
sudo grep «%it» /etc/sudoers
Copied!
Запускаем скрипт с помощью bash:
1
bash myscript
Copied!
У меня открылся visudo – это один из шагов, когда мне нужно добавить группу it в sudoers. Добавил, сохранил. Теперь опять проверяем:
1
tail /etc/passwd
Copied!
всё создалось. И это одной командной, не считая ручного заполнения visudo.
Но.. мы говорим про автоматизацию, а мне всё равно приходится добавлять запись в sudoers вручную. Давайте сделаем так, чтобы запись добавлялась без нашего участия. Помните, как мы делали с рейдом – писали echo текст и направляли в файл? Сделаем точно также. Заменим в нашем файле visudo на echo:
1
nano myscript
Copied!
echo %it ALL=(ALL) ALL
Возьмём текст в одинарные кавычки, чтоб баш никак не обработал команду и направим этот текст в файл /etc/sudoers:
1
echo '%it ALL=(ALL) ALL' >> /etc/sudoers
Copied!
с помощью двух символов больше, чтобы не перезаписать файл, а дополнить. Правда сама такая команда не сработает – перенаправление вывода (>>) выполняется от моей оболочки, не от команды sudo, а у моего пользователя не хватит прав записать что-то в sudoers.
1
sudo echo '%it ALL=(ALL) ALL' >> /etc/sudoers
Copied!
Можно, конечно, использовать команду tee, но, вообще, учитывая, что все команды тут выполняются с sudo, легче сделать по другому. Просто сотрём отсюда все sudo, а при запуске, вместо bash myscript будем писать:
1
sudo bash myscript
Copied!
Тогда весь скрипт будет выполняться в оболочку суперпользователя – это и избавит нас от проблемы с перенаправлением вывода и не будет необходимости внутри скрипта запускать sudo.
Но неплохо было бы на всякий случай сделать копию файла sudoers, чтобы случайно его не испортить. Добавим команду в начале скрипта:
1
nano myscript
Copied!
cp /etc/sudoers{,.bkp}
Хорошо, теперь опять удалим то что создали:
1
sudo userdel -r user1
2
sudo userdel -r user2
3
sudo groupdel it
4
sudo rm -r /home/{it,users}
5
sudo visudo
6
cp /etc/sudoers{,.bkp}
Copied!
И заново запустим скрипт:
1
sudo bash myscript
2
tail -2 /etc/passwd
3
sudo tail -1 /etc/sudoers
Copied!
Сработало – одной командой мы создали всё что нам нужно.
Чтобы наш скрипт выглядел более самостоятельным, то есть, чтобы нам не приходилось каждый раз перед ним писать bash, а также чтобы мы могли делиться этим скриптом с другими, кто, возможно, использует другие оболочки, мы можем внутри самого скрипта указать, а под какой именно интерпретатор написан скрипт. Так как, теоретически, у нас в скрипте могут быть всякие особенности, присущие только bash, которых нет в других интерпретаторах. Но тут могут быть нюансы – нужно понимать, что bash есть во многих системах, но не во всех. Если вы пишете скрипт, который предполагаете использовать не только на GNU/Linux, но и на всяких UNIX-ах, где может не быть bash-а, то лучше писать скрипты под интерпретатор shell. Чтобы указать, с помощью какого интерпретатора запускать скрипт, в первой строчке самого скрипта указываются два символа:
1
#!
Copied!
называемые шебанг, после чего указывается путь к интерпретатору, допустим:
1
#!/bin/bash
Copied!
Но так как в разных дистрибутивах и системах bash или другой интерпретатор могут находится в разных директориях, есть более универсальный способ написания пути:
1
#!/usr/bin/env bash
Copied!
Давайте так и оставим. Правда, так как теперь мы будем запускать скрипт напрямую, а не передавая его программе bash, ему понадобятся права для запуска – для этого пишем:
1
chmod +x myscript
Copied!
Но написать:
1
sudo myscript
Copied!
не получится – sudo будет искать программу myscript в директориях её переменной PATH. Либо нужно поместить myscript в одну из директорий переменной PATH, либо явно указывать путь к этому скрипту – достаточно поставить перед ним точку и слеш, если он в текущей директории:
1
sudo ./myscript
Copied!
Но наш скрипт получился слишком однозадачным – он нацелен на создание двух конкретных пользователей. Сойдёт на разок, но потом, если понадобится создать ещё пользователей, придётся изменять скрипт. Давайте сделаем наш скрипт более динамическим – добавим в него переменные. Пользователей и группы заменим на переменные – user1,user2,group1,group2, а так как директории совпадают с именами групп, там тоже используем переменные. В строке echo одинарные кавычки, а значит переменная не обработается. Надо немного переделать строчку. Можно по разному, но я просто оставлю переменную group1 за кавычками. Теперь, если мне понадобится выполнить скрипт для других пользователей и групп, я могу просто заменить в начале скрипта значения переменных, вместо того, чтобы переделывать весь скрипт.
Опять же получилось так себе – у нас тут скрипт на двух пользователей в двух группах – а если мне нужно добавить одного или трёх пользователей? Давайте уберём всё что касается user2 и group2. Конечно, для второго пользователя придётся опять запускать скрипт, но динамичность скрипта это компенсирует.
Хотя.. в скрипте всё ещё вручную прописаны переменные user и group. Придётся для каждого пользователя заходить и менять значения. Обычно, когда мы работаем с программами в командной строке, мы передаём ей какие-то параметры. Нельзя ли пользователя и группу передать в виде параметров, чтоб не приходилось менять скрипт? Можно.
Давайте сделаем так – создадим новый скрипт:
1
nano test
Copied!
#!/usr/bin/env bash
echo $1 $2 $3
сохраним и дадим права:
1
chmod +x test
Copied!
Запустим:
1
./test
Copied!
ничего. Теперь напишем после скрипта какие-то параметры:
1
./test a b c d e
Copied!
Как видите, первые три параметра вывелись. Что же произошло? Переменные 1, 2 и 3 в виде значений получили соответствующие аргументы:
1
cat test
Copied!
Вернёмся к нашему скрипту. Заменим значение переменной user на $1, а group на $2:
1
user=$1
2
group=$2
Copied!
Теперь запустим наш скрипт с двумя аргументами – первый – это имя пользователя, второй – имя группы:
1
sudo ./myscript user3 it
2
tail -1 /etc/passwd
Copied!
Всё сработало – у нас появился user3.
Можно сделать наоборот – добавить интерактивности, как это, например, в fdisk. Допустим, сделать так, чтобы скрипт при запуске спрашивал имя пользователя и группу. Добавим для красоты надпись в начале:
1
echo Welcome!
Copied!
Дальше используем команду read, которая будет запрашивать ввод и сохранять его в переменной, с ключом p – которая выведет текст на экран. Допустим:
1
read -p "Print username: " user
2
read -p "Print groupname: " group
Copied!
Здесь user и group – это переменные, которые получат своё значение от введённого текста.
Давайте запустим скрипт и проверим:
1
sudo ./myscript
2
tail /etc/passwd
Copied!
Всё сработало. Тут, конечно, есть ещё над чем поработать, но это оставим на следующий раз.
Подведём итоги. Мы начали разбирать скрипты. Это, конечно, совсем азы, но тут есть с чем попрактиковаться. Вспомните старые занятия – права, файлы, диски. Вспомните команды, сделайте из них скрипты – что-то интерактивное, что-то не интерактивное. Это большая тема, мы будем к ней возвращаться не раз. Но, в целом, чтобы хорошо писать скрипты нужно много много практиковаться. По ссылке можете найти цикл статей по скриптингу на bash.
Last modified 24d ago
Export as PDF
Copy link