Installing Google Drive On Raspberry Pi

Google gives you 15 GB of space for Google Drive, Gmail, and Google+ Photos, completely free. Further you can browse and open your files on Windows, MAC, Android, iPhone/iPad, on Windwows Phone and the Web Interface (see Official Page).
For Linux, there is no support from Google, but there is an Open Source program called Grive. Here I will describe how to Setup Grive on the Raspberry Pi and how to set up a Filesystem Watcher that will sync the Google Drive folder when a file is added, deleted or changed.
Fortunately, you will not have to store or even enter your Google password on the RPi. Rather the authentication is done via access tokens (see OAuth). Google issues a text token that authorizes Grive to access your Google Drive. With the token the app can see your E-Mail address with basic account info and access your Google Drive Files and Google Docs but it cannot access your Gmail or Google+ account. You can check and revoke the rights at this URL.

Grive Dependencies Installation

To install needed packages, run:

sudo apt-get install -y git cmake libgcrypt11-dev libjson0-dev libcurl4-openssl-dev libexpat1-dev libboost-filesystem-dev libboost-program-options-dev libboost-all-dev build-essential automake autoconf libtool pkg-config libcurl4-openssl-dev intltool libxml2-dev libgtk2.0-dev libnotify-dev libglib2.0-dev libevent-dev checkinstall qt4-dev-tools  

I added qt4-dev-tools to the list of packages because without it, I got the following error message when executing cmake . for Grive:

CMake Error at /usr/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:97 (MESSAGE): Could NOT find Qt4 (missing: QTQMAKEEXECUTABLE QTMOCEXECUTABLE QTRCCEXECUTABLE QTUICEXECUTABLE QTINCLUDEDIR QTLIBRARYDIR QTQTCORELIBRARY) Call Stack (most recent call first):
/usr/share/cmake-2.8/Modules/FindPackageHandleStandardArgs.cmake:288 (FPHSAFAILUREMESSAGE) /usr/share/cmake-2.8/Modules/FindQt4.cmake:1200 (FINDPACKAGEHANDLESTANDARDARGS) bgrive/CMakeLists.txt:3 (findpackage)

There is one dependency that must be installed from source:

mkdir -p /home/pi/sources  
cd /home/pi/sources  
git clone git://github.com/lloyd/yajl yajl  
cd yajl  
./configure
cmake .  
make  
sudo checkinstall --nodoc --default  


Building the Grive Executable

Grive is not installed but only the executable is built from source:

mkdir -p /home/pi/sources  
cd /home/pi/sources  
git clone git://github.com/Grive/grive.git  
cd ./grive  
cmake .  
make  


When executing make, I got the following error:

Linking CXX static library libgrive.a [ 81%] Built target grive Scanning dependencies of target btest
[ 83%] Building CXX object libgrive/CMakeFiles/btest.dir/test/btest/JsonValTest.cc.o /tmp/ccBfo0pD.s: Assembler messages: /tmp/ccBfo0pD.s:1331: Warning: swp{b} use is deprecated for ARMv6 and ARMv7 [ 84%] Building CXX object libgrive/CMakeFiles/btest.dir/test/btest/UnitTest.cc.o [ 86%] Building CXX object libgrive/CMakeFiles/btest.dir/test/btest/ValTest.cc.o /tmp/ccKQrbkl.s: Assembler messages: /tmp/ccKQrbkl.s:1331: Warning: swp{b} use is deprecated for ARMv6 and ARMv7 Linking CXX executable btest
[ 86%] Built target btest Scanning dependencies of target griveexecutable
[ 88%] Building CXX object grive/CMakeFiles/grive
executable.dir/src/main.cc.o /tmp/cchIXryd.s: Assembler messages: /tmp/cchIXryd.s:1788: Warning: swp{b} use is deprecated for ARMv6 and ARMv7 Linking CXX executable grive
../libgrive/libgrive.a(State.cc.o): In function `gr::v1::State::Write(boost::filesystem3::path const&) const': State.cc:(.text+0x19bc): undefined reference to `gr::Json::Json(long const&)'
State.cc:(.text+0x1a4c): undefined reference to `gr::Json::Json(unsigned long const&)'
State.cc:(.text+0x1b2c): undefined reference to `gr::Json::Json(long const&)'
collect2: ld returned 1 exit status
grive/CMakeFiles/griveexecutable.dir/build.make:95: recipe for target 'grive/grive' failed
make[2]: *** [grive/grive] Error 1
CMakeFiles/Makefile2:162: recipe for target 'grive/CMakeFiles/grive
executable.dir/all' failed
make[1]: *** [grive/CMakeFiles/grive_executable.dir/all] Error 2
Makefile:113: recipe for target 'all' failed
make: *** [all] Error 2

As described here, there is a simple fix. Open the file /home/pi/sources/grive/libgrive/src/drive/State.cc and in lines 251, 252 and 257, replace Json(m_ with Json((boost::uint64_t)m_. Then run make again.

In the tutorials that I read, grive was not stored in /usr/local/bin but in the directory that is synchronized. It has the advantage that the synchronization can be started without arguments, just by calling ./grive.
So, create a directory that should be synchronized and copy the Grive executable to it:

mkdir -p /home/pi/google-drive  
cp /home/pi/sources/grive/grive/grive /home/pi/google-drive  


Get an Access Token

Go to the Grive directory cd /home/pi/google-drive, start Grive with the 'Request authorization token' option ./grive -a and follow the instructions. The hidden file .grive is created that contains the access token.

Syncing Files Manually

To sync all files, and subfolders where the 'grive' executable and the '.grive' access token are located, run ./grive.

Deleting Files

If files that are already uploaded are deleted, then they are moved to the google-drive-trash. So if you are uploading a lot of data, then you will reach the 15 GB storage limit at some time, even if you delete files regularly. The trash folder is synced back to the RPi. It is a hidden folder with the name '.trash' in the directory where the Grive executable and the access token are located. To free space you can empty the trash, for example on the Google Drive Web-Interface here.
Files that are not deleted on the RPi but remotely will also be moved to the trash folder locally when syncing. For this the user that runs ./grive must have write priviledges. Further, I had to call ./grive several times until no more remote changes were detected. For local changes calling ./grive once is sufficient to push all local changes to the cloud.

Grive Filesystem Watcher

My use case for Grive is to upload files very quickly to the cloud when they are saved locally. By quickliy I mean less than 10 seconds after saving them. However Grive cannot be started to do what is described in the following sentence: "Check if files were changed locally and if yes then synchronize them." When called, Grive will always download the remote server file list. So to have a response time of less than 10 seconds, you would also need to download the remote server file list every 10 seconds.
In order to avoid calling Grive in a loop, I wrote a Node.js script in JavaScript that lets the operating system monitor a folder and all subfolders for changes. Grive is called by the script only if a file is added, removed or changed.
To use the filesystem watcher, you need to install Node.js and the node package forever, if you do not have it already. For this type wget http://node-arm.herokuapp.com/node_latest_armhf.deb and sudo dpkg -i node_latest_armhf.deb and sudo npm -g install forever. Now go to the directory of your grive executable as cd /home/pi/google-drive and download the Grive Filesystem Watcher with wget http://www.home-automation-community.com/downloads/grive-filesystem-watcher.js. You can test the script with node grive-filesystem-watcher.js. If the user does not have permissions to read, create and delete files and folders in the synchronized directories, then you can use sudo.
Since the script is supposed to run in the background, it has some advantages to start it with 'forever' instead of directly with 'node'. With forever the script runs in the background and you can ask forever for status, logs or to stop the script. The command is forever start grive-filesystem-watcher.js. forever logs will show you the log numbers of the active scripts and the location of their log files, forever logs 0 will output the logs of the script with index 0 and forever stop 0 will stop script with index 0.
A simple way to let the script start on boot is to add the line cd /home/pi/google-drive && /usr/bin/sudo /usr/local/bin/forever start -p /home/pi/.forever grive-filesystem-watcher.js to your /etc/rc.local file. Here the folder where the script is located is '/home/pi/google-drive' and it is started as user 'root'. sudo seems unnecessary here, but without it, the program will not start. Because forever was started as root, you need to use sudo to see status information as sudo forever logs.

How to Limit Grive CPU Usage and Increase Response Time

If there are only a few dozens of files in the synchronized folders, then Grive uses very few of the RPi's CPU resources. When it starts, it uses about 20% for about 2 seconds and then about 2% while it synchronizes. However I am currently having about 3000 image files on Google Drive and the step "Reading remote server file list" takes about 50 seconds at about 50% CPU usage on the RPi even if nothing has changed.
To speed up grive you can archive (zip) the files or folders. For example my camera stores pictures in folders that are named by the day when the photo was taken. Since I only need access to the folders of the current day, I zip all other folders and delete the files. A large number of files in the trash does not affect the time it takes to read the remote server file list.
If you want to limit the percentual CPU usage of Grive to e.g. 10% or 20%, then you can install the program cpulimit with sudo apt-get install -y cpulimit and then add the line /usr/bin/cpulimit -e grive -l 15 to your /etc/rc.local so the cpulimit program is started on boot. Here the limit is 15%.

Grive Syncing Incorrectness

Uploading files with grive works quite good, when ignoring the issue that it gets very slow when the number of files increases (see previous section). However I do not understand what it does when I add files to Google Drive from Windows. Grive will first download the files, then when called again it finds that some of those downloaded files were 'deleted in local' and it will delete them in remote. Further grive can be called several times when a file was uploaded from Windows and every time if finds something to do.

Alternatives to Grive

When googling for alternatives for grive I read the following comment on a blog: "having tried grive and found that it was terrible for a few reasons, but namely because it was slow and would crash trying to index huge file sets". If you agree with this, then you may try the Google Drive Sync tool that the user, who wrote the comment, made. It is called gsync. There is an issue that explaines that the version that is installed with 'pip install gsync' is lacking some features and how to get the latest version. See here.
There is also a Web API from Google with examples in different programming languages.

Sources and Further Reading

Grive Installation Manual
http://www.lbreda.com/grive/installation

Grive on GitHub
https://github.com/Grive/grive

Official Google Drive Page
https://www.google.com/drive/