Initial commit
This commit is contained in:
commit
0cd1cbb132
7 changed files with 148 additions and 0 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Pipo
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
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.
|
||||||
46
README.md
Normal file
46
README.md
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
# auto-snapclean-listener
|
||||||
|
|
||||||
|
A small macOS utility script that automatically deletes all local Time Machine snapshots once they are created.
|
||||||
|
It is useful for users who do not want macOS to keep local snapshots and prefer to rely only on external Time Machine backups.
|
||||||
|
|
||||||
|
⚠️ Tested on **macOS Tahoe**. Other versions may work, but are not guaranteed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Listens for local Time Machine snapshot creation events.
|
||||||
|
- Waits until the backup process is finished (avoids conflicts).
|
||||||
|
- Automatically deletes all local snapshots afterwards.
|
||||||
|
- Lightweight: no constant polling, event-driven.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Clone the repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/YOURUSERNAME/auto-snapclean-listener.git
|
||||||
|
cd auto-snapclean-listener
|
||||||
|
```
|
||||||
|
|
||||||
|
Make the script executable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chmod +x auto-snapclean-listener.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the LaunchDaemon:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo cp auto-snapclean-listener.plist /Library/LaunchDaemons/
|
||||||
|
sudo launchctl load /Library/LaunchDaemons/auto-snapclean-listener.plist
|
||||||
|
```
|
||||||
|
|
||||||
|
Uninstall (if needed):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo launchctl unload /Library/LaunchDaemons/auto-snapclean-listener.plist
|
||||||
|
sudo rm /Library/LaunchDaemons/auto-snapclean-listener.plist
|
||||||
|
```
|
||||||
15
launchd/com.snapclean.listener.plist
Normal file
15
launchd/com.snapclean.listener.plist
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
|
||||||
|
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key><string>com.snapclean.listener</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/usr/local/bin/auto-snapclean-listener.sh</string>
|
||||||
|
</array>
|
||||||
|
<key>RunAtLoad</key><true/>
|
||||||
|
<key>KeepAlive</key><true/>
|
||||||
|
<key>UserName</key><string>root</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
43
scripts/auto-snapclean-listener.sh
Normal file
43
scripts/auto-snapclean-listener.sh
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
#!/bin/zsh
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
LOGF="/var/log/snapclean.log"
|
||||||
|
log() { print -r -- "$(date '+%F %T') $*" >> "$LOGF"; }
|
||||||
|
|
||||||
|
is_running() {
|
||||||
|
/usr/bin/tmutil status 2>/dev/null | /usr/bin/grep -Eq '"Running" = 1|Running = 1'
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_until_tm_idle() {
|
||||||
|
local i=0
|
||||||
|
while is_running; do
|
||||||
|
sleep 2
|
||||||
|
(( i++ ))
|
||||||
|
[[ $i -gt 150 ]] && log "Timeout: TM still running. Waiting until it's finished." && break
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_all_snapshots() {
|
||||||
|
log "Deletes all local Snapshots at / …"
|
||||||
|
/usr/bin/tmutil deletelocalsnapshots / || true
|
||||||
|
log "Finished deleting."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Make sure logfile exists
|
||||||
|
[[ -f "$LOGF" ]] || { sudo touch "$LOGF"; sudo chmod 644 "$LOGF"; }
|
||||||
|
|
||||||
|
while IFS= read -r line; do
|
||||||
|
if print -r -- "$line" | /usr/bin/grep -q \
|
||||||
|
"com.apple.TimeMachine:LocalSnapshotManagement] Created Time Machine local snapshot"; then
|
||||||
|
log "Event erkannt: $line"
|
||||||
|
# Short break until the snapshot is in index
|
||||||
|
sleep 2
|
||||||
|
# Waiting until TM is finished
|
||||||
|
wait_until_tm_idle
|
||||||
|
# delete all local snapshots
|
||||||
|
delete_all_snapshots
|
||||||
|
fi
|
||||||
|
done < <(
|
||||||
|
/usr/bin/log stream --style syslog --level info \
|
||||||
|
--predicate 'process == "backupd" AND subsystem == "com.apple.TimeMachine"'
|
||||||
|
)
|
||||||
17
scripts/install.sh
Normal file
17
scripts/install.sh
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#!/bin/zsh
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PLIST_SRC="$(cd -- "$(dirname "$0")/.." && pwd)/launchd/com.snapclean.listener.plist"
|
||||||
|
SCRIPT_SRC="$(cd -- "$(dirname "$0")/.." && pwd)/scripts/auto-snapclean-listener.sh"
|
||||||
|
|
||||||
|
sudo install -m 0755 "$SCRIPT_SRC" /usr/local/bin/auto-snapclean-listener.sh
|
||||||
|
sudo install -m 0644 "$PLIST_SRC" /Library/LaunchDaemons/com.snapclean.listener.plist
|
||||||
|
sudo touch /var/log/snapclean.log /var/log/snapclean.out /var/log/snapclean.err
|
||||||
|
sudo chmod 644 /var/log/snapclean.*
|
||||||
|
|
||||||
|
# (re)load
|
||||||
|
sudo launchctl unload /Library/LaunchDaemons/com.snapclean.listener.plist 2>/dev/null || true
|
||||||
|
sudo launchctl load -w /Library/LaunchDaemons/com.snapclean.listener.plist
|
||||||
|
sudo launchctl list | grep snapclean || true
|
||||||
|
|
||||||
|
echo "✅ snapcleaner installed."
|
||||||
6
scripts/uninstall.sh
Normal file
6
scripts/uninstall.sh
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/zsh
|
||||||
|
set -euo pipefail
|
||||||
|
sudo launchctl unload /Library/LaunchDaemons/com.snapclean.listener.plist 2>/dev/null || true
|
||||||
|
sudo rm -f /Library/LaunchDaemons/com.snapclean.listener.plist
|
||||||
|
sudo rm -f /usr/local/bin/auto-snapclean-listener.sh
|
||||||
|
echo "✅ snapcleaner deleted. Logs stay in /var/log/snapclean.*"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue