1

I have a Bash script that executes an rsync command to sync files with a remote server.

#!/bin/bash
rsync -auvzP  --exclude=.bundle --exclude=node_modules --exclude=tmp  '/Volumes/Norman Data/me/.bash_profile' '/Volumes/Norman Data/me/Documents' --exclude=remote me@example.com:backup/

This works when I run it from the terminal as I have ssh key authentication set up for my user at example.com. However, when launchd calls this script, I get the following error indicating that it cannot find my user's key file or it is invalid:

Permission denied, please try again. Permission denied, please try again. me@example.com: Permission denied (publickey,password). rsync: connection unexpectedly closed (0 bytes received so far) [sender] rsync error: error in rsync protocol data stream (code 12) at /BuildRoot/Library/Caches/com.apple.xbs/Sources/rsync/rsync-52/rsync/io.c(453) [sender=2.6.9] I am specifying my user name in my plist file and when debugging, the script says it's being run by that same user both when running it from the terminal and from launchd alike.

My BackupDaemon.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>EnvironmentVariables</key>
    <dict>
        <key>HOME</key>
        <string>/Volumes/Norman Data/me</string>
    </dict>
    <key>GroupName</key>
    <string>staff</string>
    <key>InitGroups</key>
    <true/>
    <key>Label</key>
    <string>BackupDaemon</string>
    <key>Program</key>
    <string>/Volumes/Norman Data/me/backup</string>
    <key>StandardErrorPath</key>
    <string>/tmp/BackupDaemon.err</string>
    <key>StandardOutPath</key>
    <string>/tmp/BackupDaemon.out</string>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>16</integer>
        <key>Minute</key>
        <integer>6</integer>
    </dict>
    <key>UserName</key>
    <string>me</string>
</dict>
</plist>

I can't figure out for the life of me what the issue might be or how to even go about further debugging. Any insight anyone has to share will be greatly appreciated. Thx!

10
  • You have to specify the user that the launch Agent is running as. How are you running it? LaunchAgent or LaunchDaemon. If the latter, it runs as root
    – Allan
    Mar 16 '20 at 0:33
  • LaunchDaemon, I believe. My plist is in /Library/LaunchDaemons/. Is there another way to tell? Either way, how do I go about specifying the user?
    – Daveh0
    Mar 16 '20 at 0:48
  • G'aaaaaah I moved my Plist file to ~/Library/LaunchAgents/ and it works as expected. BUT, it is my understanding that doing this will cause the script only to run when I am logged in (as opposed to someone else). Not a huge issue for my use case, but ideally a backup script would run regardless of who is logged in. Is there some way to keep it in /Library/LaunchDaemons/ but have it run as my user?
    – Daveh0
    Mar 16 '20 at 1:19
  • Yes, -/Library/LaunchAgents is for when you're logged in. See apple.stackexchange.com/a/249452/119271. You can run as a specific user Check this site for a tutorial: launchd.info
    – Allan
    Mar 16 '20 at 1:39
  • so it says that Global Daemons go in /Library/LaunchDaemons and run as root or the user specified with the key UserName. I thought that's exactly what I had going on above... and it wasn't working. Am I missing something?
    – Daveh0
    Mar 16 '20 at 2:16
2

So this is what I ended up doing to get it working. For my use case it is sufficient, but I don''t think it's the best solution. Hopefully someone (see @Allan's comments in OP) can come up with a more universal solution.

I added the -e option to my rsync statement which allows you to specify the exact ssh command used.

rsync -auvzP  -e "ssh -i ~/.ssh/id_rsa_scripts" '/Volumes/Norman Data/me/Documents' me@example.com:backup/

The important part in there is ~/.ssh/id_rsa_scripts - I generated a secondary set of keys for that server, with this set having no passphrase. This is different from how I connect to that box via SSH by default and thus why it needed to be specified in the rsync command.

That was the only way I could get it to work when running unattended (as a Global Daemon). Although it is ok under my set of circumstances, a passphrase-less key is not the best idea in many situations, which is why this is not the ** best ** solution.

Hopefully someone can figure out a way to allow launchd to execute a script requiring SSH authentication using keys with a passphrase.

2
  • 1
    to my knowledge, passphrase-less is the way to go for ssh to another server if not already logged in. And, if you are logged in, ensure the key is added to an ssh agent, then you won't be asked for the passphrase again. Since the script is backing up your own directory, why make it a daemon? You're not logged in, so no changes. You could save a long ssh line by including what you need in a ~/.ssh/config for that host. Mar 18 '20 at 18:17
  • Thank you so much, I could not figure out why my LaunchAgent would not be able to run rsync... Turns out, when the computer is in sleep mode, the passphrase-protected id_rsa could not be read by ssh/rsync...!! Using a passphrase-less id_rsa_... private key worked. Thanks so much! Mar 10 at 19:46

You must log in to answer this question.

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