В Linux есть ряд инструментов с интересным состоянием: почти каждый хоть раз видел результат их работы, но мало кто знает, как это было сделано. В этой статье представлены некоторые из этих инструментов и утилит.Так же сдесь мы рассмотрим некоторые скрипты и утилиты Linux.
Генератор паролей
Генераторов паролей сейчас в изобилии. Особенно удивительно то, что для этой цели существует множество веб-приложений. Сервис random.org честно признает, что генерирует пароли на стороне сервера и использовать их для чего-либо серьезного противопоказано. Другие сервисы заявляют, что генерируют пароли локально с помощью JavaScript, но поверить им на слово и гарантировать ли их подход, что утечки безопасны, непросто.
При этом генератор случайных паролей присутствует в репозиториях всех дистрибутивов утилит Linux с 90-х годов и называется pwgen. Большинство паролей, которые вы получали в своей жизни, вероятно, были созданы им.
Что интересно, его автор — Теодор Цо, тот самый, который разработал файловую систему ext2 и ее журналируемые версии ext3 и ext4.
К примеру, pwgen
сгенерирует один пароль из шестнадцати символов.
$ pwgen 16 1
iy1naeZeeNguchae
В современных условиях куда полезнее опция -s/
, которая генерирует полностью случайные пароли без претензий на удобочитаемость. К ней же можно добавить -B/
, которая исключает из вывода похожие на вид символы вроде O/
и 1/
.
$ pwgen -sB 16 1
PiVRps3erAngsmeb
Самораспаковывающиеся архивы
Проприетарные утилиты Linux часто распространяются как исполняемые установщики. Таким образом, их авторам не нужно компилировать более одного формата пакета. Программы на независимых от платформы языках, таких как Java, также могут использовать один и тот же графический установщик во всех операционных системах — способ их запуска отличается.
Таким способом распространялись файлы с драйверами NVIDIA, некоторые игры, значительная часть пакетов Sun Microsystems / Oracle (NetBeans, SunStudio и другие). Чаще всего у них было расширение .
, иногда просто .
.
Что представляет собой установщик
Обычно этот установщик представляет собой самораспаковывающийся архив. В Windows монолитные установщики и самораспаковывающиеся архивы часто содержат двоичный код для распаковки архива. UNIX-подобные операционные системы всегда включают по крайней мере tar и gzip форматы, как того требует стандарт POSIX, поэтому вы можете работать со сценарием в стандартной оболочке Bourne.
Я долго думал, что инструменты для создания этих установщиков тоже проприетарные. Так бы я и думал, если бы не наткнулся на свободные проекты с такими же установщиками. Создателем этих форматов оказался один и тот же инструмент с открытым исходным кодом — Makeself.
Makeself — относительно небольшой формат скрипта. Как ни странно, авторы все еще не отказались от этого, и в последних версиях Makeself поддерживает сжатие xz и контрольные суммы SHA-256 вместо традиционных gzip и MD5.
Можно даже не устанавливать его, а просто скопировать файлы makeself.
и makeself-header.
в каталог проекта. Продемонстрирую на простом примере. Нам потребуется целевой файл (условно test.
) и скрипт установки, который будет выполняться после распаковки во временный каталог.
├── makeself-header.sh
├── makeself.sh
└── my-package
├── setup.sh
└── test.sh
Процесс установки полностью зависит от пользователя. Для простоты ограничимся копированием в / tmp. Скрипт выполняется в каталоге с разархивированными файлами, поэтому все пути относительны.
#!/bin/sh
cp test.sh
/tmp/
makeself. sh < каталог с файлами> < имя выходного файла> < название проекта> < команда для выполнения после распаковки>
.$ ./
Header is 678 lines long
About to compress 12 KB of data...
Adding files to archive named "my-package.run"...
./setup.sh
./test.sh
CRC: 2448166092
MD5: f46655bb0b96ea7bee4d1f6f112eebe4
Self-extractable archive "my-package.run" successfully created.
$ ./
Verifying archive integrity... 100% MD5 checksums are OK. All good.
Uncompressing My Package 100%
$
/tmp/test.sh: POSIX shell script, ASCII text executable
Есть ли смысл использовать Makeself во времена snap, Flatpak и AppImage? Я вижу два варианта, в которых собственный статус по-прежнему важен. Первый — распространять самоустанавливающиеся патчи в особых случаях, когда создание обычного пакета невозможно или нецелесообразно. Второй — поддержка проприетарных операционных систем. Автономные сценарии с параметрами по умолчанию будут работать в любой POSIX-совместимой системе, поэтому, если вам нужен установщик для Solaris или HP-UX, это самый простой способ их создания.
Малоизвестные форматы архивов
Некоторые форматы архивов достигли пика популярности и теперь ушли в прошлое. Традиционно UNIX использует разные инструменты для создания архива (то есть для объединения нескольких файлов в один) и сжатия. Из-за этого инструменты сжатия могут появляться и устаревать, не вызывая проблем — нет необходимости оставлять поддержку устаревших алгоритмов в новых архиваторах. Если вам нужно распаковать данные по старому алгоритму, вы всегда можете установить отдельную утилиту.
Если в ходе археологических раскопок тебе попадется файл .
, можно поставить ncompress и выполнить compress
, после чего понадобится только стандартный tar
. В других случаях оригинальный алгоритм LZW никому в голову не придет.
Другое дело с реальными форматами архивов. В отличие от алгоритмов сжатия трудно сравнивать способы сборки файла из нескольких сложно сравнивать между собой. Формат ZIP не поддерживает права доступа к файлам, в то время как tar поддерживает, в этом смысле tar.gz лучше, чем ZIP. В то же время, довольно трудно найти формат, который объективно и, несомненно, лучше, чем tar.
Однако есть формат файла, а есть инструменты для работы с ним. И поведение tar, и формат создаваемых файлов стандартизованы в POSIX, что и делает его популярным на всех UNIX-подобных системах. К тому же утилита tar
достаточно удобна в использовании. По крайней мере tar
и tar
быстро запоминает каждый пользователь.
cpio
Ты удивишься, но tar — это не самый распространенный формат архивов в Linux. Среди пользователей — да, но больше всего данных хранится в формате cpio, с которым редко приходится работать вручную.
Почти все машины c Linux имеют файл в этом формате, так как это то, что ядро использует для initrd (начального RAM-диска). Он также используется в формате пакета RPM. Как сказано в документации к ядру, решающим фактором была простота формата.
А вот пользоваться утилитами, которые с ним работают, совсем не просто. Вот как надо вызывать утилиту cpio, чтобы создать архив:
find /path/to/dir -depth -print | cpio -o > /path/to/archive.cpio
Для скрипта сборки — сойдет, даже в чем‑то удобно. Для ручного использования… tar
явно проще и покрывает большую часть потребностей пользователя.
Для скрипта сборки — сойдет, даже в чем‑то удобно. Для ручного использования… tar
явно проще и покрывает большую часть потребностей пользователя.
Для скрипта сборки — сойдет, даже в чем‑то удобно. Для ручного использования… tar
явно проще и покрывает большую часть потребностей пользователя.
Для скрипта сборки — сойдет, даже в чем‑то удобно. Для ручного использования… tar
явно проще и покрывает большую часть потребностей пользователя.
ar
Другой распространенный формат, который никто не использует напрямую, — это ar. Его реализация включена в пакет GNU binutils. Как он попал в пакет с утилитами Linux88 для работы с исполняемыми файлами? Дело в том, что он используется для создания статических библиотек.
В ELF нет специального формата «статической библиотеки». Каждый исходный файл компилируется в отдельный объектный файл в том же формате ELF. Такие файлы, как libfoo.a, на самом деле представляют собой архивы ar, содержащие несколько объектных файлов.Таким образом, пользователь может писать gcc
.
Второй пользователь этого формата — пакетный менеджер dpkg. Если файл .
— это сжатый cpio, то .
— сжатый ar.
Внешние отладочные символы
Один из первых уроков начинающего разработчика для UNIX: хочешь сделать исполняемый файл меньше — выполни strip
. Ценой потери возможности работы с ним в отладчике, конечно.
Со временем начинающий обязательно увидит в репозиториях пакеты с внешними отладочными символами. Как они делаются? С помощью утилиты Linux objcopy
из Binutils.
Рассмотрим на примере традиционной программы Hello world.
#include <stdio.h>
int main(void) {
printf("hello world\n");
}
Скомпилируем исполняемый файл с отладочной информацией.
$
[
./hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=a8e65e032c2a154eecc1ed609aac1a1687e5c2fd, for GNU/Linux 3.2.0, with debug_info, not stripped
Теперь извлечем отладочные символы во внешний файл hello.
и удалим их из исходного.
$
$
./hello.debug: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter empty, BuildID[sha1]=a8e65e032c2a154eecc1ed609aac1a1687e5c2fd, for GNU/Linux 3.2.0, with debug_info, not stripped
$
statically linked
Если запустить исходный файл в отладчике GDB, мы получим сообщение об отсутствующих отладочных символах. Но если загрузить символы командой symbol-file
, мы сможем отлаживать его как обычно.
$
GNU gdb (GDB) Fedora 9.1-6.fc32
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./hello...
(No debugging symbols found in ./hello)
(gdb) symbol-file hello.debug
Reading symbols from hello.debug...
(gdb) b main
Breakpoint 1 at 0x40112a: file ./hello.c, line 4.
(gdb) r
Starting program: /home/dmbaturin/tmp/hello
Breakpoint 1, main () at ./hello.c:4
4 printf("hello world\n");
(gdb)
Заключение
Вы можете не найти ни один из этих инструментов и утилит Linux полезным. А может вам просто их не хватало.Или не хватает для того, кто придет к вам завтра. И задаст вопрос «а чем сделали этот файл?» В любом случае лучше знать их, чем не знать!