Skip to content

Instantly share code, notes, and snippets.

@TheNoiselessNoise
Created December 29, 2024 22:15
Show Gist options
  • Select an option

  • Save TheNoiselessNoise/3c3746d6b21ae471db45b942a78a0b27 to your computer and use it in GitHub Desktop.

Select an option

Save TheNoiselessNoise/3c3746d6b21ae471db45b942a78a0b27 to your computer and use it in GitHub Desktop.
Linux - Fix permissions on accidental bad chown -R
#!/bin/bash
# Color and style definitions
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}${BOLD}Please run as root${NC}"
exit 1
fi
# Initialize log files
LOG_DIR="/var/log/permission-fix"
SUCCESS_LOG="${LOG_DIR}/success.log"
ERROR_LOG="${LOG_DIR}/error.log"
WARN_LOG="${LOG_DIR}/warning.log"
mkdir -p "$LOG_DIR"
date > "$SUCCESS_LOG"
date > "$ERROR_LOG"
date > "$WARN_LOG"
# Logging functions
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a "$SUCCESS_LOG"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a "$ERROR_LOG"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a "$WARN_LOG"
}
# Format functions
format_path() {
echo -e "${BLUE}${BOLD}$1${NC}"
}
format_perms() {
echo -e "${MAGENTA}${BOLD}$1${NC}"
}
format_ownership() {
echo -e "${CYAN}${BOLD}$1${NC}"
}
# Check functions
user_exists() {
id "$1" >/dev/null 2>&1
}
group_exists() {
getent group "$1" >/dev/null 2>&1
}
# Define permissions and ownership in a hierarchical structure
# Format: "path:owner:group:permissions:recursive"
# permissions: optional octal format, e.g. 755
# example 1: "/var/log:root:adm:750:false"
# example 2: "/var/log:root:adm::false
declare -a PERMISSION_LIST=(
# Base directories
"/var:root:root:755:false"
"/var/backups:root:root:755:false"
"/var/cache:root:root:755:false"
"/var/crash:root:root:755:false"
"/var/lib:root:root:755:false"
"/var/local:root:root:755:false"
"/var/lock:root:root:755:false"
"/var/log:root:root:755:false"
"/var/mail:root:mail:2775:false"
"/var/opt:root:root:755:false"
"/var/run:root:root:755:false"
"/var/spool:root:root:755:false"
"/var/tmp:root:root:1777:false"
# Special directories with recursive permissions
# graphical desktop managers
"/var/lib/gdm3:gdm:gdm::true"
# Web servers
"/var/www:www-data:www-data:755:true"
"/var/log/apache2:www-data:adm:750:false"
"/var/log/nginx:www-data:adm:750:false"
# Databases
"/var/lib/mysql:mysql:mysql:750:true"
"/var/log/mysql:mysql:adm:750:false"
"/var/run/mysqld:mysql:mysql:755:false"
"/var/lib/postgresql:postgres:postgres:750:true"
"/var/log/postgresql:postgres:adm:750:false"
# Mail servers
"/var/spool/postfix:postfix:postfix:750:true"
"/var/log/mail:root:adm:750:false"
# Print server
"/var/spool/cups:root:lp:755:true"
"/var/log/cups:root:lp:750:false"
# SSH
"/var/log/ssh:root:adm:750:false"
# PHP-FPM
"/var/log/php-fpm:www-data:adm:750:false"
"/var/run/php-fpm:www-data:www-data:755:false"
# System services
"/var/lib/systemd:root:root:755:true"
"/var/log/journal:root:systemd-journal:2755:false"
# Container runtimes
"/var/lib/docker:root:docker:710:false"
"/var/run/docker.sock:root:docker:660:false"
"/var/lib/containerd:root:root:711:false"
"/var/lib/podman:root:root:700:false"
# Package management
"/var/cache/apt:root:root:755:false"
"/var/lib/apt:root:root:755:false"
)
# Optional mount point for Live USB recovery
MOUNT_POINT=""
if [ "$1" ]; then
MOUNT_POINT="$1"
echo -e "Using mount point: $(format_path "$MOUNT_POINT")"
log_warning "Using custom mount point: $MOUNT_POINT"
fi
fix_permissions() {
local entry=$1
IFS=':' read -r path owner group permissions recursive <<< "$entry"
local full_path="${MOUNT_POINT}${path}"
local success=true
# Check if directory exists
if [ ! -d "$full_path" ]; then
log_error "Directory does not exist: $(format_path "$full_path")"
return 1
fi
# Validate owner and group
if ! user_exists "$owner"; then
log_error "User '$(format_ownership "$owner")' does not exist for $(format_path "$path")"
return 1
fi
if ! group_exists "$group"; then
log_error "Group '$(format_ownership "$group")' does not exist for $(format_path "$path")"
return 1
fi
# Apply ownership
local chown_cmd="chown"
[ "$recursive" = "true" ] && chown_cmd="chown -R"
if ! $chown_cmd "$owner:$group" "$full_path" 2>/dev/null; then
log_error "Failed to set $([ "$recursive" = "true" ] && echo "recursive ")ownership $(format_ownership "$owner:$group") on $(format_path "$path")"
success=false
else
log_success "Set $([ "$recursive" = "true" ] && echo "recursive ")ownership $(format_ownership "$owner:$group") on $(format_path "$path")"
fi
# Apply permissions if specified
if [ -n "$permissions" ]; then
local chmod_cmd="chmod"
[ "$recursive" = "true" ] && chmod_cmd="chmod -R"
if ! $chmod_cmd "$permissions" "$full_path" 2>/dev/null; then
log_error "Failed to set $([ "$recursive" = "true" ] && echo "recursive ")permissions $(format_perms "$permissions") on $(format_path "$path")"
success=false
else
log_success "Set $([ "$recursive" = "true" ] && echo "recursive ")permissions $(format_perms "$permissions") on $(format_path "$path")"
fi
fi
# Check if any attributes couldn't be set due to read-only filesystem
if ! touch "$full_path" 2>/dev/null; then
log_warning "Read-only filesystem detected for $(format_path "$path")"
fi
return $([ "$success" = true ])
}
log_warning "Starting new permission recovery session"
# Statistics variables
declare -i total=0
declare -i succeeded=0
declare -i failed=0
# Process each directory in order
for entry in "${PERMISSION_LIST[@]}"; do
((total++))
if fix_permissions "$entry"; then
((succeeded++))
else
((failed++))
fi
done
log_warning "Completed: ${GREEN}${BOLD}$succeeded${NC}/${total} succeeded, ${RED}${BOLD}$failed${NC} failed"
echo -e "\n${YELLOW}${BOLD}Logs are available at:${NC}"
echo -e "Success log: ${GREEN}${BOLD}$SUCCESS_LOG${NC}"
echo -e "Error log: ${RED}${BOLD}$ERROR_LOG${NC}"
echo -e "Warning log: ${YELLOW}${BOLD}$WARN_LOG${NC}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment