Lets-Encrypt

為什麼 Certbot 無法執行後掛鉤腳本?

  • August 29, 2018

這是我第一次嘗試通過 Certbot 更新 Let’s Encrypt 證書。仔細閱讀 Certbot 使用者指南後,我創建了兩個類似這樣的後掛鉤腳本:

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)。這成功地更新了證書,但未能執行上述後掛鉤腳本。這是相關的輸出:

[...]
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

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

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

引用自:https://serverfault.com/questions/928575