Команда не найдена при запуске скрипта Bash, но работает при непосредственном запуске команды - PullRequest
0 голосов
/ 25 апреля 2018

Я использую letsencrypt для генерации SSL-сертификатов для моего сайта, точнее, letsencrypt_webfaction. Когда я запускаю эту команду в моем проекте, она работает

letsencrypt_webfaction --letsencrypt_account_email <Email I use> --domains <domains I use> --public <public_file> --username <username> --password <password>

Однако, когда я запускаю ту же команду в скрипте bash, я получаю сообщение об ошибке

generate_certificate.sh: line 2: letsencrypt_webfaction: command not found

Я удостоверился, что у меня есть все возможные разрешения для сценария bash, используя chmod 777 generate_certificate.sh, но все еще ничего. Вдобавок ко всему, у меня есть скрипт bash, который запускается прямо перед этим, который просто перезапускает Apache и работает нормально.

Я прочитал другие статьи SO, такие как эта, и попытался запустить dos2unix script.sh , который успешно прошел, но когда я снова попытался запустить сценарий bash, он не работал

Перезапустить Apache Script

#!/bin/bash
../apache2/bin/./restart
#END

Создать скрипт SSL

#!/bin/bash
letsencrypt_webfaction --letsencrypt_account_email <Email I use> --domains <domains I use> --public <public_file> --username <username> --password <password>
#END

Я разработчик Python и не очень разбираюсь в Ruby, поэтому извините за мое незнание, но команда letsencrypt_webfaction - это функция в моем профиле bash.

~ / .bash_profile

# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

function letsencrypt_webfaction {
    PATH=$PATH:$GEM_HOME/bin GEM_HOME=$HOME/.letsencrypt_webfaction/gems RUBYLIB=$GEM_HOME/lib ruby2.2 $HOME/.letsencrypt_webfaction/gems/bin/letsencrypt_webfaction $*
}

eval "$(rbenv init -)"


PATH=$PATH:$HOME/bin

export PATH
export PATH="$HOME/.rbenv/bin:$PATH"
export TMPDIR="/home/doc4design/src/tmp"

1 Ответ

0 голосов
/ 25 апреля 2018

По умолчанию функции оболочки доступны только в той оболочке, в которой они были определены; они не наследуются подпроцессами. Ваш .bash_profile запускается только оболочкой входа в систему, а не оболочками, которые выполняются как подпроцессы (например, для запуска сценариев).

  • Вариант 1. В bash вы можете запустить export -f letsencrypt_webfaction в определяющей оболочке (т.е. в вашем .bash_profile), и она будет унаследована подпроцессами (при условии, что они также запускают bash).

  • Вариант 2. Вы можете определить функцию в вашем .bashrc вместо .bash_profile, и поскольку вы запускаете .bashrc из .bash_profile, она будет определена во всех ваших оболочках bash.

  • Вариант 3: Просто используйте полную команду в скрипте. Это было бы моим предпочтением, так как это делает сценарий более независимым. Наличие сценария, зависящего от функции оболочки, которая определена в совершенно другом месте, хрупко (как вы испытываете) и немного странно.

Пока я здесь, вот несколько общих рекомендаций по написанию сценариев:

  • В большинстве случаев вы должны помещать двойные кавычки вокруг ссылок на переменные (и строк, содержащих ссылки на переменные), чтобы избежать странных эффектов от разбиения слов и раскрытия подстановочных знаков. Правая сторона задания - это единственное место, в котором можно оставить их без внимания (например, PATH=$PATH:$HOME/bin и PATH="$PATH:$HOME/bin" оба в порядке), но я склонен рекомендовать использовать кавычки везде, так как трудно отследить, где их безопасно оставить. и где это опасно. По той же причине вы должны почти всегда использовать "$@" вместо $* (как в функции letsencrypt_webfaction).

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

  • Использование ключевого слова function для определения функции является нестандартным; стандартный синтаксис - использовать () после имени функции, например:

    letsencrypt_webfaction() {
        PATH="$PATH:$GEM_HOME/bin" GEM_HOME="$HOME/.letsencrypt_webfaction/gems" RUBYLIB="$GEM_HOME/lib" ruby2.2 "$HOME/.letsencrypt_webfaction/gems/bin/letsencrypt_webfaction" "$@"
    }
    
  • Функция, которую я только что дал, все еще может работать неправильно, так как она (пере) определяет GEM_HOME после ее использования. Анализируется вся строка (и расширяются ранее существующие определения переменных), , а затем переменные, определенные как префиксы для команды, включаются в среду команды. Это означает, что скрипт ruby ​​получает обновленное значение GEM_HOME, но обновленные значения PATH и RUBYLIB основаны на значении, которое GEM_HOME имело при запуске функции. Я уверен, что это не то, что вы намеревались.

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

...