feat: add ACME_PACKAGED for distro-packaged installs

When ACME_PACKAGED is set (e.g. exported by a distro package wrapper):
- --install does not copy the script or the hooks into LE_WORKING_DIR;
  the cron job and the shell alias point to the packaged script instead
- --upgrade, --install-online and the cron AUTO_UPGRADE path refuse and
  point to the system package manager
- --uninstall does not remove the packaged files

https://github.com/acmesh-official/acme.sh/issues/7135
This commit is contained in:
neil 2026-07-17 22:03:00 +08:00
parent 9bfcf2cf1a
commit 7fa3018219

101
acme.sh
View file

@ -7528,6 +7528,15 @@ _installalias() {
_c_home="$1"
_initpath
_alias_bin="$LE_WORKING_DIR/$PROJECT_ENTRY"
if [ ! -f "$_alias_bin" ]; then
#ACME_PACKAGED install: no copy in LE_WORKING_DIR, alias the current script
_script="$(_readlink "$_SCRIPT_")"
if [ -f "$_script" ]; then
_alias_bin="$_script"
fi
fi
_envfile="$LE_WORKING_DIR/$PROJECT_ENTRY.env"
if [ "$_upgrading" ] && [ "$_upgrading" = "1" ]; then
echo "$(cat "$_envfile")" | sed "s|^LE_WORKING_DIR.*$||" >"$_envfile"
@ -7545,7 +7554,7 @@ _installalias() {
else
_sed_i "/^export LE_CONFIG_HOME/d" "$_envfile"
fi
_setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\""
_setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$_alias_bin$_c_entry\""
if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY.completion" ]; then
#the completion file does nothing when sourced by a non-bash shell
_setopt "$_envfile" ". \"$LE_WORKING_DIR/$PROJECT_ENTRY.completion\""
@ -7572,7 +7581,7 @@ _installalias() {
else
_sed_i "/^setenv LE_CONFIG_HOME/d" "$_cshfile"
fi
_setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\""
_setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$_alias_bin$_c_entry\""
_setopt "$_csh_profile" "source \"$_cshfile\""
fi
@ -7584,7 +7593,7 @@ _installalias() {
if [ "$_c_home" ]; then
_setopt "$_cshfile" "setenv LE_CONFIG_HOME" " " "\"$LE_CONFIG_HOME\""
fi
_setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\""
_setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$_alias_bin$_c_entry\""
_setopt "$_tcsh_profile" "source \"$_cshfile\""
fi
@ -7658,30 +7667,38 @@ install() {
chmod 700 "$LE_CONFIG_HOME"
fi
cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY"
if [ "$ACME_PACKAGED" ]; then
#the script and its hooks are managed by a system package manager,
#do not copy them into LE_WORKING_DIR. https://github.com/acmesh-official/acme.sh/issues/7135
_info "ACME_PACKAGED is set, skipping the script copy."
else
cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY"
if [ "$?" != "0" ]; then
_err "Installation failed, cannot copy $PROJECT_ENTRY"
return 1
fi
if [ "$?" != "0" ]; then
_err "Installation failed, cannot copy $PROJECT_ENTRY"
return 1
fi
_info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
_info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
if [ -f "$PROJECT_ENTRY.completion" ]; then
cp "$PROJECT_ENTRY.completion" "$LE_WORKING_DIR/"
_debug "Installed bash completion to $LE_WORKING_DIR/$PROJECT_ENTRY.completion"
if [ -f "$PROJECT_ENTRY.completion" ]; then
cp "$PROJECT_ENTRY.completion" "$LE_WORKING_DIR/"
_debug "Installed bash completion to $LE_WORKING_DIR/$PROJECT_ENTRY.completion"
fi
fi
if [ "$_ACME_IN_CRON" != "1" ] && [ -z "$_noprofile" ]; then
_installalias "$_c_home"
fi
for subf in $_SUB_FOLDERS; do
if [ -d "$subf" ]; then
mkdir -p "$LE_WORKING_DIR/$subf"
cp "$subf"/* "$LE_WORKING_DIR"/"$subf"/
fi
done
if [ -z "$ACME_PACKAGED" ]; then
for subf in $_SUB_FOLDERS; do
if [ -d "$subf" ]; then
mkdir -p "$LE_WORKING_DIR/$subf"
cp "$subf"/* "$LE_WORKING_DIR"/"$subf"/
fi
done
fi
if [ ! -f "$ACCOUNT_CONF_PATH" ]; then
_initconf
@ -7709,7 +7726,7 @@ install() {
installcronjob "$_c_home"
fi
if [ -z "$NO_DETECT_SH" ]; then
if [ -z "$NO_DETECT_SH" ] && [ -z "$ACME_PACKAGED" ]; then
#Modify shebang
if _exists bash; then
_bash_path="$(bash -c "command -v bash 2>/dev/null")"
@ -7734,7 +7751,9 @@ install() {
if [ "$_accountemail" ]; then
_saveaccountconf "ACCOUNT_EMAIL" "$_accountemail"
fi
_saveaccountconf "UPGRADE_HASH" "$(_getUpgradeHash)"
if [ -z "$ACME_PACKAGED" ]; then
_saveaccountconf "UPGRADE_HASH" "$(_getUpgradeHash)"
fi
_info OK
}
@ -7748,8 +7767,12 @@ uninstall() {
_uninstallalias
rm -f "$LE_WORKING_DIR/$PROJECT_ENTRY"
rm -f "$LE_WORKING_DIR/$PROJECT_ENTRY.completion"
if [ -z "$ACME_PACKAGED" ]; then
#don't remove the script when it is managed by a system package manager,
#LE_WORKING_DIR may point to the packaged files
rm -f "$LE_WORKING_DIR/$PROJECT_ENTRY"
rm -f "$LE_WORKING_DIR/$PROJECT_ENTRY.completion"
fi
_info "The keys and certs are in \"$(__green "$LE_CONFIG_HOME")\". You can remove them by yourself."
}
@ -7785,20 +7808,24 @@ cron() {
_initpath
_info "$(__green "===Starting cron===")"
if [ "$AUTO_UPGRADE" = "1" ]; then
export LE_WORKING_DIR
(
if ! upgrade; then
_err "Cron: Upgrade failed!"
return 1
if [ "$ACME_PACKAGED" ]; then
_info "ACME_PACKAGED is set, skipping the auto upgrade."
else
export LE_WORKING_DIR
(
if ! upgrade; then
_err "Cron: Upgrade failed!"
return 1
fi
)
. "$LE_WORKING_DIR/$PROJECT_ENTRY" >/dev/null
if [ -t 1 ]; then
__INTERACTIVE="1"
fi
)
. "$LE_WORKING_DIR/$PROJECT_ENTRY" >/dev/null
if [ -t 1 ]; then
__INTERACTIVE="1"
_info "Automatically upgraded to: $VER"
fi
_info "Automatically upgraded to: $VER"
fi
_TREAT_SKIP_AS_SUCCESS="1"
renewAll
@ -8128,6 +8155,10 @@ Parameters:
}
installOnline() {
if [ "$ACME_PACKAGED" ]; then
_err "ACME_PACKAGED is set: acme.sh is managed by the system package manager, please use it to upgrade."
return 1
fi
_info "Installing from online archive."
_branch="$BRANCH"
@ -8185,6 +8216,10 @@ _getUpgradeHash() {
}
upgrade() {
if [ "$ACME_PACKAGED" ]; then
_err "ACME_PACKAGED is set: acme.sh is managed by the system package manager, please use it to upgrade."
exit 1
fi
if (
_initpath
[ -z "$FORCE" ] && [ "$(_getUpgradeHash)" = "$(_readaccountconf "UPGRADE_HASH")" ] && _info "Already up to date!" && exit 0