-Kipling
This page describes how to configure the Raspberry Pi 2 as an NFS Client and a remote Linux PC as an NFS Server so that the contents of a directory on the remote Linux box are visible on the Raspberry Pi. This page is part of a series of web pages which describe how to install C# and Mono on the Raspberry Pi 2 and also how to configure a useful remote compilation and debugging toolchain for it.
The previous page in this series described the installation and configuration of MonoDevelop on a remote Ubuntu Linux PC. This PC, known in this documentation as the Development PC, will be used to create C# projects and remotely compile them to executable form. The primary purpose of mapping a directory on the Development PC into the Raspberry Pi is to ensure that any executable code created remotely is instantly and automatically available to run on the Raspberry Pi without any user interaction. In short, a pleasant working environment with remote compilation and execution is achieved by creating an executable on the Development PC using a nice IDE and having NFS automatically move that file over to a mapped directory on the Raspberry Pi where it can be run.
The Development PC needs to be able to provide the files in a directory to the Raspberry Pi. This means the Development PC needs to act as an NFS server and the Raspberry Pi needs to be configured as an NFS Client. To set this up I followed (in general) the instructions on these two pages: https://help.ubuntu.com/community/SettingUpNFSHowTo and http://askubuntu.com/questions/8534/share-files-and-printer-between-two-ubuntu-boxes/8573#8573. The specific steps taken are outlined below.
Setting up the Ubuntu host (hereinafter referred to as the "Development PC") as an NFS server requires you to be the root user. Rather than prefacing every command by sudo
you may wish to just become the root user by issuing the sudo -s
command once before starting.
In the examples below, the user on the Development PC is dtree
and its home directory is /home/dtree
. All projects for the Raspberry Pi
created in MonoDevelop are located below the /home/dtree/RBerrySharp/CSharpCode
subdirectory. The actual executables generated by MonoDevelop
will be much lower in that tree, for example the executable of the HelloWorldTest project is in the location: /home/dtree/RBerrySharp/CSharpCode/HelloWorldTest/bin/Debug/HelloWorldTest.exe
.
I have lots of projects and
rather than map the bin/Debug
directory of each project individually over to the Raspberry Pi I chose to create every project
below the CSharpCode
directory and then just map the
entire directory over to the Raspberry Pi. I then created a small shell script on the Raspberry Pi (discussed later) which I can invoke
to run appropriate executable for each project in its location in the CSharpCode
tree.
First on the Development PC (as root) we install the required packages...
apt-get install nfs-kernel-server
Create an export filesystem:
mkdir -p /export/RP2NFS
Make sure the permissions are 777
chmod 777 /export/RP2NFS
Mount the directory we wish to map into the export filesystem
mount --bind /home/dtree/RBerrySharp/CSharpCode /export/RP2NFS
Edit the line in the /etc/default/nfs-kernel-server
file to say
NEED_SVCGSSD="no"
Confirm the /etc/idmapd.conf
file has the lines
Nobody-User = nobody Nobody-Group = nogroup
Add the line below to /etc/exports
file 192.168.1.102
is IP address of the Raspberry Pi and you can get this by issuing an ipaddr show
command on the Raspberry Pi.
/export/RP2NFS 192.168.1.102(rw,sync,no_root_squash,no_subtree_check)
Restart the nfs server
/etc/init.d/nfs-kernel-server restart
Set portmap lockdown and deny all in /etc/hosts.deny
by adding the line below to that file
rpcbind mountd nfsd statd lockd rquotad : ALL
Allow a specific IP in /etc/hosts.allow
by adding the line below to that file
rpcbind mountd nfsd statd lockd rquotad : 192.168.1.102 127.0.0.1
Restart the nfs server
service nfs-kernel-server restart
edit /etc/fstab
so it mounts our filesystem automatically by adding the line
/home/dtree/RBerrySharp/CSharpCode /export/RP2NFS none bind 0 0
At this point the Development PC is prepared to serve the contents of the /home/dtree/RBerrySharp/CSharpCode
subdirectory
to an NFS client at IP address 192.168.1.102
. The next task is to set up an NFS Client on our Raspberry Pi.
The user on the Raspberry Pi is pi
and its home directory is /home/pi
. We will
map the exported CSharpCode
directory into our local filesystem in the /home/pi/CSharpCode
directory.
Once mapped, we will have local access on the Raspberry Pi to all files in the Development PC's /home/dtree/RBerrySharp/CSharpCode
subdirectory.
This mapped file system will be fully read-write by both parties. Any changes, by either the Development PC or the Raspberry Pi, to the files in this tree
will be immediately reflected to the other party by NFS.
Install the nfs client (as root on the Raspberry Pi 2)
apt-get install nfs-common
Make a mount point for the nfs drive offered from the Development PC
mkdir /home/pi/CSharpCode
Mount the exported NFS drive. The IP address 192.168.1.64
is the address of the Linux Development PC (configured to use a static IP address)
mount -t nfs -o proto=tcp,port=2049 192.168.1.64:/export/RP2NFS /home/pi/CSharpCode
We should be good to go. We can test this by running a quick ls -l ~/CSharpCode
command to see if the Development PC's files are now
present and also by running an exe from a known project which was previously compiled over on the Development PC to see if the remotely compiled files are executable
~/CSharpCode/HelloWorldTest/HelloWorldTest/bin/Debug/HelloWorldTest.exe
Unmount the file system. We want this mapped filesystem to automatically mount up when the Raspberry Pi boots.
umount /home/pi/CSharpCode
edit the /etc/fstab
so we mount automatically by adding the line
192.168.1.64:/export/RP2NFS /home/pi/CSharpCode nfs auto 0 0
Reboot now to test this
reboot
At this point you should be able to create a new project (HelloWorldTest in this example) over on the Development PC, compile it and then
switch to the Raspberry Pi and run that projects executable with a command like: mono ~/CSharpCode/HelloWorldTest/HelloWorldTest/bin/Debug/HelloWorldTest.exe
. If you cannot do
this you
should figure out what is going wrong before proceeding to the next step. Any changes on the Development PC should always instantly
appear and be executable over on the Raspberry Pi.
As mentioned in previous sections, rather than mapping each output directory from the C# projects on the remote Development PC, a entire directory tree with multiple projects was brought over. In order to execute the executable of a remotely compiled project either the current directory has to be changed to a many levels deep subdirectory or the files have to be prefixed with a path before execution. This is rather tedious and so, as a shortcut, I have created a number of shell scripts to do the job for me.
For example a project named RPICSIOTest will have an output directory when mapped onto the Raspberry Pi 2 of
/home/pi/CSharpCode/RPICSIOTest/RPICSIOTest/bin/Debug/
.
I create a file in the CSharpCode
subdirectory named runRPICSIOTest
which contains the following contents ...
#! /bin/sh mono /home/pi/CSharpCode/RPICSIOTest/RPICSIOTest/bin/Debug/RPICSIOTest.exe
... and this means that I can run that project executable with a simple command ./runRPICSIOTest
. Every project
has its own shell script. This may seem like a rather trivial convenience - however in the
next page in this
series
we will implement
remote debugging and the command line for that is a bit more complex. You will definitely want to create an equivalent debugRPICSIOTest
to initiate the debugging rather than typing in all the command line options each time.
The contents of this web page are provided "as is" without any warranty of any kind and without any claim to accuracy. Please be aware that the information provided may be out-of-date, incomplete, erroneous or simply unsuitable for your purposes. Any use you make of the information is entirely at your discretion and any consequences of that use are entirely your responsibility. All source code is provided under the terms of the MIT License.