snapsync 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -6
- data/install.sh +4 -5
- data/lib/snapsync/Notification.rb +52 -0
- data/lib/snapsync/btrfs.rb +1 -1
- data/lib/snapsync/cli.rb +24 -4
- data/lib/snapsync/remote_pathname.rb +1 -0
- data/lib/snapsync/ssh_popen.rb +9 -8
- data/lib/snapsync/ssh_popen_exe.rb +52 -0
- data/lib/snapsync/{auto_sync.rb → tasks/AutoSync.rb} +22 -17
- data/lib/snapsync/tasks/Task.rb +79 -0
- data/lib/snapsync/version.rb +1 -1
- data/lib/snapsync.rb +6 -1
- data/snapsync.gemspec +3 -2
- data/systemd/snapsync-check-is-connection-unmetered.service +10 -0
- data/systemd/snapsync-is-connection-unmetered.service +8 -0
- data/{snapsync.service → systemd/snapsync-local.service} +1 -1
- data/{snapsync.timer → systemd/snapsync-local.timer} +1 -1
- data/systemd/snapsync-remote.service +13 -0
- data/systemd/snapsync-remote.timer +12 -0
- data/usrlib/snapsync-check-is-connection-unmetered.sh +22 -0
- metadata +43 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65f1584da8033d0abd6635cbd1a004340bf0d1f32f3b0eccc7edaecae0e97363
|
4
|
+
data.tar.gz: e20b0ef8cc9a9a20a48e3b61175da55bb1c604614785a89f52f74ff5a2b2432c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcb3043948f97f82b2f1907ad13871327f7537bad3ac13fe510a1009b936bcb5096b44e27ebfbce490b31d6874412fbb527349b5ba1c5489261d52b920fe008a
|
7
|
+
data.tar.gz: b6bc9c3be836393fcb8cb9a4762b13323b1d72a61330d8fda857aeecbf64f46d9bd00249f76b60891428b2f549b5b1c5bf172186ecf3ec0ba2a55550af6548f1
|
data/README.md
CHANGED
@@ -8,22 +8,23 @@ receive.
|
|
8
8
|
|
9
9
|
It can be used in two modes:
|
10
10
|
- in manual mode, you run snapsync
|
11
|
+
- systemd timer, runs snapsync periodically
|
11
12
|
|
12
13
|
## Installation
|
13
14
|
|
14
15
|
You need to make sure that you've installed Ruby's bundler. On Ubuntu, run
|
15
|
-
|
16
|
+
`$ apt install bundler`
|
16
17
|
|
17
18
|
Then, the following will install snapsync in /opt/snapsync
|
18
19
|
|
19
20
|
$ wget https://raw.githubusercontent.com/doudou/snapsync/master/install.sh
|
20
21
|
$ sh install.sh
|
21
22
|
|
22
|
-
The script will use sudo to get root rights when required. Add
|
23
|
-
to your PATH if you want to use
|
24
|
-
refer to
|
25
|
-
|
26
|
-
system, enables and starts it.
|
23
|
+
The script will use sudo to get root rights when required. Add `/opt/snapsync/bin`
|
24
|
+
to your PATH if you want to use `snapsync` as-is. Otherwise, you will have to
|
25
|
+
refer to `/opt/snapsync/bin/snapsync` explicitely.
|
26
|
+
|
27
|
+
If it seems that you are using systemd, the script also installs snapsync's systemd service and timer files into the system, enables the timer and starts it. By default the timer runs every day at 20:00.
|
27
28
|
|
28
29
|
## Usage
|
29
30
|
|
data/install.sh
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#! /bin/sh -ex
|
2
2
|
|
3
|
-
target=`mktemp -d`
|
3
|
+
target=`mktemp -d --suffix _snapsync-install`
|
4
4
|
cd $target
|
5
5
|
cat > Gemfile <<GEMFILE
|
6
6
|
source "https://rubygems.org"
|
@@ -16,10 +16,9 @@ sudo chmod go+rX /opt/snapsync
|
|
16
16
|
|
17
17
|
if test -d /lib/systemd/system; then
|
18
18
|
snapsync_gem=`bundler show snapsync`
|
19
|
-
sudo
|
20
|
-
( sudo systemctl
|
21
|
-
sudo systemctl enable snapsync.
|
22
|
-
sudo systemctl start snapsync.service )
|
19
|
+
sudo ln -s /opt/snapsync/systemd/* /lib/systemd/system
|
20
|
+
( sudo systemctl enable snapsync-local.timer
|
21
|
+
sudo systemctl enable snapsync-remote.timer)
|
23
22
|
fi
|
24
23
|
|
25
24
|
rm -rf $target
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'libnotify'
|
2
|
+
|
3
|
+
module Snapsync
|
4
|
+
# This class abstracts notifying each user on the system
|
5
|
+
# NOTE: Not multi-thread safe!
|
6
|
+
class Notification
|
7
|
+
# @return [Hash{Integer => Libnotify::API}]
|
8
|
+
attr_reader :notified_users
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
@notified_users = {}
|
12
|
+
|
13
|
+
|
14
|
+
Dir.each_child('/run/user') do |user_id|
|
15
|
+
# seteuid _must_ be set for session dbus to accept the connection
|
16
|
+
Process::Sys.seteuid(user_id.to_i)
|
17
|
+
ENV['DBUS_SESSION_BUS_ADDRESS'] = "unix:path=/run/user/#{user_id}/bus"
|
18
|
+
|
19
|
+
n = Libnotify.new(config)
|
20
|
+
@notified_users[user_id.to_i] = n
|
21
|
+
n.show!
|
22
|
+
end
|
23
|
+
# set euid back, so all commands works normally
|
24
|
+
Process::Sys.seteuid Process::Sys.getuid
|
25
|
+
end
|
26
|
+
|
27
|
+
def update(config)
|
28
|
+
each_raw_notification do |n|
|
29
|
+
n.update(config)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def close
|
34
|
+
each_raw_notification do |n|
|
35
|
+
n.close
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @yieldparam [Libnotify::API] n
|
40
|
+
private def each_raw_notification
|
41
|
+
notified_users.each do |user_id, n|
|
42
|
+
# seteuid _must_ be set for session dbus to accept the connection
|
43
|
+
Process::Sys.seteuid(user_id)
|
44
|
+
ENV['DBUS_SESSION_BUS_ADDRESS'] = "unix:path=/run/user/#{user_id}/bus"
|
45
|
+
|
46
|
+
yield n
|
47
|
+
end
|
48
|
+
# set euid back, so all commands works normally
|
49
|
+
Process::Sys.seteuid Process::Sys.getuid
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/snapsync/btrfs.rb
CHANGED
@@ -72,7 +72,7 @@ module Snapsync
|
|
72
72
|
Snapsync.debug "Btrfs(\"#{mountpoint}\").popen: #{args}"
|
73
73
|
|
74
74
|
if @mountpoint.is_a? RemotePathname
|
75
|
-
proc =
|
75
|
+
proc = SSHPopenExe.new(@mountpoint, [btrfs_prog, *args], **options)
|
76
76
|
return yield(proc)
|
77
77
|
else
|
78
78
|
# @type [IO,IO]
|
data/lib/snapsync/cli.rb
CHANGED
@@ -2,10 +2,16 @@ require 'thor'
|
|
2
2
|
require 'snapsync'
|
3
3
|
require 'set'
|
4
4
|
|
5
|
+
require_relative 'tasks/AutoSync'
|
6
|
+
|
5
7
|
module Snapsync
|
6
8
|
class CLI < Thor
|
7
9
|
class_option :debug, type: :boolean, default: false
|
8
10
|
class_option :ssh_debug, type: :boolean, default: false
|
11
|
+
class_option :systemd, type: :boolean, default: false,
|
12
|
+
desc: "Tells snapsync it is being run from a systemd service"
|
13
|
+
class_option :notify, type: :boolean, default: false,
|
14
|
+
desc: "Use libnotify to notify all users in system"
|
9
15
|
|
10
16
|
no_commands do
|
11
17
|
def config_from_name(name)
|
@@ -25,6 +31,8 @@ module Snapsync
|
|
25
31
|
end
|
26
32
|
|
27
33
|
Snapsync.SSH_DEBUG = options[:ssh_debug]
|
34
|
+
Snapsync.SYSTEMD = options[:systemd]
|
35
|
+
Snapsync.NOTIFY = options[:notify]
|
28
36
|
end
|
29
37
|
|
30
38
|
# Resolves a path (or nil) into a list of snapsync targets and
|
@@ -301,13 +309,25 @@ While it can easily be done manually, this command makes sure that the snapshots
|
|
301
309
|
default: false
|
302
310
|
option :config_file, desc: "path to the config file (defaults to /etc/snapsync.conf)",
|
303
311
|
default: '/etc/snapsync.conf'
|
312
|
+
option :local_only, desc: "Only synchronize to local targets", type: :boolean, default: false
|
313
|
+
option :remote_only, desc: "Only synchronize to remote targets", type: :boolean, default: false
|
304
314
|
def auto_sync
|
305
315
|
handle_class_options
|
306
|
-
|
307
|
-
if options[:
|
308
|
-
|
309
|
-
|
316
|
+
|
317
|
+
if options[:local_only] and options[:remote_only]
|
318
|
+
raise ArgumentError, '--local-only and --remote-only cannot be used together'
|
319
|
+
end
|
320
|
+
|
321
|
+
while true
|
322
|
+
auto = AutoSync.new(SnapperConfig.default_config_dir,
|
323
|
+
snapsync_config_file: Pathname.new(options[:config_file]),
|
324
|
+
sync_local: options[:local_only] || !options[:remote_only],
|
325
|
+
sync_remote: options[:remote_only] || !options[:local_only])
|
310
326
|
auto.run
|
327
|
+
break if options[:one_shot]
|
328
|
+
|
329
|
+
Snapsync.info "done all declared autosync partitions, sleeping #{period}s"
|
330
|
+
sleep 600
|
311
331
|
end
|
312
332
|
end
|
313
333
|
|
data/lib/snapsync/ssh_popen.rb
CHANGED
@@ -60,17 +60,18 @@ module Snapsync
|
|
60
60
|
raise ExitSignal, "Exited due to signal: #{exit_signal}"
|
61
61
|
end
|
62
62
|
|
63
|
-
channel.on_process do
|
64
|
-
begin
|
65
|
-
channel.send_data(write_buffer_out.read_nonblock(2 << 20))
|
66
|
-
rescue IO::EAGAINWaitReadable
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
63
|
channel.exec(Shellwords.join command)
|
71
64
|
end
|
72
65
|
|
73
|
-
|
66
|
+
write_buffer_out.extend(Net::SSH::BufferedIo)
|
67
|
+
ssh.listen_to(write_buffer_out) do
|
68
|
+
begin
|
69
|
+
channel.send_data(write_buffer_out.read_nonblock(2 << 20))
|
70
|
+
rescue IO::EAGAINWaitReadable
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
ssh.loop {
|
74
75
|
if write_buffer_out.closed?
|
75
76
|
channel.close
|
76
77
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Snapsync
|
2
|
+
class SSHPopenExe
|
3
|
+
# @return [IO]
|
4
|
+
attr_reader :ssh_proc
|
5
|
+
|
6
|
+
class NonZeroExitCode < RuntimeError
|
7
|
+
end
|
8
|
+
class ExitSignal < RuntimeError
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [IO]
|
12
|
+
attr_reader :read_buffer
|
13
|
+
|
14
|
+
# @return [IO]
|
15
|
+
attr_reader :write_buffer
|
16
|
+
|
17
|
+
# @param machine [RemotePathname]
|
18
|
+
# @param [Array] command
|
19
|
+
# @param options [Hash]
|
20
|
+
def initialize(machine, command, **options)
|
21
|
+
# @type [IO,IO]
|
22
|
+
@err_r, err_w = IO.pipe
|
23
|
+
full_cmd = ['ssh', machine.uri.host, *command]
|
24
|
+
Snapsync.debug "Opening SSH Tunnel: #{full_cmd}"
|
25
|
+
@ssh_proc = IO.popen(full_cmd, err: err_w, mode: 'r+')
|
26
|
+
end
|
27
|
+
|
28
|
+
def sync=(sync)
|
29
|
+
# ignore
|
30
|
+
end
|
31
|
+
|
32
|
+
def read(nbytes = nil)
|
33
|
+
begin
|
34
|
+
return ssh_proc.read nbytes
|
35
|
+
rescue Errno::EWOULDBLOCK
|
36
|
+
return ''
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def write(data)
|
41
|
+
ssh_proc.write data
|
42
|
+
end
|
43
|
+
|
44
|
+
def close
|
45
|
+
ssh_proc.close_write
|
46
|
+
end
|
47
|
+
|
48
|
+
def err
|
49
|
+
@err_r.read
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
|
+
require_relative 'Task'
|
2
|
+
|
1
3
|
module Snapsync
|
2
4
|
# Implementation of the auto-sync feature
|
3
5
|
#
|
4
6
|
# This class implements the 'snapsync auto' functionality. It monitors for
|
5
7
|
# partition availability, and will run sync-all on each (declared) targets
|
6
8
|
# when they are available, optionally auto-mounting them
|
7
|
-
class AutoSync
|
9
|
+
class AutoSync < Task
|
8
10
|
AutoSyncTarget = Struct.new :partition_uuid, :mountpoint, :relative, :automount, :name
|
9
11
|
|
10
12
|
attr_reader :config_dir
|
@@ -14,9 +16,16 @@ module Snapsync
|
|
14
16
|
|
15
17
|
DEFAULT_CONFIG_PATH = Pathname.new('/etc/snapsync.conf')
|
16
18
|
|
17
|
-
def initialize(config_dir = SnapperConfig.default_config_dir,
|
19
|
+
def initialize(config_dir = SnapperConfig.default_config_dir,
|
20
|
+
snapsync_config_file: DEFAULT_CONFIG_PATH,
|
21
|
+
sync_local: true,
|
22
|
+
sync_remote: true)
|
18
23
|
@config_dir = config_dir
|
19
24
|
@targets = Hash.new
|
25
|
+
|
26
|
+
@sync_local = sync_local
|
27
|
+
@sync_remote = sync_remote
|
28
|
+
|
20
29
|
@partitions = PartitionsMonitor.new
|
21
30
|
partitions.poll
|
22
31
|
|
@@ -34,7 +43,7 @@ module Snapsync
|
|
34
43
|
migrated = false
|
35
44
|
if conf.is_a? Array
|
36
45
|
# Version 1
|
37
|
-
|
46
|
+
info "Migrating config from v1 to v2"
|
38
47
|
conf = config_migrate_v1_v2(conf)
|
39
48
|
migrated = true
|
40
49
|
elsif conf['version'] != 2
|
@@ -47,7 +56,7 @@ module Snapsync
|
|
47
56
|
end
|
48
57
|
|
49
58
|
private def config_migrate_v1_v2(conf)
|
50
|
-
|
59
|
+
info "Migrating config from version 1 to version 2"
|
51
60
|
targets = conf.map do |target|
|
52
61
|
target['relative'] = target['path']
|
53
62
|
target.delete('path')
|
@@ -122,11 +131,11 @@ module Snapsync
|
|
122
131
|
mountpoint = target.mountpoint
|
123
132
|
if not mountpoint.mountpoint?
|
124
133
|
if not target.automount
|
125
|
-
|
134
|
+
info "partition #{uuid} is present, but not mounted and automount is false. Ignoring"
|
126
135
|
next
|
127
136
|
end
|
128
137
|
|
129
|
-
|
138
|
+
info "partition #{uuid} is present, but not mounted, automounting"
|
130
139
|
begin
|
131
140
|
if mountpoint.is_a? RemotePathname
|
132
141
|
# TODO: automounting of remote paths
|
@@ -136,7 +145,7 @@ module Snapsync
|
|
136
145
|
end
|
137
146
|
mounted = true
|
138
147
|
rescue Exception => e
|
139
|
-
|
148
|
+
warn "failed to mount, ignoring this target"
|
140
149
|
next
|
141
150
|
end
|
142
151
|
end
|
@@ -182,21 +191,17 @@ module Snapsync
|
|
182
191
|
end
|
183
192
|
end
|
184
193
|
|
185
|
-
def
|
194
|
+
def _task_name
|
195
|
+
'Auto-Sync'
|
196
|
+
end
|
197
|
+
|
198
|
+
def _run
|
186
199
|
each_available_autosync_target do |path, t|
|
187
|
-
|
200
|
+
info "sync-all on #{path} (partition #{t.partition_uuid})"
|
188
201
|
op = SyncAll.new(path, config_dir: config_dir)
|
189
202
|
op.run
|
190
203
|
end
|
191
204
|
end
|
192
|
-
|
193
|
-
def run(period: 600)
|
194
|
-
while true
|
195
|
-
sync
|
196
|
-
Snapsync.info "done all declared autosync partitions, sleeping #{period}s"
|
197
|
-
sleep period
|
198
|
-
end
|
199
|
-
end
|
200
205
|
end
|
201
206
|
end
|
202
207
|
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative '../Notification'
|
2
|
+
|
3
|
+
module Snapsync
|
4
|
+
# Tasks extending this should implement `_run`, `_task_name`
|
5
|
+
#
|
6
|
+
# All messages should be sent through `info`, `warn`, `error`
|
7
|
+
# All sub-tasks should be executed by `task` or appropriately adding parent to <Task>.new
|
8
|
+
# Progress (if the task implements it) should be notified by `set_progress`
|
9
|
+
class Task
|
10
|
+
|
11
|
+
def info(msg)
|
12
|
+
Snapsync.info msg
|
13
|
+
if Snapsync.NOTIFY
|
14
|
+
@notification.update({:body => msg})
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def warn(msg)
|
19
|
+
Snapsync.warn msg
|
20
|
+
if Snapsync.NOTIFY
|
21
|
+
@notification.update({:body => msg, :urgency => :critical})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def error(msg)
|
26
|
+
Snapsync.error msg
|
27
|
+
if Snapsync.NOTIFY
|
28
|
+
@notification.update({:body => msg, :urgency => :critical})
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param [Integer] percent
|
33
|
+
def set_progress(percent)
|
34
|
+
if Snapsync.NOTIFY
|
35
|
+
@notification.update({:body => "[#{'#'*(percent / 10)}]"})
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param [Task, nil] parent
|
40
|
+
def initialize(parent: nil)
|
41
|
+
@parent = parent
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_status(status)
|
45
|
+
if Snapsync.NOTIFY
|
46
|
+
@notification.update({ :summary => "#{_task_name} #{status}" })
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
def run
|
52
|
+
if Snapsync.NOTIFY
|
53
|
+
@notification = Notification.new({
|
54
|
+
:app_name => "Snapsync"+(Snapsync.SYSTEMD ? ' [systemd service]' : ''),
|
55
|
+
:body => "Starting...", :summary => "#{_task_name} Running",
|
56
|
+
:urgency => :normal, :append => false, :transient => false, :timeout => 15.0,
|
57
|
+
:icon_path => "/usr/share/icons/gnome/scalable/emblems/emblem-default.svg"})
|
58
|
+
end
|
59
|
+
|
60
|
+
begin
|
61
|
+
_run
|
62
|
+
rescue Exception => e
|
63
|
+
set_status "Failed"
|
64
|
+
error e.message
|
65
|
+
raise e
|
66
|
+
end
|
67
|
+
|
68
|
+
set_status "Finished"
|
69
|
+
end
|
70
|
+
|
71
|
+
def _task_name
|
72
|
+
raise NotImplementedError
|
73
|
+
end
|
74
|
+
|
75
|
+
def _run
|
76
|
+
raise NotImplementedError
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/snapsync/version.rb
CHANGED
data/lib/snapsync.rb
CHANGED
@@ -24,6 +24,7 @@ require 'snapsync/cleanup'
|
|
24
24
|
|
25
25
|
require 'snapsync/remote_pathname'
|
26
26
|
require 'snapsync/ssh_popen'
|
27
|
+
require 'snapsync/ssh_popen_exe'
|
27
28
|
|
28
29
|
require 'snapsync/default_sync_policy'
|
29
30
|
require 'snapsync/timeline_sync_policy'
|
@@ -32,7 +33,7 @@ require 'snapsync/sync_last_policy'
|
|
32
33
|
require 'snapsync/partitions_monitor'
|
33
34
|
require 'snapsync/sync'
|
34
35
|
require 'snapsync/sync_all'
|
35
|
-
|
36
|
+
|
36
37
|
|
37
38
|
module Logging
|
38
39
|
module Installer
|
@@ -103,8 +104,12 @@ module Snapsync
|
|
103
104
|
|
104
105
|
class << self
|
105
106
|
attr_accessor :SSH_DEBUG
|
107
|
+
attr_accessor :SYSTEMD
|
108
|
+
attr_accessor :NOTIFY
|
106
109
|
end
|
107
110
|
Snapsync.SSH_DEBUG = false
|
111
|
+
Snapsync.SYSTEMD = false
|
112
|
+
Snapsync.NOTIFY = false
|
108
113
|
|
109
114
|
# @param [String] dir
|
110
115
|
# @return [AgnosticPath]
|
data/snapsync.gemspec
CHANGED
@@ -29,10 +29,11 @@ EOD
|
|
29
29
|
spec.add_dependency 'ruby-dbus', "~> 0.16.0"
|
30
30
|
spec.add_dependency 'thor', "~> 1.1"
|
31
31
|
spec.add_dependency 'uri-ssh_git', "~> 2.0.0"
|
32
|
-
spec.add_dependency '
|
33
|
-
spec.add_dependency 'net-sftp', "
|
32
|
+
spec.add_dependency 'net-ssh', "~> 7.0"
|
33
|
+
spec.add_dependency 'net-sftp', ">= 4.0.0.rc1", "< 5.0"
|
34
34
|
spec.add_dependency 'ed25519', ">= 1.2"
|
35
35
|
spec.add_dependency 'bcrypt_pbkdf', ">= 1.0"
|
36
|
+
spec.add_dependency 'libnotify', '~> 0.9'
|
36
37
|
|
37
38
|
spec.add_development_dependency "bundler", "~> 2"
|
38
39
|
spec.add_development_dependency "rake", "~> 13"
|
@@ -0,0 +1,10 @@
|
|
1
|
+
[Unit]
|
2
|
+
Description=Checks if the current default connection is unmetered
|
3
|
+
After=NetworkManager-dispatcher.service
|
4
|
+
|
5
|
+
[Service]
|
6
|
+
Type=oneshot
|
7
|
+
ExecStart=/usr/local/lib/snapsync/snapsync-check-is-connection-unmetered.sh
|
8
|
+
|
9
|
+
[Install]
|
10
|
+
WantedBy=NetworkManager-dispatcher.service
|
@@ -4,7 +4,7 @@ Wants=udisks2.service
|
|
4
4
|
|
5
5
|
[Service]
|
6
6
|
Type=simple
|
7
|
-
ExecStart=/usr/bin/env HOME=/root /usr/bin/snapsync auto-sync --one-shot
|
7
|
+
ExecStart=/usr/bin/env HOME=/root /usr/bin/snapsync auto-sync --one-shot --systemd --notify --local-only
|
8
8
|
Nice=19
|
9
9
|
IOSchedulingClass=idle
|
10
10
|
KillSignal=SIGINT
|
@@ -0,0 +1,13 @@
|
|
1
|
+
[Unit]
|
2
|
+
Description=service that synchronizes snapper snapshots to other media
|
3
|
+
Wants=udisks2.service
|
4
|
+
|
5
|
+
[Service]
|
6
|
+
Type=simple
|
7
|
+
ExecStart=/usr/bin/env HOME=/root /usr/bin/snapsync auto-sync --one-shot --systemd --notify --remote-only
|
8
|
+
Nice=19
|
9
|
+
IOSchedulingClass=idle
|
10
|
+
KillSignal=SIGINT
|
11
|
+
|
12
|
+
[Install]
|
13
|
+
WantedBy=default.target
|
@@ -0,0 +1,12 @@
|
|
1
|
+
[Unit]
|
2
|
+
Description=Run snapsync for remote filesystems
|
3
|
+
BindsTo=snapsync-is-connection-unmetered.service
|
4
|
+
After=snapsync-is-connection-unmetered.service
|
5
|
+
|
6
|
+
[Timer]
|
7
|
+
OnCalendar=*-*-* 20:00:00
|
8
|
+
RandomizedDelaySec=5min
|
9
|
+
Persistent=true
|
10
|
+
|
11
|
+
[Install]
|
12
|
+
WantedBy=snapsync-is-connection-unmetered.service
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
default_dev=$(ip r | grep '^default via' | cut -d ' ' -f 5)
|
6
|
+
|
7
|
+
if [ "$default_dev" == '' ]; then
|
8
|
+
# Disconnected
|
9
|
+
echo "State: Disconnected"
|
10
|
+
systemctl stop snapsync-is-connection-unmetered.service
|
11
|
+
exit 0
|
12
|
+
fi
|
13
|
+
|
14
|
+
if [ "$(nmcli -g general.metered dev show "$default_dev" | cut -d ' ' -f 1)" == 'no' ]; then
|
15
|
+
echo "State: Unmetered"
|
16
|
+
systemctl start snapsync-is-connection-unmetered.service
|
17
|
+
else
|
18
|
+
echo "State: Metered"
|
19
|
+
systemctl stop snapsync-is-connection-unmetered.service
|
20
|
+
fi
|
21
|
+
|
22
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snapsync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sylvain Joyeux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rexml
|
@@ -101,33 +101,39 @@ dependencies:
|
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: 2.0.0
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
|
-
name:
|
104
|
+
name: net-ssh
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
|
-
- - "
|
107
|
+
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
109
|
+
version: '7.0'
|
110
110
|
type: :runtime
|
111
111
|
prerelease: false
|
112
112
|
version_requirements: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
114
|
-
- - "
|
114
|
+
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
|
-
version:
|
116
|
+
version: '7.0'
|
117
117
|
- !ruby/object:Gem::Dependency
|
118
118
|
name: net-sftp
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
|
-
- - "
|
121
|
+
- - ">="
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version:
|
123
|
+
version: 4.0.0.rc1
|
124
|
+
- - "<"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '5.0'
|
124
127
|
type: :runtime
|
125
128
|
prerelease: false
|
126
129
|
version_requirements: !ruby/object:Gem::Requirement
|
127
130
|
requirements:
|
128
|
-
- - "
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 4.0.0.rc1
|
134
|
+
- - "<"
|
129
135
|
- !ruby/object:Gem::Version
|
130
|
-
version:
|
136
|
+
version: '5.0'
|
131
137
|
- !ruby/object:Gem::Dependency
|
132
138
|
name: ed25519
|
133
139
|
requirement: !ruby/object:Gem::Requirement
|
@@ -156,6 +162,20 @@ dependencies:
|
|
156
162
|
- - ">="
|
157
163
|
- !ruby/object:Gem::Version
|
158
164
|
version: '1.0'
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: libnotify
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - "~>"
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0.9'
|
172
|
+
type: :runtime
|
173
|
+
prerelease: false
|
174
|
+
version_requirements: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - "~>"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0.9'
|
159
179
|
- !ruby/object:Gem::Dependency
|
160
180
|
name: bundler
|
161
181
|
requirement: !ruby/object:Gem::Requirement
|
@@ -273,7 +293,7 @@ files:
|
|
273
293
|
- bin/snapsync
|
274
294
|
- install.sh
|
275
295
|
- lib/snapsync.rb
|
276
|
-
- lib/snapsync/
|
296
|
+
- lib/snapsync/Notification.rb
|
277
297
|
- lib/snapsync/btrfs.rb
|
278
298
|
- lib/snapsync/btrfs_subvolume.rb
|
279
299
|
- lib/snapsync/cleanup.rb
|
@@ -286,17 +306,25 @@ files:
|
|
286
306
|
- lib/snapsync/snapshot.rb
|
287
307
|
- lib/snapsync/snapshot_transfer.rb
|
288
308
|
- lib/snapsync/ssh_popen.rb
|
309
|
+
- lib/snapsync/ssh_popen_exe.rb
|
289
310
|
- lib/snapsync/sync.rb
|
290
311
|
- lib/snapsync/sync_all.rb
|
291
312
|
- lib/snapsync/sync_last_policy.rb
|
292
313
|
- lib/snapsync/sync_target.rb
|
314
|
+
- lib/snapsync/tasks/AutoSync.rb
|
315
|
+
- lib/snapsync/tasks/Task.rb
|
293
316
|
- lib/snapsync/test.rb
|
294
317
|
- lib/snapsync/timeline_sync_policy.rb
|
295
318
|
- lib/snapsync/util.rb
|
296
319
|
- lib/snapsync/version.rb
|
297
320
|
- snapsync.gemspec
|
298
|
-
- snapsync.service
|
299
|
-
- snapsync.
|
321
|
+
- systemd/snapsync-check-is-connection-unmetered.service
|
322
|
+
- systemd/snapsync-is-connection-unmetered.service
|
323
|
+
- systemd/snapsync-local.service
|
324
|
+
- systemd/snapsync-local.timer
|
325
|
+
- systemd/snapsync-remote.service
|
326
|
+
- systemd/snapsync-remote.timer
|
327
|
+
- usrlib/snapsync-check-is-connection-unmetered.sh
|
300
328
|
homepage: https://github.com/doudou/snapsync
|
301
329
|
licenses:
|
302
330
|
- MIT
|
@@ -316,7 +344,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
316
344
|
- !ruby/object:Gem::Version
|
317
345
|
version: '0'
|
318
346
|
requirements: []
|
319
|
-
rubygems_version: 3.3.
|
347
|
+
rubygems_version: 3.3.23
|
320
348
|
signing_key:
|
321
349
|
specification_version: 4
|
322
350
|
summary: tool to automate backing up snapper snapshots to other medias
|