Delete Mobile Accounts on macOS Devices
This comprehensive guide demonstrates how to delete mobile accounts on macOS devices for effective user management, device reassignment, and organizational cleanup scenarios.
Overview
Mobile accounts on macOS are user profiles designed for seamless access to resources across different devices within organizations. Unlike local accounts, mobile accounts are centrally managed by directory services like Open Directory or Active Directory, enabling administrators to control access, enforce policies, and manage user data centrally.
Common Scenarios for Mobile Account Deletion
- Employee departures: Clean up accounts when employees leave the organization
- Role changes: Remove old mobile accounts when users change positions
- Device reassignment: Prepare devices for new users
- Security compliance: Remove inactive or compromised accounts
- Storage optimization: Free up disk space by removing unused accounts
- Organizational restructuring: Clean up accounts during company changes
Basic Mobile Account Deletion
Simple Mobile Account Removal Script
Create a basic script to remove all mobile accounts from a macOS device:
#!/bin/bash
# Basic mobile account deletion script
# Usage: ./delete_mobile_accounts.sh
delete_mobile_accounts() {
echo "Starting mobile account deletion process..."
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "Error: This script must be run as root"
exit 1
fi
# Counter for deleted accounts
local deleted_count=0
# Loop through all users
for username in $(dscl . -list /Users | grep -v '^_'); do
# Check if user has mobile account authentication
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
echo "Removing mobile account: $username"
# Delete user from directory services
dscl . -delete "/Users/$username"
# Remove user's home directory
rm -rf "/Users/$username"
((deleted_count++))
fi
done
echo "Mobile accounts removal complete. Deleted $deleted_count accounts."
echo "Note: Please restart the device for changes to take full effect."
}
# Execute deletion
delete_mobile_accounts
Enhanced Mobile Account Management Script
#!/bin/bash
# Enhanced mobile account management with safety checks and logging
# Usage: ./enhanced_mobile_account_manager.sh
enhanced_mobile_account_manager() {
local log_file="/var/log/macfleet_mobile_accounts.log"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
local backup_dir="/var/backups/macfleet/mobile_accounts"
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "Error: This script must be run as root"
exit 1
fi
# Create log directory
mkdir -p /var/log
mkdir -p "$backup_dir"
echo "[$timestamp] Enhanced mobile account manager started" >> "$log_file"
# Display current mobile accounts
display_mobile_accounts
# Confirm deletion
echo ""
read -p "Do you want to proceed with mobile account deletion? (y/N): " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
create_account_backup
delete_mobile_accounts_enhanced
else
echo "Operation cancelled."
echo "[$timestamp] Mobile account deletion cancelled by user" >> "$log_file"
fi
}
display_mobile_accounts() {
echo "======================================="
echo "Current Mobile Accounts on Device"
echo "======================================="
local mobile_accounts_found=false
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
mobile_accounts_found=true
# Get additional user information
local real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | cut -d: -f2 | xargs)
local uid=$(dscl . -read "/Users/$username" UniqueID 2>/dev/null | cut -d: -f2 | xargs)
local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
local last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $3, $4, $5, $6}')
echo "Username: $username"
echo " Real Name: $real_name"
echo " UID: $uid"
echo " Home Directory: $home_dir"
echo " Last Login: $last_login"
# Check home directory size
if [ -d "$home_dir" ]; then
local dir_size=$(du -sh "$home_dir" 2>/dev/null | cut -f1)
echo " Home Directory Size: $dir_size"
fi
echo ""
fi
done
if [ "$mobile_accounts_found" = false ]; then
echo "No mobile accounts found on this device."
echo "[$timestamp] No mobile accounts found on device" >> "$log_file"
exit 0
fi
}
create_account_backup() {
echo "Creating backup of mobile account information..."
local backup_file="$backup_dir/mobile_accounts_backup_$(date +%Y%m%d_%H%M%S).txt"
cat > "$backup_file" << EOF
MacFleet Mobile Account Backup
Generated: $(date)
Device: $(scutil --get ComputerName)
macOS Version: $(sw_vers -productVersion)
Mobile Accounts Found:
EOF
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
echo "Username: $username" >> "$backup_file"
dscl . -read "/Users/$username" >> "$backup_file"
echo "---" >> "$backup_file"
fi
done
echo "Backup created: $backup_file"
echo "[$timestamp] Mobile account backup created: $backup_file" >> "$log_file"
}
delete_mobile_accounts_enhanced() {
echo "======================================="
echo "Deleting Mobile Accounts"
echo "======================================="
local deleted_count=0
local failed_count=0
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
echo "Processing mobile account: $username"
# Check if user is currently logged in
if who | grep -q "^$username "; then
echo " Warning: User $username is currently logged in. Skipping..."
echo "[$timestamp] Skipped deletion of $username - user currently logged in" >> "$log_file"
((failed_count++))
continue
fi
# Delete user from directory services
if dscl . -delete "/Users/$username" 2>/dev/null; then
echo " Deleted user record from directory services"
else
echo " Warning: Failed to delete user record from directory services"
echo "[$timestamp] Failed to delete user record for $username" >> "$log_file"
((failed_count++))
continue
fi
# Remove user's home directory
local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
if [ -d "$home_dir" ]; then
if rm -rf "$home_dir" 2>/dev/null; then
echo " Removed home directory: $home_dir"
else
echo " Warning: Failed to remove home directory: $home_dir"
echo "[$timestamp] Failed to remove home directory for $username: $home_dir" >> "$log_file"
fi
fi
echo " Successfully deleted mobile account: $username"
echo "[$timestamp] Successfully deleted mobile account: $username" >> "$log_file"
((deleted_count++))
fi
done
echo ""
echo "======================================="
echo "Mobile Account Deletion Summary"
echo "======================================="
echo "Successfully deleted: $deleted_count accounts"
echo "Failed to delete: $failed_count accounts"
echo "Total processed: $((deleted_count + failed_count)) accounts"
echo ""
echo "Note: Please restart the device for changes to take full effect."
echo "[$timestamp] Mobile account deletion completed - Success: $deleted_count, Failed: $failed_count" >> "$log_file"
}
# Execute enhanced management
enhanced_mobile_account_manager
Advanced Mobile Account Management
Selective Mobile Account Management
#!/bin/bash
# Selective mobile account management system
# Usage: ./selective_mobile_account_manager.sh
selective_mobile_account_manager() {
local log_file="/var/log/macfleet_selective_mobile_accounts.log"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "Error: This script must be run as root"
exit 1
fi
echo "[$timestamp] Selective mobile account manager started" >> "$log_file"
while true; do
display_selective_menu
read -p "Select an option (1-7): " choice
case $choice in
1)
list_mobile_accounts_detailed
;;
2)
delete_specific_mobile_account
;;
3)
delete_inactive_mobile_accounts
;;
4)
delete_mobile_accounts_by_criteria
;;
5)
export_mobile_account_report
;;
6)
restore_mobile_account_backup
;;
7)
echo "Exiting selective mobile account manager."
exit 0
;;
*)
echo "Invalid option. Please try again."
;;
esac
echo ""
read -p "Press Enter to continue..."
done
}
display_selective_menu() {
clear
echo "======================================="
echo "MacFleet Selective Mobile Account Manager"
echo "======================================="
echo ""
echo "1. List all mobile accounts with details"
echo "2. Delete specific mobile account"
echo "3. Delete inactive mobile accounts"
echo "4. Delete mobile accounts by criteria"
echo "5. Export mobile account report"
echo "6. Restore from backup"
echo "7. Exit"
echo ""
}
list_mobile_accounts_detailed() {
echo "======================================="
echo "Detailed Mobile Account Information"
echo "======================================="
local mobile_accounts=()
local count=0
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
mobile_accounts+=("$username")
((count++))
echo "[$count] Mobile Account: $username"
# Get detailed information
local real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | cut -d: -f2 | xargs)
local uid=$(dscl . -read "/Users/$username" UniqueID 2>/dev/null | cut -d: -f2 | xargs)
local gid=$(dscl . -read "/Users/$username" PrimaryGroupID 2>/dev/null | cut -d: -f2 | xargs)
local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
local shell=$(dscl . -read "/Users/$username" UserShell 2>/dev/null | cut -d: -f2 | xargs)
echo " Real Name: $real_name"
echo " UID: $uid"
echo " GID: $gid"
echo " Home Directory: $home_dir"
echo " Shell: $shell"
# Check if user is currently logged in
if who | grep -q "^$username "; then
echo " Status: Currently logged in"
else
echo " Status: Not logged in"
fi
# Get last login information
local last_login=$(last -1 "$username" 2>/dev/null | head -1)
if [ -n "$last_login" ]; then
echo " Last Login: $last_login"
else
echo " Last Login: Never"
fi
# Check home directory size
if [ -d "$home_dir" ]; then
local dir_size=$(du -sh "$home_dir" 2>/dev/null | cut -f1)
echo " Home Directory Size: $dir_size"
# Check last modification time
local last_modified=$(stat -f "%Sm" "$home_dir" 2>/dev/null)
echo " Last Modified: $last_modified"
else
echo " Home Directory: Not found"
fi
echo ""
fi
done
if [ $count -eq 0 ]; then
echo "No mobile accounts found on this device."
else
echo "Total mobile accounts found: $count"
fi
}
delete_specific_mobile_account() {
echo "======================================="
echo "Delete Specific Mobile Account"
echo "======================================="
# List mobile accounts with numbers
local mobile_accounts=()
local count=0
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
mobile_accounts+=("$username")
((count++))
echo "[$count] $username"
fi
done
if [ $count -eq 0 ]; then
echo "No mobile accounts found on this device."
return
fi
echo ""
read -p "Enter the number of the account to delete (1-$count): " selection
if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le $count ]; then
local selected_user="${mobile_accounts[$((selection-1))]}"
echo ""
echo "Selected account: $selected_user"
# Show account details
local real_name=$(dscl . -read "/Users/$selected_user" RealName 2>/dev/null | cut -d: -f2 | xargs)
local home_dir=$(dscl . -read "/Users/$selected_user" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
echo "Real Name: $real_name"
echo "Home Directory: $home_dir"
# Check if user is logged in
if who | grep -q "^$selected_user "; then
echo "Warning: User is currently logged in!"
read -p "Do you want to continue anyway? (y/N): " force_delete
if [ "$force_delete" != "y" ] && [ "$force_delete" != "Y" ]; then
echo "Deletion cancelled."
return
fi
fi
echo ""
read -p "Are you sure you want to delete this account? (y/N): " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
delete_single_mobile_account "$selected_user"
else
echo "Deletion cancelled."
fi
else
echo "Invalid selection."
fi
}
delete_single_mobile_account() {
local username="$1"
echo "Deleting mobile account: $username"
# Create backup of user data
local backup_dir="/var/backups/macfleet/mobile_accounts"
mkdir -p "$backup_dir"
local backup_file="$backup_dir/${username}_backup_$(date +%Y%m%d_%H%M%S).txt"
echo "Creating backup of user data..."
dscl . -read "/Users/$username" > "$backup_file"
# Delete user from directory services
if dscl . -delete "/Users/$username" 2>/dev/null; then
echo "User record deleted from directory services"
else
echo "Failed to delete user record from directory services"
return 1
fi
# Remove user's home directory
local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
if [ -d "$home_dir" ]; then
read -p "Do you want to remove the home directory? (y/N): " remove_home
if [ "$remove_home" = "y" ] || [ "$remove_home" = "Y" ]; then
if rm -rf "$home_dir"; then
echo "Home directory removed: $home_dir"
else
echo "Failed to remove home directory: $home_dir"
fi
else
echo "Home directory preserved: $home_dir"
fi
fi
echo "Successfully deleted mobile account: $username"
echo "Backup created: $backup_file"
echo "[$timestamp] Successfully deleted mobile account: $username" >> "$log_file"
}
delete_inactive_mobile_accounts() {
echo "======================================="
echo "Delete Inactive Mobile Accounts"
echo "======================================="
read -p "Enter number of days since last login to consider inactive (default: 30): " days_inactive
days_inactive=${days_inactive:-30}
echo "Searching for mobile accounts inactive for more than $days_inactive days..."
local inactive_accounts=()
local current_timestamp=$(date +%s)
local cutoff_timestamp=$((current_timestamp - (days_inactive * 24 * 60 * 60)))
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
# Check last login
local last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $3, $4, $5, $6}')
if [ -n "$last_login" ]; then
local last_login_timestamp=$(date -j -f "%a %b %d %H:%M:%S %Y" "$last_login" +%s 2>/dev/null)
if [ -n "$last_login_timestamp" ] && [ "$last_login_timestamp" -lt "$cutoff_timestamp" ]; then
inactive_accounts+=("$username")
echo "Inactive account found: $username (last login: $last_login)"
fi
else
# No login record found - consider as inactive
inactive_accounts+=("$username")
echo "Inactive account found: $username (no login record)"
fi
fi
done
if [ ${#inactive_accounts[@]} -eq 0 ]; then
echo "No inactive mobile accounts found."
return
fi
echo ""
echo "Found ${#inactive_accounts[@]} inactive mobile accounts."
read -p "Do you want to delete all inactive accounts? (y/N): " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
for username in "${inactive_accounts[@]}"; do
echo "Deleting inactive account: $username"
delete_single_mobile_account "$username"
done
echo "Inactive mobile accounts deletion completed."
else
echo "Deletion cancelled."
fi
}
delete_mobile_accounts_by_criteria() {
echo "======================================="
echo "Delete Mobile Accounts by Criteria"
echo "======================================="
echo "Available criteria:"
echo "1. By UID range"
echo "2. By home directory pattern"
echo "3. By real name pattern"
echo "4. By last login date"
echo ""
read -p "Select criteria (1-4): " criteria
case $criteria in
1)
delete_by_uid_range
;;
2)
delete_by_home_pattern
;;
3)
delete_by_name_pattern
;;
4)
delete_by_login_date
;;
*)
echo "Invalid criteria selected."
;;
esac
}
delete_by_uid_range() {
read -p "Enter minimum UID: " min_uid
read -p "Enter maximum UID: " max_uid
echo "Searching for mobile accounts with UID between $min_uid and $max_uid..."
local matching_accounts=()
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
local uid=$(dscl . -read "/Users/$username" UniqueID 2>/dev/null | cut -d: -f2 | xargs)
if [ "$uid" -ge "$min_uid" ] && [ "$uid" -le "$max_uid" ]; then
matching_accounts+=("$username")
echo "Found matching account: $username (UID: $uid)"
fi
fi
done
if [ ${#matching_accounts[@]} -eq 0 ]; then
echo "No mobile accounts found matching the UID criteria."
return
fi
echo ""
echo "Found ${#matching_accounts[@]} matching mobile accounts."
read -p "Do you want to delete all matching accounts? (y/N): " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
for username in "${matching_accounts[@]}"; do
delete_single_mobile_account "$username"
done
echo "Mobile accounts deletion by UID range completed."
else
echo "Deletion cancelled."
fi
}
delete_by_home_pattern() {
read -p "Enter home directory pattern (e.g., /Users/temp*): " pattern
echo "Searching for mobile accounts with home directory matching pattern: $pattern"
local matching_accounts=()
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
if [[ "$home_dir" == $pattern ]]; then
matching_accounts+=("$username")
echo "Found matching account: $username (Home: $home_dir)"
fi
fi
done
if [ ${#matching_accounts[@]} -eq 0 ]; then
echo "No mobile accounts found matching the home directory pattern."
return
fi
echo ""
echo "Found ${#matching_accounts[@]} matching mobile accounts."
read -p "Do you want to delete all matching accounts? (y/N): " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
for username in "${matching_accounts[@]}"; do
delete_single_mobile_account "$username"
done
echo "Mobile accounts deletion by home directory pattern completed."
else
echo "Deletion cancelled."
fi
}
delete_by_name_pattern() {
read -p "Enter real name pattern (e.g., *Test*): " pattern
echo "Searching for mobile accounts with real name matching pattern: $pattern"
local matching_accounts=()
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
local real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | cut -d: -f2 | xargs)
if [[ "$real_name" == $pattern ]]; then
matching_accounts+=("$username")
echo "Found matching account: $username (Real Name: $real_name)"
fi
fi
done
if [ ${#matching_accounts[@]} -eq 0 ]; then
echo "No mobile accounts found matching the real name pattern."
return
fi
echo ""
echo "Found ${#matching_accounts[@]} matching mobile accounts."
read -p "Do you want to delete all matching accounts? (y/N): " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
for username in "${matching_accounts[@]}"; do
delete_single_mobile_account "$username"
done
echo "Mobile accounts deletion by real name pattern completed."
else
echo "Deletion cancelled."
fi
}
delete_by_login_date() {
read -p "Enter cutoff date (YYYY-MM-DD): " cutoff_date
local cutoff_timestamp=$(date -j -f "%Y-%m-%d" "$cutoff_date" +%s 2>/dev/null)
if [ -z "$cutoff_timestamp" ]; then
echo "Invalid date format. Please use YYYY-MM-DD format."
return
fi
echo "Searching for mobile accounts with last login before $cutoff_date..."
local matching_accounts=()
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
local last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $3, $4, $5, $6}')
if [ -n "$last_login" ]; then
local last_login_timestamp=$(date -j -f "%a %b %d %H:%M:%S %Y" "$last_login" +%s 2>/dev/null)
if [ -n "$last_login_timestamp" ] && [ "$last_login_timestamp" -lt "$cutoff_timestamp" ]; then
matching_accounts+=("$username")
echo "Found matching account: $username (last login: $last_login)"
fi
else
# No login record - consider as before cutoff
matching_accounts+=("$username")
echo "Found matching account: $username (no login record)"
fi
fi
done
if [ ${#matching_accounts[@]} -eq 0 ]; then
echo "No mobile accounts found with last login before $cutoff_date."
return
fi
echo ""
echo "Found ${#matching_accounts[@]} matching mobile accounts."
read -p "Do you want to delete all matching accounts? (y/N): " confirm
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
for username in "${matching_accounts[@]}"; do
delete_single_mobile_account "$username"
done
echo "Mobile accounts deletion by login date completed."
else
echo "Deletion cancelled."
fi
}
export_mobile_account_report() {
echo "======================================="
echo "Export Mobile Account Report"
echo "======================================="
local report_file="/tmp/mobile_accounts_report_$(date +%Y%m%d_%H%M%S).txt"
cat > "$report_file" << EOF
MacFleet Mobile Account Report
Generated: $(date)
Device: $(scutil --get ComputerName)
macOS Version: $(sw_vers -productVersion)
Mobile Accounts Summary:
EOF
local count=0
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
((count++))
echo "" >> "$report_file"
echo "[$count] Username: $username" >> "$report_file"
# Get detailed information
local real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | cut -d: -f2 | xargs)
local uid=$(dscl . -read "/Users/$username" UniqueID 2>/dev/null | cut -d: -f2 | xargs)
local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
local last_login=$(last -1 "$username" 2>/dev/null | head -1)
echo " Real Name: $real_name" >> "$report_file"
echo " UID: $uid" >> "$report_file"
echo " Home Directory: $home_dir" >> "$report_file"
echo " Last Login: $last_login" >> "$report_file"
# Check if user is logged in
if who | grep -q "^$username "; then
echo " Status: Currently logged in" >> "$report_file"
else
echo " Status: Not logged in" >> "$report_file"
fi
# Check home directory size
if [ -d "$home_dir" ]; then
local dir_size=$(du -sh "$home_dir" 2>/dev/null | cut -f1)
echo " Home Directory Size: $dir_size" >> "$report_file"
fi
fi
done
echo "" >> "$report_file"
echo "Total Mobile Accounts: $count" >> "$report_file"
echo "Mobile account report exported to: $report_file"
}
restore_mobile_account_backup() {
echo "======================================="
echo "Restore Mobile Account Backup"
echo "======================================="
local backup_dir="/var/backups/macfleet/mobile_accounts"
if [ ! -d "$backup_dir" ]; then
echo "No backup directory found: $backup_dir"
return
fi
echo "Available backups:"
ls -la "$backup_dir"/*.txt 2>/dev/null || echo "No backup files found."
echo ""
read -p "Enter the backup filename to restore: " backup_file
if [ -f "$backup_dir/$backup_file" ]; then
echo "Backup file found: $backup_dir/$backup_file"
echo "Note: This feature shows backup content for reference."
echo "Manual restoration may be required for complex scenarios."
echo ""
cat "$backup_dir/$backup_file"
else
echo "Backup file not found: $backup_dir/$backup_file"
fi
}
# Execute selective management
selective_mobile_account_manager
Enterprise Mobile Account Management
Automated Mobile Account Cleanup
#!/bin/bash
# Automated mobile account cleanup for enterprise environments
# Usage: ./automated_mobile_cleanup.sh
automated_mobile_cleanup() {
local config_file="/etc/macfleet/mobile_cleanup_config.conf"
local log_file="/var/log/macfleet_automated_cleanup.log"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Check if running as root
if [ "$EUID" -ne 0 ]; then
echo "Error: This script must be run as root"
exit 1
fi
# Create configuration if it doesn't exist
if [ ! -f "$config_file" ]; then
create_cleanup_config
fi
source "$config_file"
echo "[$timestamp] Automated mobile account cleanup started" >> "$log_file"
# Execute cleanup based on configuration
execute_automated_cleanup
}
create_cleanup_config() {
mkdir -p /etc/macfleet
cat > "/etc/macfleet/mobile_cleanup_config.conf" << 'EOF'
# MacFleet Automated Mobile Account Cleanup Configuration
# Organization settings
ORGANIZATION_NAME="MacFleet Organization"
IT_CONTACT="support@macfleet.com"
# Cleanup criteria
CLEANUP_INACTIVE_DAYS="30"
CLEANUP_ENABLED="true"
PRESERVE_ADMIN_ACCOUNTS="true"
# Safety settings
REQUIRE_CONFIRMATION="true"
CREATE_BACKUP="true"
PRESERVE_HOME_DATA="false"
SKIP_LOGGED_IN_USERS="true"
# Notification settings
SEND_NOTIFICATIONS="true"
NOTIFICATION_EMAIL="admin@macfleet.com"
# Scheduling
ENABLE_SCHEDULED_CLEANUP="false"
CLEANUP_SCHEDULE="weekly"
CLEANUP_TIME="02:00"
# Logging
ENABLE_DETAILED_LOGGING="true"
LOG_RETENTION_DAYS="90"
EOF
echo "Cleanup configuration created at /etc/macfleet/mobile_cleanup_config.conf"
}
execute_automated_cleanup() {
echo "[$timestamp] Executing automated mobile account cleanup" >> "$log_file"
# Check if cleanup is enabled
if [ "$CLEANUP_ENABLED" != "true" ]; then
echo "[$timestamp] Automated cleanup is disabled" >> "$log_file"
echo "Automated cleanup is disabled in configuration."
return
fi
# Display cleanup configuration
echo "======================================="
echo "MacFleet Automated Mobile Account Cleanup"
echo "======================================="
echo "Organization: $ORGANIZATION_NAME"
echo "Cleanup inactive accounts older than: $CLEANUP_INACTIVE_DAYS days"
echo "Preserve admin accounts: $PRESERVE_ADMIN_ACCOUNTS"
echo "Create backup: $CREATE_BACKUP"
echo "Skip logged in users: $SKIP_LOGGED_IN_USERS"
echo ""
# Require confirmation if enabled
if [ "$REQUIRE_CONFIRMATION" = "true" ]; then
read -p "Do you want to proceed with automated cleanup? (y/N): " confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
echo "[$timestamp] Automated cleanup cancelled by user" >> "$log_file"
echo "Automated cleanup cancelled."
return
fi
fi
# Find accounts to cleanup
local accounts_to_cleanup=()
local current_timestamp=$(date +%s)
local cutoff_timestamp=$((current_timestamp - (CLEANUP_INACTIVE_DAYS * 24 * 60 * 60)))
echo "Scanning for mobile accounts to cleanup..."
for username in $(dscl . -list /Users | grep -v '^_'); do
auth_authority=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep "LocalCachedUser")
if [ -n "$auth_authority" ]; then
local should_cleanup=true
# Check if user is admin (if preservation is enabled)
if [ "$PRESERVE_ADMIN_ACCOUNTS" = "true" ]; then
if dscl . -read "/Groups/admin" GroupMembership 2>/dev/null | grep -q "$username"; then
echo "Skipping admin account: $username"
echo "[$timestamp] Skipped admin account: $username" >> "$log_file"
should_cleanup=false
fi
fi
# Check if user is logged in (if skip is enabled)
if [ "$SKIP_LOGGED_IN_USERS" = "true" ] && who | grep -q "^$username "; then
echo "Skipping logged in user: $username"
echo "[$timestamp] Skipped logged in user: $username" >> "$log_file"
should_cleanup=false
fi
# Check last login date
if [ "$should_cleanup" = true ]; then
local last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $3, $4, $5, $6}')
if [ -n "$last_login" ]; then
local last_login_timestamp=$(date -j -f "%a %b %d %H:%M:%S %Y" "$last_login" +%s 2>/dev/null)
if [ -n "$last_login_timestamp" ] && [ "$last_login_timestamp" -lt "$cutoff_timestamp" ]; then
accounts_to_cleanup+=("$username")
echo "Account marked for cleanup: $username (last login: $last_login)"
fi
else
# No login record - consider for cleanup
accounts_to_cleanup+=("$username")
echo "Account marked for cleanup: $username (no login record)"
fi
fi
fi
done
if [ ${#accounts_to_cleanup[@]} -eq 0 ]; then
echo "No mobile accounts found that meet cleanup criteria."
echo "[$timestamp] No mobile accounts found for cleanup" >> "$log_file"
return
fi
echo ""
echo "Found ${#accounts_to_cleanup[@]} mobile accounts for cleanup:"
for account in "${accounts_to_cleanup[@]}"; do
echo " - $account"
done
# Create backup if enabled
if [ "$CREATE_BACKUP" = "true" ]; then
create_automated_backup "${accounts_to_cleanup[@]}"
fi
# Cleanup accounts
local success_count=0
local failure_count=0
echo ""
echo "Starting automated cleanup..."
for username in "${accounts_to_cleanup[@]}"; do
echo "Processing: $username"
# Delete user from directory services
if dscl . -delete "/Users/$username" 2>/dev/null; then
echo " Deleted user record from directory services"
# Handle home directory based on configuration
local home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
if [ -d "$home_dir" ]; then
if [ "$PRESERVE_HOME_DATA" = "true" ]; then
echo " Preserved home directory: $home_dir"
else
if rm -rf "$home_dir" 2>/dev/null; then
echo " Removed home directory: $home_dir"
else
echo " Warning: Failed to remove home directory: $home_dir"
fi
fi
fi
echo " Successfully cleaned up account: $username"
echo "[$timestamp] Successfully cleaned up account: $username" >> "$log_file"
((success_count++))
else
echo " Failed to cleanup account: $username"
echo "[$timestamp] Failed to cleanup account: $username" >> "$log_file"
((failure_count++))
fi
done
# Generate cleanup summary
echo ""
echo "======================================="
echo "Automated Cleanup Summary"
echo "======================================="
echo "Total accounts processed: ${#accounts_to_cleanup[@]}"
echo "Successfully cleaned up: $success_count"
echo "Failed to cleanup: $failure_count"
echo "Cleanup completed at: $(date)"
echo "[$timestamp] Automated cleanup completed - Success: $success_count, Failed: $failure_count" >> "$log_file"
# Send notification if enabled
if [ "$SEND_NOTIFICATIONS" = "true" ]; then
send_cleanup_notification "$success_count" "$failure_count"
fi
echo ""
echo "Note: Please restart the device for changes to take full effect."
}
create_automated_backup() {
local accounts=("$@")
local backup_dir="/var/backups/macfleet/automated_cleanup"
local backup_file="$backup_dir/cleanup_backup_$(date +%Y%m%d_%H%M%S).txt"
mkdir -p "$backup_dir"
echo "Creating backup of accounts to be cleaned up..."
cat > "$backup_file" << EOF
MacFleet Automated Cleanup Backup
Generated: $(date)
Device: $(scutil --get ComputerName)
Organization: $ORGANIZATION_NAME
Cleanup Criteria: Inactive for $CLEANUP_INACTIVE_DAYS days
Accounts to be cleaned up:
EOF
for username in "${accounts[@]}"; do
echo "" >> "$backup_file"
echo "Username: $username" >> "$backup_file"
dscl . -read "/Users/$username" >> "$backup_file" 2>/dev/null
echo "---" >> "$backup_file"
done
echo "Backup created: $backup_file"
echo "[$timestamp] Automated cleanup backup created: $backup_file" >> "$log_file"
}
send_cleanup_notification() {
local success_count=$1
local failure_count=$2
local notification_subject="MacFleet Mobile Account Cleanup Report"
local notification_body="Automated mobile account cleanup completed.
Device: $(scutil --get ComputerName)
Organization: $ORGANIZATION_NAME
Cleanup Date: $(date)
Results:
- Successfully cleaned up: $success_count accounts
- Failed to cleanup: $failure_count accounts
- Total processed: $((success_count + failure_count)) accounts
For detailed logs, check: /var/log/macfleet_automated_cleanup.log
Contact: $IT_CONTACT"
# Use osascript to display notification (for local notifications)
osascript -e "display notification \"Cleanup completed: $success_count success, $failure_count failed\" with title \"MacFleet Mobile Account Cleanup\""
echo "[$timestamp] Cleanup notification sent" >> "$log_file"
}
# Execute automated cleanup
automated_mobile_cleanup
Troubleshooting and Best Practices
Common Issues and Solutions
- Permission Errors: Always run scripts as root using
sudo
- Logged-in Users: Check for active sessions before deletion
- Directory Services: Verify mobile account identification using
LocalCachedUser
attribute - Home Directory Protection: Create backups before removing home directories
- Network Accounts: Ensure network connectivity for directory service operations
Best Practices
- Test First: Always test scripts in controlled environments
- Create Backups: Maintain backups of user data before deletion
- Log Operations: Keep detailed logs of all account operations
- User Communication: Notify users before account cleanup
- Schedule Maintenance: Perform cleanup during maintenance windows
Conclusion
Mobile account management is crucial for maintaining clean and secure macOS environments. These scripts provide comprehensive solutions for deleting mobile accounts, from simple cleanup to enterprise-grade automation. Always ensure proper testing and backup procedures before implementing in production environments.