Необходимо вернуть булевое определение исполняемого файла.

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

Я пытаюсь создать символическую ссылку на исполняемые файлы в директории bin внутри docker-скрипта. Мне нужен способ идентифицировать исполняемые файлы и вернуть булевый статус. Я пробовал это. Это не работает, и я не понимаю, почему.

for i in ../src/u-boot/tools/*; do if ! [[ "readelf -h $i | grep -q DYN" ]]; then ln -s $i .; fi; done

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

root@0f1bca692c90:/home/work/bin# readelf -h ../src/u-boot/tools/mkimage |grep -q DYN 
root@0f1bca692c90:/home/work/bin# echo $?
0
root@0f1bca692c90:/home/work/bin# readelf -h ../src/u-boot/tools/mkimage.c |grep -q DYN
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
root@0f1bca692c90:/home/work/bin# echo $?
1

Я предполагаю, что неправильно понимаю, как bash интерпретирует возвращаемые значения. Я пробовал с одинарными и двойными скобками, и поведение остается тем же.

Проблема имеет несколько аспектов, но основной из них заключается в том, что вы выбрали конструкцию теста Bash [[ ... ]] и поместили условие теста полностью в двойные кавычки. Это означает, что все условие интерпретируется как строка, которая, будучи непустой, всегда оценивается как “истина”.

Второй момент заключается в том, что вам на самом деле не нужна конструкция теста. Поскольку вы основываете свой тест на наличии свойства DYN в выводе readelf, который вы проверяете с помощью grep, вы можете просто указать

if readelf -h "$i" | grep -q "DYN"
then
   ...
fi

Так как код выхода конвейера команд – это код последней команды в конвейере, вы получите “истину”, если DYN был найден в выводе, и “ложь”, если DYN не был найден.

Последний момент может быть заблуждением относительно значения $?. Для тестов оболочки код выхода 0 означает истину, а ненулевой означает ложь, поэтому отрицание (if ! ....), которое вы использовали, (если я правильно понимаю ваше намерение) неправильно на данном этапе.

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

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

Проблема в коде

В приведённом вами коде имеется ошибка в использовании конструкции [[ ... ]], которая неправильно интерпретируется из-за размещения команды readelf внутри двойных кавычек. Это приводит к тому, что Bash воспринимает условие как строку, которая всегда возвращает истину (true).

Исходный код

for i in ../src/u-boot/tools/*; do
    if ! [[ "readelf -h $i | grep -q DYN" ]]; then
        ln -s $i .
    fi
done

Как правильно реализовать проверку

Для корректной реализации проверки, лучше всего воспользоваться напрямую выполнением команды readelf, вместо обрамления её в конструкцию [[ ... ]]. Это обеспечит правильную обработку возвращаемых кодов завершения команд. Попробуйте следующий вариант кода:

for i in ../src/u-boot/tools/*; do
    if readelf -h "$i" | grep -q "DYN"; then
        # Ссылка на исполняемый файл (файл, который мы хотим сохранить)
        ln -s "$i" .
    fi
done

Объяснение работы кода

  1. Цикл for: Итерирует по всем файлам в директории ../src/u-boot/tools/.
  2. Команда readelf: Получает заголовок файла и передаёт его на обработку grep.
  3. Проверка с помощью grep: Если в выводе есть строка DYN, команда grep возвращает 0 (true).
  4. Создание символической ссылки: Если условие истинно, создаётся символическая ссылка на нужный файл.

Понимание возвращаемых кодов

Важно помнить, что в Unix-подобных системах:

  • Код завершения 0 указывает на успешное выполнение операции (true).
  • Код завершения 1 или любой другой ненулевой код говорит о неуспешном выполнении (false).

Заключение

Таким образом, вы сможете успешно определить, является ли файл исполняемым и эффективно создать символическую ссылку на него в нужной директории. Приведённое выше решение является оптимальным и правильно использует средства Bash для выполнения поставленной задачи. Убедитесь, что у вас есть соответствующие права на выполнение команд в Docker-контейнере, чтобы избежать проблем с доступом.

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

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