Command line¶
arrowloop sync -left <path> -right <path> -state <db> run one pair once
arrowloop run -config <file> <job> run one named job now
arrowloop web -config <file> serve the interface, schedules included
arrowloop daemon -config <file> run every scheduled job, no interface
arrowloop jobs -config <file> what is configured, and when each last worked
arrowloop history -config <file> [-job <name>] what the runs did
arrowloop service [-config <file>] [-os <goos>] the service file for this system
arrowloop version which build this is
Every command takes -h for its own flags.
sync¶
The shape for setting a job up: nothing to write to disk first, and -dry-run
to see what would happen before anything does.
-dry-run prints the plan and changes nothing. Both sides accept anything
rclone accepts, so sftp:backup/photos and s3:bucket/photos work alongside
plain paths.
| flag | default | meaning |
|---|---|---|
-quiet-period |
5s | how long a file must sit unchanged before it is touched, 0 disables |
-exclude |
- | glob of paths to leave alone entirely, repeatable |
-no-default-excludes |
off | also sync half-written files such as *.part and Office owner files |
-transfers |
4 | how many files may be copied at the same time |
-bwlimit |
- | bandwidth limit in rclone syntax, 1M or a timetable like 08:00,512k 19:00,off |
-empty-dirs |
off | also carry folders that hold no files |
-metadata |
off | carry permissions, ownership and extended attributes where both sides can |
-brake-percent |
50 | refuse a run deleting more than this share of known files, 0 disables |
-change-percent |
50 | refuse a run overwriting more than this share of known files, 0 disables |
-brake-floor |
10 | never trip a brake below this many deletions or overwrites |
-mod-window |
2s | how far modification times may differ and still count as equal |
-v |
off | let rclone report what it is doing underneath |
The modification window only ever applies when a side cannot produce a hash. Where hashes exist the comparison is exact, because with a two-second window a file edited twice within two seconds and left at the same length would count as unchanged.
jobs¶
Reports when each job last succeeded, not when it last ran.
"When did this last run" is the easy question. A job failing every quarter of an hour for a week looks busy in a log while being of no use at all.
web and daemon¶
web serves the interface and runs the schedules in the same process. One
process rather than two: a browser tab that could start a job but could not see
the scheduled ones would be lying by omission, and two processes sharing one
state database is the sort of arrangement that works until the day both happen
to run the same job.
It listens on loopback unless told otherwise. The interface can start a job that
deletes files and asks for no password until one is set under Settings,
Security, or through ARROWLOOP_PASSWORD_HASH, so making it reachable has to be
a decision somebody took on purpose. What the interface sets is kept in
security.json beside the configuration file. Until there is a password it
answers only on an IP address or a local name, so a web page elsewhere cannot
point a name of its own at it; installing lists the names.
daemon is the same scheduler with no interface, for a machine where nobody is
looking. It trims the run log once as it starts, keeping what historyKeep in
the configuration asks for; -keep-history sets another age for that start,
and 0 keeps every record.
service¶
Prints the file this operating system wants in order to keep the daemon alive,
and the one command that switches it on: a systemd unit file on Linux, a
LaunchAgent plist on macOS, and an sc.exe line on Windows. It prints rather
than installs: registering a service means writing outside your own files and,
on two of the three systems, asking for administrative rights.
What it tells you that is otherwise found out the hard way:
- A Windows service runs as LocalSystem, which has no mapped network drives. A job pointing at a UNC path works; one pointing at a drive letter does not.
- LocalSystem also runs the jobs' before and after commands. Register a copy of the program under Program Files and a configuration file an administrator created, not the desktop app's copy under AppData or a file in a user's profile: whoever can change either file can run anything as LocalSystem.
- A Linux user service needs
loginctl enable-lingerto survive a logout. - macOS asks for permission the first time the agent touches Documents, and until that is granted the job fails with an ordinary permission error that looks like a bug and is not one.
hash-password¶
Prints the value ARROWLOOP_PASSWORD_HASH wants. The interface sets its own
password without it; the variable is for a password managed from outside, such
as in a container template, and it wins over the one set in the interface,
which makes it the way back in after that one is forgotten.
The hash is made under the key of the install whose configuration -config
names, so run it where that install runs; in the container that is
-config /config/arrowloop.json. Without a configuration there it refuses,
unless ARROWLOOP_APP_KEY names the key.
At a terminal it asks for the password twice without echoing it; piped, it takes the first line.
arrowloop hash-password -config /config/arrowloop.json
printf '%s\n' "$PASSWORD" | arrowloop hash-password -config /config/arrowloop.json
The password never goes on the command line, where it would end up in a shell history and in the process list.
version¶
Prints which build this binary is, and nothing else, so it can be read from a script.
A release build prints its tag, a build from a commit prints the commit, and a
build from an edited tree adds -dirty, because a binary from uncommitted
changes is not the commit it names. An unstamped local go build prints dev.
The desktop application answers the same question in two more places: under Product version in the Windows file properties dialog, and on its About card. All three read one stamp, so they cannot disagree. This command exists because a Go binary carries no version resource, so the properties dialog has nothing to show for this one.