So now that we can play almost every movie around, it's time to move on to the next task. As mentioned earlier, my Apple TV 160GB drive was mostly empty since I've been using iTunes to sync with my 80GB laptop. It would be nice to do arbitrary, automatic synchronization from any of my computers or NAS devices, so that's what I set out to do.
The basic task will be for the Apple TV to periodically check an external source to see if any changes have been made, and if so, move them over. We could make the synchronization two-way, but for now, I'm satisfied with a one-way sync. The tool I'm most familiar with for this type of work, is rsync.
Rsync is a powerful tool providing fast incremental synchronization between directories, local and remote. It's available on a number of platforms, including Apple's OS X. Unfortunately it's not included on the Apple TV. But a quick copy of the rsync binary from my OS X machine to the Apple TV /usr/bin/ directory solves that issue.
Next, we need to set up a script to define our synchronization. For my purposes, I created a scripts subdirectory in the home directory of the Frontrow user. Inside that directory, I created the following simple script, called periodic.sh, which defined my transfer:
#!/bin/sh # Check to see if we are already running, if so exit if test -e /tmp/time ; then echo "Already running"; exit 0; fi # create a timestamp touch /tmp/time # synch from a remote system, to the local rsync -r email@example.com:appleTVDropBox/ /Users/frontrow/Movies/local/ # remove the timestamp rm /tmp/time
This script lacks a bit of bulletproofing to protect against a crash and the subsequent stale timestamp file, but it's a start.
In order for the script to run properly in an unattended mode, you'll need to set up a trusted, no password required, ssh relationship between the Apple TV and the remote system. There's not room in this article for this step, but you can find a good description of the process here. This also assumes that the remote side is running a ssh daemon and that rsync is available on the remote side. OS X users can just turn on Remote login under the Sharing system preference. Windows users have a more involved process, and Linux users likely already have rsync, and are running a ssh daemon.
After you get the ssh relationship set up, make the script executable (chmod +x periodic.sh) and try it out a few times to make sure it runs and that it doesn't ask for a password. An alternative to using ssh and a remote rsync command is just have the script do a network mount, let rsync do its thing on two "local" directories, and then unmount the network drive.
Once you're satisfied with the script, you need to get it to run periodically. As an old Linux guy, my first thought was cron. Cron is a powerful tool designed to run processes at specified intervals. OS X includes cron, but once again, the Apple TV doesn't.
Apple is also moving away from the use of cron toward a new system called launchd which is included on the Apple TV. So to learn something new, I ended up writing a launchd XML description file that specified how and when to kick off my synchronization script. The XML file was named periodic.plist and was placed in the /Library/LaunchAgents/ directory on the Apple TV. The following is my file:
<xml version="1.0" encoding="UTF-8"?> <DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label<key> <string>test<string> <key>Program<key> <string>Users/frontrow/scripts/periodic.sh<string> <key>ProgramArguments<key> <array> <string>Users/frontrow/scripts/periodic.sh<string> <array> <key>RunAtLoad<key> <true/> <key>ServiceDescription<key> <string>periodic<string> <key>StartInterval<key> <integer>1800<integer> <dict> <plist> <xml>
This file calls out the name of my script and tells the launchd daemon to run it every 1800 seconds.
The final step in getting the script to run is to tell the launchd about it with the following command:
# launchctl load /Library/LaunchAgents/periodic.plist
Similarly, an "unload" can be used to remove the script. Now with this in place, I have transparent, unattended synchronization between my Apple TV and other systems on my network. Very cool.