Skip to content

Instantly share code, notes, and snippets.

@JohnRDOrazio
Created January 23, 2026 01:20
Show Gist options
  • Select an option

  • Save JohnRDOrazio/10728742dd22bfbeb3de90a89e6e4357 to your computer and use it in GitHub Desktop.

Select an option

Save JohnRDOrazio/10728742dd22bfbeb3de90a89e6e4357 to your computer and use it in GitHub Desktop.
A bash script that downloads the latest ICU release, the shivammathur intl binaries for PHP, and automates restoring them when Plesk updates PHP and reloads PHP-FPM
#!/bin/bash
# install-latest-icu-and-php-intl.sh
# Idempotent installer for latest ICU and PHP intl for Plesk
set -euo pipefail
# -----------------------------
# Configuration
# -----------------------------
INSTALL_PREFIX="/opt"
TMP_DIR="/tmp/icu-build"
PHP_INTL_DIR="/usr/local/php-intl"
mkdir -p "$TMP_DIR"
mkdir -p "$PHP_INTL_DIR"
# -----------------------------
# Detect latest ICU release from GitHub
# -----------------------------
echo "[INFO] Fetching latest ICU release info from GitHub..."
LATEST_TAG=$(curl -s https://api.github.com/repos/unicode-org/icu/releases/latest \
| grep -Po '"tag_name": "\K.*?(?=")')
if [ -z "$LATEST_TAG" ]; then
echo "[ERROR] Could not fetch latest ICU release."
exit 1
fi
ICU_VERSION="${LATEST_TAG#release-}"
ICU_DIR="$INSTALL_PREFIX/icu-$ICU_VERSION"
echo "[INFO] Latest ICU release: $ICU_VERSION"
# -----------------------------
# Install ICU if not already present
# -----------------------------
if [ -d "$ICU_DIR" ] && [ -x "$ICU_DIR/bin/icu-config" ]; then
echo "[INFO] ICU $ICU_VERSION already installed at $ICU_DIR. Skipping build."
else
echo "[INFO] Installing ICU $ICU_VERSION..."
cd "$TMP_DIR"
SRC_TGZ="icu4c-${ICU_VERSION}-sources.tgz"
DOWNLOAD_URL="https://github.com/unicode-org/icu/releases/download/$LATEST_TAG/$SRC_TGZ"
wget -q --show-progress "$DOWNLOAD_URL" -O "$TMP_DIR/$SRC_TGZ"
tar -xvf "$SRC_TGZ"
cd icu/source
./configure --prefix="$ICU_DIR"
make -j"$(nproc)"
make -j"$(nproc)" check || echo "[WARN] ICU tests failed"
sudo make install
echo "[INFO] ICU installation complete: $($ICU_DIR/bin/icu-config --version)"
# Make libraries visible system-wide
CONF_FILE="/etc/ld.so.conf.d/icu-$ICU_VERSION.conf"
if [ ! -f "$CONF_FILE" ]; then
echo "$ICU_DIR/lib" | sudo tee "$CONF_FILE" >/dev/null
sudo ldconfig
echo "[INFO] Registered $ICU_DIR/lib via ldconfig"
else
echo "[INFO] ld.so.conf for ICU already exists: $CONF_FILE"
fi
cd /
rm -rf "$TMP_DIR"
fi
# -----------------------------
# Detect installed Plesk PHP versions
# -----------------------------
PHP_VERSIONS=()
for PHP_BIN in /opt/plesk/php/*/bin/php; do
if [ -x "$PHP_BIN" ]; then
PHP_VER=$("$PHP_BIN" -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
PHP_VERSIONS+=("$PHP_VER")
fi
done
if [ ${#PHP_VERSIONS[@]} -eq 0 ]; then
echo "[ERROR] No Plesk PHP versions detected under /opt/plesk/php/"
exit 1
fi
echo "[INFO] Detected Plesk PHP versions: ${PHP_VERSIONS[*]}"
# -----------------------------
# Download shivammathur PHP intl binaries
# -----------------------------
for PHP in "${PHP_VERSIONS[@]}"; do
TARGET_DIR="$PHP_INTL_DIR/php$PHP"
mkdir -p "$TARGET_DIR"
TARGET_SO="$TARGET_DIR/intl.so"
BINARY_URL="https://github.com/shivammathur/icu-intl/releases/download/intl-$ICU_VERSION/php${PHP}-intl-$ICU_VERSION.so"
if [ -f "$TARGET_SO" ]; then
echo "[INFO] PHP $PHP intl.so already exists at $TARGET_SO. Skipping download."
else
echo "[INFO] Downloading PHP $PHP intl.so for ICU $ICU_VERSION..."
curl -L --fail -o "$TARGET_SO" "$BINARY_URL"
chmod 664 "$TARGET_SO"
chown "$USER":"$USER" "$TARGET_SO"
echo "[INFO] Saved $TARGET_SO"
fi
done
# -----------------------------
# Create fix-plesk-intl.sh restore script
# -----------------------------
RESTORE_SCRIPT="/usr/local/bin/fix-plesk-intl.sh"
if [ ! -f "$RESTORE_SCRIPT" ]; then
echo "[INFO] Creating restore script at $RESTORE_SCRIPT..."
sudo tee "$RESTORE_SCRIPT" >/dev/null <<EOF
#!/bin/bash
# Restore ICU $ICU_VERSION intl.so for a specific Plesk PHP version
PHP_VERSION="\$1"
if [ -z "\$PHP_VERSION" ]; then
echo "Usage: \$0 <PHP_VERSION>"
exit 1
fi
ICU_BIN_DIR="$PHP_INTL_DIR"
MODULE_PATH="/opt/plesk/php/\$PHP_VERSION/lib/php/modules/intl.so"
BACKUP="\$ICU_BIN_DIR/php\$PHP_VERSION/intl.so"
if [ -f "\$BACKUP" ]; then
if [ -f "\$MODULE_PATH" ]; then
PLESK_SHA=\$(sha256sum "\$MODULE_PATH" | awk '{print \$1}')
else
PLESK_SHA=""
fi
BACKUP_SHA=\$(sha256sum "\$BACKUP" | awk '{print \$1}')
if [ "\$PLESK_SHA" != "\$BACKUP_SHA" ]; then
echo "[\$(date)] Restoring intl.so for PHP \$PHP_VERSION"
[ -f "\$MODULE_PATH" ] && mv "\$MODULE_PATH" "\$MODULE_PATH.bak"
cp -f "\$BACKUP" "\$MODULE_PATH"
fi
else
echo "[\$(date)] Backup for PHP \$PHP_VERSION not found: \$BACKUP"
fi
EOF
sudo chmod +x "$RESTORE_SCRIPT"
echo "[INFO] Restore script created."
else
echo "[INFO] Restore script already exists at $RESTORE_SCRIPT. Skipping creation."
fi
# -----------------------------
# Create hook-plesk-php-intl.sh script
# -----------------------------
HOOK_SCRIPT="/usr/local/bin/hook-plesk-php-intl.sh"
if [ ! -f "$HOOK_SCRIPT" ]; then
echo "[INFO] Creating PHP-FPM hook script at $HOOK_SCRIPT..."
sudo tee "$HOOK_SCRIPT" >/dev/null <<'HOOK'
#!/bin/bash
# Automatically hook fix-plesk-intl.sh into all Plesk PHP-FPM services
for PHP_DIR in /opt/plesk/php/*; do
PHP_VERSION=$(basename "$PHP_DIR")
SERVICE="plesk-php${PHP_VERSION}-fpm"
if systemctl list-unit-files | grep -q "$SERVICE"; then
OVERRIDE_DIR="/etc/systemd/system/$SERVICE.service.d"
OVERRIDE_FILE="$OVERRIDE_DIR/override.conf"
if [ ! -f "$OVERRIDE_FILE" ]; then
echo "[INFO] Configuring $SERVICE to run fix-plesk-intl.sh on start..."
sudo mkdir -p "$OVERRIDE_DIR"
sudo tee "$OVERRIDE_FILE" >/dev/null <<OVERRIDE
[Service]
ExecStartPre=/usr/local/bin/fix-plesk-intl.sh $PHP_VERSION
OVERRIDE
else
echo "[INFO] Override already exists for $SERVICE, skipping."
fi
fi
done
sudo systemctl daemon-reload
HOOK
sudo chmod +x "$HOOK_SCRIPT"
echo "[INFO] Hook script created."
else
echo "[INFO] Hook script already exists at $HOOK_SCRIPT. Skipping creation."
fi
# -----------------------------
# Optionally hook all PHP-FPM services now
# -----------------------------
read -rp "Do you want to automatically hook fix-plesk-intl.sh into all Plesk PHP-FPM services now? [y/N] " answer
case "$answer" in
[Yy]* )
echo "[INFO] Running hook-plesk-php-intl.sh..."
sudo /usr/local/bin/hook-plesk-php-intl.sh
echo "[DONE] All detected PHP-FPM services now call fix-plesk-intl.sh on start."
;;
* )
echo "[INFO] Skipping automatic service hooks. You can run /usr/local/bin/hook-plesk-php-intl.sh manually later."
;;
esac
echo "[DONE] ICU $ICU_VERSION and PHP intl binaries are ready."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment