Знаете ли вы, что внутрь schell-скрипта можно записать бинарные данные? Я, до недавнего времени, об этом не знал и наткнулся на эту возможность, когда искал способы инсталляции Java-приложения на *nix-сервере.
Администраторы и гики поклоняющиеся *nix-системам наверняка подумают, что я несу чепуху, ведь уже давно изобретен велосипед – rpm. Спешу вас расстоить – рассматривал этот вариант и он, к сожалению, не способен решить всех моих задач.
А задачи следующие:
- хочется иметь возможность собирать пакет на любой платформе: Windows, *nix
- инсталлятору хочется передавать параметры: путь установки, энвайронмент и т.д.
- для установки rpm требуется root-доступ, обычно такого не бывает
- кроме всего этого надо вкурить в spec-файл (Creating the Spec file)
Исходя из этого инсталлятор на shell-скрипте намного проще и предоставляет большую гибкость:
- это простостой файл, который содержит скрипт установки и приложение в виде, например, tar-архива
- такой файл можно создать на любой платформе
- можно передавать какие душе угодно параметры
- заложить любую логику по установке (rpm это тоже позволяет, там внутри тоже shell-скрипт)
- с программированием на shell знакомы, как правило, все Java разработчики
- очень много информации по shell для решения любых проблем
Для создания инсталлятора нам потребуется:
- исталлятор
- архив приложения
#!/bin/bash EXTRACT_PATH=$1 function extract() { PAYLOAD_START=$(grep --text --line-number '^==================== PAYLOAD START ====================$' $0 | cut -d ':' -f 1) PAYLOAD_START=$((PAYLOAD_START + 1)) tail -n +$PAYLOAD_START $0 | tar -xvf - -C $1 } extract ${EXTRACT_PATH} exit 0 ==================== PAYLOAD START ====================
Этот скрипт ищет положение разделителя (==================== PAYLOAD START ====================), считывает все, что находится после него, прогоняет через tar и все. В данной версии после разделителя обязательно должен быть символ новой строки, чтобы бинарные данные начинались со следующей строки.
Склеить инсталлятор и архив прилижения можно вот таким Ant-скритом:
<?xml version="1.0" encoding="UTF-8"?> <project name="Create installer" default="installer" basedir="."> <property name="target" location="target"/> <property name="target.installer" location="${target}/installer"/> <property name="installer" location="<path to installer>"/> <property name="package" location="<path to package>"/> <target name="installer"> <mkdir dir="${target}"/> <mkdir dir="${target.installer}"/> <copy file="${installer}" todir="${target.installer}" /> <fixcrlf eol="unix" srcdir="${target.installer}" includes="installer.sh"/> <concat destfile="${target.installer}/package-installer.sh"> <filelist> <file name="${target.installer}/installer.sh"/> <file name="${package}"/> </filelist> </concat> </target> </project>
Пример использования:
./package-installer.sh ./app