Skip to content

Instantly share code, notes, and snippets.

@mlocati
Last active January 23, 2026 16:38
Show Gist options
  • Select an option

  • Save mlocati/2195c70caeca3df1240e35d5db871587 to your computer and use it in GitHub Desktop.

Select an option

Save mlocati/2195c70caeca3df1240e35d5db871587 to your computer and use it in GitHub Desktop.
Script to safely and fully update ConcreteCMS
#!/bin/sh
# First argument (required): path to the directory that contains the ConcreteCMS installation
# Subsequent arguments (optional): language codes to install/update translations for (e.g. 'fr_FR', 'de_DE', etc.)
#
# Copyright Michele Locati <michele@locati.it> - 2026
# License: MIT - https://opensource.org/license/mit
# Source: https://gist.github.com/mlocati/2195c70caeca3df1240e35d5db871587
set -o nounset
set -o errexit
concreteBin=
resetMaintenanceMode=0
safeEcho() {
printf -- '%s\n' "${1:-}" || :
}
cleanup() {
if [ $resetMaintenanceMode -ne 1 ] || [ -z "$concreteBin" ]; then
return
fi
safeEcho '# Turning off maintenance mode'
if "$concreteBin" --no-ansi --no-interaction c5:config -g set concrete.maintenance_mode false; then
resetMaintenanceMode=0
safeEcho 'Maintenance mode turned off.'
else
safeEcho 'Failed to turn off maintenance mode!'
fi
safeEcho
}
died() {
cleanup
exit 1
}
exitWithError() {
safeEcho "$1"
exit 1
}
buildInstallLanguageArgs() {
oldIFS=$IFS
IFS=' '
args=
for lang in "$@"; do
args="$args --add $lang"
done
IFS=$oldIFS
echo $args
}
trap '' HUP
trap cleanup EXIT
trap 'exit 1' INT TERM
if [ "$(id -u 2>/dev/null)" -eq 0 ]; then
safeEcho "$(basename -- "$0") must not be run as root."
exit 1
fi
if [ $# -lt 1 ]; then
safeEcho "$(basename -- "$0") requires at least one argument (the path to the directory that contains the ConcreteCMS installation)."
exit 1
fi
dirBase="$1"
if ! [ -d "$dirBase" ]; then
safeEcho "The specified directory '$dirBase' does not exist or is not a directory."
exit 1
fi
concreteBin="$dirBase/concrete/bin/concrete5"
if ! [ -f "$concreteBin" ]; then
safeEcho "The specified directory '$dirBase' does not appear to contain a ConcreteCMS installation (concrete/bin/concrete5 not found in it)."
exit 1
fi
shift
installLanguageArgs=$(buildInstallLanguageArgs "$@")
safeEcho '# Turning on maintenance mode'
"$concreteBin" --no-ansi --no-interaction --verbose c5:config -g set concrete.maintenance_mode true || exitWithError 'Failed to enable maintenance mode!'
resetMaintenanceMode=1
safeEcho 'Maintenance mode turned on.'
safeEcho
safeEcho '# Updating ConcreteCMS'
"$concreteBin" --no-ansi --no-interaction --verbose c5:update || exitWithError 'Failed to update ConcreteCMS!'
safeEcho 'ConcreteCMS updated.'
safeEcho
safeEcho '# Updating packages'
"$concreteBin" --no-ansi --no-interaction --verbose c5:package:update --all || exitWithError 'Failed to update packages!'
safeEcho
safeEcho "# Installing/updating translations ($( [ -z "$installLanguageArgs" ] && echo 'no args' || echo "args: $installLanguageArgs" ))"
if ! "$concreteBin" --no-ansi --no-interaction --verbose c5:install-language --update --core --packages $installLanguageArgs; then
safeEcho 'Failed to install/update translations!'
fi
safeEcho
safeEcho '# Refreshing Doctrine entities'
"$concreteBin" --no-ansi --no-interaction --verbose c5:entities:refresh || exitWithError 'Failed to refresh Doctrine entities!'
safeEcho
safeEcho '# Clearing ConcreteCMS cache'
"$concreteBin" --no-ansi --no-interaction --verbose c5:clear-cache || exitWithError 'Failed to clear ConcreteCMS cache!'
safeEcho
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment