3

We'd like to use unison to sync two servers. From the command line and in bash files the following command works fine:

unison -batch /var/www/html/test ssh://host-2//var/www/html/test

Files are being synchronized and unison.log is being updated. so far so good.

in combination with a preference file, such as .unison/default.prf and simply executing unison from the command line as described here, things work fine too.

We've also installed incrond inotify cron daemon and it's running smooth. The following cron job is being executes just fine:

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE touch /root/test

/root/test is being updated every time I make changes to files in /var/www/html/test

So far so good! But the only things that don't work using the incrontab are:

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE unison

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE /usr/bin/unison

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE /usr/local/sbin/unison

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE unison -batch /var/www/html/test ssh://host-2//var/www/html/test

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE /usr/bin/unison -batch /var/www/html/test ssh://host-2//var/www/html/test

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE /usr/local/sbin/unison -batch /var/www/html/test ssh://host-2//var/www/html/test'

Nothing shows in the unison.log file, let alone updating the remote server.The following also doesn't output anything.

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE unison &> /root/test.log

/root/test.log is not even being created.

Another test using a batch file named sync.sh also doesn't work.

in the incrontab:

/var/www/html/test IN_MODIFY,IN_ATTRIB,IN_CREATE /root/sync.sh

and in sync.sh:

#!/bin/bash

touch /root/test
/usr/bin/unison -batch /var/www/html/test ssh://host-2//var/www/html/test

Again, /root/test is being touched just fine, meaning inofify works great every time I update a file in /var/www/html/test, but again no result at all from unison.

/var/log/cron looks like this:

May 21 06:33:44 Host-1 incrond[28339]: (root) CMD (sh /root/sync.sh)

and the unison.log is not being updated at all.

Conclusions:

  1. inotify works fine, detects every change in the file system and executes a task, except for any unison task.
  2. unison works fine from command line and in batch, except when called by the incrond daemon.

Am I overlooking something?

1
  • Some background from a working installation: unison.log only gets updated if files were actually synchronized. Nothing gets logged if the check determines that there were no changes that needed synchronization, or if the check fails altogether, for whatever reason. Other information gets written to stdout/stderr, but does not end up in the log file by default unless you explicitly redirect it.
    – user149408
    Mar 22, 2022 at 14:15

1 Answer 1

1

In order to establish an SSH connection, the client needs to authenticate to the server. You're probably using key-based authentication, with a key stored in a password-protected file and loaded into the SSH agent. The SSH client knows how to find the agent through the environment variable SSH_AUTH_SOCK. In a cron or incron job, the environment is not the same as in your interactive session, it's a pretty minimal one, without SSH_AUTH_SOCK, so the SSH client can't connect to the remote machine.

If the SSH connection can't be established, Unison doesn't even start looking for files to synchronize and nothing gets written to unison.log.

There are error messages on the script's standard error, but you aren't logging them anywhere. Add something like exec 2>&1 >>~/.unison-sync.log; date to the beginning of your script.

To get the SSH connection to work, you'll either need to arrange for the Unison job to have access to your agent, or to set up a passwordless key. If you want to go through your agent, see Not able to ssh in to remote machine using shell script in Crontab; but then it'll only work while you're logged in. If you want the synchronization to work all the time, a passwordless key is the only solution. Since you're running Unison and thus SSH as root, the private key need to be in /root/.ssh, not on your account. The same goes for any relevant option in .ssh/config. On the server side, you can authorize the public key only to run a specific unison command with a command=… directive in .ssh/authorized_keys (see Creating a UNIX account which only executes one command for an example). With a command restriction, if someone gains access to the local root account, they'll only be able to run that specific unison … command on host-2; I don't know whether Unison can be tricked into executing arbitrary code that way.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .