7 декабря 2010 г.

Файлы внутри скриптов или deploy на bash'е

Одним из интересных свойств bash-скриптов является то, что в них можно запихивать файлы, которые затем сам скрипт будет из себя извлекать при запуске. Таким образом, например, устроены скрипты установки JRE и JDK для Linux. Используя это свойство, можно довольно легко создавать скрипты для автоматизированного развертывания каких-либо систем, библиотек и т.п.. Приведу примеры извлечения текстовых и бинарных данных из bash-скриптов.


Скрипты внутри скриптов

Используя команду cat, из выполняющегося скрипта можно вытащить любые данные, которые находятся между вызовом cat и какой-либо текстовой меткой. Это удобно использовать в первую очередь для извлечения текстовых данных, например скриптов. Т.е. можно создавать bash-скрипты, которые при выполнении сами будут создавать различные скрипты, причем используя переменные можно добиться хорошей гибкости.

Простой пример скрипта создающего другие скрипты:
#!/bin/bash

# Каталог для развертывания
DEPLOY_PATH="./scripts/inner-scripts"
# Имя первого вложенного скрипта
FIRST_SCRIPT_NAME="script-inner-1.sh"
# Имя второго вложенного скрипта
SECOND_SCRIPT_NAME="script-inner-2.sh"

echo "Развертывание вложенных скриптов"

# Создание каталога для развертывания если его нет
if [ ! -d $DEPLOY_PATH ]
then
    echo "Создание каталога $DEPLOY_PATH"
    mkdir -p $DEPLOY_PATH
fi

cd $DEPLOY_PATH

echo "Создание скрипта $FIRST_SCRIPT_NAME"

# Извлечение текста между вызовом cat и первой меткой _EOF_
cat  > ./$FIRST_SCRIPT_NAME << _EOF_
#!/bin/bash
# первый вложенный скрипт
echo "Первый скрипт запущен!"
echo "Запуск второго скрипта..."
./$SECOND_SCRIPT_NAME
_EOF_

echo "Создание скрипта $SECOND_SCRIPT_NAME"

# Извлечение текста между вызовом cat и второй меткой _EOF_
cat > ./$SECOND_SCRIPT_NAME << _EOF_
#!/bin/bash
# второй вложенный скрипт
echo "Второй скрипт запущен!"
_EOF_

# Установка прав на выполнение скриптов
chmod 755 $FIRST_SCRIPT_NAME $SECOND_SCRIPT_NAME

echo "Развертывание скриптов закончено!"
Приведенный код создаст два скрипта, причем первый скрипт будет запускать второй скрипт при выполнении.

Бинарные файлы внутри скриптов

Помимо текстовых данных из скрипта можно извлекать предварительно записанные в них бинарные файлы, например архивы. Особенность при создании такого скрипта в том, что сначала надо написать сам скрипт, а потом с помощью команды cat загнать в него необходимый файл. Пример скрипта, который извлекает из себя архив с jar-файлами, распаковывает его и удаляет архив:
#!/bin/bash

DEPLOY_PATH="./libs/jar/odfdom-simple"
ARCH_NAME="odfdom-libs.tar.gz"

echo "Развертывание библиотек ODFDOM"

# Создание каталога если его нет
if [ ! -d $DEPLOY_PATH ]
then
    echo "Создание каталога $DEPLOY_PATH"
    mkdir -p $DEPLOY_PATH
fi

echo "Создание скрипта $FIRST_SCRIPT_NAME"
# Вытаскиваем архив из скрипта (начиная с 30-й строки до конца скрипта)
tail -n +30 "$0" > $DEPLOY_PATH/$ARCH_NAME

cd $DEPLOY_PATH

# Распаковка архива
tar xzf $ARCH_NAME

# Удаление архива
rm -f $ARCH_NAME

# Выход из программы с кодом 0
exit 0
##################################################################
# 30-я строка; здесь начнутся бинарные данные; эту строку включать в скрипт не надо
После того, как будет написана последовательность команд скрипта, необходимо в конце вставить пустую строку, сохранить скрипт и выполнить в терминале нечто вроде:

cat my_arch.tar.gz >> my_script.sh

После выполнения этой команды архив my_arch.tar.gz станет частью скрипта my_script.sh. Для извлечения архива в приведенном примере используется команда tail -n +30 "$0" > $DEPLOY_PATH/$ARCH_NAME, которая в данном случае извлекает бинарные данные и перенаправляет вывод в файл ./libs/jar/odfdom-simple/odfdom-libs.tar.gz. Параметр -n +30 означает, что выводить данные надо начиная с 30 строки файла, а под "$0" скрывается имя выполняющегося скрипта.

После того как данные извлечены, можно распаковывать архив, распихивать файлы по каталогам, создавать симлинки и в общем делать всё, что нужно для развертывания вашей системы. Самое главное не забудьте вызвать команду exit до того, как начнутся бинарные данные, иначе bash попытается выполнить и их :)

Комментариев нет:

Отправить комментарий