Вступление
Здравствуйте. В этой статье я расскажу как засунуть любые данные в bash скрипт.
Засунуть текстовые данные в bash скрипт не составляет труда, т.к. скрипт сам является текстом. При попытке засунуть в скрипт бинарные данные возникает проблема с непечатаемыми символами. Данные могут содержать символы из синтаксиса языка и это может привести к неправильной работе скрипта.
Несмотря на наличие непечатаемых символов бинарные данные все таки можно поместить внутрь скрипта. Есть две пути:
1) использовать base64;
2) поместить данные в конец скрипта после команды выхода.
Второй способ используется в инсталяторе нвидии.
Попробуем сделать свой инсталятор.
Для примера я буду делать инсталятор для драйвера видеокарты семейства SIS M671/M672. Сам драйвер ставиться вот такими командами:
sudo apt-get install git xorg-dev mesa-common-dev libdrm-dev libtool
git clone git://github.com/hellnest/xf86-video-sismedia-0.9.1.git
cd xf86-video-sismedia-0.9.1/
./configure --prefix=/usr --disable-static
make && sudo make install
Плюс еще надо в xorg.conf записать
Section "Device"
Identifier "Configured Video Device"
Option "UseTiming1366" "yes"
EndSection
Section "Monitor"
Identifier "Configured Monitor"
EndSection
Section "Screen"
Identifier "Default Screen"
Monitor "Configured Monitor"
Device "Configured Video Device"
EndSection
Пишем скрипт
Сперва мы напишем скрипт. Поехали.
Проверяем свои права:
#! /bin/bash
ROOT_UID=0
E_NOTROOT=67
if [ "$UID" -ne "$ROOT_UID" ]
then
echo "Для работы сценария требуются права root."
exit $E_NOTROOT
fi
определяем переменные
skip=0000
installCMD='aptitude install'
xorgconfpath=/etc/X11/xorg.conf
xorgconf=XQAAAAL//////////wAFFctzCkzEu1LrBLc+0hvebMMmOEwhHZP3QZNzJWGEBNT1EwOr1Vf9jQxDHglWaEnyCGd2lQPMeKJZEDTaz1sUqpuB65Tfr0QxfWonNv6bcc1LsmIEJI+DJPJpLKwnd4fKdqVESxYA2UuwjrDLpqs27RiIHVhbBxQ8GNZzlHYRFLmncpgLyXkXrUCiR///4PwM4A==
Рассмотрим по подробнее переменные. Переменная skip содержит размер скрипта в байтах. Он нам понадобиться при распаковке данных, находящихся в конце скрипта, пока забъем 4 нулями. Переменная installCMD содержит команду для установки пакетов. xorgconfpath — путь к xorg.conf. Далее идет переменная xorgconf, он содержит данные файла xorg.conf, сжатый и закодированный в base64. Как закодировать в base64 и использовать читайте далее.
Base64
Упаковка
Чтобы работать с base64 есть одноименная утилита. Для наших целей необходимос использовать опцию
-w0
, это заставит выдавать данные одной строкой. Пример:
cat $filename | base64 -w0
. При этом можно и нужно использовать сжатие.
Пример со сжатием:
cat $filename | lzma -9 | base64 -w0
А использование утилиты tar позволяет упаковать даже директории.
Пример:
tar -c $dirname | lzma -9 | base64 -w0
В нашем инсталяторе строка xorgconf получена командой
cat xorg.conf | lzma -9 | base64 -w0
Распаковка
Распаковка данных идет в обратном упаковке порядке.
echo $string | base64 -d
echo $string | base64 -d | lzma -d
echo $string | base64 -d | lzma -d| tar -x
в нашем примере мы сделали распаковку вот так
function setconfig() {
echo $xorgconf|base64 -d|lzma -d > $xorgconfpath
}
Запись данных в конец скрипта
Сами исходники драйвера я решил засунуть в конец файла. Этот способ используется в инсталяторе от Nvidia.
Упаковка
Упаковка очень простая
cat $script_name $data_file > pack.run
В конец скрипта можно дописывать любое количество файлов. Но лучше дописывать 1 файл. При записи нескольких файлов вам понадобится хранить смещение и размер для каждого файла.
Распаковка
В данной статье я приведу пример распаковки только одного присоединенного файла. Для распаковки используется команда
dd if=$0 ibs=$skip skip=1 of=$filename
Так как я заранее упаковал исходники драйвера tar и lzma, то необходимо распаковать их
function extract() {
dd if=$0 ibs=$skip skip=1 2>/dev/null|lzma -d|tar -x
}
Завершение
Дополним скрипт вызовами наших функций и командами компиляции, установки и конфигурирования.
$installCMD xorg-dev mesa-common-dev libdrm-dev libtool
cd xf86-video-sismedia-0.9.1/ && ./configure --prefix=/usr --disable-static && make && make install && setconfig
cd ..
rm -rf xf86-video-sismedia-0.9.1
а всякий случай добавим команду, которая скачает драйвер, на случай, если конец окажется битым.
function download() {
(which git > /dev/null || $installCMD git) && git clone git://github.com/hellnest/xf86-video-sismedia-0.9.1.git
}
В конце необходимо добавить команду выхода иначе интерпретатор попытается выполнить наши данные.
Окончательный вид скрипта:
#! /bin/bash
ROOT_UID=0
E_NOTROOT=67
if [ "$UID" -ne "$ROOT_UID" ]
then
echo "Для работы сценария требуются права root."
exit $E_NOTROOT
fi
skip=0000
installCMD='aptitude install'
xorgconfpath=/etc/X11/xorg.conf
xorgconf=XQAAAAL//////////wAFFctzCkzEu1LrBLc+0hvebMMmOEwhHZP3QZNzJWGEBNT1EwOr1Vf9jQxDHglWaEnyCGd2lQPMeKJZEDTaz1sUqpuB65Tfr0QxfWonNv6bcc1LsmIEJI+DJPJpLKwnd4fKdqVESxYA2UuwjrDLpqs27RiIHVhbBxQ8GNZzlHYRFLmncpgLyXkXrUCiR///4PwM4A==
function extract() {
dd if=$0 ibs=$skip skip=1 2>/dev/null|lzma -d|tar -x
}
function download() {
(which git > /dev/null || $installCMD git) && git clone git://github.com/hellnest/xf86-video-sismedia-0.9.1.git
}
function setconfig() {
echo $xorgconf|base64 -d|lzma -d > $xorgconfpath
}
if [ "$1" == "-d" ]
then
download || extract
else
extract
fi
$installCMD xorg-dev mesa-common-dev libdrm-dev libtool
cd xf86-video-sismedia-0.9.1/ && ./configure --prefix=/usr --disable-static && make && make install && setconfig
cd ..
rm -rf xf86-video-sismedia-0.9.1
exit 0
После того как наш скрипт готов, нам необходимо записать правильное значение переменной skip. У меня получилось 1043 байта.
Теперь можно, после того как скрипт написан, а переменная skip указывает на рамер скрипта, можно сшивать скрипт и наши данные (упакованные исходники драйвера).
cat myscript.sh driver.tar.lzma > sisdriver.run
Заключение
Таким образом можно упаковать любые данные. В отличии от инсталятора нвидии наш не имеет справки и возможности проверки целостности. Поэтому есть куда расти.