linux - 运行 Bash 脚本时找不到命令,但直接运行命令时有效

标签 linux bash apache lets-encrypt

我一直在使用 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

我使用 chmod 777 generate_certificate.sh 确保我对 bash 脚本拥有所有可能的权限,但仍然没有权限。最重要的是,我有一个在此之前运行的 bash 脚本,它只需重新启动 Apache,就可以正常工作。

我阅读了其他 S.O 文章,例如这篇文章,并尝试运行 dos2unix script.sh,它确实运行成功,但是当我再次尝试运行 bash 脚本时, 它没有用。

重启 Apache 脚本

#!/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"

最佳答案

默认情况下,shell 函数仅在定义它们的 shell 中可用;它们不会被子流程继承。您的 .bash_profile 仅由登录 shell 运行,而不是作为子进程运行的 shell(例如运行脚本)。

  • 选项 1:在 bash 中,您可以在定义的 shell 中运行 export -f letsencrypt_webfaction(即在您的 .bash_profile 中),它会被子进程继承(前提是它们'我们也在运行 bash)。

  • 选项 2:您可以在 .bashrc 而不是 .bash_profile 中定义函数,并且由于您从 .bash_profile 运行 .bashrc,它将在所有 bash shell 中定义。

  • 选项 3:只需在脚本中使用完整命令。这是我的偏好,因为它使脚本更加独立。让脚本依赖于在完全不同的地方定义的 shell 函数是脆弱的(正如您所经历的那样)而且有点奇怪。

虽然我在做,但这里有一些一般的脚本建议:

  • 在大多数情况下,您应该在变量引用(和包含变量引用的字符串)两边加上双引号,以避免分词和通配符扩展产生奇怪的效果。作业的右侧是一个可以将其关闭的地方(例如 PATH=$PATH:$HOME/binPATH="$PATH:$HOME/bin" 都可以),但我倾向于建议在任何地方都使用引号,因为很难跟踪在哪里可以安全地离开它们以及哪里是危险的。出于同样的原因,您应该几乎总是使用 "$@" 而不是 $*(如在 letsencrypt_webfaction 函数中)。

    shellcheck.net非常擅长发现这样的错误,因此我建议通过它运行 shell 脚本并根据它的建议采取行动。

  • 使用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 的更新值,但是 PATHRUBYLIB 的更新值基于任何值 GEM_HOME 在函数运行时有。我很确定这不是您想要的。

  • 在重新启动 apache 脚本中,您使用 restart 命令的相对路径。这将相对于运行脚本的进程的工作目录进行评估,而不是相对于脚本的位置。这可以在任何地方。

关于linux - 运行 Bash 脚本时找不到命令,但直接运行命令时有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50013492/

相关文章:

bash - 操作系统启动时显示IP地址

bash - 将子目录中的特定文件复制到一个目录中

Apache/Tomcat/mod_jk 当你使用 Webjars 时......可能吗?

linux - 在 Linux 上编写 SOAP 服务 - 需要工具和帮助

c# - 无法使 CustomBinding 在 Mono 中工作

c++ - 应用程序中两个不同版本的库

bash - 值对于 base 来说太大了(错误标记是 "0925")

php - 尝试创建搜索引擎友好 URL 时出现索引 404 错误

virtualhost - 我想为图像创建一个单独的域

c++ - PHP 的 is_dir() 的 C++ 等价物是什么?