Обычный файл архива требует отдельной программы (например tar, gunzip) для извлечения контента из архива, самораспаковывающийся (SFX) архив сам является исполняемым, и может сам извлекать свой контент при запуске. Самораспаковывающийся же инсталлятор делает то же самое, но при этом копирует извлекаемые файлы в соответствующие каталоги. То есть инсталлятор, это самораспаковывающийся архив с добавленным скриптом-исталлятором.
Создание SFX-инсталлера.
Первым делом нужно создать tar-архив с устанавливаемыми файлами. При чём tar-архив может содержать как файлы, так и каталоги содержащие в себе файлы. Это можно сделать при помощи следующей команды:
tar cf files.tar *
Для создания архива служит опция с. В сочетании с опцией f опция с приводит к созданию архива в файле или на устройстве. Опция c ставится непосредственно перед опцией f. Обратите внимание, что дефиса перед опцией нет.
files.tar - название создаваемого архива с расширением .tar
Далее следует символ "*", который указывает утилите tar включить в архив все без исключения файлы и каталоги, находящиеся в каталоге, в котором дана эта команда.
Для примера создадим архив с файлами русифицирующими дистрибутив Slackware.
Основным русифицирующим файлом дистрибутива Slackware является файл lang.sh, который находится в каталоге /etc/profile.d
Именно в нём объявляется русская локаль в кодировке utf-8.
Выглядит этот скрипт в упрощенном варианте так:
#!/bin/sh
export LANG=ru_RU.UTF-8
export LC_COLLATE=C
Я использую полную версию скрипта, хотя вполне хватает и приведённого примера выше. Мой скрипт:
#!/bin/sh[/font]
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ Russian locale ║
#╚═════════════════════════════════════════════════════════════════════════════╝
export LC_ALL=
export LANG=ru_RU.UTF-8 # определяет языковую локаль системы
export LC_CTYPE=ru_RU.UTF-8 # определяет одиночные символы и тип символа (буква, цифра,...)
export LC_NUMERIC=C # формат чисел
export LC_TIME=ru_RU.UTF-8 # формат времени
export LC_COLLATE=C # используется для сравнения строк
export LC_MONETARY=ru_RU.UTF-8 # валюта
export LC_MESSAGES=ru_RU.UTF-8 # системные сообщения
export LC_PAPER=ru_RU.UTF-8 # формат бумаги
export LC_NAME=ru_RU.UTF-8 # формат имён
export LC_ADDRESS=ru_RU.UTF-8 # формат адресов
export LC_TELEPHONE=ru_RU.UTF-8 # формат телефонов
export LC_MEASUREMENT=ru_RU.UTF-8 # формат измерений
export LC_IDENTIFICATION=ru_RU.UTF-8 # идентификация
export LESSCHARSET=UTF-8 # Эта команда решает некоторые проблемы связанные с man
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ End scripts ║
#╚═════════════════════════════════════════════════════════════════════════════╝
Следующий скрипт rc.font подключает шрифт с кириллическими символами и находится в каталоге /etc/rc.d/
[font=Courier New]#!/bin/sh
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ Russian fonts ║
#╚═════════════════════════════════════════════════════════════════════════════╝
setfont LatArCyrHeb-16
for i in 1 2 3 4 5 6; do
echo -ne "\033%G" > /dev/tty$i
done
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ End scripts ║
#╚═════════════════════════════════════════════════════════════════════════════╝
Третий скрипт - rc.keymap, даёт нам возможность переключать раскладки клавиатуры между английской и русской и находится в том же каталоге /etc/rc.d/
#!/bin/sh
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ Load the keyboard map. More maps are in /usr/share/kbd/keymaps. ║
#╚═════════════════════════════════════════════════════════════════════════════╝
if [ -x /usr/bin/loadkeys ]; then
/usr/bin/loadkeys /usr/share/kbd/keymaps/i386/qwerty/ruwin_ct_sh-UTF-8.map.gz
fi
#╔═════════════════════════════════════════════════════════════════════════════╗
#║ End scripts ║
#╚═════════════════════════════════════════════════════════════════════════════╝
С файлами и каталогами мы определились, теперь создадим tar-архив из этих файлов.
Для начала разместим их в рабочем каталоге, в котором будет создаваться архив.
Создаём рабочий каталог:
mkdir -p $HOME/installer/payload
Каталог payload и будет отправной точкой для создания архивируемых скриптов с каталогами и в нём же будет создан tar-архив.
Создаём дерево архивируемых каталогов в рабочем каталоге payload:
mkdir -p $HOME/installer/payload/etc/profile.d
mkdir -p $HOME/installer/payload/etc/rc.d
Каталоги созданы, теперь нужно поместить в них устанавливаемые файлы. Можно сделать это с помощью файл менеджера midnight commander, а можно и с помощью команд в консоли. Я скопирую свои готовые файлы из системы:
cp /etc/profile.d/lang.sh $HOME/installer/payload/etc/profile.d
cp /etc/rc.d/rc.font $HOME/installer/payload/etc/rc.d
cp /etc/rc.d/rc.keymap $HOME/installer/payload/etc/rc.d
Всё, каталоги созданы, файлы скопированы можно создавать tar-архив:
cd $HOME/installer/payload/ # Переход в рабочий каталог
tar cf files.tar * # Создаём tar-архив
Всё архив создан. Удаляем каталог /etc с вложенными файлами и каталогами из рабочего каталога payload, они нам больше не нужны:
rm -rf $HOME/installer/payload/etc
Таким образом, в каталоге $HOME/installer/payload остался созданный нами для инсталляции tar-архив files.tar.
Следующим шагом будет создание скрипта-инсталлера, который разархивирует архив с файлами в корневой каталог системы, установив таким образом файлы на свои места. Скрипт будет такого содержания:
#!/bin/bash
echo "Running Installer"
tar xvf ./files.tar -C /
Что же делает этот скрипт? После вывода на экран сообщения "Running Installer", он разархивирует архив в корень системы, что предписывается знаком "/" в конце строки. Если вы хотите разархивировать архив в другой каталог, так и пропишите вместо символа "/" путь к каталогу. У команды tar есть отличная опция "С" после которой нужно указать путь куда нужно разархивировать контент архива. Допустим, у вас есть каталог /home/other/work и вы хотите архив распаковать именно туда. Тогда команда будет выглядеть так:
tar xvf ./files.tar -C /home/other/work
Если каталога не существует, но вы всё равно хотите распаковать именно в него, то можно обязать скрипт инсталлер предварительно его создать, вписав в инсталлер команду:
mkdir -p /home/other/work
Опция "-p" предписывает команде mkdir создавать промежуточные каталоги.
В окончательном варианте, с придуманными мной изменениями, скрипт installer может выглядеть так:
#!/bin/bash
echo "Running Installer"
mkdir -p /home/other/work
tar xvf ./files.tar -C /home/other/work
Пример с изменениями приведён для того, что бы показать гибкость этого метода и возможность установки файлов с любого каталога и в любой же каталог.
В следующем пункте нам нужно объединить уже созданный архив files.tar и скрипт-инсталлер installer в ещё один tar-архив с названием payload.tar. Именно этот архив будет входить в тело скрипта-распаковщика.
Алгоритм прост - при запуске скрипта-распаковщика он отделяет от себя сжатый архив и разархивирует с декомпрессией его во временной каталог. Во временном каталоге у нас будут разархивированы tar-архив files.tar и скрипт installer. Затем будет передано управление скрипту installer, который установит наши файлы туда, куда мы их хотели установить. И после установки временной каталог с содержимым будет удалён. Ну, я немного забежал наперёд...
Итак, идём дальше... Объединяем архив files.tar и скрипт installer в новый tar-архив с помощью команды:
cd $HOME/installer/payload/ # Переходим в payload
tar cf ../payload.tar ./* # Создаем payload.tar в каталоге $HOME/installer/
Заметьте, tar-архив payload.tar помещён в каталоге выше! Этого мы добились указанием относительного пути "../" перед названием tar-архива.
Теперь мы его сожмём компрессором xz со страшной силой с помощью такой команды:
cd $HOME/installer # Переход в каталог выше
export XZ_OPT="-9 --extreme"; xz -z payload.tar
Теперь самое время показать скрипт decompress. Его нужно создать в каталоге $HOME/installer/ рядом с созданным архивом payload.tar:
#!/bin/bash
echo ""
echo "Self Extracting Installer"
echo ""
export TMPDIR=`mktemp -d /tmp/selfextract.XXXXXX`
ARCHIVE=`awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0; }' $0`
echo "$0"
tail -n+$ARCHIVE $0 | tar -xv -J -C $TMPDIR
CDIR=`pwd`
cd $TMPDIR
./installer
cd $CDIR
rm -rf $TMPDIR
exit 0
__ARCHIVE_BELOW__
Вкратце, что делает этот скрипт:
1. Выводит сообщение "Self Extracting Installer"
2. Создаёт временной каталог /tmp/selfextract.XXXXXX, где "XXXXXX" случайный набор символов для его неповторимости и уникальности.
3. Отделяет от своего тела сжатый tar-архив payload.tar.xz и разархивирует его во временной каталог /tmp/selfextract.XXXXXX.
4. Вызывает скрипт installer
5. После окончания установки файлов, удаляет временной каталог /tmp/selfextract.XXXXXX.
И последнее, создаём самораспаковывающийся архив-инсталлятор командой:
cat decompress payload.tar.xz > selfextract.sfx
Все скрипты и самораспаковывающийся архив-инсталлятор selfextract.sfx нужно сделать исполняемыми, как то так:
chmod +x selfextract.sfx
В качестве примера можно скачать созданный мною самораспаковывающийся инсталлятор. После установки у вас будет каталог со скриптами для создания своих установщиков пакетов.
Скачать sfx-install.sfx