Знаете ли вы, что внутрь 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