這是我第一次嘗試透過 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_DOMAINS
並RENEWED_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(可能很混亂)來解決問題。