Компилированные shell-скрипты лучше по производительности?

Вопрос или проблема

После некоторого гугления я нашел способ компилировать BASH-скрипты в исполняемые бинарные файлы (с помощью shc).

Я знаю, что оболочка является интерпретируемым языком, но что делает этот компилятор? Улучшит ли он производительность моего скрипта каким-либо образом?

Чтобы ответить на вопрос в вашем заголовке, скомпилированные shell-скрипты могут быть лучше для производительности — если результат компиляции будет представлять результат интерпретации без необходимости повторного интерпретирования команд в скрипте. Смотрите, например, shcomp в ksh93, zcompile в zsh или развивающийся Bunster для bash.

Однако shc не компилирует скрипты таким образом. Это не настоящий компилятор, это инструмент “шифрования” скрипта с различными методами защиты сомнительной эффективности. Когда вы компилируете скрипт с помощью shc, результатом является бинарный файл, содержимое которого не сразу читается; когда он запускается, он расшифровывает свое содержимое и запускает инструмент, для которого был предназначен скрипт, с расшифрованным скриптом, что делает оригинальный скрипт легкодоступным (он передается целиком в командной строке интерпретатора, с добавленными пробелами в попытке усложнить его поиск). Поэтому общая производительность всегда будет хуже: помимо времени, потраченного на выполнение оригинального скрипта, добавляется время, потраченное на настройку среды и расшифровку скрипта.

После некоторого гугления я нашел способ компилировать BASH-скрипты в исполняемые бинарные файлы (с помощью shc).

Досадно, что это приспособление shc все еще появляется в результатах поиска Google, даже после того, как оно было полностью развенчано за все эти годы: shc не является компилятором и не предотвращает просмотр и “кражу” исходного кода скрипта.

Вообще, shc даже глупее, чем должно быть, потому что после снятия маскировки исходного кода скрипт просто передается как аргумент bash -c, что делает его видимым в /proc/<pid>/cmdline для любого пользователя, а не только для того, кто запускает скрипт. Это также сталкивается с ограничением длины одного аргумента командной строки в Linux (128k байт). Но чтобы сделать вещи еще более нелепыми, первая часть этого аргумента заполнена пробелами, чтобы он не появлялся в ps 😉

Улучшит ли он производительность моего скрипта каким-либо образом?

Да, ваш скрипт может вообще не работать, что означает, что он завершится быстрее.

В общем, нет способа скомпилировать shell-скрипт, потому что новый исходный текст может быть введен несколькими методами во время выполнения, которые, следовательно, обходят фазу компиляции. Этот новый исходный код не сможет взаимодействовать с скомпилированными функциями или переменными.

Два метода создания исходного кода во время выполнения:

Подключить сторонний файл, который мог быть создан или изменен после компиляции оригинального скрипта.

Создать во время выполнения произвольную команду в строке и исполнить ее.

.

Ответ или решение

Когда мы говорим о производительности скриптов на Shell, мы, как правило, подразумеваем несколько аспектов: скорость выполнения команд, размер и объем используемой памяти, а также эффективность использования ресурсов системы. Предполагается, что компилирование скриптов способно улучшить некоторые из этих аспектов. Однако важно учитывать, что термин "компилирование" может восприниматься различными способами в зависимости от подхода и инструмента.

Теоретическая основа

Shell-языки, такие как Bash, традиционно являются интерпретируемыми, что означает, что команды выполняются напрямую командной строкой или интерпретатором. Это позволяет получить взаимодействие в реальном времени и изменять скрипты "на лету". Основным недостатком является то, что каждоразовый анализ и выполнение команд занимает больше времени, особенно если скрипт содержит большие циклы или включает в себя сложные логические структуры.

В теоретическом смысле, компиляция подразумевает преобразование исходного кода в исполняемый двоичный формат, что снижает накладные расходы на интерпретацию и может ускорить выполнение. В классическом программировании, когда говорят о компиляции, обычно имеется в виду процесс преобразования высокоуровневого языкового кода в машинный код. Это действительно часто приводит к увеличению производительности.

Примеры существующих решений

В контексте скриптов Shell компиляция часто реализуется не так, как в традиционных языках программирования. Например, инструменты вроде shc, shcomp для ksh или zcompile для zsh предоставляют различные механизмы для работы с Shell-скриптами. Важно заметить, что большинство таких инструментов, включая shc, не являются настоящими компиляторами.

shc: Этот инструмент не столько компилирует скрипты, сколько применяет своего рода шифровку, создавая изначально не читаемый двоичный файл. Когда такой файл запускается, он расшифровывает данные и передает их в интерпретатор, например, в Bash. Это снижает производительность, так как добавляется предварительная обработка по расшифровке данных и подготовки окружения, прежде чем фактически начать выполнение скрипта.

shcomp и zcompile: Эти инструменты в некоторой степени ближе к компиляции, но также не обходятся без интерпретации. Они пре-компилируют скрипт, выполняя его синтаксический анализ заранее. Однако реальная польза от этого часто незначительная, особенно в условиях сложных динамических скриптов, где выполнение зависит от ввода или внесенного ранее кода.

Применение и выводы

Практически, каким бы заманчивым ни казался подход компиляции для повышения производительности, в случае Shell-скриптов он редко оправдывает ожидания. Современные интерпретаторы уже достаточно оптимизированы, чтобы интерпретация не была основным узким местом в их производительности. Обычно узким местом становится время, затрачиваемое на выполнение самих команд, особенно если это внешние программы или сложные вычислительные операции.

Кроме того, интерпретируемый характер Shell-скриптов предоставляет значительные преимущества в гибкости, возможности динамического формирования и выполнения команд, а также легкости модификации. Компиляция же, как правило, снижает эти преимущества за счет дополнительной статичности и ограничивает возможности изменения исходного кода без повторной процедуры компиляции.

Для улучшения производительности Shell-скриптов лучше сосредоточить усилия на оптимизации самого кода: использовать локальные переменные, избегать излишних циклов, минимизировать вызовы внешних программ, и адаптировать алгоритмы таким образом, чтобы они эффективно использовали ресурсы системы.

Таким образом, если рассматривать "компиляцию" Shell-скриптов с использованием shc или схожих инструментов, улучшения в производительности скрипта достичь не удастся. Наоборот, это может лишь добавить ненужные накладные расходы. Для тех, кто желает защиты исходного кода, необходимо рассмотреть альтернативные механизмы, так как шифровка с использованием shc не является надежным средством защиты.

Оцените материал
Добавить комментарий

Капча загружается...