|
|
| (8 intermediate revisions by 2 users not shown) |
| Line 13: |
Line 13: |
| * If you are a normal user, you can run on either the <code>home-manager</code> or <code>channels</code> profiles too. | | * If you are a normal user, you can run on either the <code>home-manager</code> or <code>channels</code> profiles too. |
|
| |
|
| === Example script output === | | == Script (trim-generations.sh) == |
|
| |
|
| ==== Without parameters (defaults) ==== | | The script is available here: [https://gist.github.com/MaxwellDupre/3077cd229490cf93ecab08ef2a79c852 Github Gist - NixOS: trim-generations.sh] |
| | |
| | == Example script output == |
| | |
| | === Without parameters (defaults) === |
|
| |
|
| <syntaxHighlight lang=bash> | | <syntaxHighlight lang=bash> |
| ❯ ./trim-generations.sh | | ❯ ./trim-generations.sh |
| Keeping default: 10 generations OR 7 days, whichever is more
| |
| Operating on profile: /nix/var/nix/profiles/per-user/user/profile
| |
|
| |
|
| oldest generation: 27 | | The current defaults are: |
| oldest generation created: 2021-09-24 | | Keep-Gens=30 Keep-Days=30 |
| minutes before now: 3918 | | |
| hours before now: 65 | | Keep these defaults? (y/n):y |
| days before now: 2 | | Using defaults.. |
| | Keeping default: 30 generations OR 30 days, whichever is more |
| | Operating on profile: /nix/var/nix/profiles/per-user/dougal/profile |
| | |
| | oldest generation: 75 |
| | oldest generation created: 2023-08-05 |
| | minutes before now: 46740 |
| | hours before now: 779 |
| | days before now: 32 |
| | |
| | current generation: 217 |
| | current generation created: 2023-09-06 |
| | minutes before now: 660 |
| | hours before now: 11 |
| | days before now: 0 |
| | |
| | Something to do... |
|
| |
|
| current generation: 33
| | Found the following generation(s) to delete: |
| current generation created: 2021-09-25
| | generation 75 2023-08-05, 32 day(s) old |
| | generation 76 2023-08-05, 32 day(s) old |
| | generation 77 2023-08-05, 32 day(s) old |
| | generation 78 2023-08-05, 32 day(s) old |
| | generation 79 2023-08-05, 32 day(s) old |
| | generation 80 2023-08-05, 32 day(s) old |
| | generation 81 2023-08-05, 32 day(s) old |
| | generation 82 2023-08-05, 32 day(s) old |
| | generation 83 2023-08-05, 32 day(s) old |
| | generation 84 2023-08-05, 32 day(s) old |
| | generation 85 2023-08-05, 32 day(s) old |
| | generation 86 2023-08-05, 32 day(s) old |
|
| |
|
| All generations are no more than 7 days older than current generation.
| | Do you want to delete these? [Y/n]: |
| Oldest gen difference from current gen: 1
| |
|
| |
|
| Nothing to do!
| |
| </syntaxHighlight> | | </syntaxHighlight> |
|
| |
|
| ==== With parameters ====
| | === With parameters === |
|
| |
|
| <syntaxHighlight lang=bash> | | <syntaxHighlight lang=bash> |
| Line 66: |
Line 93: |
| </syntaxHighlight> | | </syntaxHighlight> |
|
| |
|
| ==== With parameters (not enough though) ====
| | === With parameters (not enough though) === |
|
| |
|
| Example if you accidentally don't specify all parameters / arguments. | | Example if you accidentally don't specify all parameters / arguments. |
| Line 76: |
Line 103: |
|
| |
|
| Usage: | | Usage: |
| trim-generations.sh (defaults are: Keep-Gens=10 Keep-Days=7 Profile=user)
| | ./trim-generations.sh <keep-gernerations> <keep-days> <profile> |
|
| |
|
| If you enter any parameters, you must enter all three.
| |
|
| |
|
| | (defaults are: Keep-Gens=30 Keep-Days=30 Profile=user) |
| | |
| | If you enter any parameters, you must enter all three, or none to use defaults. |
| Example: | | Example: |
| trim-generations.sh 15 10 home-manager
| | trim-generations.sh 15 10 home-manager |
| ... this will work on the home-manager profile and keep all generations from the last 10 days, and keep at least 15 generations no matter how old.
| | this will work on the home-manager profile and keep all generations from the |
| | last 10 days, and keep at least 15 generations no matter how old. |
|
| |
|
| Profile choices available: user, home-manager, channels, system (root only)
| | Profiles available are: user, home-manager, channels, system (root) |
| | |
| | -h or --help prints this help text. |
| </syntaxHighlight> | | </syntaxHighlight> |
|
| |
|
| ==== Run as root (default) ====
| | === Run as root (default) === |
|
| |
|
| <syntaxHighlight lang=bash> | | <syntaxHighlight lang=bash> |
| ❯ sudo ./trim-generations.sh | | ❯ sudo ./trim-generations.sh |
| Keeping default: 10 generations OR 7 days, whichever is more
| | The current defaults are: |
| Operating on profile: /nix/var/nix/profiles/default
| | Keep-Gens=30 Keep-Days=30 |
|
| |
|
| oldest generation: 8
| | Keep these defaults? (y/n):y |
| oldest generation created: 2021-09-04
| | Using defaults.. |
| minutes before now: 32725
| | Keeping default: 30 generations OR 30 days, whichever is more |
| hours before now: 545
| | Operating on profile: /nix/var/nix/profiles/system |
| days before now: 22
| |
|
| |
|
| current generation: 8
| | oldest generation: 65 |
| current generation created: 2021-09-04
| | oldest generation created: 2023-08-05 |
| | minutes before now: 46727 |
| | hours before now: 778 |
| | days before now: 32 |
|
| |
|
| All generations are no more than 7 days older than current generation. | | current generation: 102 |
| Oldest gen days difference from current gen: 0 | | current generation created: 2023-09-04 |
| | minutes before now: 3527 |
| | hours before now: 58 |
| | days before now: 2 |
| | |
| | All generations are no more than 30 days older than current generation. |
| | Oldest gen days difference from current gen: 30 |
|
| |
|
| Nothing to do!
| | Nothing to do! |
| </syntaxHighlight> | | </syntaxHighlight> |
|
| |
|
| ==== Run as root (on system profile) ====
| | === Run as root (on system profile) === |
|
| |
|
| <syntaxHighlight lang=bash> | | <syntaxHighlight lang=bash> |
| Line 129: |
Line 169: |
| </syntaxHighlight> | | </syntaxHighlight> |
|
| |
|
| ==== Run as root (wrong profile) ====
| | === Run as root (wrong profile) === |
|
| |
|
| Example if you accidentally give wrong profile (no home-manager on root): | | Example if you accidentally give wrong profile (no home-manager on root): |
| Line 139: |
Line 179: |
|
| |
|
| Usage: | | Usage: |
| trim-generations.sh (defaults are: Keep-Gens=10 Keep-Days=7 Profile=user)
| | ./trim-generations.sh <keep-gernerations> <keep-days> <profile> |
| | |
|
| |
|
| If you enter any parameters, you must enter all three.
| | (defaults are: Keep-Gens=30 Keep-Days=30 Profile=user) |
|
| |
|
| | If you enter any parameters, you must enter all three, or none to use defaults. |
| Example: | | Example: |
| trim-generations.sh 15 10 home-manager
| | trim-generations.sh 15 10 home-manager |
| ... this will work on the home-manager profile and keep all generations from the last 10 days, and keep at least 15 generations no matter how old.
| | this will work on the home-manager profile and keep all generations from the |
| | last 10 days, and keep at least 15 generations no matter how old. |
|
| |
|
| Profile choices available: user, home-manager, channels, system (root only)
| | Profiles available are: user, home-manager, channels, system (root) |
| | |
| | -h or --help prints this help text. |
| </syntaxHighlight> | | </syntaxHighlight> |
|
| |
|
|
| |
|
| | | [[Category:Tutorial]] |
| | |
| | |
| == Script (trim-generations.sh) ==
| |
| | |
| {{file|trim-generations.sh|bash|<nowiki>
| |
| #!/usr/bin/env bash
| |
| set -euo pipefail
| |
| | |
| ## Defaults
| |
| keepGensDef=10; keepDaysDef=7
| |
| keepGens=$keepGensDef; keepDays=$keepDaysDef
| |
| | |
| ## Usage
| |
| usage () {
| |
| printf "Usage:\n\t trim-generations.sh (defaults are: Keep-Gens=$keepGensDef Keep-Days=$keepDaysDef Profile=user)\n\n"
| |
| printf "If you enter any parameters, you must enter all three.\n\n"
| |
| printf "Example:\n\t trim-generations.sh 15 10 home-manager\n"
| |
| printf "... this will work on the home-manager profile and keep all generations from the last 10 days, and keep at least 15 generations no matter how old.\n"
| |
| printf "\nProfile choices available: \t user, home-manager, channels, system (root only)\n"
| |
| }
| |
| | |
| ## Handle parameters (and change if root)
| |
| if [[ $EUID -ne 0 ]]; then
| |
| profile=$(readlink /home/$USER/.nix-profile)
| |
| else
| |
| profile="/nix/var/nix/profiles/default"
| |
| fi
| |
| if (( $# < 1 )); then
| |
| printf "Keeping default: 10 generations OR 7 days, whichever is more\n"
| |
| elif [[ $# -le 2 ]]; then
| |
| printf "\nError: Not enough arguments.\n\n" >&2
| |
| usage
| |
| exit 1
| |
| elif (( $# > 4)); then
| |
| printf "\nError: Too many arguments.\n\n" >&2
| |
| usage
| |
| exit 2
| |
| else
| |
| keepGens=$1; keepDays=$2;
| |
| (( keepGens < 1 )) && keepGens=1
| |
| (( keepDays < 0 )) && keepDays=0
| |
| if [[ $EUID -ne 0 ]]; then
| |
| if [[ $3 == "user" ]] || [[ $3 == "default" ]]; then
| |
| profile=$(readlink /home/$USER/.nix-profile)
| |
| elif [[ $3 == "home-manager" ]]; then
| |
| profile="/nix/var/nix/profiles/per-user/$USER/home-manager"
| |
| elif [[ $3 == "channels" ]]; then
| |
| profile="/nix/var/nix/profiles/per-user/$USER/channels"
| |
| else
| |
| printf "\nError: Do not understand your third argument. Should be one of: (user / home-manager/ channels)\n\n"
| |
| usage
| |
| exit 3
| |
| fi
| |
| else
| |
| if [[ $3 == "system" ]]; then
| |
| profile="/nix/var/nix/profiles/system"
| |
| elif [[ $3 == "user" ]] || [[ $3 == "default" ]]; then
| |
| profile="/nix/var/nix/profiles/default"
| |
| else
| |
| printf "\nError: Do not understand your third argument. Should be one of: (user / system)\n\n"
| |
| usage
| |
| exit 3
| |
| fi
| |
| fi
| |
| printf "OK! \t Keep Gens = $keepGens \t Keep Days = $keepDays\n\n"
| |
| fi
| |
| | |
| printf "Operating on profile: \t $profile\n\n"
| |
| | |
| ## Runs at the end, to decide whether to delete profiles that match chosen parameters.
| |
| choose () {
| |
| local default="$1"
| |
| local prompt="$2"
| |
| local answer
| |
| | |
| read -p "$prompt" answer
| |
| [ -z "$answer" ] && answer="$default"
| |
| | |
| case "$answer" in
| |
| [yY1] ) #printf "answered yes!\n"
| |
| nix-env --delete-generations ${!gens[@]}
| |
| exit 0
| |
| ;;
| |
| [nN0] ) printf "answered no! exiting\n"
| |
| exit 6;
| |
| ;;
| |
| * ) printf "%b" "Unexpected answer '$answer'!" >&2
| |
| exit 7;
| |
| ;;
| |
| esac
| |
| } # end of function choose
| |
| | |
| | |
| ## Query nix-env for generations list
| |
| IFS=$'\n' nixGens=( $(nix-env --list-generations -p $profile | sed 's:^\s*::; s:\s*$::' | tr '\t' ' ' | tr -s ' ') )
| |
| timeNow=$(date +%s)
| |
| | |
| ## Get info on oldest generation
| |
| IFS=' ' read -r -a oldestGenArr <<< "${nixGens[0]}"
| |
| oldestGen=${oldestGenArr[0]}
| |
| oldestDate=${oldestGenArr[1]}
| |
| printf "%-30s %s\n" "oldest generation:" $oldestGen
| |
| #oldestDate=${nixGens[0]:3:19}
| |
| printf "%-30s %s\n" "oldest generation created:" $oldestDate
| |
| oldestTime=$(date -d "$oldestDate" +%s)
| |
| oldestElapsedSecs=$((timeNow-oldestTime))
| |
| oldestElapsedMins=$((oldestElapsedSecs/60))
| |
| oldestElapsedHours=$((oldestElapsedMins/60))
| |
| oldestElapsedDays=$((oldestElapsedHours/24))
| |
| printf "%-30s %s\n" "minutes before now:" $oldestElapsedMins
| |
| printf "%-30s %s\n" "hours before now:" $oldestElapsedHours
| |
| printf "%-30s %s\n\n" "days before now:" $oldestElapsedDays
| |
| | |
| ## Get info on current generation
| |
| for i in "${nixGens[@]}"; do
| |
| IFS=' ' read -r -a iGenArr <<< "$i"
| |
| genNumber=${iGenArr[0]}
| |
| genDate=${iGenArr[1]}
| |
| if [[ "$i" =~ current ]]; then
| |
| currentGen=$genNumber
| |
| printf "%-30s %s\n" "current generation:" $currentGen
| |
| currentDate=$genDate
| |
| printf "%-30s %s\n\n" "current generation created:" $currentDate
| |
| currentTime=$(date -d "$currentDate" +%s)
| |
| fi
| |
| done
| |
| | |
| ## Compare oldest and current generations
| |
| timeBetweenOldestAndCurrent=$((currentTime-oldestTime))
| |
| elapsedDays=$((timeBetweenOldestAndCurrent/60/60/24))
| |
| generationsDiff=$((currentGen-oldestGen))
| |
| | |
| ## Figure out what we should do, based on generations and options
| |
| if [[ elapsedDays -le keepDays ]]; then
| |
| printf "All generations are no more than $keepDays days older than current generation. \nOldest gen days difference from current gen: $elapsedDays \n\n\tNothing to do!\n"
| |
| exit 4;
| |
| elif [[ generationsDiff -lt keepGens ]]; then
| |
| printf "Oldest generation ($oldestGen) is only $generationsDiff generations behind current ($currentGen). \t Nothing to do!\n"
| |
| exit 5;
| |
| else
| |
| printf "\tSomething to do...\n"
| |
| declare -a gens
| |
| for i in "${nixGens[@]}"; do
| |
| IFS=' ' read -r -a iGenArr <<< "$i"
| |
| genNumber=${iGenArr[0]}
| |
| genDiff=$((currentGen-genNumber))
| |
| genDate=${iGenArr[1]}
| |
| genTime=$(date -d "$genDate" +%s)
| |
| elapsedSecs=$((timeNow-genTime))
| |
| genDaysOld=$((elapsedSecs/60/60/24))
| |
| if [[ genDaysOld -gt keepDays ]] && [[ genDiff -ge keepGens ]]; then
| |
| gens["$genNumber"]="$genDate, $genDaysOld day(s) old"
| |
| fi
| |
| done
| |
| printf "\nFound the following generation(s) to delete:\n"
| |
| for K in "${!gens[@]}"; do
| |
| printf "generation $K \t ${gens[$K]}\n"
| |
| done
| |
| printf "\n"
| |
| choose "y" "Do you want to delete these? [Y/n]: "
| |
| fi
| |
| </nowiki>}}
| |