Ошибка сценария оболочки Linux Bash: невозможно выполнить: требуемый файл не найден

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

У меня есть два похожих скрипта с разными именами. Один работает нормально, а другой выдает ошибку. Может кто-нибудь сказать, в чем проблема?

Это мой скрипт test.sh, который работает нормально

[nnice@myhost Scripts]$ cat test.sh 
#!/bin/bash
function fun {     
        echo "`hostname`"
}
fun 
[nnice@myhost Scripts]$ ./test.sh 
myhost.fedora

Вот мой другой скрипт demo.sh, который выдает ошибку

[nnice@myhost Scripts]$ cat demo.sh 
#!/bin/bash
function fun { 
    echo "`hostname`"
}
fun
[nnice@myhost Scripts]$ ./demo.sh 
bash: ./demo.sh: cannot execute: required file not found

Оба скрипта имеют одинаковые разрешения

[nnice@myhost Scripts]$ ll test.sh 
-rwxr-xr-x. 1 nnice nnice 65 Oct 21 10:47 test.sh
[nnice@myhost Scripts]$ ll demo.sh 
-rwxr-xr-x. 1 nnice nnice 58 Oct 21 10:46 demo.sh

Ваш скрипт demo.sh является текстовым файлом в формате DOS. Такие файлы имеют окончания строк CRLF, и этот лишний символ CR (возврат каретки) в конце строки вызывает у вас проблемы.

Конкретная проблема заключается в том, что путь интерпретатора в строке #! теперь ссылается на что-то под названием /bin/bash\r (где \r символизирует возврат каретки, который является символом, похожим на пробел, поэтому обычно не видно). Этот файл не найден, поэтому это вызывает ваше сообщение об ошибке.

Чтобы решить эту проблему, преобразуйте свой скрипт из текстового файла DOS в текстовый файл Unix. Если вы редактируете скрипты на Windows, вы, вероятно, можете сделать это, настроив текстовый редактор Windows для создания текстовых файлов Unix, но вы также можете использовать утилиту dos2unix, доступную для большинства распространенных вариантов Unix.

$ ./script
bash: ./script: cannot execute: required file not found
$ dos2unix script
$ ./script
harpo.local

Что касается вашего кода: Пожалуйста, никогда не используйте echo `some-command` или echo $(some-command) для вывода результата some-command. Просто используйте команду напрямую:

#!/bin/sh

fun () {
    hostname
}

fun

(Поскольку скрипт теперь не использует ничего, что требует bash, я также перешел на приглашение более простого шелла /bin/sh.)

(Поскольку мой поиск привел сюда), у меня был test.sh

#!/bin/bash
echo "test"

который я скопировал на NixOS и получил

-bash: ./test.sh: cannot execute: required file not found

Я пытался использовать свой метод с vim для удаления возвратов каретки:

:e ++ff=unix 
:%s/\r\(\n\)/\1/g

но это не помогло.

Я изменил первую строку на

#!/usr/bin/env bash

и теперь это работает.

Я мог бы изменить это на

#!/bin/sh

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

Если вы откроете файл в notepad++, вы увидите возвраты каретки (CR LF) в правом нижнем углу файла, вы можете дважды щелкнуть и изменить на “Unix (LF)”.

смотрите изображение ниже

Контейнеры разработки Docker

Это, похоже, происходит, если вы клонируете репозиторий Git на файловую систему Windows, а затем (используя VS Code) открываете эту директорию внутри контейнера разработки Docker

Другими словами, вы можете столкнуться с этим, если вы сделали следующее:

  • Установили Git для Windows со всеми настройками по умолчанию
  • Клонировали репозиторий на файловую систему Windows
  • Открыли эту директорию с помощью VS Code
  • Удаленное подключение (внизу слева) -> Открыть заново в контейнере разработки

Внутри контейнера разработки git diff YOUR_BASH_SCRIPT.sh не показывает никаких очевидных различий.

Он покажет, что каждая строка была изменена. Он покажет, что все строки удалены, а затем все строки добавлены.

Почему это происходит, я не совсем уверен. Похоже, нет разницы, писали ли вы свой скрипт bash сначала на другой системе Linux. Это акт клонирования репозитория на файловую систему Windows, который все ломает.

Единственное решение, о котором я знаю на данный момент, это переписать ваш скрипт bash внутри контейнера.

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

Извините, я знаю, что это не очень ответ (по крайней мере, не сейчас, я надеюсь обновить его в будущем, когда получу больше информации) – если вы можете внести что-то, пожалуйста, оставьте комментарий.

Для тех, кто сталкивается с такой же проблемой с контейнером разработки Docker, упомянутой пользователем @user3728501, вы можете попробовать удалить возвраты каретки (CR, "\r", 0x0d) из вашего файла скрипта перед его выполнением. Этот пост показывает различные способы сделать это.

Мне удалось решить эту проблему, добавив ниже в мой devcontainer.json.

"postCreateCommand": sed -i 's/\r$//' your-script.sh; your-script.sh

В моем случае, на Windows, это было вызвано тем, что я пытался выполнить bash-скрипт, используя этот шебанг #! /user/bin/bash вместо #!/bin/bash.

Я сталкивался с аналогичными проблемами в прошлом. Если вы находитесь на компьютере с Windows, например, VSCode, измените формат файла на LF вместо CRLF

.

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

Ваша проблема, связанная с ошибкой "cannot execute: required file not found" при выполнении скрипта demo.sh, указывает на возможность наличия неподходящего формата файла. Причина такой ошибки кроется в различных символах окончания строки.

Причины возникновения проблемы

  1. Формат файла: Судя по вашему описанию, скрипт demo.sh был создан или редактировался в текстовом редакторе, который по умолчанию использует символы конца строки Windows (CRLF), а не Unix (LF). Это приводит к добавлению непонятного интерпретатору символа возврата каретки (\r) в строке с шебангом (#!/bin/bash), что, в свою очередь, приводит к ошибке:

    bash: ./demo.sh: cannot execute: required file not found

    Здесь интерпретатор пытается запустить bash\r, что не соответствует фактическому пути к исполняемому файлу.

  2. Проблемы с правами доступа: Хотя вы упомянули, что права доступа к обоим скриптам идентичны, стоит проверить, не изменены ли они в процессе копирования или редактирования файла.

Решение

Чтобы исправить эту проблему, вам необходимо преобразовать ваш скрипт demo.sh из формата Windows (CRLF) в формат Unix (LF). Для этого вы можете использовать утилиту dos2unix, которая доступна в большинстве дистрибутивов Unix и Linux. Команда выглядит следующим образом:

dos2unix demo.sh

Если у вас нет этой утилиты, вы можете воспользоваться другими способами:

  1. Использование текстовых редакторов:

    • Если вы используете Notepad++, откройте файл и в правом нижнем углу выберите "Convert to Unix (LF)".
    • В Vim командой :set fileformat=unix можно конвертировать формат файла.
  2. Сторонние инструменты:

    • Можно использовать sed для удаления символов возврата:
      sed -i 's/\r$//' demo.sh

Рекомендации по коду

Также стоит обратить внимание на структуру вашего скрипта. Вместо использования конструкции echo \hostname“, рекомендуется вызывать команду напрямую, например:

#!/bin/bash
function fun { 
    hostname
}
fun

Это улучшит читаемость и упростит код.

Вывод

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

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

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