Last active
February 25, 2024 03:46
-
-
Save jordanlambrecht/7edce0914e5ae2785e0fce0880adf94c to your computer and use it in GitHub Desktop.
MacOS: Create New System User
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
## This code is based off of https://raw.githubusercontent.com/Servarr/Wiki/master/servarr/servarr-install-script.sh and re-worked for MacOS users | |
### Boilerplate Warning | |
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
#EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
#MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
#NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | |
#LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | |
#OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
#WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
## Remixed by Jordan Lambrecht (https://github.com/jordanlambrecht) | |
scriptversion="3.0.11" | |
scriptdate="2024-2-24" | |
set -euo pipefail | |
printf "\n" | |
echo "Running Servarr Install Script - Version [$scriptversion] as of [$scriptdate]" | |
printf "\n" | |
bold=$(tput bold) | |
normal=$(tput sgr0) | |
# Ensure the script is run with root privileges | |
if [ "$EUID" -ne 0 ]; then | |
echo "Please run as root." | |
exit | |
fi | |
echo "${bold}🚨 DANGER 🚨 This script is hella powerful and may cause permanent damage to your file system. Use at your own risk${normal}" | |
printf "\n" | |
echo "📋 Listing all user-defined groups (excluding system and specific groups):" | |
# Initialize counter for formatting output | |
counter=0 | |
echo "---------------------------------------------------------------------------------------------------------------------" | |
# Retrieve, sort, and filter groups, then process each line | |
dscl . -list /Groups PrimaryGroupID | sort | while IFS= read -r line; do | |
group_name=$(echo "$line" | awk '{print $1}') | |
group_id=$(echo "$line" | awk '{print $2}') | |
# Exclude groups starting with '_', containing 'com.apple.', or matching specific names | |
if ! [[ $group_name =~ ^_ || $group_name =~ com.apple. || $group_name =~ ^(wheel|sys|tty|utmp|procview|procmod|kmem)$ ]]; then | |
# Print group info with formatting, three names per row | |
printf "%-1s %8s %-30s" "|" "[$group_id]" "${bold}$group_name${normal}" | |
((counter++)) | |
if (( counter % 3 == 0 )); then | |
printf "\n" | |
fi | |
fi | |
done | |
# Ensure there's a newline at the end of the output if the last line wasn't complete | |
if (( counter % 3 != 0 )); then | |
printf "\n" | |
fi | |
printf "\n" | |
echo "---------------------------------------------------------------------------------------------------------------------" | |
read -r -p "${bold}✌️ Hi there.${normal} Enter the name of the group you would like to use or create (Default: staff): " app_group_name | |
app_group_name=$(echo "${app_group_name:-staff}" | tr -d ' ') | |
if dscl . -read /Groups/"$app_group_name" &>/dev/null; then | |
app_group_id=$(dscl . -read /Groups/"$app_group_name" PrimaryGroupID | awk '{print $2}') | |
echo "⚠️ Group name already exists as group number ${bold}$app_group_id${normal}. Using this group." | |
else | |
echo "✅ Group does not exist yet. We'll create a new one." | |
while true; do | |
read -r -p "Enter a group ID to use (or hit enter to auto-assign): " app_group_id | |
if [ -z "$app_group_id" ]; then | |
# Auto-assign logic | |
highest_group_id=$(dscl . -list /Groups PrimaryGroupID | awk '{print $2}' | sort -n | tail -1) | |
app_group_id=$((highest_group_id + 1)) | |
echo "🤖 Auto-assigned group ID is $app_group_id." | |
sudo dscl . -create /Groups/"$app_group_name" | |
sudo dscl . -create /Groups/"$app_group_name" PrimaryGroupID "$app_group_id" | |
echo "✅ Created Group [$app_group_name] with auto-assigned ID [$app_group_id]." | |
break | |
elif ! dscl . -read /Groups gid "$app_group_id" &>/dev/null; then | |
echo "✅ Group ID $app_group_id is available." | |
sudo dscl . -create /Groups/"$app_group_name" | |
sudo dscl . -create /Groups/"$app_group_name" PrimaryGroupID "$app_group_id" | |
echo "✅ Created Group [$app_group_name] with specified ID [$app_group_id]." | |
break | |
else | |
existing_group_name=$(dscl . -search /Groups PrimaryGroupID "$app_group_id" | awk '{print $1}') | |
echo "❗️ Group ID $app_group_id already exists for group $existing_group_name." | |
read -r -p "Use this group? (y/n): " decision | |
if [[ "$decision" =~ ^[yY]$ ]]; then | |
app_group_name="$existing_group_name" | |
echo "✅ Using existing group $app_group_name with ID $app_group_id." | |
break | |
else | |
echo "❌ Please enter a new group ID." | |
fi | |
fi | |
done | |
fi | |
# Prompt for the username | |
read -r -p "✍️ Enter the name of the user you would like to create: " app_username | |
app_username=$(echo "$app_username" | tr -d ' ') | |
# Prompt for a unique identifier for the user, though macOS generally handles this automatically | |
read -r -p "✍️ Enter a unique ID for the user (leave blank to auto-generate): " app_uid | |
echo "This will create user ${bold}$app_username${normal} with UID ${bold}$app_uid${normal}, and add to group ${bold}$app_group_name${normal}." | |
# Wait for user confirmation | |
read -n 1 -r -s -p $'Press enter to continue or ctrl+c to exit...\n' | |
# Now, determine if the user exists | |
if ! dscl . -read /Users/"$app_username" &>/dev/null; then | |
# User does not exist, create the user and set primary group | |
if [ -z "$app_uid" ]; then | |
sudo sysadminctl -addUser "$app_username" -fullName "$app_username" -password "" -home "" -admin | |
else | |
sudo sysadminctl -addUser "$app_username" -UID "$app_uid" -fullName "$app_username" -password "" -home "" -admin | |
fi | |
echo "✅Created User ${bold}$app_username${normal} successfully." | |
# Set the primary group ID for the new user | |
sudo dscl . -create /Users/"$app_username" PrimaryGroupID "$app_group_id" | |
echo "✅ I set primary group of User ${bold}$app_username${normal} to ${bold}$app_group_id${normal}" | |
else | |
echo "❗️ User ${bold}$app_username${normal} already exists." | |
# For an existing user, only add them to the group without changing their primary group ID | |
# Check if the group exists or was created during this script execution | |
if dscl . -read /Groups/"$app_group_name" &>/dev/null || [ ! -z "$app_group_id" ]; then | |
# Add the existing user to the specified group as a supplementary group | |
sudo dseditgroup -o edit -a "$app_username" -t user "$app_group_name" | |
echo "Added User [$app_username] to Group [$app_group_name] as a supplementary group." | |
else | |
echo "Specified group does not exist and was not created. No changes made to User [$app_username]." | |
fi | |
fi | |
read -r -p "❓ Would you like to see a list of all users/groups on the system? (y/n): " response | |
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then | |
# Define the format string for the header and the data rows | |
format="%-2s %-5s %-2s %-18s %-2s %-10s %-2s %-18s \n" | |
headerFormat="%-2s %-5s %-2s %-18s %-2s %-10s %-2s %-18s \n" | |
# Print the header | |
printf "\n" | |
printf "$headerFormat" "| " "ID" "| " "Name" "| " "GUID" "| " "Group Name" | |
echo "-------------------------------------------------------------" | |
# Fetch and print user information excluding system accounts | |
dscacheutil -q user | awk -v OFS='\t' ' | |
/uid:/ {uid=$2} | |
/name:/ {name=$2} | |
/gid:/ {gid=$2; if (uid >= 500) print uid, name, gid, "Fetching..."}' | sort -n | while IFS=$'\t' read -r uid name gid fetching; do | |
# Use dscl to directly query the group name from the GID | |
gname=$(dscl . -search /Groups gid "$gid" | awk 'NR==1 {print $1}') | |
# Check if gname is not empty before printing. Safely handle potential leading dashes in variables. | |
if [ ! -z "$gname" ]; then | |
printf "$format" "| " "$uid" "| " "$name" "| " "$gid" "| " "$gname" | |
else | |
printf "$format" "| " "$uid" "| " "$name" "| " "$gid" "Unknown" | |
fi | |
done | |
echo "-------------------------------------------------------------" | |
fi | |
printf "\n" | |
echo "👋 It's been a pleasure working with you, hit me up if you ever need additional assistance." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment