為什麼 Certbot 無法執行 post hook 腳本?

為什麼 Certbot 無法執行 post hook 腳本?

這是我第一次嘗試透過 Certbot 更新 Let's Encrypt 憑證。仔細閱讀 Certbot 使用者指南後,我建立了兩個如下的 post hook 腳本:

root@pelargir:~# ls -l /etc/letsencrypt/renewal-hooks/post
total 8
-rwxr-xr-x 1 root root 697 Aug 29 16:35 10-setup-courier.sh
-rwxr-xr-x 1 root root 377 Aug 29 16:32 20-restart-services.sh

然後我在命令列上手動運行更新過程(即不通過 cron)。更新憑證成功,但未能執行上述 post hook 腳本。這是相關的輸出:

[...]
Running post-hook command: /etc/letsencrypt/renewal-hooks/post/10-setup-courier.sh
Hook command "/etc/letsencrypt/renewal-hooks/post/10-setup-courier.sh" returned error code 127
Error output from 10-setup-courier.sh:
/bin/sh: /etc/letsencrypt/renewal-hooks/post/10-setup-courier.sh: not found

Running post-hook command: /etc/letsencrypt/renewal-hooks/post/20-restart-services.sh
Hook command "/etc/letsencrypt/renewal-hooks/post/20-restart-services.sh" returned error code 127
Error output from 20-restart-services.sh:
/bin/sh: /etc/letsencrypt/renewal-hooks/post/20-restart-services.sh: not found
[...]

我不知道為什麼會發生這種情況。我仔細檢查了一下:

  • 腳本文件存在
  • 腳本檔案是可執行的
  • 我可以手動運行腳本(使用環境變數RENEWED_DOMAINSRENEWED_LINEAGE設定和匯出),它們按預期完成工作

我可能應該提到的另一件事是我在 Docker 映像中執行 Certbot,因為我正在使用通配符憑證。我的 DNS 提供者是 Cloudflare。這是我用來啟動續訂程序的命令列:

docker run -it --rm --name certbot \
           -v "/etc/letsencrypt:/etc/letsencrypt" \
           -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
           certbot/dns-cloudflare
           renew

Docker 映像運行 Certbot 版本 0.25.0。系統是 Debian 9 (stretch),最近從 Debian 8 (jessie) 升級。

有什麼線索可能是什麼問題嗎?


編輯:根據要求,這是兩個文件的內容,請稍加編輯以將我的網域替換為“example.com”:

root@pelargir:~# cat /etc/letsencrypt/renewal-hooks/post/10-setup-courier.sh 
#!/bin/bash

# Exit immediately if a command exits with non-zero status
set -e

case $RENEWED_DOMAINS in
  # Courier runs only under a example.com subdomain
  example.com)

    # We don't care about file permissions because we know that the
    # filesystem folder where we generate the file is not generally
    # accessible
    cat "$RENEWED_LINEAGE/fullchain.pem" "$RENEWED_LINEAGE/privkey.pem" >"$RENEWED_LINEAGE/courier.cert-and-key.unsecure"
    ;;
esac

root@pelargir:~# cat /etc/letsencrypt/renewal-hooks/post/20-restart-services.sh
#!/bin/bash

# Exit immediately if a command exits with non-zero status
set -e

case $RENEWED_DOMAINS in
  # Courier and Exim run only under a example.com subdomain
  *example.com*)
    systemctl restart courier-imap.service
    systemctl restart exim4.service
    systemctl restart apache2.service
    ;;

  # Apache has vhosts for all domains. Unfortunately the daemon is
  # restarted several times if several certificates are renewed.
  *)
    systemctl restart apache2.service
    ;;
esac

答案1

您的 shell 腳本使用 shebang #!/bin/bash,這表示它們將使用該程式執行,但它們運行的 Docker 容器不包含 bash。這就是為什麼在呼叫這些明顯存在的腳本時/bin/sh會報告令人困惑的錯誤。not found並不是找不到腳本,而是您要求要運行它們的 bash 解釋器。

/bin/sh您可以透過更改腳本解釋器並從腳本中刪除任何 bash-ism(可能快速且簡單)或在容器中安裝 bash(可能很混亂)來解決問題。

相關內容