Skip to content

Instantly share code, notes, and snippets.

@efann
Last active August 23, 2024 16:59
Show Gist options
  • Select an option

  • Save efann/30816efae16b663ffa02 to your computer and use it in GitHub Desktop.

Select an option

Save efann/30816efae16b663ffa02 to your computer and use it in GitHub Desktop.
Refresh/Maintain Drupal Script
#!/bin/bash
# License: Eclipse Public License - v 2.0 (https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html)
# Updated on August 23, 2024
# From http://drupal.stackexchange.com/questions/373/what-are-the-recommended-directory-permissions
# And more recent
# https://www.drupal.org/node/244924
#------------------------------------------------------------------------------
function updateVendorBinRights {
declare -r lcBinFolder="$1"
if [ -d "${lcBinFolder}" ]; then
echo -e "Changing ${lcBinFolder} permissions. . . .\n"
chmod +x "${lcBinFolder}"/*
ls -l "${lcBinFolder}"
echo -e "\n=====================================\n"
else
echo - e "${lcBinFolder} does not exist!!"
exit
fi
}
#------------------------------------------------------------------------------
DRUSHTEST="$(which drush)"
if [ -z "$DRUSHTEST" ]; then
echo -e "\nThis script needs drush installed. You can find more information here: https://docs.drush.org/en/master/install/. Exiting. . . .\n\n"
exit 1
fi
# From https://stackoverflow.com/questions/3976362/bash-scripts-requiring-sudo-password
# Force asking for the password, so you don't have to wait till running the below external scripts.
if [[ ! $(sudo echo 0) ]]; then
echo -e "sudo password was not correct. Exiting. . . .\n\n"
exit
fi
# From https://github.com/composer/composer/issues/6195
# Otherwise, composer will run a sudo -K command in Application.php, around line #273,
# which silently clobbers any sudo credentials. And you will be prompted again for a sudo password.
# Geesh. . . .
export COMPOSER_ALLOW_SUPERUSER=1
llSuperUser=0
llAll=0
# First, we initialize the $lcWebFolder & $lcWebFolderSites
# Default to /home/<user>/public_html
# These variables tend to be over-ridden by arguments.
lcWebFolder=/home/"$(whoami)"/public_html
lcWebFolderSites="$lcWebFolder"/sites
# Next try /home/user/public_html/drupal if sites doesn't exist.
if [ ! -d "$lcWebFolderSites" ]; then
lcWebFolder=/home/"$(whoami)"/public_html/drupal
lcWebFolderSites="$lcWebFolder"/sites
fi
# From http://stackoverflow.com/questions/15696636/looping-over-arguments-in-bash
for ((i = 1; i <= $#; i++)); do
lnNext=$((i + 1))
lnPrev=$((i - 1))
lcCurrent="${!i}"
lcNext="${!lnNext}"
lcPrev="${!lnPrev}"
# If the first argument does not start with a dash, then assume it's a base folder name.
if [ $i == 1 ]; then
if [ "${lcCurrent:0:1}" != '-' ]; then
# Remove trailing backslash, if exists, from lcCurrent.
lcWebFolder=/var/www/"${lcCurrent%/}"/public_html
lcWebFolderSites="$lcWebFolder"/sites
fi
fi
case "$lcCurrent" in
-h | --help)
echo -e "\n$0 -h -folder <drupal folder> -root allow.\n"
echo -e "-h: displays this help screen.\n"
echo -e "-folder: overrides the default Drupal folder of /home/$(whoami)/public_html.\n"
echo -e "-root allow: allows the root to run this script.\n"
exit 0
;;
-root)
if [ "$lcNext" = "allow" ]; then
llSuperUser=1
fi
;;
-folder)
lcWebFolder="$lcNext"
lcWebFolderSites="$lcWebFolder"/sites
;;
-all)
llAll=1
;;
esac
done
if [ $llSuperUser -eq 0 ]; then
# Make sure that root cannot run the script.
if [[ $EUID -eq 0 ]]; then
echo -e "\nThis script may not be run as root. Exiting. . . .\n\n"
exit 1
fi
else
echo -e "\nRoot may run this script. . . ."
fi
if [ ! -d "$lcWebFolder" ]; then
echo -e "\nDrupal main folder, $lcWebFolder, does not exist. Exiting. . . .\n\n"
exit 1
fi
if [ ! -d "$lcWebFolderSites" ]; then
echo -e "\nSites folder for Drupal, $lcWebFolderSites, does not exist. Exiting. . . .\n\n"
exit 1
fi
# ------------------------------------
# Ensure that all files match the owner:group of the Drupal folder
# ------------------------------------
lcOwner=$(stat -c '%U' $lcWebFolder)
lcGroup=$(stat -c '%G' $lcWebFolder)
# I found that even if I change the value of folder group
# it gets changed back to nobody at a later time . . . probably by cPanel / WHM
# and their bookkeeping.
if [ "$lcGroup" == "nobody" ]; then
lcGroup="$lcOwner"
fi
llWwwData=0
if [ "$lcGroup" == "www-data" ]; then
llWwwData=1
fi
if [ $llWwwData == 1 ]; then
sudo chown -R "$lcOwner":"$lcGroup" "$lcWebFolder"
else
chown -R "$lcOwner":"$lcGroup" "$lcWebFolder"
fi
# ------------------------------------
# Change to the Drupal folder
# ------------------------------------
echo -e "Changing to $lcWebFolder. . . .\n"
cd "$lcWebFolder"
declare -r VENDOR_BIN_FOLDER="./vendor/bin"
updateVendorBinRights "${VENDOR_BIN_FOLDER}"
# From https://github.com/drush-ops/drush-launcher/issues/106
# Now test drush as drush launcher does not work with drush 12+
lcDrushTest="$(drush version)"
DRUSH="drush"
if [[ "${lcDrushTest}" == *" Composer "* ]]; then
DRUSH="${VENDOR_BIN_FOLDER}/drush"
fi
echo -e "Using ${DRUSH}\n"
# ------------------------------------
# Ensure that the config_sync_directory exists.
# ------------------------------------
# Realize that Apache is setup to access /var/www. It's not setup to access /tmp or /tmp/drupal.SyncTmp
CONFIG_SYNC_TMP="$(${DRUSH} core-status --fields=*)"
# From https://unix.stackexchange.com/questions/145672/print-last-element-of-each-row
# Get the last field using awk and NF, the variable holding the total count of fields or words.
CONFIG_SYNC=$(echo "${CONFIG_SYNC_TMP#*:}" | grep 'Drupal config' | awk '{print $NF}')
if [ -z "$CONFIG_SYNC" ]; then
echo -e "\nThis site needs the following set in settings.php: \$settings['config_sync_directory']. Exiting. . . .\n\n"
exit 1
fi
echo -e "config_sync_directory: $CONFIG_SYNC\n"
if [ ! -d "$CONFIG_SYNC" ]; then
echo -e "$CONFIG_SYNC is missing so will try to re-create. . . .\n"
sudo mkdir -p "$CONFIG_SYNC"
if [ ! -d "$CONFIG_SYNC" ]; then
echo -e "\nConfig Sync Directory does not exist: $CONFIG_SYNC. Exiting. . . .\n\n"
exit 1
fi
fi
echo -e "\nConfig Sync Directory exists ($CONFIG_SYNC)\n"
echo -e "Ensuring that the permissions are correct.\n"
sudo chown -R "$lcOwner":"$lcGroup" "$CONFIG_SYNC"
ls -ld "$CONFIG_SYNC"
# ------------------------------------
# Update permissions
# ------------------------------------
echo -e "\nChanging file permissions. . . .\n"
find . -type f -exec chmod 644 '{}' \;
echo -e "Changing directory permissions. . . .\n"
find . -type d -exec chmod 755 '{}' \;
echo -e "Changing settings.php permissions. . . .\n"
find -name settings.php -type f -exec chmod 440 '{}' \;
# From Drupal Security Review module
laFolders=("./includes" "./misc" "./modules" "./profiles" "./scripts" "./themes")
for lcFolder in "${laFolders[@]}"; do
if [ -d "$lcFolder" ]; then
echo -e "Changing Drupal $lcFolder directory permissions. . . .\n"
find "$lcFolder" -type f -exec chmod 644 '{}' \;
fi
done
# Run again as the rights get reset.
updateVendorBinRights "${VENDOR_BIN_FOLDER}"
# ------------------------------------
# Change to the sites folder
# ------------------------------------
echo -e "Changing to $lcWebFolderSites. . . ."
cd "$lcWebFolderSites"
lcPWD=$(pwd)
lcFilesDir="files"
for lcSettingsPHP in $(find -name "settings.php"); do
lcPath="$(dirname $lcSettingsPHP)"
echo -e "Changing to $lcPath. . . .\n"
cd "$lcPath"
if [ -d "$lcFilesDir" ]; then
echo -e "Running chmod -R 775 $lcFilesDir. . . .\n"
chmod -R 775 "$lcFilesDir"
fi
# From https://www.drupal.org/node/244924
echo -e "Setting recommended rights for folder structures under files/"
for lcFiles in files/*; do
echo -e " $lcFiles"
if [ $llWwwData == 1 ]; then
find "$lcFiles" -type d -exec chmod ug=rwx,o= '{}' \;
find "$lcFiles" -type f -exec chmod ug=rw,o= '{}' \;
else
find "$lcFiles" -type d -exec chmod ug=rwx,o=rx '{}' \;
find "$lcFiles" -type f -exec chmod ug=rw,o=r '{}' \;
fi
done
echo -e ""
echo -e "Changing to $lcWebFolder. . . ."
cd "$lcWebFolder"
"${DRUSH}" status
# Determine the major version of Drupal.
lcDrupalVersion=$("${DRUSH}" status | grep -i 'Drupal version' | cut -d ":" -f2)
# Trim the string.
lcDrupalVersion=${lcDrupalVersion//[[:blank:]]/}
# Grab the first character and convert to an integer.
# By the way, bash works well with integers, not floats.
# And we just need to know if Drupal 8 or above.
# From https://stackoverflow.com/questions/18015233/get-the-value-before-decimal-point
lnDrupalVersion="$((${lcDrupalVersion%%.*} + 0))"
if [ $llAll == 1 ]; then
if [ $lnDrupalVersion -ge 9 ]; then
# From https://drupal.stackexchange.com/questions/269305/how-can-i-update-core-all-the-modules-and-the-themes-from-the-command-line
composer update drupal/* --with-all-dependencies
"${DRUSH}" updatedb -y
composer outdated "drupal/*"
composer update
if [ $lnDrupalVersion -ge 10 ]; then
composer audit
else
"${DRUSH}" pm:security
fi
else
"${DRUSH}" updatedb -y
"${DRUSH}" pm-update -y
fi
fi
if [ $lnDrupalVersion -ge 8 ]; then
"${DRUSH}" cr
else
"${DRUSH}" cc all
fi
echo -e "Changing back to $lcPWD. . . .\n"
cd "$lcPWD"
done
# End of file
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment