#!/usr/bin/env bash function run_installer() { ####### Init vars HOMEBREW_PREFIX=/usr/local HOMEBREW_CACHE=/Library/Caches/Homebrew HOMEBREW_REPO=https://github.com/Homebrew/homebrew OSX_REQUIERED_VERSION="10.7.0" declare OS_TYPE declare OSX_VERSION declare GIT_PATH declare RUBY_PATH declare BREW_PATH declare INSTALL_FILES="" errorMessages="" isOsVersion=false isGit=false isRuby=false isBrew=false canContinue=true depCount=0 depFound=0 ####### Setup colors red=`tput setaf 1` green=`tput setaf 2` yellow=`tput setaf 3` blue=`tput setaf 4` magenta=`tput setaf 5` cyan=`tput setaf 6` white=`tput setaf 7` b=`tput bold` u=`tput sgr 0 1` ul=`tput smul` xl=`tput rmul` stou=`tput smso` xtou=`tput rmso` dim=`tput dim` reverse=`tput rev` reset=`tput sgr0` n=$'\n' function head() { echo "${blue}${b}==>${white} $1${reset}" } function info() { echo "${blue}${b}==>${reset} $1" } function successHeading() { echo "${green}${b}==> $1${reset}" } function success() { echo "${green}${b}==>${reset}${green} $1${reset}" } function error() { echo "${red}==> ${u}${b}${red}$1${reset}" } function smallError() { echo "${red}==>${reset} $1" } function green() { echo "${green}$1${reset}" } function red() { echo "${red}$1${reset}" } function check() { echo "${green}${bold} ✓${reset} $1${reset}" } function uncheck() { echo "${red}${bold} ✘${reset} $1${reset}" } ####### Setup methods function wait_for_user() { if [[ $( ask_user "$1" ) == false ]]; then abort_install "${red}==>${reset} Process stopped by user. To resume the install run the one-liner command again." fi } function ask_user() { while : do read -p "${blue}==>${reset} $1 [Y/n] " imp case $imp in [yY] ) echo true; break ;; '' ) echo true; break ;; [nN] ) echo false; break ;; * ) echo "Unrecognized option provided. Please provide either 'Y' or 'N'"; esac done } function prompt_for_input() { while : do read -p "$1 " imp echo $imp return done } function exe() { echo "\$ $@"; "$@" } function sudo() { if $isSudo; then `which sudo` "$@" else "$@" fi } function detect_os() { if [[ "$OSTYPE" == "linux-gnu" ]] then OS_TYPE="linux" get_linux_dependencies elif [[ "$OSTYPE" == "darwin"* ]] then OS_TYPE="osx" get_osx_dependencies else OS_TYPE="win" abort_install "${red}==>${reset} ${b}OS not supported:${reset} Parity one-liner currently support OS X and Linux.${n}For instructions on installing parity on other platforms please visit ${u}${blue}http://ethcore.io/${reset}" fi echo if [[ $depCount == $depFound ]] then green "Found all dependencies ($depFound/$depCount)" else if [[ $canContinue == true ]] then red "Some dependencies are missing ($depFound/$depCount)" elif [[ $canContinue == false && $depFound == 0 ]] then red "All dependencies are missing and cannot be auto-installed ($depFound/$depCount)" abort_install "$errorMessages"; elif [[ $canContinue == false ]] then red "Some dependencies which cannot be auto-installed are missing ($depFound/$depCount)" abort_install "$errorMessages"; fi fi } function get_osx_dependencies() { macos_version find_git find_ruby find_brew } function macos_version() { declare -a reqVersion declare -a localVersion depCount=$((depCount+1)) OSX_VERSION=`/usr/bin/sw_vers -productVersion 2>/dev/null` if [ -z "$OSX_VERSION" ] then uncheck "OS X version not supported 🔥" isOsVersion=false canContinue=false else IFS='.' read -a localVersion <<< "$OSX_VERSION" IFS='.' read -a reqVersion <<< "$OSX_REQUIERED_VERSION" if (( ${reqVersion[0]} <= ${localVersion[0]} )) && (( ${reqVersion[1]} <= ${localVersion[1]} )) then check "OS X Version ${OSX_VERSION}" isOsVersion=true depFound=$((depFound+1)) return else uncheck "OS X version not supported" isOsVersion=false canContinue=false fi fi errorMessages+="${red}==>${reset} ${b}Mac OS version too old:${reset} eth requires OS X version ${red}$OSX_REQUIERED_VERSION${reset} at least in order to run.${n}" errorMessages+=" Please update the OS and reload the install process.${n}" } function find_eth() { ETH_PATH=`which eth 2>/dev/null` if [[ -f $ETH_PATH ]] then check "Found eth: $ETH_PATH" echo "$($ETH_PATH -V)" isEth=true else uncheck "Eth is missing" isEth=false fi } function find_git() { depCount=$((depCount+1)) GIT_PATH=`which git 2>/dev/null` if [[ -f $GIT_PATH ]] then check "$($GIT_PATH --version)" isGit=true depFound=$((depFound+1)) else uncheck "Git is missing" isGit=false fi } function find_ruby() { depCount=$((depCount+1)) RUBY_PATH=`which ruby 2>/dev/null` if [[ -f $RUBY_PATH ]] then RUBY_VERSION=`ruby -e "print RUBY_VERSION"` check "Ruby ${RUBY_VERSION}" isRuby=true depFound=$((depFound+1)) else uncheck "Ruby is missing 🔥" isRuby=false canContinue=false errorMessages+="${red}==>${reset} ${b}Couldn't find Ruby:${reset} Brew requires Ruby which could not be found.${n}" errorMessages+=" Please install Ruby using these instructions ${u}${blue}https://www.ruby-lang.org/en/documentation/installation/${reset}.${n}" fi } function find_brew() { BREW_PATH=`which brew 2>/dev/null` if [[ -f $BREW_PATH ]] then check "$($BREW_PATH -v)" isBrew=true depFound=$((depFound+1)) else uncheck "Homebrew is missing" isBrew=false INSTALL_FILES+="${blue}${dim}==> Homebrew:${reset}${n}" INSTALL_FILES+=" ${blue}${dim}➜${reset} $HOMEBREW_PREFIX/bin/brew${n}" INSTALL_FILES+=" ${blue}${dim}➜${reset} $HOMEBREW_PREFIX/Library${n}" INSTALL_FILES+=" ${blue}${dim}➜${reset} $HOMEBREW_PREFIX/share/man/man1/brew.1${n}" fi depCount=$((depCount+1)) } function install_brew() { if [[ $isBrew == false ]] then head "Installing Homebrew" if [[ $isRuby == true ]] then ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" else cd /usr if [[ ! -d $HOMEBREW_PREFIX ]] then sudo mkdir $HOMEBREW_PREFIX sudo chmod g+rwx $HOMEBREW_PREFIX fi if [[ ! -d $HOMEBREW_CACHE ]] then sudo mkdir $HOMEBREW_CACHE sudo chmod g+rwx $HOMEBREW_CACHE fi DEVELOPER_DIR=`/usr/bin/xcode-select -print-path 2>/dev/null` if [[ ! $(ls -A $DEVELOPER_DIR) || ! -f $DEVELOPER_DIR/usr/bin/git ]] then info "Installing the Command Line Tools (expect a GUI popup):" sudo /usr/bin/xcode-select --install echo "Press any key when the installation has completed" fi cd $HOMEBREW_PREFIX bash -o pipefail -c "curl -fsSL ${HOMEBREW_REPO}/tarball/master | tar xz -m --strip 1" fi find_brew echo if [[ $isBrew == false ]] then abort_install "Couldn't install brew" fi fi } function osx_installer() { osx_dependency_installer info "Updating brew" exe brew update echo info "Installing rocksdb" exe brew install rocksdb info "Installing multirust" exe brew install multirust sudo multirust update nightly sudo multirust default nightly echo } function osx_dependency_installer() { if [[ $isGit == false ]]; then echo "Installing Git" fi if [[ $isRuby == false ]]; then echo "Installing Ruby" fi if [[ $isBrew == false ]]; then install_brew fi } function linux_version() { source /etc/lsb-release if [[ $DISTRIB_ID == "Ubuntu" ]]; then if [[ $DISTRIB_RELEASE == "14.04" || $DISTRIB_RELEASE == "15.04" || $DISTRIB_RELEASE == "15.10" ]]; then check "Ubuntu" isUbuntu=true else check "Ubuntu, but version not supported" isUbuntu=false fi else check "Ubuntu not found" isUbuntu=false fi } function get_linux_dependencies() { linux_version find_multirust find_rocksdb find_curl find_git find_make find_gcc find_apt find_sudo } function find_rocksdb() { depCount=$((depCount+1)) if [[ $(ldconfig -v 2>/dev/null | grep rocksdb | wc -l) == 1 ]]; then depFound=$((depFound+1)) check "apt-get" isRocksDB=true INSTALL_FILES+="${blue}${dim}==> librocksdb:${reset}$n" else uncheck "librocksdb is missing" isRocksDB=false INSTALL_FILES+="${blue}${dim}==> librocksdb:${reset}$n" fi } function find_multirust() { depCount=$((depCount+2)) MULTIRUST_PATH=`which multirust 2>/dev/null` if [[ -f $MULTIRUST_PATH ]]; then depFound=$((depFound+1)) check "multirust" isMultirust=true if [[ $(multirust show-default 2>/dev/null | grep nightly | wc -l) == 4 ]]; then depFound=$((depFound+1)) check "rust nightly" isMultirustNightly=true else uncheck "rust is not nightly" isMultirustNightly=false INSTALL_FILES+="${blue}${dim}==> multirust -> rust nightly:${reset}${n}" fi else uncheck "multirust is missing" uncheck "rust nightly is missing" isMultirust=false isMultirustNightly=false INSTALL_FILES+="${blue}${dim}==> multirust:${reset}${n}" fi } function find_apt() { depCount=$((depCount+1)) APT_PATH=`which apt-get 2>/dev/null` if [[ -f $APT_PATH ]] then depFound=$((depFound+1)) check "apt-get" isApt=true else uncheck "apt-get is missing" isApt=false if [[ $isGCC == false || $isGit == false || $isMake == false || $isCurl == false ]]; then canContinue=false errorMessages+="${red}==>${reset} ${b}Couldn't find apt-get:${reset} We can only use apt-get in order to grab our dependencies.${n}" errorMessages+=" Please switch to a distribution such as Debian or Ubuntu or manually install the missing packages.${n}" fi fi } function find_gcc() { depCount=$((depCount+1)) GCC_PATH=`which g++ 2>/dev/null` if [[ -f $GCC_PATH ]] then depFound=$((depFound+1)) check "g++" isGCC=true else uncheck "g++ is missing" isGCC=false INSTALL_FILES+="${blue}${dim}==> g++:${reset}${n}" fi } function find_sudo() { depCount=$((depCount+1)) SUDO_PATH=`which sudo 2>/dev/null` if [[ -f $SUDO_PATH ]] then depFound=$((depFound+1)) check "sudo" isSudo=true else uncheck "sudo is missing" if [[ `whoami` == "root" ]]; then if [[ $isApt == false && $isMultirust == false ]]; then canContinue=false errorMessages+="${red}==>${reset} ${b}Couldn't find sudo:${reset} Sudo is needed for the installation of multirust.${n}" errorMessages+=" Please ensure you have sudo installed or alternatively install multirust manually.${n}" fi isSudo=false else canContinue=false errorMessages+="${red}==>${reset} ${b}Couldn't find sudo:${reset} Root access is needed for parts of this installation.${n}" errorMessages+=" Please ensure you have sudo installed or alternatively run this script as root.${n}" fi fi } function find_git() { depCount=$((depCount+1)) GIT_PATH=`which git 2>/dev/null` if [[ -f $GIT_PATH ]] then depFound=$((depFound+1)) check "git" isGit=true else uncheck "git is missing" isGit=false INSTALL_FILES+="${blue}${dim}==> git:${reset}${n}" fi } function find_make() { depCount=$((depCount+1)) MAKE_PATH=`which make 2>/dev/null` if [[ -f $MAKE_PATH ]] then depFound=$((depFound+1)) check "make" isMake=true else uncheck "make is missing" isMake=false INSTALL_FILES+="${blue}${dim}==> make:${reset}${n}" fi } function find_curl() { depCount=$((depCount+1)) CURL_PATH=`which curl 2>/dev/null` if [[ -f $CURL_PATH ]] then depFound=$((depFound+1)) check "curl" isCurl=true else uncheck "curl is missing" isCurl=false INSTALL_FILES+="${blue}${dim}==> curl:${reset}${n}" fi } function ubuntu_rocksdb_installer() { sudo apt-get update -qq sudo apt-get install -qq -y software-properties-common sudo apt-add-repository -y ppa:ethcore/ethcore sudo apt-get -f -y install sudo apt-get update -qq sudo apt-get install -qq -y librocksdb-dev librocksdb } function linux_rocksdb_installer() { if [[ $isUbuntu == true ]]; then ubuntu_rocksdb_installer else oldpwd=`pwd` cd /tmp exe git clone --branch v4.2 --depth=1 https://github.com/facebook/rocksdb.git cd rocksdb exe make shared_lib sudo cp -a librocksdb.so* /usr/lib sudo ldconfig cd /tmp rm -rf /tmp/rocksdb cd $oldpwd fi } function linux_installer() { if [[ $isGCC == false || $isGit == false || $isMake == false || $isCurl == false ]]; then info "Installing build dependencies..." sudo apt-get update -qq if [[ $isGit == false ]]; then sudo apt-get install -q -y git fi if [[ $isGCC == false ]]; then sudo apt-get install -q -y g++ gcc fi if [[ $isMake == false ]]; then sudo apt-get install -q -y make fi if [[ $isCurl == false ]]; then sudo apt-get install -q -y curl fi echo fi if [[ $isRocksDB == false ]]; then info "Installing rocksdb..." linux_rocksdb_installer echo fi if [[ $isMultirust == false ]]; then info "Installing multirust..." if [[ $isSudo == false ]]; then apt-get install -q -y sudo fi curl -sf https://raw.githubusercontent.com/brson/multirust/master/blastoff.sh | sudo sh -s -- --yes echo fi if [[ $isMultirustNightly == false ]]; then info "Installing rust nightly..." multirust update nightly multirust default nightly echo fi } function install() { echo head "Installing Parity build dependencies" if [[ $OS_TYPE == "osx" ]] then osx_installer elif [[ $OS_TYPE == "linux" ]] then linux_installer fi } function verify_installation() { info "Verifying installation" if [[ $OS_TYPE == "linux" ]]; then find_curl find_git find_make find_gcc find_rocksdb find_multirust if [[ $isCurl == false || $isGit == false || $isMake == false || $isGCC == false || $isRocksDB == false || $isMultirustNightly == false ]]; then abort_install fi fi } function build_parity() { info "Downloading Parity..." git clone https://github.com/ethcore/parity cd parity git submodule init git submodule update info "Building..." cargo build --release cd .. echo successHeading "Parity is built!" info "Parity source code is in ${b}$(pwd)/parity${reset}. From there, you can:" info "- Run a client & sync the chain with:" info " ${b}cargo run --release${reset}" info "- Run a JSONRPC-capable client (for use with netstats) with:" info " ${b}cargo run --release -- -j --jsonrpc-url 127.0.0.1:8545${reset}" info "- Run tests with:" info " ${b}cargo test --release --features ethcore/json-tests -p ethcore${reset}" info "- Install the client with:" info " ${b}sudo cp parity/target/release/parity${reset}" echo } function install_netstats() { echo "Installing netstats" secret=$(prompt_for_input "Please enter the netstats secret:") instance_name=$(prompt_for_input "Please enter your instance name:") contact_details=$(prompt_for_input "Please enter your contact details (optional):") # install ethereum & install dependencies sudo apt-get install -y -qq build-essential git unzip wget nodejs npm ntp cloud-utils # add node symlink if it doesn't exist [[ ! -f /usr/bin/node ]] && sudo ln -s /usr/bin/nodejs /usr/bin/node # set up time update cronjob sudo bash -c "cat > /etc/cron.hourly/ntpdate << EOF #!/bin/sh pm2 flush sudo service ntp stop sudo ntpdate -s ntp.ubuntu.com sudo service ntp start EOF" sudo chmod 755 /etc/cron.hourly/ntpdate [ ! -d "www" ] && git clone https://github.com/cubedro/eth-net-intelligence-api netstats cd netstats git pull git checkout 95d595258239a0fdf56b97dedcfb2be62f6170e6 sudo npm install sudo npm install pm2 -g cat > app.json << EOL [ { "name" : "node-app", "script" : "app.js", "log_date_format" : "YYYY-MM-DD HH:mm Z", "merge_logs" : false, "watch" : false, "max_restarts" : 10, "exec_interpreter" : "node", "exec_mode" : "fork_mode", "env": { "NODE_ENV" : "production", "RPC_HOST" : "localhost", "RPC_PORT" : "8545", "LISTENING_PORT" : "30303", "INSTANCE_NAME" : "${instance_name}", "CONTACT_DETAILS" : "${contact_details}", "WS_SERVER" : "wss://rpc.ethstats.net", "WS_SECRET" : "${secret}", "VERBOSITY" : 2 } } ] EOL pm2 start app.json cd .. } function abort_install() { echo error "Installation aborted" echo -e "$1" echo exit 0 } function finish() { echo successHeading "Installation successful!" echo exit 0 } ####### Run the script tput clear echo echo echo " ${blue}∷ ${b}${green} WELCOME TO PARITY ${reset} ${blue}∷${reset}" echo echo # Check dependencies head "Checking OS dependencies" detect_os if [[ $INSTALL_FILES != "" ]]; then echo head "In addition to the Parity build dependencies, this script will install:" echo "$INSTALL_FILES" echo fi # Prompt user to continue or abort wait_for_user "${b}Last chance!${reset} Sure you want to install this software?" # Install dependencies and eth install # Check installation verify_installation if [[ ! -e parity ]]; then # Maybe install parity if [[ $(ask_user "${b}Parity${reset} Would you like to download and build parity?") == true ]]; then # Do get parity. build_parity fi fi if [[ $OS_TYPE == "linux" && $DISTRIB_ID == "Ubuntu" ]]; then if [[ $(ask_user "${b}Netstats${reset} Would you like to download, install and configure a Netstats client?${n}${b}${red}WARNING: ${reset}${red}This will need a secret and reconfigure any existing node/NPM installation you have.${reset} ") == true ]]; then install_netstats fi fi # Display goodby message finish } run_installer