Ne v kontakte Asocial programmer's blog

Собираем bash, запускающийся где угодно.

Feature image

Ну, если быть честным, то не совсем где угодно, а на любом дистрибутиве линукса. Возможно, так же заработает и на других *NIX системах, хотя я в этом и не уверен: проверить не на чем, а знание матчасти в этом отношении подкачало.

И так, наша цель собрать минималистичный bash свежей версии, без зависимостей и не требующий установки, чтобы потом запускать его с флешки или, как в моем случае, для выполнения скриптов для bash 4 в условиях CentOS 5.5, поставляющегося с ископаемым bash 3.2.

Кстати, только сегодня узнал, что на той неделе вышел CentOS 5.6, с более актуальными версиями софта, но в моем случае это ничего не меняет.

Для пущего осложнения жизни собирать будем 32-битный bash (чтобы запускался и на 32-х и на 64-х битах) в 64-битной Ubuntu.

Далее, пошаговые инструкции:

  1. $ sudo apt-get install build-essential gcc-multilib Это мы устанавливаем инструменты для сборки + библиотеки для кросс-компиляции под x86 (помним, что Ubuntu у нас x86_64 и компилятор в ней по дефолту тоже 64-битный).
  2. $ wget http://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz && tar -xzf bash-4.2.tar.gz && cd cd bash-4.2/ Качаем и распаковываем исходники bash. Я привел ссылку на актуальную на момент написания этого поста версию, однако возможно, вам в будущем захочется bash 4.3 или даже 5.0 ;-)
  3. $ export CC="gcc -m32" CFLAGS="-m32" Это и есть главная хитрость, необходимая для сборки 32-битного bash. То ли я не до конца разобрался, то ли у них Makefile корявый, но каждой из этих опций по отдельности недостаточно для сборки не под текущую архитектуру. Равно как и не работают параметры –host и –target у скрипта ./configure.
  4. $ ./configure --enable-static-link --without-bash-malloc Конфигурируем сборку. Параметр –enable-static-link требует статически линковать исполняемый файл с необходимыми библиотеками, тем самым минимизируя зависимости, а –without-bash-malloc устраняет один не вполне понятный для меня конфликт при линковке. Так же возможно вам захочется добавить свои параметры, включив дополнительный функционал. В моем случае нужен был –enable-array-variables, ради которого все и затевалось.
  5. $ make Собираем :-) Если у вас многоядерный процессор, можно добавить параметр -j N, где N - количество параллельных потоков сборки. Обычно его рекомендуют ставить равным удвоенному количеству реальных ядер. Кстати, в моем случае этот параметр существенно ускорил сборку, так что игнорировать его не стоит.

Если все шаги завершились успешно, то мы должны получить в текущем каталоге исполняемый файл bash, о котором утилита file должна говорить примерно следующее:

1
2
3
$ file bash

bash: ELF **32-bit** LSB executable, Intel 80386, version 1 (GNU/Linux), **statically linked**, for GNU/Linux 2.6.15, not stripped

Обратите внимание на выделенные жирным фрагменты. Если они отличаются, то значит при сборке что-то пошло не так, и bash собрался 64-х битный, либо со внешними зависимостями.

Если хочется, можно немного уменьшить размер бинарника, сделав $ strip bash.

У меня это дало экономию аж в 202365 байта.

Теперь этот файл можно копировать куда угодно и запускать, а он должен работать.

P.S. Space One — Intergalactic Space Crusaders