Введение
Машины всегда будут быстрее, независимо от того насколько мы продуктивны и как быстро мы набираем команды. Суровая правда жизни. С другой стороны, если мы выполняем одно и тоже действие множество раз, то почему бы не заставить машины страдать. Написать скрипт на
bash
(ваш любимый язык программирования) и каждый раз вызывать этот скрипт, а не набирать монотонные команды, которые забирают так много времени, сил и энергии. А мы, пока скрипт будет выполнять свою работу, можем помечтать о том, как космические корабли бороздят просторы нашей Вселенной.В прошлой статье мы рассмотрели основы программирования на
bash
. Сегодня мы будем применять полученные знания на практике.План автоматизации
- Быстрый
diff
- Быстрый
diff
+ Jira API - Очистка
_dist
- Up большого числа репозиториев
- Клонирование большого числа репозиториев
- Полезные алиасы
В этот список попали задачи, которые я выполняю ежедневно несколько раз в день, а то и в час. Вообще, автоматизация рутинных процессов — это творческий и сугубо личный процесс.
Автоматизировать можно все, что вы только можете придумать. Надеюсь, что в конце статьи у вас появится свой план по автоматизации и вы заставите машины страдать. Сделайте себе чашечку ароматного кофе и усаживайтесь поудобней. Вас ждет увлекательное путешествие в мир автоматизации средствами
bash
.Быстрый diff
В своей работе на проекте мы используем Git. Создание
diff
является довольно частой задачей. Чтобы создать diff
для конкретной ветки нужно выполнить следующую команду:git diff origin/master origin/<branch-name> > "${HOME}/diff/diff-<branch-name>.diff"
<branch-name>
— имя ветки для которой нужно создать diff
Недостатки данного подхода
- Каждый раз команду нужно набирать вручную
- Большая вероятность ошибки в процессе набора
- Сложно запомнить
Эти недостатки можно с легкостью решить при помощи
bash
. В идеале все должно работать так:- Набрали команду
- Передали ей имя ветки
- Получили
diff
Финальный вид команды
gdd <branch-name>
Автоматизируем
Теперь вместо длинной строки команд, достаточно набрать на клавиатуре
./fast_diff.sh <branch-name>
. Если забыли указать имя ветки, нам об этом любезно сообщит данный скрипт.Финальный штрих
Стоп, скажете вы. А как же финальный вид команды. Ведь в текущем виде данный скрипт не очень удобен, мы привязаны к директории в которой он находится.
Рассмотрим более подробно как сделать для исполняемого файла отдельную команду, а не писать к нему каждый раз относительный/абсолютный путь.
У каждого пользователя в его домашней директории (
~
) располагается поддиректория bin
. Если такой нет, то ее можно создать. В ней могут хранится исполняемые файлы. Удобство заключается в том, что такие файлы доступны по имени и к ним не нужно указывать относительный/абсолютный путь. В эту директорию я поместил файл gdd
, который отвечает за создание diff
:#!/bin/bash
"${HOME}/htdocs/rybka/tools/fast_diff.sh" "$@"
Несколько важных моментов:
- У файла не принято указывать расширение.
- Для файла нужно явно указать атрибут
x (chmod +x <filename>)
.
- Если директория
bin
не находится в переменной$PATH
, нужно добавить ее явноPATH="${PATH}:${HOME}/bin"
.
Для того, чтобы этот файл стал доступным, перезапустите терминал. Теперь, чтобы создать
diff
, достаточно выполнить следующую команду:gdd <branch-name>
Не очень удобно все время создавать отдельный файл в директории
bin
для каждой команды. Мы можем это оптимизировать воспользовавшись символическими ссылками:ln -s "${HOME}/htdocs/rybka/tools/fast_diff.sh" gdd
Быстрый diff + Jira API
Если вы используете в своей работе менеджер задач Jira или любой другой менеджер задач, который предоставляет API, то можно пойти еще дальше. К примеру, можно с помощью Jira API прикреплять
diff
к конкретной задаче. Для этого нам понадобится еще и cURL.Алгоритм решения
- Вызываем скрипт
- Передаем
id
задачи - Если
id
задачи не передано, выводим сообщение пользователю - Если все верно, генерируем
diff
и прикрепляем его к задаче
Финальный вид команды
gdd_jira <issue_id>
Автоматизируем
Как вы могли заметить, имя ветки не нужно указывать. Ее мы получаем при помощи нехитрых манипуляций с командами git:
branch=$(git rev-parse --abbrev-ref HEAD)
Очистка _dist
Для начала, давайте разберемся за что отвечает директория
_dist
. Это место, куда попадают файлы CSS
, JavaScript
, всевозможные шаблоны (Jade/Pug, Handlebars, др.) и прочие файлы после запуска системы сборки (Grunt, Gulp, др.). Эта директория не обязательно должна называться _dist
. Возможны вариации.Для одного из проектов мы используем Grunt. Довольно часто наша команда сталкивается с проблемой, что Grunt не всегда замечает изменения в некоторых файлах (проблема в основном, с Less файлами). Чтобы исправить эту ситуацию нужно очистить директорию
_dist
для одной из тем или для всех тем сразу. Да, данную задачу можно решить и с помощью Grunt. Даже можно все время удалять данную директорию вручную. Но это будет не так эффективно и удобно, как в случае с bash
. Количество этих директорий (_dist
) не одна и не две, и даже не десять или двадцать. Их много. Основное требование к скрипту — не применять лишние обертки и/или зависимости без необходимости.Рассмотрим вариант без применения
bash
. Используем всю мощь оболочки для решения этой задачи:find <path-to-themes> -type d -name "_dist" | xargs rm -rfv
<path-to-themes>
— путь к директории, где находятся все темыНедостатки у данного подхода примерно те же, что я приводил и в случае с задачей по созданию
diff
. Плюс ко всему в данном случае нет возможности указывать для какой конкретно темы нужно удалить директорию _dist
.Алгоритм решения
- Вызываем скрипт
- Если название темы не было передано, удаляем директорию
_dist
во всех темах - Если имя темы было передано, выполняем удаление директории
_dist
в конкретной теме
Финальный вид команды
clean_dist [<theme_name>]
Автоматизируем
Up большого числа репозиториев
Представьте, что вы работаете с большим проектом. В этом проекте есть директория, отведенная под сторонние репозитории, которые вы не разрабатываете, но поддерживать их в актуальном состоянии обязаны. Конечно, если этих репозиториев два-три, то это не такая большая проблема. Хотя и тут я бы поспорил. А если у вас таких репозиториев 10-15, и эта цифра постоянно растет. В результате вы не успеваете за ними следить или тратите несоизмеримо много времени на поддержку. Почему бы эту задачу не автоматизировать.
Алгоритм решения
- Перейти в директорию с репозиторием
- Проверить, чтобы репозиторий был на ветке
master
- Если репозиторий не на ветке
master
, сделатьgit checkout
- Сделать
git pull
Важный момент. Даже, если репозиторий находится на ветке
master
, мы не можем быть уверены, что он в актуальном состоянии. Исходя из этого, делаем git pull
в любом случае.Финальный вид команды
up_repo
Автоматизируем
Клонирование большого числа репозиториев
Данная задача тесно связана с предыдущим пунктом автоматизации. Чтобы конечный пользователь имел возможность воспользоваться предыдущей командой на практике, необходимо предоставить набор репозиториев сторонних разработчиков, которые будут располагаться в директории
bash/core/vendors
, и о которых пользователю, по большому счету, не нужно ничего знать. По аналогии с npm модулями этот набор репозиториев не должен поставляться вместе с основным репозиторием. Все что нужно сделать пользователю — это выполнить команду и дождаться завершения клонирования репозиториев.Алгоритм решения
- Список репозиториев задан в виде массива
- Запускаем цикл по этому массиву
- Уделяем особое внимание, если один вендор имеет больше одного репозитория
- Выполняем дополнительные проверки
- Выполняем
git clone
Финальный вид команды
clone_repo
Автоматизируем
Полезные алиасы
У меня есть несколько вопросов к читателям. Вы должны ответить честно самому себе. Как часто вы используете эту команду?
git branch
А эту команду?
git status
А вот эту команду?
git push origin <branch-name>
Как насчет этой команды?
ps aux | grep <user-name>
Все верно, этот список можно продолжать бесконечно и он у каждого свой. И тут, неожиданно, к нам приходит озарение:
Правильно. Для команд, которые вы используете часто — создавайте алиасы. Вот лишь небольшой список тех алиасов, что я использую:
Чтобы проверить какие алиасы у вас заданы, достаточно выполнить команду
alias
без параметров.Куда поместить алиасы
В большинстве случаев для таких целей используют файл
.bashrc
, который располагается в домашней директории пользователя. Еще есть файл под названием .gitconfig
, в который можно добавлять алиасы для работы с git
.Не стоит менять алиасы поздно ночью
Алиасы — это мощный инструмент. Только тут как с паролями. Не стоит менять алиасы поздно ночью. В одну прекрасную ночь, я поменял один из алиасов и забыл. На следующий день я потратил полдня, разбираясь почему ничего не работает.
Вместо заключения
Как только я начал разбираться с основами программирования на
bash
, первая мысль, которая меня посетила: «Стоп, это же нужно больше для системных администраторов...». Но в то же время, я понимал, что мне нужны эти знания, чтобы хоть как-то избавить себя от ежедневных рутинных задач. Сейчас я могу с уверенностью сказать, что эти знания нужны не только системным администраторам. Они пригодятся всем, кто хоть как-то взаимодействует с удаленным сервером или работает на OS *nix
подобных системах. Для пользователей, которые работают на Windows OS эти знания тоже пригодятся (Bash on Ubuntu on Windows, Windows and Ubuntu Interoperability). В простейшем случае, скрипт — это ни что иное, как простой список команд системы, записанный в файл. Такой файл может облегчить вам рабочие будни и избавит от необходимости выполнять рутинные задачи вручную.Полезные ссылки по некоторым возможностям
bash
, которые были использованы в примерах:- Перенаправление ввода/вывода
- Функции
- Массивы
- Двойные круглые скобки
- Объединение команд в цепочки (конвейер)
- Завершение и код завершения
- Псевдонимы
- Как правильно добавлять пути в переменную $PATH
На этом все. Спасибо за внимание. Кто дочитал до конца, отдельное спасибо.