Консоль в массы. Переход на светлую сторону. Автоматизация рутинных задач

в 4:29, , рубрики: bash, front-end разработка, screen, terminal, tmux, wsd, отладка, Разработка веб-сайтов, системное программирование, Совершенный код

routine tasks automation

Введение

Машины всегда будут быстрее, независимо от того насколько мы продуктивны и как быстро мы набираем команды. Суровая правда жизни. С другой стороны, если мы выполняем одно и тоже действие множество раз, то почему бы не заставить машины страдать. Написать скрипт на bash (ваш любимый язык программирования) и каждый раз вызывать этот скрипт, а не набирать монотонные команды, которые забирают так много времени, сил и энергии. А мы, пока скрипт будет выполнять свою работу, можем помечтать о том, как космические корабли бороздят просторы нашей Вселенной.

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

План автоматизации

  1. Быстрый diff
  2. Быстрый diff + Jira API
  3. Очистка _dist
  4. Up большого числа репозиториев
  5. Клонирование большого числа репозиториев
  6. Полезные алиасы

В этот список попали задачи, которые я выполняю ежедневно несколько раз в день, а то и в час. Вообще, автоматизация рутинных процессов — это творческий и сугубо личный процесс. Автоматизировать можно все, что вы только можете придумать. Надеюсь, что в конце статьи у вас появится свой план по автоматизации и вы заставите машины страдать. Сделайте себе чашечку ароматного кофе и усаживайтесь поудобней. Вас ждет увлекательное путешествие в мир автоматизации средствами bash.

Быстрый diff

В своей работе на проекте мы используем Git. Создание diff является довольно частой задачей. Чтобы создать diff для конкретной ветки нужно выполнить следующую команду:

git diff origin/master origin/<branch-name> > "${HOME}/diff/diff-<branch-name>.diff"

<branch-name> — имя ветки для которой нужно создать diff

Недостатки данного подхода

  1. Каждый раз команду нужно набирать вручную
  2. Большая вероятность ошибки в процессе набора
  3. Сложно запомнить

Эти недостатки можно с легкостью решить при помощи bash. В идеале все должно работать так:

  1. Набрали команду
  2. Передали ей имя ветки
  3. Получили diff

Финальный вид команды

gdd <branch-name>

Автоматизируем

Теперь вместо длинной строки команд, достаточно набрать на клавиатуре ./fast_diff.sh <branch-name>. Если забыли указать имя ветки, нам об этом любезно сообщит данный скрипт.

Финальный штрих

Стоп, скажете вы. А как же финальный вид команды. Ведь в текущем виде данный скрипт не очень удобен, мы привязаны к директории в которой он находится.

Рассмотрим более подробно как сделать для исполняемого файла отдельную команду, а не писать к нему каждый раз относительный/абсолютный путь.

У каждого пользователя в его домашней директории (~) располагается поддиректория bin. Если такой нет, то ее можно создать. В ней могут хранится исполняемые файлы. Удобство заключается в том, что такие файлы доступны по имени и к ним не нужно указывать относительный/абсолютный путь. В эту директорию я поместил файл gdd, который отвечает за создание diff:

#!/bin/bash

"${HOME}/htdocs/rybka/tools/fast_diff.sh" "$@"

Два важных момента:

  1. У файла не должно быть расширения
  2. Для файла нужно явно указать атрибут x (chmod +x <filename>).

Для того, чтобы этот файл стал доступным, перезапустите терминал. Теперь, чтобы создать diff, достаточно выполнить следующую команду:

gdd <branch-name>

Быстрый diff + Jira API

Если вы используете в своей работе менеджер задач Jira или любой другой менеджер задач, который предоставляет API, то можно пойти еще дальше. К примеру, можно с помощью Jira API прикреплять diff к конкретной задаче. Для этого нам понадобится еще и cURL.

Алгоритм решения

  1. Вызываем скрипт
  2. Передаем id задачи
  3. Если id задачи не передано, выводим сообщение пользователю
  4. Если все верно, генерируем diff и прикрепляем его к задаче

Финальный вид команды

gdd_jira <issue_id>

Автоматизируем

Как вы могли заметить, имя ветки не нужно указывать. Ее мы получаем при помощи нехитрых манипуляций с командами git:

branch=$(git rev-parse --abbrev-ref HEAD)

Очистка _dist

Для начала, давайте разберемся за что отвечает директория _dist. Это место, куда попадают файлы CSS, JavaScript, всевозможные шаблоны (Jade/Pug, Handlebars, др.) и прочие файлы после запуска системы сборки (Grunt, Gulp, др.). Эта директория не обязательно должна называться _dist. Возможны вариации.
Очистка _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.

Алгоритм решения

  1. Вызываем скрипт
  2. Если название темы не было передано, удаляем директорию _dist во всех темах
  3. Если имя темы было передано, выполняем удаление директории _dist в конкретной теме

Финальный вид команды

clean_dist [<theme_name>]

Автоматизируем

Up большого числа репозиториев

Up большого числа репозиториев
Представьте, что вы работаете с большим проектом. В этом проекте есть директория, отведенная под сторонние репозитории, которые вы не разрабатываете, но поддерживать их в актуальном состоянии обязаны. Конечно, если этих репозиториев два-три, то это не такая большая проблема. Хотя и тут я бы поспорил. А если у вас таких репозиториев 10-15, и эта цифра постоянно растет. В результате вы не успеваете за ними следить или тратите несоизмеримо много времени на поддержку. Почему бы эту задачу не автоматизировать.

Алгоритм решения

  1. Перейти в директорию с репозиторием
  2. Проверить, чтобы репозиторий был на ветке master
  3. Если репозиторий не на ветке master, сделать git checkout
  4. Сделать git pull

Важный момент. Даже, если репозиторий находится на ветке master, мы не можем быть уверены, что он в актуальном состоянии. Исходя из этого, делаем git pull в любом случае.

Финальный вид команды

up_repo

Автоматизируем

Клонирование большого числа репозиториев

Данная задача тесно связана с предыдущим пунктом автоматизации. Чтобы конечный пользователь имел возможность воспользоваться предыдущей командой на практике, необходимо предоставить набор репозиториев сторонних разработчиков, которые будут располагаться в директории bash/core/vendors, и о которых пользователю, по большому счету, не нужно ничего знать. По аналогии с npm модулями этот набор репозиториев не должен поставляться вместе с основным репозиторием. Все что нужно сделать пользователю — это выполнить команду и дождаться завершения клонирования репозиториев.

Алгоритм решения

  1. Список репозиториев задан в виде массива
  2. Запускаем цикл по этому массиву
  3. Уделяем особое внимание, если один вендор имеет больше одного репозитория
  4. Выполняем дополнительные проверки
  5. Выполняем git clone

Финальный вид команды

clone_repo

Автоматизируем

Полезные алиасы

У меня есть несколько вопросов к читателям. Вы должны ответить честно самому себе. Как часто вы используете эту команду?

git branch

А эту команду?

git status

А вот эту команду?

git push origin <branch-name>

Как насчет этой команды?

ps aux | grep <user-name>

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

Aliases

Правильно. Для команд, которые вы используете часто — создавайте алиасы. Вот лишь небольшой список тех алиасов, что я использую:

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

alias showaliases='cat $HOME/.bashrc | grep alias'

Куда поместить алиасы

В большинстве случаев для таких целей используют файл .bashrc, который располагается в домашней директории пользователя. Еще есть файл под названием .gitconfig, в который можно добавлять алиасы для работы с git.

Не стоит менять алиасы поздно ночью

Алиасы — это мощный инструмент. Только тут как с паролями. Не стоит менять алиасы поздно ночью. В одну прекрасную ночь, я поменял один из алиасов и забыл. На следующий день я потратил полдня, разбираясь почему ничего не работает.

Вместо заключения

Как только я начал разбираться с основами программирования на bash, первая мысль, которая меня посетила: «Стоп, это же нужно больше для системных администраторов...». Но в то же время, я понимал, что мне нужны эти знания, чтобы хоть как-то избавить себя от ежедневных рутинных задач. Сейчас я могу с уверенностью сказать, что эти знания нужны не только системным администраторам. Они пригодятся всем, кто хоть как-то взаимодействует с удаленным сервером или работает на OS *nix подобных системах. Для пользователей, которые работают на Windows OS эти знания тоже пригодятся (Bash on Ubuntu on Windows, Windows and Ubuntu Interoperability). В простейшем случае, скрипт — это ни что иное, как простой список команд системы, записанный в файл. Такой файл может облегчить вам рабочие будни и избавит от необходимости выполнять рутинные задачи вручную.

Полезные ссылки по некоторым возможностям bash, которые были использованы в примерах:

  1. Перенаправление ввода/вывода
  2. Функции
  3. Массивы
  4. Двойные круглые скобки
  5. Объединение команд в цепочки (конвейер)
  6. Завершение и код завершения
  7. Псевдонимы

На этом все. Спасибо за внимание. Кто дочитал до конца, отдельное спасибо.

Автор: var_bin

Источник

Поделиться

* - обязательные к заполнению поля