diff --git a/scripts/Enroll-SguLinuxDomainClient.sh b/scripts/Enroll-SguLinuxDomainClient.sh index bd1ad12..2fd208c 100755 --- a/scripts/Enroll-SguLinuxDomainClient.sh +++ b/scripts/Enroll-SguLinuxDomainClient.sh @@ -67,6 +67,31 @@ need_command() { command -v "$1" >/dev/null 2>&1 || fail "Required command is unavailable: $1" } +packages_are_installed() { + local package_name + for package_name in "$@"; do + dpkg-query -W -f='${db:Status-Status}' "$package_name" 2>/dev/null | grep -Fxq 'installed' \ + || return 1 + done +} + +apt_get_with_retry() { + local attempt + for attempt in $(seq 1 60); do + if apt-get "$@"; then + return 0 + fi + if fuser /var/lib/dpkg/lock-frontend /var/lib/dpkg/lock /var/lib/apt/lists/lock \ + >/dev/null 2>&1; then + printf 'Waiting for another package operation before retrying apt-get %s.\n' "$1" >&2 + sleep 5 + continue + fi + fail "apt-get $1 failed for a reason other than a temporary package lock." + done + fail 'Timed out waiting for another package operation to finish.' +} + while (($#)); do case "$1" in --domain-controller) DOMAIN_CONTROLLER=${2:?Missing value for --domain-controller}; shift 2 ;; @@ -126,9 +151,16 @@ install_prerequisites() { done fi export DEBIAN_FRONTEND=noninteractive - apt-get update - apt-get install -y "${packages[@]}" - pam-auth-update --enable mkhomedir --force + if ! packages_are_installed "${packages[@]}"; then + apt_get_with_retry update + apt_get_with_retry install -y "${packages[@]}" + fi + # `pam-auth-update` takes the debconf database lock even when its + # profile is already enabled. Avoid that unnecessary package-manager + # dependency on repeat enrollment runs. + if ! grep -Eq '^[[:space:]]*[^#].*pam_mkhomedir\.so' /etc/pam.d/common-session; then + pam-auth-update --enable mkhomedir --force + fi return fi @@ -350,7 +382,7 @@ install_welcome_wallpaper() { # Desktop branding is optional and must never invalidate an otherwise valid # domain join. Install its distribution-specific dependencies best-effort. if command -v apt-get >/dev/null 2>&1; then - if ! apt-get install -y imagemagick ldap-utils fontconfig; then + if ! apt_get_with_retry install -y imagemagick ldap-utils fontconfig; then printf 'WARNING: Could not install welcome wallpaper dependencies; enrollment remains valid.\n' >&2 return 0 fi diff --git a/scripts/Install-SguLinuxRustDeskClient.sh b/scripts/Install-SguLinuxRustDeskClient.sh index 21c9c50..d318253 100644 --- a/scripts/Install-SguLinuxRustDeskClient.sh +++ b/scripts/Install-SguLinuxRustDeskClient.sh @@ -44,6 +44,23 @@ need_command() { command -v "$1" >/dev/null 2>&1 || fail "Required command is unavailable: $1" } +apt_get_with_retry() { + local attempt + for attempt in $(seq 1 60); do + if apt-get "$@"; then + return 0 + fi + if fuser /var/lib/dpkg/lock-frontend /var/lib/dpkg/lock /var/lib/apt/lists/lock \ + >/dev/null 2>&1; then + printf 'Waiting for another package operation before retrying apt-get %s.\n' "$1" >&2 + sleep 5 + continue + fi + fail "apt-get $1 failed for a reason other than a temporary package lock." + done + fail 'Timed out waiting for another package operation to finish.' +} + while (($#)); do case "$1" in --domain-name) DOMAIN_NAME=${2:?Missing value for --domain-name}; shift 2 ;; @@ -60,8 +77,8 @@ done install_prerequisites() { if command -v apt-get >/dev/null 2>&1; then export DEBIAN_FRONTEND=noninteractive - apt-get update - apt-get install -y curl openssl smbclient dnsutils + apt_get_with_retry update + apt_get_with_retry install -y curl openssl smbclient dnsutils return fi if command -v dnf >/dev/null 2>&1; then @@ -131,7 +148,7 @@ install_rustdesk() { [[ $actual_hash == "$EXPECTED_SHA256" ]] || fail 'RustDesk package SHA-256 verification failed.' if command -v apt-get >/dev/null 2>&1; then - dpkg -i "$installer_path" || apt-get install -f -y + dpkg -i "$installer_path" || apt_get_with_retry install -f -y else fail 'The pinned RustDesk package is currently provided as a Debian package only.' fi