#!/bin/bash if ! [ "${LOGNAME}" == "root" ]; then echo "Please run this script as root or with sudo..." exit 1 fi ################################################################################ # Global variables ################################################################################ TIMEOUT="60s" MODE="" ################################################################################ # Functions ################################################################################ show_help() { cat << HELP Check the brick logs of a repository for "Permission denied" errors due to lost permissions while expanding. Normally folders look like # stat /gluster/repositories/hydmedia//HYD$/data/current/VOLUME3692/169 File: /gluster/repositories/hydmedia//HYD$/data/current/VOLUME3692/169 Size: 4096 Blocks: 8 IO Block: 131072 directory Device: 48h/72d Inode: 12128098184435013363 Links: 2 Access: (0000/d---------) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2026-04-20 11:51:40.722905693 +0000 Modify: 2026-04-20 12:40:36.049491386 +0000 Change: 2026-04-20 12:40:36.049491386 +0000 Birth: - Owner and group should be fsnobody Access should be 0755 Usage: $1 [OPTION] Mandatory: -r|--repo REPO The repository to check Optionial: -t|--timeout TIMEOUT Timout to wait after scanning the brick logs for the next iteration (DEFAULT: ${TIMEOUT} -m|--mode MODE Scan for names or GFIDs. (DEFAULT: both) HELP exit 0 } get_bricks() { MY_HOSTNAME=$(echo "${HOSTNAME}" | cut -d '.' -f 1) if ! BRICKS=$(gluster vol info "${REPO}" | grep -i "${MY_HOSTNAME}" | grep -o 'brick[0-9]\+'); then return 1 fi for BRICK in ${BRICKS}; do BRICK_LOGS="${BRICK_LOGS} /var/log/glusterfs/bricks/*${BRICK}*log" done } header() { echo "################################################################################" date echo "Checking following logs:" for BRICK_LOG in ${BRICK_LOGS}; do echo " ${BRICK_LOG}" done echo "" } get_pathnames_by_name() { PATHNAMES_BY_NAME=$(zgrep "error=Permission denied" ${BRICK_LOGS} | grep -o 'path=\S\+' | cut -d '=' -f 2 | egrep -v '' -f 1 | sort -u) PATHNAMES_BY_GFID="" for GFID in ${GFIDS}; do NEW_PATHNAME=$(getfattr -n glusterfs.ancestry.path -e text /gluster/repositories/"${REPO}"/.gfid/"${GFID}" |& grep glusterfs.ancestry.path | cut -d '=' -f 2 | sed -e's/\"//g') PATHNAMES_BY_GFID="${PATHNAMES_BY_GFID} ${NEW_PATHNAME}" done } scan_paths() { while true; do header if [ "${MODE}" == "names" ] || [ "${MODE}" == "" ]; then get_pathnames_by_name fi if [ "${MODE}" == "gfid" ] || [ "${MODE}" == "" ]; then get_pathnames_by_gfid fi PATHNAMES="${PATHNAMES_BY_NAME} ${PATHNAMES_BY_GFID}" echo "Folders fixed:" for PATHNAME in ${PATHNAMES}; do if [ -f /gluster/repositories/"${REPO}"/"${PATHNAME}" ]; then PATHNAME=$(dirname "${PATHNAME}") fi if [ -d /gluster/repositories/"${REPO}"/"${PATHNAME}" ]; then find /gluster/repositories/"${REPO}"/"${PATHNAME}" -maxdepth 0 -type d -perm 0000 -exec chown fsnobody: "{}" \; -exec chmod 0755 "{}" \; -printf '%p\n' fi done sleep "${TIMEOUT}" done } ################################################################################ # Argument parser ################################################################################ die() { printf '%s\n' "$1" >&2 exit 1 } while :; do case $1 in -h|-\?|--help) show_help # Display a usage synopsis. exit ;; -r|--repo) if [ "$2" ]; then REPO=$2 shift else die 'ERROR: "-r|--repo" requires a non-empty option argument.' fi ;; -m|--mode) if [ "$2" ]; then MODE=$2 shift else die 'ERROR: "-r|--repo" requires a non-empty option argument.' fi ;; -t|--timeout) if [ "$2" ]; then TIMEOUT=$2 shift else die 'ERROR: "-t|--timeout" requires a non-empty option argument.' fi ;; --) # End of all options. shift break ;; *) # Default case: No more options, so break out of the loop. break esac shift done ################################################################################ # Main Main Main ################################################################################ if [ "${REPO}" == "" ]; then echo "Repository is needed" exit 1 fi if ! get_bricks; then echo "Could not get bricks of repository \"${REPO}\". Will exit now..." exit 1 fi scan_paths