From 2013da5a920b2e656645c8b55aecc44738b39a5e Mon Sep 17 00:00:00 2001 From: Thomas Gebert Date: Thu, 7 May 2026 13:56:47 +0200 Subject: [PATCH] Add script to check brick logs for permission denied This script helps to find permission denied in realtion to wrong folder permissions during a repo expansion. It scans the brick logs of the given repository and tries to fix permissions and ownership of the folders. Additionally a find over the whole repo should be run in paralllel. This script is only intended to help against errors actually happens due to access attemps. --- gluster/check-and-fix-permissions.sh | 173 +++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 gluster/check-and-fix-permissions.sh diff --git a/gluster/check-and-fix-permissions.sh b/gluster/check-and-fix-permissions.sh new file mode 100644 index 0000000..1c61808 --- /dev/null +++ b/gluster/check-and-fix-permissions.sh @@ -0,0 +1,173 @@ +#!/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 +} + +################################################################################ +# 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 + +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 +} + +################################################################################ +# 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