Основы работы с терминалом / Создание bash скриптов, основы

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

Допустим мы в прошлый раз создавали папку под проект, инициализировали там репозиторий добавляли там файл README.md, подключали его к гиту, создавали ключики.

И каждую команду нам приходилось вводить вручную. Что конечно было лениво

Когда вам часто приходится выполнять какие-то операции, было бы неплохо это как-то упростить. Например, так чтобы вам вместо ввода 10 команд достаточно было ввести одну команду.

Автоматизируем создание проекта

Давайте напишем скрипт который объединяет все эти команды. Но сначала нам надо определится со списком команд:

теперь попробуем вывести все эти команды

mkdir new_project
git init
touch README.md
git add README.md
git commit -a -m "первый коммит"

давайте пока реализуем без ключей.

Теперь создадим папку project03 и будем экспериментировать в ней

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

в общем по идее у нас должна появится папка new_project, внутри которой будет лежать файлик README.md

посмотрим, что у нас получилось (через ls -la):

то есть у нас в текущей папке появилась папка new_project, что уже неплохо, но файл README.md создался не внутри папки new_project, а в текущей. Ну и папка .git не там оказалась не в папке new_project, а в текущей

Глянем что в папке new_project:

кстати давайте поставим программку которая позволяет просматривать папки не по одной, а сразу в виде дерева. Пишем команду

sudo apt install tree

вводим пароль и видим такое, это означает что пакет уже установлен:

ну установлен и хорошо, давайте тогда воспользуемся ей, пишем

tree 

и видим структуру

тут не очень наглядно, давайте добавим руками файлик в new_project

touch new_project/test_file.txt

и снова посмотрим содержимое

можно добавить флаг -a тогда увидим и содержимое скрытой папки .git

Так, ну в принципе проблема понятна. Надо чтобы файлик и репозиторий создавались не в текущей папке, а в папке new_project, а как это сделать?

Надо просто после создания папки перейти в нее через

cd new_project

Давайте, все почистим. Для удаления файлов и папок используется команда rm от слова remove (англ. удалить). Запускаем:

чтобы удалять папки надо добавить флаг -r (от слова recursive, то бишь рекурсивно),

еще у нас есть скрытая папка .git ее тоже надо удалить. Правда при попытке это сделать он начинает задавать лишние вопросы

чтобы прервать выполнение команды тыкайте Ctrl+C и чтобы вопросы не возникали добавьте флаг -f (от слова force, то бишь «принуждать» по-английски)

вызываем tree -a чтобы убедится, что в каталоге ничего не осталось:

ну вроде все ок.

Вернемся к нашему набору команд. Напоминаю, они у нас такие

mkdir new_project
git init
touch README.md
git add README.md
git commit -a -m "первый коммит"

надо добавить переход в папку new_project

mkdir new_project
cd new_project # добавил
git init
touch README.md
git add README.md
git commit -a -m "первый коммит"

Пробуем выполнять

красота =О

Немного о встроенной документации man

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

пожалуйста! Полная документация! К сожалению, только на английском, но шо поделаешь =) Кстати, чтобы из нее выйти надо нажать q (от слова quit – то бишь выход по-английски)

Создаем скрипт

Давайте теперь попробуем это как-нибудь улучшить. Удалим папку new_project

cd .. # выйдем из папки
rm -rf new_project

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

Создадим файл. Вообще для создания файла не обязательно сначала писать touch, а потом уже nano, можно просто после nano указать имя файла. Для файлов с командами bash принято указывать расширение *.sh

nano create_git_project.sh

открывается редактор, в который загоняем команды

сохраняем через Ctrl+O и выходим Ctrl+X

теперь собственно надо его как-то запустить. Для этого можно написать так

bash create_git_project.sh

но на самом деле так не принято. Есть альтернативный способ. Мы можем пометить файл как исполняемый. И вызывать файл напрямую.

Тут кстати важное отличие от windows. В винде есть фиксированный набор расширений файлов, которые винда на автомате рассматривает как исполняемые ну там exe, bat, msi и т. д.

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

Для добавления флага используется команда chmod. Что за такие флаги спросите вы. А мы на самом деле их уже видели. Давайте еще раз посмотрим. Выполним команду ls -l

у каждого файла (папка тоже считается за файл есть 10 флагов)

если где-то стоит прочерк — значит права отсутствуют. Кстати может возникнуть вопрос, а что за владельцы и группы у файла? А это надо глянуть вот сюда

Ну с владельцем вроде понятно, кто файл создал тот им и владеет. А группа — это такой способ объединять пользователей по какому-нибудь признаку. По умолчанию, когда создается новый пользователь, создается группу с тем же именем что и пользователь. Ее можно рассматривать как своего рода группу друзей пользователя. Туда можно добавить других юзеров и дать им права на манипуляции какими-то файлами.

Весь список групп хранится в файлике /etc/group, можно посмотреть его:

cat /etc/group

кстати часто бывают файлы которые не влазят на один экран, да что там, они не влазят даже в одну консоль (дело в том, что количество строк, которые могут отображаться в консоли даже через скролл ограничено)

Для таких целей есть еще одна команда которая позволяет выводить файл не весь целиком а как будто вы создали мини консольку со скроллом внутри настоящей консоли со скроллом =)

less /etc/group

Это очень полезная команда, с помощью нее можно спокойно открывать файлы, которые весят десятки гигабайт. Тут только вопрос зачем вам такие файлы открывать? =) На самом деле с логами такое часто бывает, так что пригодится

выйти из нее можно так же как из man, через нажатие клавиши q

Делаем файл исполняемым

Ну что-то я отвлекся. Вернемся к нашему желанию сделать файл исполняемым. Для того чтобы сделать файл исполняемым надо добавить ему флаг x делается это так

chmod +x create_git_project.sh

но тут сразу надо глянуть что возможность выполнять файл мы добавили всем и юзеру (user) и группе (group) и остальным пользователям (other).

Давайте запретим другим пользователям запускать этот файл. Для этого надо вместо +x использовать -x и чтобы убрать флаг только у остальным пользователей надо добавить букву o от слова other

chmod o-x create_git_project.sh

так, ну ладно, исполняемым файла мы сделали. Запускать то как?

А тут все просто, мы теперь вместо того чтобы писать bash имя_файла просто пишем

./create_git_project.sh

только не забудьте удалить папку new_project

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

Работаем с входными параметрами

Давайте теперь улучшим нашу команду и добавим ей возможность указывать название проекта. Для этого в bash есть возможность передать параметры скрипту, а скрипту в свою очередь подхватить их. Обращаться к параметрам можно через знак доллара $

Подправим наш скрипт

echo $0
echo $1
echo $2
exit 0 # добавил выход из скрипта чтобы не создавать пока проект

mkdir new_project
cd new_project
git init
touch README.md
git add README.md
git commit -a -m "первый коммит"

и глянем что это выдаст

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

echo "Ваша программа называется: $0"
echo "Ваш первый параметр: $1"
echo "Ваш второй параметр: $2"
exit 0

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

при необходимости можно вводить и переменные:

echo "Ваша программа называется: $0"
echo "Ваш первый параметр: $1"
echo "Ваш второй параметр: $2"

# тут важный момент, после название переменной не должно быть пробела
my_var="первый: $1 второй: $2" 

# переменную вставляют в текст оборачивая в ${}
echo "Значение my_var = ${my_var}"

exit 0

проверяем:

Ну и очевидно вы можете передать значение переменной или аргумента в качестве параметра другой команде

echo "Ваша программа называется: $0"
echo "Ваш первый параметр: $1"
echo "Ваш второй параметр: $2"

my_var="первый: $1 второй: $2"
echo "Значение my_var = ${my_var}"

new_folder_name="project_$1"

# при обращении к переменной надо добавлять ей знак доллара
mkdir $new_folder_name

exit 0

запускаем, должна создаться папка с именем project_123:

красота =)

Пишем значения переменных в файл

Ну и вишенка на торте! Вы можете значения переменных записывать в файл. Для этого используется оператор потока >

Работает так:

new_folder_name="project_$1"
mkdir $new_folder_name

text="Значение второй переменной $2"

# то есть echo $text > можно проинтерпретировать как
# запиши в файл "${new_folder_name}/README.md" значение $text
# кстати файл не обязательно создавать заранее, он будет создан автоматом
echo $text > "${new_folder_name}/README.md"

exit 0

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

new_folder_name="project_$1"
mkdir $new_folder_name

text="
Всем привет! =) \n\
Вот вам значение второй переменной: $2
"

# и тут добавляем флаг -e
echo -e $text > "${new_folder_name}/README.md"

exit 0

Ну и все теперь можно задание пилить

1.3

Доделать скрипт из подсказки.

  • скрипт должен принимать на вход название проекта
  • при запуске скрипта в директории ~/projects должна создаться папка с названием проекта
  • скрипт должен работать из любой папки, то есть если вы запустите скрипт из папки /home/m, то папка с названием проекта все равно должна создаться в папке ~/projects
  • внутри файла README.md должен быть заголовок, в котором будет указано название проекта. А также текст, который вы загоняли вручную в прошлом задании
  • По желанию, добавьте в README.md немного ASCII графики https://manytools.org/hacker-tools/ascii-banner/