parent
bb4079fa99
commit
c5e596a9d5
@ -0,0 +1,14 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
@ -0,0 +1,58 @@
|
||||
|
||||
# Restictray
|
||||
|
||||
A macOS system tray wrapper around [Restic](https://restic.net/), the Go-powered cmd-line backup tool.
|
||||
|
||||
With Restictray, you can monitor and trigger backups from the system tray:
|
||||
|
||||

|
||||
|
||||
Restictray is designed in such a way that it checks whether or not a backup is needed every hour by looking at the latest date in the `restic snapshot` output that's also part of the menu. If the backup command fails, the SFTP network goes down, or your laptop is offline, it will resume next time it's booted.
|
||||
|
||||
It's also possible to trigger a backup manually.
|
||||
|
||||
For convenience, browsing backups in Finder is done through `restic mount`, which means you will need to **install MacFUSE 4.x** through https://osxfuse.github.io/ for it to work!
|
||||
|
||||
This was designed for my wife to access backups with a button press.
|
||||
|
||||
## Configuration
|
||||
|
||||
Restictray currently expects the following files in `~/.restic/`:
|
||||
|
||||
1. `password.txt` as hardcoded `--password-file` argument
|
||||
2. `excludes.txt` as hardcoded `--exclude-file` argument
|
||||
3. `config.json` that configures the repository, the folder(s)/file(s) to backup, and the interval in hours:
|
||||
|
||||
```json
|
||||
{
|
||||
"repository": "sftp:user@server:/somewhere/resticdir",
|
||||
"backup": "/Users/username",
|
||||
"backupTimeInHours": 24
|
||||
}
|
||||
```
|
||||
|
||||
Where `repository` is the restic `-r` argument and `backup` the folder(s)/file(s) fed into the `backup` command.
|
||||
|
||||
**The repository should already be initialized!** You'll have to do this yourself using `restic -r [repo] init`.
|
||||
|
||||
If `backupTimeInHours` is absent, it will default to **24**: backup once a day.
|
||||
|
||||
For more information on how the restic arguments themselves work, please see the restic docs at https://restic.readthedocs.io/en/stable/.
|
||||
|
||||
### Dev config
|
||||
|
||||
If environment variable `RESTICTRAY_DEV` is set, Restictray configures Zerolog to use stdout and the prettyprint formatter instead of the external log, plus it relies on the `restic` command in `$PATH` instead of looking for it in the currently executing folder.
|
||||
|
||||
## Deploying
|
||||
|
||||
Restictray can be wrapped as a macOS `.app` folder that can be distributed. See `build.sh` on how to do this---I've used `fyne package`: see docs at https://developer.fyne.io/started/packaging.
|
||||
|
||||

|
||||
|
||||
The app also wraps the `restic` binary so no local install is needed.
|
||||
|
||||
Please note that the current supplied one in `build/` is an ARM64 macOS-specific binary for that very reason.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Restictray uses Lumberjack and Zerolog to log info to `~/.restic/log.txt`. If a command fails, it should be logged there.
|
@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cmd := neverReturningThing()
|
||||
//cmd := returningThingWithinThreeSecs()
|
||||
//cmd := returningThingAfterThreeSecs()
|
||||
stdout, _ := cmd.StdoutPipe()
|
||||
|
||||
busy := make(chan bool, 1)
|
||||
cmd.Start()
|
||||
|
||||
scanner := bufio.NewScanner(stdout)
|
||||
scanner.Split(bufio.ScanLines)
|
||||
|
||||
go func() {
|
||||
fmt.Println("starting scanner.scan (blocking)")
|
||||
for scanner.Scan() {
|
||||
fmt.Println("scanned")
|
||||
m := scanner.Text()
|
||||
fmt.Println(m)
|
||||
if busy != nil {
|
||||
busy <- true
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
fmt.Println("starting select chans")
|
||||
var err error
|
||||
select {
|
||||
case <-busy:
|
||||
fmt.Println("busy chan")
|
||||
busy = nil
|
||||
case <-time.After(3 * time.Second):
|
||||
pkill := cmd.Process.Kill()
|
||||
fmt.Println("timeout triggered? err: %w", pkill)
|
||||
}
|
||||
|
||||
fmt.Println("starting Wait()")
|
||||
err = cmd.Wait()
|
||||
fmt.Printf("done? here's an error: %w", err)
|
||||
}
|
||||
|
||||
func returningThingWithinThreeSecs() *exec.Cmd {
|
||||
return exec.Command("echo", "sup")
|
||||
}
|
||||
|
||||
func returningThingAfterThreeSecs() *exec.Cmd {
|
||||
return exec.Command("ping", "google.com")
|
||||
}
|
||||
|
||||
func neverReturningThing() *exec.Cmd {
|
||||
return exec.Command("ssh", "user@unknown.local")
|
||||
}
|
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 32 KiB |
Loading…
Reference in new issue