From 4d2b666c847c7939d3b4c89c74ef61bab182b512 Mon Sep 17 00:00:00 2001 From: Jonathan Yoder Date: Wed, 28 Aug 2019 11:09:30 -0400 Subject: [PATCH] Quick Install Script --- Makefile | 9 ++ README.md | 12 +- install.sh | 466 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 486 insertions(+), 1 deletion(-) create mode 100755 install.sh diff --git a/Makefile b/Makefile index 9251248..91c1f2d 100644 --- a/Makefile +++ b/Makefile @@ -36,4 +36,13 @@ rebuild-all: deps fetch-serverless-custom-file serverless-deploy.%: deps fetch-serverless-custom-file $(SLS_BINARY) deploy --stage $* +# Helper for launching a bash session on a docker image of your choice. Defaults +# to "ubuntu:xenial". +TARGET_IMAGE?=ubuntu:xenial +bash: + docker run --privileged=true -it --rm \ + -v $(CURDIR):/r-builds \ + -w /r-builds \ + ${TARGET_IMAGE} /bin/bash + .PHONY: deps docker-build docker-push docker-down docker-build-package docker-shell-package-env ecr-login fetch-serverless-custom-file serverless-deploy diff --git a/README.md b/README.md index 3f61bf6..1cb4474 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,16 @@ R binaries are built for the following Linux operating systems: ## Installation +### Quick Installer + +To use our quick install script to install R, simply run the following +command. To use the quick installer, you must have root or sudo privileges, +and `curl` must be installed. + +```sh +bash -c "$(curl -L https://rstd.io/r-install)" +``` + ### Specify R version Define the version of R that you want to install. Available versions @@ -34,7 +44,7 @@ of R can be found here: https://cdn.rstudio.com/r/versions.json R_VERSION=3.5.3 ``` -### Download and install R +### Download and install R Manually #### Ubuntu/Debian Linux diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..205a37a --- /dev/null +++ b/install.sh @@ -0,0 +1,466 @@ +#!/bin/bash + +# Call with: +# bash -c "$(curl -L https://rstd.io/r-install)" + +SCRIPT_ACTION=$1 +SCRIPT_ACTION=${SCRIPT_ACTION:-install} + +CWD=`pwd` + +# User running the command +ME=`whoami` + +# To automate, set the version and RUN_UNATTENDED=1, for example: +# RUN_UNATTENDED=1 R_VERSION=3.5.2 /path/to/install.sh +# +# Set to the full version to install. Must be either available on S3 or in the working directory +R_VERSION=${R_VERSION:-} +# +# Run unattended; show no questions, assume default answers. This was +# ported from Connect and only affects usages of the `ask_yes_no` +# function +RUN_UNATTENDED=${RUN_UNATTENDED:-0} + +# A list of short versions versions. +# The first version will always be considered "latest". +R_DISTROS="\ +debian-9 \ +centos-6 \ +centos-7 \ +opensuse-42 \ +opensuse-15 \ +ubuntu-1604 \ +ubuntu-1804" + +SUDO= +if [[ $(id -u) != "0" ]]; then + SUDO=sudo +fi + +# The root of the S3 URL for downloads +CDN_URL='https://cdn.rstudio.com/r' + +# The URL for listing available R versions +VERSIONS_URL="${CDN_URL}/versions.json" + +R_VERSIONS=$(curl ${VERSIONS_URL} | \ + # Matches the JSON line that contains the r versions + grep r_versions | \ + # Gets the value of the `r_version` property (e.g., "[ 3.0.0, 3.0.3, ... ]") + cut -f2 -d ":" | \ + # Removes the opening and closing brackets of the array + cut -f2 -d "[" | cut -f1 -d "]" | \ + # Removes the quotes and commas from the values + sed -e 's/\"//g' | sed -e 's/\,//g' | \ + # Reverses the order of the list + ( while read -d ' ' f;do g="$f${g+ }$g" ;done;echo "$g" )) + +# Returns the OS +detect_os () { + OS='cat /etc/*-release' + distro=$($OS | grep DISTRIB_ID | cut -f2 -d "=") + if test -f /etc/SuSE-release + then + distro="SUSE" + fi + if [[ -f /etc/centos-release || -f /etc/redhat-release ]] + then + distro="RedHat" + fi + if [[ $(cat /etc/os-release | grep -e "^CPE_NAME\=*" | cut -f 2 -d '=') == "\"cpe:/o:opensuse:leap:15.0\"" ]] + then + distro="SUSE15" + fi + if [[ $(cat /etc/os-release | grep -e "^CPE_NAME\=*" | cut -f 2 -d '=') == "\"cpe:/o:suse:sles:15\"" ]] + then + distro="SUSE15" + fi + if [[ $(cat /etc/os-release | grep -e "^ID\=*" | cut -f 2 -d '=') == "debian" ]]; then + distro="Debian" + fi + echo "${distro}" +} + +# Returns the OS version +detect_os_version () { + os=$1 + if [[ "${os}" == "RedHat" ]]; then + if [[ $(cat /etc/os-release | grep -e "^VERSION_ID\=*" | cut -f 2 -d '=') =~ ^(\"8.|28) ]]; then + echo "8" + else + if [[ -f /etc/os-release ]]; then + cat /etc/os-release | grep -e "^VERSION_ID\=*" | cut -f 2 -d '=' | sed -e 's/"//g' + else + if [[ -f /etc/redhat-release ]]; then + if [[ $(cat /etc/redhat-release | grep "6.") ]]; then + echo 6 + fi + fi + fi + fi + fi + if [[ "${os}" == "Ubuntu" ]]; then + cat /etc/os-release | grep -e "^VERSION_ID\=*" | cut -f 2 -d '=' | sed -e 's/[".]//g' + fi +} + +# Returns the installer type +detect_installer_type () { + os=$1 + if [ "${os}" = "SUSE" ]; then + echo "rpm" + else + if [ "${os}" = "SUSE15" ]; then + echo "rpm" + else + if [ "${os}" = "RedHat" ]; then + echo "rpm" + else + echo "deb" + fi + fi + fi +} + +# Lists available distros +show_distros () { + for v in ${R_DISTROS} + do + echo " ${v}" + done +} + +# Lists available R versions +show_versions () { + for v in ${R_VERSIONS} + do + echo " ${v}" + done +} + +# Returns the installer name for a given version and OS +download_name () { + os=$1 + version=$2 + case $os in + "RedHat" | "CentOS") + echo "R-${version}-1-1.x86_64.rpm" + ;; + "Ubuntu" | "Debian") + echo "r-${version}_1_amd64.deb" + ;; + "SUSE" | "SUSE15") + echo "R-${version}-1-1.x86_64.rpm" + ;; + esac +} + +# Returns a download URL for a given version and OS +download_url () { + os=$1 + name=$2 + ver=$3 + + # If the current directory already contains the download, then + # there's no need to download it + if [ -f ${name} ]; then + echo "" + else + + case $os in + "RedHat" | "CentOS") + echo "${CDN_URL}/centos-${ver}/pkgs/${name}" + ;; + "Ubuntu") + echo "${CDN_URL}/ubuntu-${ver}/pkgs/${name}" + ;; + "Debian") + echo "${CDN_URL}/debian-9/pkgs/${name}" + ;; + "SUSE") + echo "${CDN_URL}/opensuse-42/pkgs/${name}" + ;; + "SUSE15") + echo "${CDN_URL}/opensuse-15/pkgs/${name}" + ;; + esac + fi +} + +# Given a version or "latest", returns a version to download. If no +# valid input version is given, returns blank (""). +get_version () { + versions=(${R_VERSIONS}) + version_input=$1 + if [ "${version_input}" = "latest" ]; then + version_input=${versions[0]} + fi + # Convert short version to real version + echo $(valid_version $version_input) +} + +# Checks to see if a version is valid +valid_version () { + ver=$1 + result= + for v in ${R_VERSIONS} + do + if [[ "${v}" = "${ver}" ]]; then + result=${v} + fi + done + echo ${result} +} + +# Prompts for the version until a valid version is entered. +SELECTED_VERSION=${RSPM_VERSION} +prompt_version () { + while [ "$SELECTED_VERSION" = "" ]; do + echo "Available Versions" + show_versions + echo "Enter version to install: ( for latest)" + read version_input + if [ "$version_input" = "" ]; then + version_input="latest" + fi + SELECTED_VERSION=$(get_version "${version_input}") + done +} + +# Installs R +install () { + installer_type=$1 + installer_name=$2 + os=$3 + ver=$4 + if [ "$installer_type" = "deb" ]; then + install_deb ${installer_name} + else + install_rpm ${installer_name} ${os} ${ver} + fi +} + +# Installs R for Ubuntu/Debian +install_deb () { + installer_name=$1 + echo "Install from DEB installer ${installer_name}..." + + if ! has_sudo "apt-get"; then + echo "Must have sudo privileges to run apt-get" + exit 1 + fi + + ${SUDO} apt-get install gdebi-core + ${SUDO} gdebi "${installer_name}" +} + +# Installs R for RHEL/CentOS and SUSE +install_rpm () { + installer_name=$1 + os=$2 + ver=$3 + echo "User install from RPM installer ${installer_name}..." + install_pre "${os}" "${ver}" + case $os in + "RedHat" | "CentOS") + if ! has_sudo "yum"; then + echo "Must have sudo privileges to run yum" + exit 1 + fi + ${SUDO} yum install "${installer_name}" + ;; + "SUSE" | "SUSE15") + if ! has_sudo "zypper"; then + echo "Must have sudo privileges to run zypper" + exit 1 + fi + ${SUDO} zypper --no-gpg-checks install "${installer_name}" + ;; + esac +} + +# Installs prerequisites for RHEL/CentOS and SUSE +install_pre () { + os=$1 + ver=$2 + + case $os in + "RedHat" | "CentOS") + install_epel "${ver}" + ;; + "SUSE") + install_sci + ;; + "SUSE15") + ;; + esac +} + +# Installs EPEL for RHEL/CentOS +install_epel () { + ver=$1 + + case $ver in + "6") + ${SUDO} yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm + ;; + "7") + ${SUDO} yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + ;; + "8") + ;; + esac +} + +# Installs the Science repository for SLES 12 +install_sci () { + ${SUDO} zypper --gpg-auto-import-keys addrepo https://download.opensuse.org/repositories/science/SLE_12/science.repo +} + +do_download () { + url=$1 + file_name=$(basename "${url}") + + wget_rc=$(check_command "wget") + curl_rc=$(check_command "curl") + rc=0 + + if [ "${url}" = "" ]; then + echo "Installer already exists. Not downloading." + else + echo "Downloading installer from ${url}..." + + if [[ -z "${wget_rc}" ]]; then + echo "Downloading ${url}..." + wget --progress=bar "${url}" + rc=$? + # Or, If curl is around, use that. + elif [[ -z "${curl_rc}" ]]; then + echo "Downloading ${url}..." + curl --output "${file_name}" --progress-bar "${url}" + rc=$? + # Otherwise, we can't go on. + else + echo + echo "You need either wget or curl to be able to download an installation bundle." + echo "Either install one of those two tools or download the installation bundle" + echo "manually." + return 7 + fi + + if [[ "${rc}" -ne "0" ]]; then + echo + echo "We were unable to download the installation bundle." + exit ${rc} + fi + fi +} + +# This helps determine whether a given command exists or not. +check_command () { + cmd=$1 + type "${cmd}" > /dev/null 2> /dev/null + rc=$? + + if [[ "${rc}" = "0" ]]; then + echo "" + else + echo "${rc}" + fi +} + +# This asks a yes/no question and waits for an answer. If running unattended, return +# the default as the answer without asking the question. +ask_yes_no () { + prompt=$1 + default=$2 + answer= + if [[ "${RUN_UNATTENDED}" -eq "0" ]]; then + letters="yn" + if [[ "Y" = "${default}" ]]; then + letters="Yn" + elif [[ "N" = "${default}" ]]; then + letters="yN" + fi + prefix= + while true; do + read -r -p "${prefix}${prompt} [${letters}]? " answer + [[ -z "${answer}" ]] && { answer=${default}; } + case ${answer} in + [Yy]*) echo "Y"; return;; + [Nn]*) echo "N"; return;; + *) prefix=$'\nPlease answer with y or n.\n';; + esac + done + else + answer=${default} + fi + echo "${answer}" +} + +has_sudo () { + if [[ "${SUDO}" == "" ]]; then + test "0" == "0" + else + cmd=$1 + output=$(sudo -n -l "${cmd}") + rc=$? + + test "0" == "${rc}" + fi +} + +check_curl () { + curl_rc=$(check_command "curl") + if [[ "${curl_rc}" != "" ]]; then + echo "The curl command is required." + exit 1 + fi + + if [[ "${SUDO}" != "" ]]; then + sudo_rc=$(check_command "sudo") + if [[ "${sudo_rc}" != "" ]]; then + echo "The sudo command is required." + exit 1 + fi + fi +} + +do_install () { + + # Check for curl + check_curl + + # Detect OS + os=$(detect_os) + [ -z $os ] && { echo "OS not detected"; exit 1; } + + # Also detect the OS version (this may be blank if it's not relevant) + os_ver=$(detect_os_version "${os}") + + # Determine version to download + prompt_version + [ -z $SELECTED_VERSION ] && { echo "Invalid version"; exit 1; } + + # Get the name of the installer to use + installer_file_name=$(download_name "${os}" "${SELECTED_VERSION}") + + # Get the URL to download from. If the installer already exists in the current + # directory, this will return a blank string. + url=$(download_url "${os}" "${installer_file_name}" "${os_ver}") + + # Download the installer if necessary + do_download ${url} + + # Install R + installer_type=$(detect_installer_type "${os}") + install "${installer_type}" "${installer_file_name}" "${os}" "${os_ver}" +} + +# Choose a command to perform +case ${SCRIPT_ACTION} in + "install") + do_install + ;; +esac