summaryrefslogtreecommitdiff
path: root/dss.suite.m4
blob: 3fe3122b6b619bcfa600a4ce61ab31b292f4415a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
# SPDX-License-Identifier: GPL-2.0

[suite dss]
caption = Subcommands

[supercommand dss]
	[description]
		DESCRIPTION1()

		DESCRIPTION2()

		DESCRIPTION3()
	[/description]
	purpose = SLOGAN()
	synopsis = [global-options...] [--] [<subcommand> [subcommand-options...]]

	[option general-options-section]
		summary = General options
		flag ignored
	[option help]
		summary = print help and exit
		short_opt = h
	[option detailed-help]
		summary = print help, including all details, and exit
	[option version]
		summary = print version and exit
		short_opt = V
	[option config-file]
		short_opt = c
		summary = use alternative config file (default: ~/.dssrc)
		typestr = path
		arg_info = required_arg
		arg_type = string
		[help]
			Options may be given at the command line or in the configuration
			file. As usual, if an option is given both at the command line and
			in the configuration file, the command line option takes precedence.

			However, there is one exception to this rule: The run subcommand
			re-reads the configuration file when it receives the HUP signal. In
			this case the options in the config file override any options that
			were previously given at the command line. This allows changing the
			configuration of a running dss process by sending SIGHUP.
		[/help]
	[option loglevel]
		short_opt = l
		summary = set loglevel (0-6)
		typestr = level
		arg_info = required_arg
		arg_type = uint32
		default_val = 4
		[help]
			Lower values mean more verbose logging.
		[/help]
	[option dry-run]
		short_opt = n
		summary = only print what would be done
		[help]
			This flag does not make sense for all subcommands. The run subcommand
			refuses to start if this option was given while the ls subcommand
			silently ignores the flag.
		[/help]
	[option source-dir]
		summary = the remote directory to snapshot
		typestr = dirname
		arg_info = required_arg
		arg_type = string
		flag multiple
		[help]
			The directory on the remote host from which snapshots are taken.
			Of course, the user specified as --remote-user must have read access
			to this directory.

			This option is mandatory for the create and run subcommands: It may
			be given multiple times to specify more than one source directory.
			However, all source directories must reside on the same server.
		[/help]
	[option dest-dir]
		summary = where snapshots are stored
		typestr = dirname
		arg_info = required_arg
		arg_type = string
		[help]
			The destination directory on the local host where snapshots will be
			written. This must be writable by the user who runs dss.

			This option is mandatory for all subcommands except kill.
			Unlike --source-dir, this option may only be given once.
		[/help]
	[option mountpoint]
		summary = abort if destination directory is not a mountpoint
		[help]
			This option checks whether a file system is mounted on the directory
			specified as the argument to --dest-dir. Operation proceeds only
			if this is the case. Otherwise dss exits unsuccessfully without
			performing any action. Use this option to prevent snapshot creation
			if the snapshot file system is not mounted.

			This option is silently ignored for subcommands which do not depend
			on the destination directory.
		[/help]
	[option Rsync-options]
		summary = Controlling how rsync is run
		flag ignored
		[help]
			These options are only relevant to the run and the create subcommands.
		[/help]
	[option remote-host]
		short_opt = H
		summary = host to take snapshots from
		typestr = hostname
		arg_info = required_arg
		arg_type = string
		default_val = localhost
		[help]
			If this option is given and its value differs from the local
			host, then rsync uses ssh. Make sure there is no password
			needed for the ssh connection. To achieve that, use public key
			authentication for ssh and, if needed, set the remote user name
			by using the --remote-user option.
		[/help]
	[option remote-user]
		short_opt = U
		summary = Remote user name (default: current user)
		arg_info = required_arg
		typestr = username
		arg_type = string
		[help]
			Set this if the user that runs dss is different from the user on the
			remote host.
		[/help]
	[option checksum]
		summary = run rsync with --checksum occasionally
		typestr = permille
		arg_info = required_arg
		arg_type = uint32
		default_val = 0
		[help]
			If a file on the backup becomes corrupt in a way that file size
			and modification time still match the original file, rsync will not
			consider the file for transfer ("quick check"). Hence the corruption
			stays on the backup until the file is modified on the source.
			The --checksum option of rsync disables the quick check and compares
			the contents of each file, fixing such corruptions. Since computing
			the checksums adds a significant slowdown due to a lot of disk I/O,
			the option is not enabled by default.

			The argument to the --checksum option of dss is a number between 0
			and 1000, inclusively, which determines the probability of adding
			--checksum to the rsync options each time a snapshot is created. The
			default value zero means to never add the option. The value 100 will
			create every tenth snapshot (on average) using checksums, and the
			value 1000 will always pass --checksum to rsync.
		[/help]
	[option rsync-option]
		short_opt = O
		summary = further rsync options
		typestr = option
		arg_info = required_arg
		arg_type = string
		flag multiple
		[help]
			This option may be given multiple times. The given argument is
			passed verbatim to the rsync command. Note that in order to use
			rsync options that require an argument, you have to specify the
			option and its argument as separate --rsync-options, like this:

				--rsync-option --exclude --rsync-option /proc
		[/help]
	[option intervals]
		summary = Fine tuning the number of snapshots per time unit
		flag ignored
	[option unit-interval]
		short_opt = u
		summary = the duration of a unit interval
		typestr = days
		arg_info = required_arg
		arg_type = uint32
		default_val = 4
		[help]
			Increasing this number instructs dss to create fewer snapshots per
			time unit while the number of snapshots to keep stays the same.
		[/help]
	[option num-intervals]
		short_opt = n
		summary = the number of unit intervals
		typestr = num
		arg_info = required_arg
		arg_type = uint32
		default_val = 5
		[help]
			Increasing this number by one doubles the total number of
			snapshots.
		[/help]
	[option hooks]
		summary = Commands to be run on certain events
		flag ignored
		[help]
			All hooks default to "true". That is, the true(1) utility (which
			always returns with exit code zero) is executed if the hook command
			is not specified.
		[/help]
	[option pre-create-hook]
		short_opt = r
		summary = executed before a snapshot is created
		typestr = command
		arg_info = required_arg
		arg_type = string
		default_val = true
		[help]
			This command is executed before dss runs rsync to create a new
			snapshot. If the command returns with a non-zero exit status, no
			snapshot will be created and the operation is retried later.

			For example, the command could execute a script that checks whether
			all snapshot-related file systems are mounted.

			Another possible application of the pre-create hook is to return
			non-zero during office hours in order to not slow down the file
			systems by taking snapshots.
		[/help]
	[option post-create-hook]
		summary = executed after a snapshot has been created
		typestr = command
		arg_info = required_arg
		arg_type = string
		default_val = true
		[help]
			This is only executed if a snapshot has successfully been created. The
			full path of the newly created snapshot is passed to the hook as the
			first argument. The exit code of this hook is ignored.

			For instance this hook could count the number of files per user
			and/or compute disk usage patterns to be stored in a database for
			further analysis.
		[/help]
	[option pre-remove-hook]
		summary = executed before a snapshot is removed
		typestr = command
		arg_info = required_arg
		arg_type = string
		default_val = true
		[help]
			The full path to the snapshot which is about to be removed is passed
			to the command as the first argument. If the command returns with
			a non-zero exit status, the snapshot is not going to be removed and
			the operation is retried later.

			For example, one could execute a script that checks whether the
			snapshot to be deleted is currently used by another process, e.g. by
			a tape-based backup system that runs concurrently to dss.

			Another possible application of this is to record disk-usage
			patterns before and after snapshot removal.
		[/help]
	[option post-remove-hook]
		summary = executed after snapshot removal
		typestr = command
		arg_info = required_arg
		arg_type = string
		default_val = true
		[help]
			As for the pre-remove hook, the full path of the removed snapshot is
			passed to the hook as the first argument. The exit code of this hook
			is ignored.
		[/help]
	[option exit-hook]
		summary = executed before the run command exits
		typestr = command
		arg_info = required_arg
		arg_type = string
		default_val = true
		[help]
			This hook is only relevant to the run subcommand. It is executed just
			before dss terminates. The reason for termination is passed as the
			first argument.

			One possible application for this hook is to send email to the system
			administrator to let her know that no more snapshots are going to
			be created.
		[/help]

	[option disk-space-monitoring]
		summary = Disk space monitoring
		flag ignored
		[help]
			The options of this section control the aggressiveness of snapshot
			removal. That is, they define under which circumstances existing
			snapshots are removed. These options are only relevant to the run
			and the prune subcommands.
		[/help]
	[option min-free-mb]
		short_opt = m
		summary = minimal amount of free disk space
		arg_info = required_arg
		arg_type = uint32
		typestr = megabytes
		default_val = 100
		[help]
			If disk space on the file system containing the destination
			directory gets low, the run subcommand suspends the currently
			running rsync process and starts to remove snapshots in order to
			free disk space. This option specifies the minimal amount of free
			disk space. If less than the given number of megabytes is available,
			snapshots are being deleted. See also the --min_free_percent and the
			min-free-percent-inodes options below.

			A value of zero deactivates this check.
		[/help]
	[option min-free-percent]
		short_opt = p
		summary = minimal percentage of free disk space
		arg_info = required_arg
		arg_type = uint32
		typestr = percent
		default_val = 2
		[help]
			This is like --min-free-mb but the amount of free disk space
			is specified as a percentage. It is not recommended to set both
			--min-free-mb and --min-free-percent to zero as this will cause your
			file system to fill up quickly.
		[/help]
	[option min-free-percent-inodes]
		short_opt = i
		summary = minimal percent of free inodes
		arg_info = required_arg
		arg_type = uint32
		typestr = percent
		default_val = 0
		[help]
			The minimum amount of free inodes on the file system containing the
			destination dir. If the percentage of free inodes drops below the
			given value, snapshot removal kicks in like in case of low disk space.

			The number of free inodes is determined from the f_ffree field of
			the statvfs structure. However, some file systems set this field to
			zero, indicating that the number of inodes is basically unlimited.
			Moreover it is not possible to reliably detect whether this is the
			case. Therefore this feature is disabled by default. It's safe to
			enable it for ext2/ext3/ext4 file systems on linux though.

			A value of zero (the default) deactivates this check.
		[/help]
	[option keep-redundant]
		short_opt = k
		summary = prune by disk space only
		[help]
			By default, redundant and outdated snapshots are removed automatically
			to keep the number of snapshots in harmony with the configured
			policy. If this flag is given, dss removes such snapshots only if
			disk space or number of free inodes becomes low.
		[/help]
	[option min-complete]
		summary = minimal number of complete snapshots to keep
		arg_info = optional_arg
		arg_type = uint32
		typestr = num
		default_val = 1
		[help]
			This option is only relevant if snapshots must be deleted because
			disk space gets low.

			dss refuses to remove old snapshots if there are fewer complete
			snapshots left than the given number. The default value of one
			guarantees that at least one complete snapshot is available at
			all times.

			If only <num> complete snapshots are left, and there is not enough
			disk space available for another snapshot, the program terminates
			with a "No space left on device" error.
		[/help]

[introduction]
	dss supports the subcommands described below. If no subcommand is
	given, the list of available subcommands is shown and the program
	terminates successfully without performing any further action.
[/introduction]

[subcommand run]
	purpose = start creating and pruning snapshots
	[description]
		This is the main mode of operation. Snapshots are created in an endless
		loop as needed and pruned automatically. The loop only terminates on
		fatal errors or if a terminating signal was received. See also the
		--exit-hook option.
	[/description]
	[option daemon]
		short_opt = d
		summary = run as background daemon
		[help]
			If this option is given, the dss command detaches from the console
			and continues to run in the background. It is not possible to let
			a daemonized process re-attach to the console by editing the config
			file and sending SIGHUP. However, log output may be redirected to a
			different file in this way.

			See --logfile.
		[/help]
	[option logfile]
		short_opt = l
		summary = where to write log output
		arg_info = required_arg
		arg_type = string
		typestr = path
		default_val = /dev/null
		[help]
			This option is only honored if --daemon is given, in which case
			log messages go to the given file. Otherwise the option is silently
			ignored and log output is written to stderr.
		[/help]
	[option max-rsync-errors]
		summary = terminate after this many rsync failures
		typestr = count
		arg_info = required_arg
		arg_type = uint32
		default_val = 10
		[help]
			If the rsync process exits with a fatal error, dss restarts the command
			in the hope that the problem is transient and subsequent rsync runs
			succeed. After the given number of consecutive rsync error exits,
			however, dss gives up, executes the exit hook and terminates. Set
			this to zero if dss should exit immediately on the first rsync error.

			The only non-fatal error is when rsync exits with code 24. This
			indicates a partial transfer due to vanished source files and happens
			frequently when snapshotting a directory which is concurrently being
			modified.
		[/help]
[subcommand create]
	purpose = execute rsync once to create a new snapshot
	[description]
		This command does not check the amount free disk space. The pre-create
		and post-create hooks are honored, however.

		Specify --dry-run to see the rsync command which is executed to create
		snapshots.
	[/description]
[subcommand prune]
	purpose = remove snapshots
	[description]
		A snapshot is said to be (a) outdated if its interval number is greater
		or equal than the specified number of unit intervals, (b) redundant if
		the interval it belongs to contains more than the configured number of
		snapshots, and (c) orphaned if it is incomplete and not being created
		or deleted. All other snapshots are called regular.

		Unless --dry-run is given, which just prints the snapshot that would be
		removed, this subcommand gets rid of non-regular snapshots.  At most
		one snapshot is removed per invocation. If no such snapshot exists
		and disk space is low, the subcommand also removes regular snapshots,
		always picking the oldest one.

		The subcommand fails if there is another dss "run" process.
	[/description]
	[option disk-space]
		summary = act as if free disk space was high/low
		arg_info = required_arg
		arg_type = string
		typestr = mode
		values = {
			FDS_CHECK = "check",
			FDS_HIGH = "high",
			FDS_LOW = "low"
		}
		default_val = check
		[help]
			By default, free disk space is checked and even regular snapshots
			become candidates for removal if disk space is low. This option
			overrides the result of the check.
		[/help]
[subcommand ls]
	purpose = print the list of all snapshots
	[description]
		The list contains all existing snapshots, no matter of their state.
		Incomplete snapshots and snapshots being deleted will also be listed.
	[/description]
[subcommand kill]
	purpose = send a signal to a running dss process
	[description]
		This sends a signal to the dss process that corresponds to the given
		config file. If --dry-run is given, the PID of the dss process is
		written to stdout, but no signal is sent.
	[/description]
	[option signal]
		short_opt = s
		summary = send the given signal rather than SIGTERM
		typestr = signal
		arg_info = required_arg
		arg_type = string
		default_val = SIGTERM
		[help]
			Like for kill(1), alternate signals may be specified in three ways: as
			a signal number (e.g., 9), the signal name (e.g., KILL), or the signal
			name prefixed with "SIG" (e.g., SIGKILL). In the latter two forms,
			the signal name and the prefix are case insensitive, so "sigkill"
			works as well.

			Sending SIGHUP causes the running dss process to reload its config file.
		[/help]
	[option wait]
		short_opt = w
		summary = wait until the signalled process has terminated
		[help]
			This option is handy for system shutdown scripts which would like
			to terminate the dss daemon process.

			Without --wait the dss process which executes the kill subcommand
			exits right after the kill(2) system call returns. At this point the
			signalled process might still be alive (even if SIGKILL was sent).
			If --wait is given, the process waits until the signalled process
			has terminated or the timeout expires.

			If --wait is not given, the kill subcommand exits successfully if
			and only if the signal was sent (i.e., if there exists another dss
			process to receive the signal). With --wait it exits successfully
			if, additionally, the signalled process has terminated before the
			timeout expires.

			It makes only sense to use the option for signals which terminate dss.
		[/help]
[subcommand configtest]
	purpose = run a configuration file syntax test
	[description]
		This command checks the command line options and the configuration
		file for syntactic correctness. It either reports "Syntax Ok" and
		exits successfully or prints information about the first syntax error
		detected and terminates with exit code 1.
	[/description]
[subcommand help]
	purpose = list available subcommands or print subcommand-specific help
	non-opts-name = [subcommand]
	[description]
		If the optional subcommand argument is given, the help text of that
		subcommand is shown. Without the argument the available subcommands
		are listed instead.
	[/description]
	[option long]
		short_opt = l
		summary = show the long help text of a subcommand
		[help]
			If this option is given, the command also shows the description of
			the subcommand and the help text of each option, Otherwise only the
			purpose, the synopsis and the option list of the subcommand is shown.
			If no subcommand is supplied, the option has no effect.
		[/help]

[section examples]
	Suppose you'd like to create snapshots of the existing directory
	.I /foo/bar
	in the directory
	.IR /baz/qux .
	Create the config file
	.I ~/.dssrc
	containing
	the values for the source and the destination directories
	as follows:

	.RS 6
	.EX
		echo 'source-dir "/foo/bar"' > ~/.dssrc
		echo 'dest-dir "/baz/qux"' >> ~/.dssrc
	.EE
	.RE

	Then execute the commands

	.RS 6
	.EX
		mkdir /baz/qux
		dss run
	.EE
	.RE

	To print the list of all snapshots created so far, run
	.IR dss\~ls .

	The second example involves a slightly more sophisticated config
	file. It instructs dss to exclude everything which matches at least
	one pattern of the given exclude file, prevents rsync from crossing
	file system boundaries and increases the number of snapshots.

	.RS 6
	.EX
		source-dir "/foo/bar"
		dest-dir "/baz/qux"
		# exclude files matching patterns in /etc/dss.exclude
		rsync-option \-\-exclude\-from=/etc/dss.exclude
		# don't cross filesystem boundaries
		rsync-option \-\-one\-file\-system
		# maintain 2^6 - 1 = 63 snapshots
		num-intervals "6"
	.EE
	.RE

	The
	.I /etc/dss.exclude
	file could look like this (see rsync(1) for more examples)

	.RS 6
	.EX
		 - /proc
		 - /**/tmp/
	.EE
	.RE
[/section]

[section snapshot distribution]
	The age of a snapshot is measured in terms of unit
	intervals. Given
	the duration
	.I u
	of a unit
	interval and the number
	.I n
	of unit intervals to consider, dss tries to keep
	.I 2^(n-k-1)
	snapshots in interval
	.IR k ,
	where the interval number
	.I k
	counts
	from zero to
	.IR n-1 ,
	with zero being the most recent unit interval. Snapshots older than
	.I n
	unit intervals are regarded as outdated and are removed. There are
	.I 2^n-1
	snapshots in total.

	For example, with four unit intervals, the 2^4 - 1 = 15 snapshots
	are distributed as follows.

	.TS
	allbox;
	lb r r r r
	lb r r r r.
	Interval	3	2	1	0
	Snapshots	\~\~\~\~*\~\~\~	\~\~*\~\~*\~\~	\~*\~*\~*\~*	********
	.TE

	Note that for this to work out the system must be fast enough to
	create at least
	.I 2^(n-1)
	snapshots per unit interval because this is the number of snapshots
	in interval zero.
[/section]

[section copyright]
	Written by AUTHOR()
	.br
	Copyright (C) 2008 - present AUTHOR()
	.br
	License: LICENSE()
	.br
	This is free software: you are free to change and redistribute it.
	.br
	There is NO WARRANTY, to the extent permitted by law.
	.P
	Project web page:
	.UR URL()
	.UE
	.br
	Git clone «URL»:
	.UR CLONE_URL()
	.UE
	.br
	Gitweb:
	.UR GITWEB_URL()
	.UE
	.br
	Author's home page:
	.UR HOME_URL()
	.UE
	.br
	Report bugs to
	.MT EMAIL()
	AUTHOR()
	.ME
[/section]

[section see also]
	.BR ssh (1) ,
	.BR rsync (1)
[/section]