par , 09/11/2015 à 04h23 (3274 Affichages)
Un développement inattendu est survenu qui va me permettre d’écrire une suite à mon précédent billet concernant sur l'installation d'un serveur R-shiny sur Ubuntu : un de mes collègues vient de suggérer d'installer un serveur Shiny sur nos deux Raspberry Pi B (le sien et le mien). Je me suis inspiré des instructions disponibles sur ce blog post : Install Shiny Server on Raspberry Pi.
Prérequis
Voici la liste des prérequis :
- Rasberry Pi tournant sous Raspbian ;
- Un écran et un clavier si vous voulez opérer directement sur le Pi ;
- Ou un serveur SSH si vous voulez vous connecter à distance ;
- Dans le cas d'une connexion à distance, rajoutez également un terminal permettant de faire du SSH sur le poste client (bash, cygwin, PuTTY, etc.) ;
- Une connexion Internet ;
- git de même que python doit être présent sur votre Pi ;
- Suffisamment d'espace sur votre SD Card pour installer et compiler R, ses dépendances, Shiny-server, etc.
- Et armez vous de beaucoup de patience : votre Raspberry Pi n'est pas aussi rapide que votre PC de bureau et donc, même si les téléchargements sont plutôt rapides, tout ce qui est configuration, compilation ou installation s'y exécutera BEAUCOUP plus lentement et prendra parfois jusqu'à plusieurs heures.
Ah oui, et bien sur une fois tout ceci terminé, ne vous attendez pas à des performances mirobolantes de la part de votre serveur Shiny : il vous faudra plusieurs secondes avant que votre web app écrite en R ne s'affiche dans votre navigateur. Compte tenu des sévères limitations du Pi, il vous faudra non seulement faire attention à la consommation mémoire de votre application R mais aussi à celle du serveur lorsque plusieurs utilisateurs sont connectés dessus en même temps.
Préparation du PI
Commencez par mettre à jour votre Raspberry Pi en installant les dernières mises à jour :
1 2
| sudo apt-get update
sudo apt-get ugrade |
Pour tenter d’étendre au maximum l'espace utilisable sur la SD Card, vous pouvez ensuite lancer :
Vous n'avez pas besoin d'effectuer cette opération si vous avez configuré votre Pi avec l'utilitaire NOOBS.
Attention : cette opération peut prendre plusieurs heures.
Lorsque ceci est fini, redémarrez votre Pi en faisant :
Vous pouvez aussi le faire en débranchant et en rebranchant son alimentation.
Installation et configuration de R
Par défaut Raspbian fournit la version 2.15.x de R qui est trop ancienne pour faire tourner Shiny. Nous allons donc devoir récupérer les sources de R et les recompiler. Au 05/11/2015, j'ai utilisé la version 3.2.2 "Fire Safety" de R :
1 2 3 4 5 6 7
| mkdir temp
wget http://cran.rstudio.com/src/base/R-3/R-3.2.2.tar.gz
tar zxvf R-3.2.2.tar.gz
cd R-3.2.2/
./configure
make
sudo make install |
Ici, ce sont les étapes de configuration et de compilation qui seront les plus longues. R sera installé dans /usr/local/lib/R. Vous pouvez ensuite vérifier que c'est bien R 3.2.2 qui est lance en exécutant which R ; ceci devrait vous retourner /usr/local/bin/R. Et bien sur en lancant R vous verrez s'afficher :
R version 3.2.2 (2015-08-14) -- "Fire Safety"
Installation des package dans R
Nous allons ensuite télécharger des packages nécessaires à l’exécution de shiny dans cette version de R. Contrairement à la version de bureau de R, nous n'allons pas effectuer les installations depuis R car cela consomme pas mal de memoire. Nous allons donc télécharger chacun des packages et ensuite les installer depuis la ligne de commande.
Note : la liste des packages donnés ici est valide au 05/11/2015 ; vous devrez sans doute aller sur le miroir du CRAN pour vérifier si certains packages n'ont pas été mise à jour depuis et changer leur nom en conséquence.
1 2 3 4 5 6 7 8 9 10 11
| cd ..
wget http://cran.r-project.org/src/contrib/Rcpp_0.12.1.tar.gz
wget http://cran.r-project.org/src/contrib/httpuv_1.3.3.tar.gz
wget http://cran.r-project.org/src/contrib/mime_0.4.tar.gz
wget http://cran.r-project.org/src/contrib/jsonlite_0.9.17.tar.gz
wget http://cran.r-project.org/src/contrib/digest_0.6.8.tar.gz
wget http://cran.r-project.org/src/contrib/htmltools_0.2.6.tar.gz
wget http://cran.r-project.org/src/contrib/xtable_1.8-0.tar.gz
wget http://cran.r-project.org/src/contrib/R6_2.1.1.tar.gz
wget http://cran.r-project.org/src/contrib/Cairo_1.5-9.tar.gz
wget http://cran.r-project.org/src/contrib/shiny_0.12.2.tar.gz |
Ensuite nous installons chacun de ces packages en invoquant R :
1 2 3 4 5 6 7 8 9 10
| sudo R CMD INSTALL Rcpp_0.12.1.tar.gz
sudo R CMD INSTALL httpuv_1.3.3.tar.gz
sudo R CMD INSTALL mime_0.4.tar.gz
sudo R CMD INSTALL jsonlite_0.9.17.tar.gz
sudo R CMD INSTALL digest_0.6.8.tar.gz
sudo R CMD INSTALL htmltools_0.2.6.tar.gz
sudo R CMD INSTALL xtable_1.8-0.tar.gz
sudo R CMD INSTALL R6_2.1.1.tar.gz
sudo R CMD INSTALL Cairo_1.5-9.tar.gz
sudo R CMD INSTALL shiny_0.12.2.tar.gz |
Ici, à nouveau, c'est la compilation et l'installation de chaque package qui prendra le plus de temps.
Le module rmarkdown_0.8.1.tar.gz et ses nombreuses dépendances qui sont décrites ci-après sont nécessaires pour l’exécution d'un des exemples fournis avec Shiny-server (qui ne fonctionne pas d’ailleurs sur mon installation). Sachant que cela va vous rajouter une bonne heure de compilation, vous n'avez pas besoin de télécharger et d'installer pour que shiny soit fonctionnel :
1 2 3 4 5 6 7 8 9 10 11 12
| wget http://cran.r-project.org/src/contrib/magrittr_1.5.tar.gz
wget http://cran.r-project.org/src/contrib/stringi_1.0-1.tar.gz
wget http://cran.r-project.org/src/contrib/stringr_1.0.0.tar.gz
wget http://cran.r-project.org/src/contrib/evaluate_0.8.tar.gz
wget http://cran.r-project.org/src/contrib/formatR_1.2.1.tar.gz
wget http://cran.r-project.org/src/contrib/highr_0.5.1.tar.gz
wget http://cran.r-project.org/src/contrib/markdown_0.7.7.tar.gz
wget http://cran.r-project.org/src/contrib/knitr_1.11.tar.gz
wget http://cran.r-project.org/src/contrib/yaml_2.1.13.tar.gz
wget http://cran.r-project.org/src/contrib/bitops_1.0-6.tar.gz
wget http://cran.r-project.org/src/contrib/caTools_1.17.1.tar.gz
wget http://cran.r-project.org/src/contrib/rmarkdown_0.8.1.tar.gz |
Et pour l'installation :
1 2 3 4 5 6 7 8 9 10 11 12
| sudo R CMD INSTALL magrittr_1.5.tar.gz
sudo R CMD INSTALL stringi_1.0-1.tar.gz
sudo R CMD INSTALL stringr_1.0.0.tar.gz
sudo R CMD INSTALL evaluate_0.8.tar.gz
sudo R CMD INSTALL formatR_1.2.1.tar.gz
sudo R CMD INSTALL highr_0.5.1.tar.gz
sudo R CMD INSTALL knitr_1.11.tar.gz
sudo R CMD INSTALL markdown_0.7.7.tar.gz
sudo R CMD INSTALL yaml_2.1.13.tar.gz
sudo R CMD INSTALL bitops_1.0-6.tar.gz
sudo R CMD INSTALL caTools_1.17.1.tar.gz
sudo R CMD INSTALL rmarkdown_0.8.1.tar.gz |
Installation et configuration de cmake
La version de cmake présente sur Raspbian n'est pas assez récente, donc nous allons en récupérer une nouvelle et la compiler :
1 2 3 4 5 6
| wget http://cmake.org/files/v2.8/cmake-2.8.11.2.tar.gz
tar xzf cmake-2.8.11.2.tar.gz
cd cmake-2.8.11.2
./configure
make
sudo make install |
La configuration et la compilation de cmake prendra sans doute plus d'une heure. Le programme sera installé dans /usr/local/share/cmake-2.8/ et les répertoires Linux habituels. Executer which cmake devrait vous retourner /usr/local/bin/cmake.
Installation et configuration Shiny-server
RStudio ne fournit que des binaires pré-compilés de Shiny-server en version 64bit pour les distro Linux principales tournant sur processeurs Intel, donc nous allons maintenant cloner le répo de Shiny-server et recompiler ses sources pour produire une version 32bit de Shiny-server pour processeurs ARM. Cette dernière étape peut prendre près de 3 heures donc prévoyez un film, une série ou un bon bouquin...
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| cd ..
git clone https://github.com/rstudio/shiny-server.git
cd shiny-server
DIR=`pwd`
PATH=$DIR/bin:$PATH
mkdir tmp
cd tmp
PYTHON=`which python`
cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DPYTHON="$PYTHON" ../
make
mkdir ../build
(cd .. && ./bin/npm --python="$PYTHON" rebuild)
(cd .. && ./bin/node ./ext/node/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js --python="$PYTHON" rebuild)
sudo make install |
Le programme sera installé dans /usr/local/shiny-server/.
Nous avons ensuite besoin de créer les divers répertoires nécessaires à l’exécution de Shiny-server ainsi que l'utilisateur shiny sous lequel tourneront les processus. Nous en profitons egalement pour créer des liens vers les exemples fournis avec le programme, ce qui permettra de lancer des tests de connexion sur la page par défaut :
1 2 3 4 5 6 7 8 9
| sudo ln -s /usr/local/shiny-server/bin/shiny-server /usr/bin/shiny-server
sudo useradd -r -m shiny
sudo mkdir -p /var/log/shiny-server
sudo mkdir -p /srv/shiny-server
sudo ln -s /usr/local/shiny-server/samples/* /srv/shiny-server/
sudo mv /srv/shiny-server/welcome.html /srv/shiny-server/index.html
sudo mkdir -p /var/lib/shiny-server
sudo chown shiny /var/log/shiny-server
sudo mkdir -p /etc/shiny-server |
Vous devez ensuite créer le fichier /etc/shiny-server/shiny-server.conf qui contiendra la configuration du serveur :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| # Instruct Shiny Server to run applications as the user "shiny"
run_as shiny;
# Define a server that listens on port 3838
server {
listen 3838;
# Define a location at the base URL
location / {
# Host the directory of Shiny Apps stored in this directory
site_dir /srv/shiny-server;
# Log all Shiny output to files in this directory
log_dir /var/log/shiny-server;
# When a user visits the base URL rather than a particular application,
# an index of the applications available in this directory will be shown.
directory_index on;
}
} |
À ce stade, vous pouvez désormais lancer le serveur en exécutant :
Normalement le serveur devrait pouvoir démarrer sans erreur. Aussi longtemps que le serveur tourne, vous pouvez ouvrir un navigateur web sur http://<nom de votre pi>:3838 pour voir la page de garde du serveur Shiny qui sera similaire à celle que nous avions précédemment. Par contre soyez patient, l'affichage ne sera pas forcément rapide
:
PS : le second exemple (Shiny Doc sur l'image ci-dessus) plante d'ailleurs au final sur mon installation et se contente d'afficher Error: subscript out of bounds.
Lancement au démarrage
Pour que le serveur soit lancé au démarrage du Pi, vous devez créer /etc/init.d/shiny-server contenant les instructions nécessaires pour lancer et stopper shiny-server en tant que daemon. À cet effet, j'ai légèrement altéré le script disponible sur le GitHub de Shiny-server :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| #! /bin/sh
### BEGIN INIT INFO
# Provides: shiny-server
# Required-Start: $remote_fs
# Required-Stop: $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: shiny Server
# Description: shiny server deploys R shiny applications
### END INIT INFO
# Author: RStudio <info@rstudio.org>
#
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="shiny server"
NAME=shiny-server
DAEMON=`which shiny-server`
SCRIPTNAME=/etc/init.d/shiny-server
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --background --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --background --exec $DAEMON \
|| return 2
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
return "$RETVAL"
}
case "$1" in
start)
log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) log_end_msg 0 ;;
2) log_end_msg 1 ;;
esac
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) log_end_msg 0 ;;
2) log_end_msg 1 ;;
esac
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac
exit 0 |
Donnez ensuite les bonne permissions exécutables à ce fichier :
sudo chmod 755 /etc/init.d/shiny-server
Vérifiez que vous n'avez pas d'erreur lorsque vous lancez :
sudo /etc/init.d/shiny-server start
Terminez en enregistrant le fichier de démarrage auprès de init.d :
sudo update-rc.d shiny-server defaults
Désormais shiny-server devrait être lancé à chaque démarrage du Raspberry Pi.
Si vous redémarrez votre Pi, vous devriez voir les messages de lancement de Shiny-server et vous pouvez ensuite vérifier que ce dernier tourne en faisant :
ps aux | grep shiny-server
Voila, c'est fini, nous avons désormais un serveur Shiny disponible sur notre Raspberry Pi.