SHARE
TWEET

Untitled

a guest Jul 8th, 2018 43 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ##
  2. ## "THE SCRIPT" is the product of many months of work and includes (if you select them):
  3. ##
  4. ##    Mosquitto (port 1883) with web sockets (Port 9001)
  5. ##    SQLITE ( xxx.xxx.xxx.xxx/phpliteadmin),
  6. ##    Node-Red (xxx.xxx.xxx:1880)
  7. ##    Node-Red-Dashboard (xxx.xxx.xxx.xxx:1880/ui)
  8. ##    Webmin (xxx.xxx.xxx:10000)
  9. ##    Apache (xxx.xxx.xxx)
  10. ##    mpg123
  11. ##    and Grafana (xxx.xxx.xxx:3000)
  12. ##    also web-page-based software like mc and /phpsysinfo
  13. ##
  14. ## Regards - Peter Scargill  https://tech.scargill.net  - See also: BigTimer and ESP-GO
  15. ##
  16. ## IMPORTANT:-
  17. ## 1. Run ONLY as ROOT (or PI user on Raspberry Pi). If ROOT, PI user will be checked/created for you as the main
  18. ##    script must be run as pi.
  19. ##    User PI must be in the SUDO group. Other groups are added by the script.
  20. ## 2. When selecting GPIO for non-Raspberry Pi devices note - specific support for ODROID C2 only
  21. ## 3. This script could take 3+ hours on a slow Pi Zero Wifi.... steer away from midnight to avoid any updates
  22. ##    such as dietpi upgrades etc.
  23. ## 4. For non-Raspberry Pi systems, when asked by Armbian to make a new user - don't bother - the script will do it.
  24. ## 5. For Node-Red on Pi Zero,  if the serial port won't connect - look at serial port permissions in /dev/
  25. ## 6. Do not access this script as SUDO.
  26. ##
  27. ## For Log2RAM customising see this - https://github.com/azlux/log2ram
  28. ##
  29. ## See https://tech.scargill.net/orange-pi-pc-battle-of-the-pis/
  30. ##
  31. ## We cannot answer questions on board/operating system comninations we have not tested. See notes below for tested combos.
  32. ##
  33. ## 01/05/2018 Redone InfluxDB/Grafana/Chronograf install, now works on every platform tested, and succesfully tested on Rock64+eMMc
  34. ## 05/10/2017 Added glances - use directly - glances - or as webserver glances -w
  35. ## 08/09/2017 Added name change for Node-Red flows files - and tested Roseapple Pi with DietPi successfully
  36. ## 31/08/2017 Scrapped JED as MC is much better - added rpi-clone which works a treat with NANOPI
  37. ## 30/08/2017 Changed Webmin to NOT be installed by default
  38. ## 24/08/2017 Tested Ubuntu on Odroid C2 and Roseapple Pi
  39. ## 23/08/2017 Tested on the NanoPi K2 board running Ubuntu, installs perfectly (but note that
  40. ## FriendlyArm's WiringPi i2c is currently bust)
  41. ## 18/08/2017 Modified to handle latest Raspbian Stretch - tested on RPI3
  42. ## 10/08/2017 Added "nrlog" utility for viewing and "tailing" - i.e. monitoring node-red logs in colour in
  43. ## a terminal
  44. ## 10/08/2017 Tested RPI3 - turns out the new GPIO nodes work perfectly on that - as does i2c
  45. ##  - commenting out the RPI contrib GPIO as it needs ROOT permissions!!!!!
  46. ## see https://tech.scargill.net/the-real-raspberry-pi/
  47. ## 29/07/2017 Added rule to help node-red-contrib-opi-gpio utility with various boards using GPIO. See docs
  48. ## for that node - very promising - tried various nano boards with success
  49. ## 24/07/2017 Tested on the new NanoPi Neo Plus2 - worked a treat - I2c running - lovely
  50. ## 24/07/2017 Tested on a Raspberry Pi 2 using current Jessie
  51. ## 24/07/2017 Tested NanoPi Neo Air using Ubuntu Core Xenial 4.11.2
  52. ## 30/06/2017 added LOG FILE generation, same folder and name as script + datetime + .log - by MrShark
  53. ## 26/06/2017 added support for Debian 9 (Stretch), right now only tested in VM - by MrShark
  54. ## 26/06/2017 updated node 6.10.3 references to 6.11.0 references
  55. ## 26/04/2017 added option for Log2Ram
  56. ## 26/04/2017 Updated NodeJS as they took the previous version off the server!!!
  57. ## 29/03/2017 Tested on NanoPi Neo2 using Armbian nightly build of 27/03/2017 - added temperature and processor checks
  58. ## 25/03/2017 Tested on NanoPi M1+, host updating added and defaults on inputs added
  59. ## 18/03/2017 Tested on NanoPi M3
  60. ## 16/03/2017 Modifications to handle experimental Android Phone setup
  61. ## 10/03/2017 Modifications to detect and run with the Raspberry Pi Zero Lite (ARM6) (not recommended, Zero is very slow)
  62. ## 30/01/2017 Minor change to let the script work on Mint Linux on a laptop (Looks like Ubuntu)
  63. ## 14/01/2017 Updated webmin and habridge installations
  64. ## 04/01/2017 Tested DietPi on Orange Pi Zero - installed perfectly - 1 hour. WIFI still iffy
  65. ## 04/07/2017 OrangePi Plus 2 - thanks to blog reader RoyG for that
  66. ## 26/12/2016 - complete re-hash for new menus
  67.  
  68. ## 02/12/2016 Tested Roseapple Pi using Armbian - for Node-Red serial, had to
  69. ## enable permissions for the serial - everything worked first time
  70. ## 16/5/2016 Tested on NanoPi M1 - (got 3 UARTS out of the M1)
  71.  
  72. ## 22/06/2016 tested on NanoPi NEO using Armbian Jessie Server
  73. ## 28/12/2016 tested in DietPi and Xenial virtual machines
  74. ## http://www.armbian.com/donate/?f=Armbian_5.20_Nanopineo_Debian_jessie_3.4.112.7z
  75. ##
  76. ## NOTE:- removed node-red-contrib-admin from Node-red setup as you can now do installs in the palette manager
  77. ## within the editor
  78. ## Note also  - the PHONE setting is experimental assuming an Android phone, rooted and set up with "Linux Deploy"
  79. ## as per the relevant blog entry on https://tech.scargill.net
  80. ##
  81. ## Typically, sitting in your home directory (/home/pi) as user Pi you might want to use NANO to install this script
  82. ## and after giving the script execute permission (sudo chmod 0744 /home/pi/script.sh)
  83. ## you could run the file as ./script.sh
  84. ##
  85. ##
  86. ## Note- on the Odroid C2 everything installed except webmin. After reboot this is what I did to get it running..
  87. ##    wget http://prdownloads.sourceforge.net/webadmin/webmin_1.850_all.deb
  88. ##    sudo dpkg --install webmin_1.850_all.deb
  89. ##    That complained about missing bits so I used...
  90. ##       sudo apt-get install -y perl libnet-ssleay-perl openssl libauthen-pam-perl
  91. ##       libpam-runtime libio-pty-perl apt-show-versions python
  92. ##    That seemed to fail and suggested I use...
  93. ##       sudo apt-get -y -f install
  94. ##    That installed the lot - working - something to do with it being 64 bits - but it works -
  95. ##    pi or root user and password and https://whatever:10000
  96. ##
  97. ## Thanks for contributions from Antonio Fragola, Aidan Ruff and others. Thank you.
  98. ##
  99. ## Node-Red security added as standard - using the ADMIN login. MQTT also has same ADMIN login.
  100. ##
  101. ## ROUTINES
  102. ## Here at the beginning, a load of useful routines - see further down
  103.  
  104. # Get time as a UNIX timestamp (seconds elapsed since Jan 1, 1970 0:00 UTC)
  105. startTime="$(date +%s)"
  106. columns=$(tput cols)
  107. user_response=""
  108.  
  109. # High Intensity
  110. IGreen='\e[0;92m'       # Green
  111. IYellow='\e[0;93m'      # Yellow
  112. IBlue='\e[0;94m'        # Blue
  113. ICyan='\e[0;96m'        # Cyan
  114. IWhite='\e[0;97m'       # White
  115.  
  116. # Bold High Intensity
  117. BIRed='\e[1;91m'        # Red
  118. BIGreen='\e[1;92m'      # Green
  119. BIYellow='\e[1;93m'     # Yellow
  120. BIPurple='\e[1;95m'     # Purple
  121. BIMagenta='\e[1;95m'    # Purple
  122. BICyan='\e[1;96m'       # Cyan
  123. BIWhite='\e[1;97m'      # White
  124.  
  125. skip=0
  126. other=0
  127.  
  128. clean_stdin()
  129. {
  130.     while read -r -t 0; do
  131.         read -n 256 -r -s
  132.     done
  133. }
  134.  
  135. # Permanent loop until both passwords are the same..
  136. function user_input {
  137.     local VARIABLE_NAME=${1}
  138.     local VARIABLE_NAME_1="A"
  139.     local VARIABLE_NAME_2="B"
  140.     while true; do
  141.         printf "${BICyan}$2: ${BIWhite}";
  142.         if [ "$3" = "hide" ] ; then
  143.             stty -echo;
  144.         fi
  145.         read VARIABLE_NAME_1;
  146.         stty echo;
  147.         if [ "$3" = "hide" ] ; then
  148.             printf "\n${BICyan}$2 (again) : ${BIWhite}";
  149.             stty -echo;
  150.             read VARIABLE_NAME_2;
  151.             stty echo;
  152.         else
  153.             VARIABLE_NAME_2=$VARIABLE_NAME_1;
  154.         fi
  155.         if [ $VARIABLE_NAME_1 != $VARIABLE_NAME_2 ] ; then
  156.             printf "\n${BIRed}Sorry, did not match!${BIWhite}\n";
  157.         else
  158.             break;
  159.         fi
  160.     done
  161.     readonly ${VARIABLE_NAME}=$VARIABLE_NAME_1;
  162.     if [ "$3" == "hide" ] ; then
  163.         printf "\n";
  164.     fi
  165. }
  166.  
  167. stopit=0
  168. other=0
  169. yes=0
  170. nohelp=0
  171. hideother=0
  172.  
  173. timecount(){
  174.     sec=30
  175.     while [ $sec -ge 0 ]; do
  176.         if [ $nohelp -eq 1 ]; then
  177.            
  178.             if [ $hideother -eq 1 ]; then
  179.                 printf "${BIPurple}Continue ${BIWhite}y${BIPurple}(es)/${BIWhite}n${BIPurple}(o)/${BIWhite}a${BIPurple}(ll)/${BIWhite}e${BIPurple}(nd)-  ${BIGreen}00:0$min:$sec${BIPurple} remaining\033[0K\r${BIWhite}"
  180.             else
  181.                 printf "${BIPurple}Continue ${BIWhite}y${BIPurple}(es)/${BIWhite}o${BIPurple}(ther)/${BIWhite}e${BIPurple}(nd)-  ${BIGreen}00:0$min:$sec${BIPurple} remaining\033[0K\r${BIWhite}"
  182.             fi
  183.         else
  184.             printf "${BIPurple}Continue ${BIWhite}y${BIPurple}(es)/${BIWhite}h${BIPurple}(elp)-  ${BIGreen}00:0$min:$sec${BIPurple} remaining\033[0K\r${BIWhite}"
  185.         fi
  186.         sec=$((sec-1))
  187.         trap '' 2
  188.         stty -echo
  189.         read -t 1 -n 1 user_response
  190.         stty echo
  191.         trap - 2
  192.         if [ -n  "$user_response" ]; then
  193.             break
  194.         fi
  195.     done
  196. }
  197.  
  198.  
  199. task_start(){
  200.     printf "\r\n"
  201.     printf "${BIGreen}%*s\n" $columns | tr ' ' -
  202.     printf "$1"
  203.     clean_stdin
  204.     skip=0
  205.     printf "\n${BIGreen}%*s${BIWhite}\n" $columns | tr ' ' -
  206.     elapsedTime="$(($(date +%s)-startTime))"
  207.     printf "Elapsed: %02d hrs %02d mins %02d secs\n" "$((elapsedTime/3600%24))" "$((elapsedTime/60%60))" "$((elapsedTime%60))"
  208.     clean_stdin
  209.     if [ "$user_response" != "a" ]; then
  210.         timecount
  211.     fi
  212.     echo -e "                                                                        \033[0K\r"
  213.     if  [ "$user_response" = "e" ]; then
  214.         printf "${BIWhite}"
  215.         exit 1
  216.     fi
  217.     if  [ "$user_response" = "n" ]; then
  218.         skip=1
  219.     fi
  220.     if  [ "$user_response" = "o" ]; then
  221.         other=1
  222.     fi
  223.     if  [ "$user_response" = "h" ]; then
  224.         stopit=1
  225.     fi
  226.     if  [ "$user_response" = "y" ]; then
  227.         yes=1
  228.     fi
  229.     if [ -n  "$2" ]; then
  230.         if [ $skip -eq 0 ]; then
  231.             printf "${BIYellow}$2${BIWhite}\n"
  232.         else
  233.             printf "${BICyan}%*s${BIWhite}\n" $columns '[SKIPPED]'
  234.         fi
  235.     fi
  236. }
  237.  
  238. task_end(){
  239.     printf "${BICyan}%*s${BIWhite}\n" $columns '[OK]'
  240. }
  241.  
  242.  
  243. # credits to DietPi
  244.  
  245. CPU_TEMP_CURRENT='Unknown'
  246. CPU_TEMP_PRINT='Unknown'
  247. ACTIVECORES=$(grep -c processor /proc/cpuinfo)
  248.  
  249. #Array to store possible locations for temp read.
  250. aFP_TEMPERATURE=(
  251.     '/sys/class/thermal/thermal_zone0/temp'
  252.     '/sys/devices/virtual/thermal/thermal_zone1/temp'
  253.     '/sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/temp1_input'
  254.     '/sys/class/hwmon/hwmon0/device/temp_label'
  255. )
  256.  
  257. Obtain_Cpu_Temp(){
  258.     for ((i=0; i<${#aFP_TEMPERATURE[@]}; i++))
  259.     do
  260.         if [ -f "${aFP_TEMPERATURE[$i]}" ]; then
  261.             CPU_TEMP_CURRENT=$(cat "${aFP_TEMPERATURE[$i]}")
  262.             # - Some devices (pine) provide 2 digit output, some provide a 5 digit ouput.
  263.             #       So, If the value is over 1000, we can assume it needs converting to 1'c
  264.             if (( $CPU_TEMP_CURRENT == 0 )); then
  265.                 continue
  266.             fi
  267.             if (( $CPU_TEMP_CURRENT >= 1000 )); then
  268.                 CPU_TEMP_CURRENT=$( echo -e "$CPU_TEMP_CURRENT" | awk '{print $1/1000}' | xargs printf "%0.0f" )
  269.             fi
  270.             if (( $CPU_TEMP_CURRENT >= 70 )); then
  271.                 CPU_TEMP_PRINT="\e[91mWarning: $CPU_TEMP_CURRENT'c\e[0m"
  272.                 elif (( $CPU_TEMP_CURRENT >= 60 )); then
  273.                 CPU_TEMP_PRINT="\e[38;5;202m$CPU_TEMP_CURRENT'c\e[0m"
  274.                 elif (( $CPU_TEMP_CURRENT >= 50 )); then
  275.                 CPU_TEMP_PRINT="\e[93m$CPU_TEMP_CURRENT'c\e[0m"
  276.                 elif (( $CPU_TEMP_CURRENT >= 40 )); then
  277.                 CPU_TEMP_PRINT="\e[92m$CPU_TEMP_CURRENT'c\e[0m"
  278.                 elif (( $CPU_TEMP_CURRENT >= 30 )); then
  279.                 CPU_TEMP_PRINT="\e[96m$CPU_TEMP_CURRENT'c\e[0m"
  280.             else
  281.                 CPU_TEMP_PRINT="\e[96m$CPU_TEMP_CURRENT'c\e[0m"
  282.             fi
  283.             break
  284.         fi
  285.     done
  286. }
  287.  
  288. LOGFILE=$HOME/$0-`date +%Y-%m-%d_%Hh%Mm`.log
  289.  
  290. printl() {
  291.     printf $1
  292.     echo -e $1 >> $LOGFILE
  293. }
  294.  
  295. printstatus() {
  296.     Obtain_Cpu_Temp
  297.     h=$(($SECONDS/3600));
  298.     m=$((($SECONDS/60)%60));
  299.     s=$(($SECONDS%60));
  300.     printf "\r\n${BIGreen}==\r\n== ${BIYellow}$1"
  301.     printf "\r\n${BIGreen}== ${IBlue}Total: %02dh:%02dm:%02ds Cores: $ACTIVECORES Temperature: $CPU_TEMP_PRINT \r\n${BIGreen}==${IWhite}\r\n\r\n"  $h $m $s;
  302.     echo -e "############################################################" >> $LOGFILE
  303.     echo -e $1 >> $LOGFILE
  304. }
  305.  
  306.  
  307. ############################################################################
  308. ##
  309. ## MAIN SECTION OF SCRIPT - action begins here
  310. ##
  311. #############################################################################
  312. ##
  313.  
  314. printstatus "Welcome to THE SCRIPT!"
  315.  
  316. AQUIET="-qq"
  317. NQUIET="-s"
  318.  
  319. # install sudo on devices without it
  320. [ ! -x /usr/bin/sudo ] && apt-get $AQUIET -y update > /dev/null 2>&1 && apt-get $AQUIET -y install sudo 2>&1 | tee -a $LOGFILE
  321.  
  322. # Whiptail menu may already be installed by default, on the other hand maybe not.
  323. sudo apt-get $AQUIET -y install whiptail ccze 2>&1 | tee -a $LOGFILE
  324. # Another way - Xenial should come up in upper case in $DISTRO
  325. . /etc/os-release
  326. OPSYS=${ID^^}
  327. echo -e OPSYS: $OPSYS >> $LOGFILE
  328.  
  329. printstatus "Grabbing some preliminaries..."
  330.  
  331. # test internet connection
  332. sudo chmod u+s /bin/ping
  333. if [[ "$(ping -c 1 23.1.68.60  | grep '100%' )" != "" ]]; then
  334.     printl "${IRed}!!!! No internet connection available, aborting! ${IWhite}\r\n"
  335.     exit 0
  336. fi
  337.  
  338. # install lsb_release on devices without it
  339. [ ! -x /usr/bin/lsb_release ] && apt-get $AQUIET -y update > /dev/null 2>&1 && apt-get $AQUIET -y install lsb-release 2>&1 | tee -a $LOGFILE
  340. DISTRO=$(/usr/bin/lsb_release -rs)
  341. CHECK64=$(uname -m)
  342. echo -e DISTRO: $DISTRO >> $LOGFILE
  343. echo -e CHECK64: $CHECK64 >> $LOGFILE
  344.  
  345. if [[ $OPSYS == *"UBUNTU"* ]]; then
  346.     if [ $DISTRO != "16.04" ] ; then
  347.         printl "${IRed}!!!! Wrong version of Ubuntu - not 16.04, aborting! ${IWhite}\r\n"
  348.         exit 0
  349.     fi
  350. fi
  351.  
  352. # user pi existance/creation
  353. echo -e USER: $USER >> $LOGFILE
  354. if [[ $USER != "pi" ]]; then
  355.     if [[ $USER == "root" ]]; then
  356.         printf "\r\n${ICyan}Hello ROOT... ${IWhite}"
  357.         getent passwd pi > /dev/null 2>&1
  358.         if [ $? -eq 0 ]; then
  359.             printf "${ICyan}user \"pi\" exists, please log-out as root and run script as pi.${IWhite}\r\n\r\n"
  360.             usermod pi -g sudo -G ssh -a
  361.             echo "pi ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/pi
  362.             chmod 0440 /etc/sudoers.d/pi
  363.             chmod 4755 /usr/bin/sudo           
  364.             cp $(readlink -f $0) /home/pi && chown pi.pi /home/pi/$0 && chmod 755 /home/pi/$0
  365.             chown pi.pi $LOGFILE && chmod 644 $LOGFILE && cp $LOGFILE /home/pi
  366.         else
  367.             adduser --quiet --disabled-password --shell /bin/bash --home /home/pi --gecos "User" pi
  368.             echo "pi:password" | chpasswd
  369.             usermod pi -g sudo -G ssh -a
  370.             echo "pi ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/pi
  371.             chmod 0440 /etc/sudoers.d/pi
  372.             chmod 4755 /usr/bin/sudo
  373.             printf "${ICyan}user PI created, password is \"password\". Please log-out as root and login as pi, and redo the procedure ${IWhite}\r\n\r\n"
  374.             cp $(readlink -f $0) /home/pi && chown pi.pi /home/pi/$0 && chmod 755 /home/pi/$0
  375.             chown pi.pi $LOGFILE && chmod 644 $LOGFILE && cp $LOGFILE /home/pi
  376.         fi
  377.         exit
  378.     else
  379.         printstatus "Leaving script as you are neither PI nor ROOT user."
  380.         exit
  381.     fi
  382. else
  383.     sudo touch /etc/AlreadyRun
  384. fi
  385.  
  386. if [ ! -f /etc/AlreadyRun ]; then
  387.     printstatus "Stopping IPV6 access"
  388.     echo "net.ipv6.conf.all.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf > /dev/null 2>&1
  389.     echo "net.ipv6.conf.default.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf > /dev/null 2>&1
  390.     echo "net.ipv6.conf.lo.disable_ipv6 = 1" | sudo tee -a /etc/sysctl.conf > /dev/null 2>&1
  391.     sudo sysctl -p
  392.  
  393.     printstatus "Allow remote root login and speed up SSH"
  394.     sudo sed -i -e 's/PermitRootLogin no/PermitRootLogin yes/g' /etc/ssh/sshd_config
  395.     sudo sed -i -e 's/PermitRootLogin without-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
  396.     sudo sed -i -e 's/PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
  397.     sudo sed -i -e 's/TCPKeepAlive yes/TCPKeepAlive no/g' /etc/ssh/sshd_config
  398.     sudo sed -i '$ a UseDNS no' /etc/ssh/sshd_config
  399.     sudo sed -i '$ a ClientAliveInterval 30' /etc/ssh/sshd_config
  400.     sudo sed -i '$ a ClientAliveCountMax 100' /etc/ssh/sshd_config
  401.     sudo /etc/init.d/ssh restart 2>&1 | tee -a $LOGFILE
  402.  
  403.     sudo update-alternatives --set newt-palette /etc/newt/palette.original 2>&1 | tee -a $LOGFILE
  404.  
  405.     # setup a progress bar
  406.     echo "Dpkg::Progress-Fancy \"1\";" | sudo tee /etc/apt/apt.conf.d/99progressbar > /dev/null
  407.     echo "APT::Color \"1\";" | sudo tee -a /etc/apt/apt.conf.d/99progressbar > /dev/null
  408.    
  409.     if [[ $OPSYS != *"RASPBIAN"* ]]; then
  410.         printstatus "Adding user Pi permissions"
  411.         for additionalgroup in cdrom games users i2c adm gpio input sudo netdev audio video dialout plugdev bluetooth ; do
  412.             getent group ${additionalgroup} | grep -w -l pi || sudo adduser pi ${additionalgroup} 2>&1 | tee -a $LOGFILE
  413.         done
  414.     fi
  415.     sudo apt-get install avahi-daemon avahi-utils -y 2>&1 | tee -a $LOGFILE
  416.     sudo sed -i -e 's/use-ipv6=yes/use-ipv6=no/g' /etc/avahi/avahi-daemon.conf
  417. else
  418.         printstatus "Script is re-running, avoiding un-necessary repeats"
  419. fi
  420.  
  421. if [[ $OPSYS == "LINUXMINT" ]]; then
  422.     OPSYS="UBUNTU"
  423. fi
  424.  
  425. if [[ $OPSYS != *"RASPBIAN"* ]] && [[ $OPSYS != *"DEBIAN"* ]] && [[ $OPSYS != *"UBUNTU"* ]] && [[ $OPSYS != *"DIETPI"* ]]; then
  426.     printl "${BIRed}By the look of it, not one of the supported operating systems - aborting${BIWhite}\r\n"; exit
  427. fi
  428.  
  429. username="user"
  430. userpass="password123"
  431.  
  432. adminname="admin"
  433. adminpass="password123"
  434.  
  435. newhostname=$(hostname)
  436.  
  437. SECONDS=0
  438.  
  439. if [[ $OPSYS == *"RASPBIAN"* ]];then
  440.     MYMENU=$(whiptail --title "Main Raspberry Pi Selection" --checklist \
  441.         "\nSelect items for your Pi as required then hit OK" 31 73 24 \
  442.         "quiet" "Quiet(er) install - untick for lots of info " ON \
  443.         "prereq" "Install general pre-requisites " ON \
  444.         "phone" "Install on Android Smartphone - see blog" OFF \
  445.         "mosquitto" "Install Mosquitto" ON \
  446.         "apache" "Install Apache/PHP/SQLITE + PHPLITEADMIN " ON \
  447.         "nodejs" "Install NodeJS" ON \
  448.         "nodered" "Install Node-Red" ON \
  449.         "webmin" "Install Webmin" OFF \
  450.         "screen" "Install Screen" ON \
  451.         "java" "Update Java" ON \
  452.         "wiringpi" "Wiring Pi for the GPIO utility" OFF \
  453.         "mpg123" "Install MPG123" ON \
  454.         "modpass" "Mod USER and ADMIN passwords (password123)" ON \
  455.         "phpsysinfo" "Install PHPSYSYINFO" ON \
  456.         "addindex" "Add an index page and some CSS" ON \
  457.         "passwords" "Update ROOT and PI user passwords" OFF \
  458.         "installcu" "Install CU for serial VT100 Terminal" ON \
  459.         "installmc" "Install MC+MCEDIT  file manager + editor " ON \
  460.         "rpiclone" "Install RPI-Clone" ON \
  461.         "habridge" "Install HA-bridge on port 82" OFF \
  462.         "log2ram" "Install Log2RAM default 40Meg" OFF \
  463.         "grafana" "Install Grafana and InfluxDB" OFF \
  464.         "wolfram" "Remove Wolfram on a PI to save space" OFF \
  465.         "office" "Remove LibreOffice on PI to save space" OFF 3>&1 1>&2 2>&3)
  466. else
  467.     MYMENU=$(whiptail --title "Main Non-Pi Selection" --checklist \
  468.         "\nSelect items as required then hit OK" 32 74 25 \
  469.         "quiet" "Quiet(er) install - untick for lots of info " ON \
  470.         "prereq" "Install general pre-requisites" ON \
  471.         "phone" "Install on Android Smartphone - see blog" OFF \
  472.         "mosquitto" "Install Mosquitto" ON \
  473.         "apache" "Install Apache/PHP/SQLITE + PHPLITEADMIN" ON \
  474.         "nodejs" "Install NodeJS" ON \
  475.         "nodered" "Install Node-Red" ON \
  476.         "odroid" "Install ODROID C2-specific GPIO" OFF \
  477.         "generich3" "Install GENERIC H3 GPIO (not Raspberry Pi) " OFF \
  478.         "webmin" "Install Webmin" OFF \
  479.         "screen" "Install Screen" ON \
  480.         "java" "Update Java" ON \
  481.         "modpass" "Mod USER and ADMIN passwords (password123)" ON \
  482.         "mpg123" "Install MPG123" ON \
  483.         "opimonitor" "Install OPI-Monitor - H3 ONLY" OFF \
  484.         "phpsysinfo" "Install PHPSYSYINFO" ON \
  485.         "addindex" "Add an index page and some CSS" ON \
  486.         "passwords" "Update ROOT and PI user passwords" OFF \
  487.         "installcu" "Install CU for serial VT100 Terminal" ON \
  488.         "installmc" "Install MC+MCEDIT file manager + editor" ON \
  489.         "rpiclone" "Install RPI-Clone" ON \
  490.         "log2ram" "Install Log2RAM default 40Meg" OFF \
  491.         "grafana" "Install Grafana and InfluxDB" OFF \
  492.         "habridge" "Install HA-bridge on port 82" OFF 3>&1 1>&2 2>&3)
  493. fi
  494.  
  495. if [[ $MYMENU != *"quiet"* ]]; then
  496.     AQUIET=""
  497.     NQUIET=""
  498. fi
  499.  
  500. if [[ $MYMENU == "" ]]; then
  501.     whiptail --title "Installation Aborted" --msgbox "Cancelled as requested." 8 78
  502.     exit
  503. fi
  504.  
  505. cd
  506. newhostname=$(whiptail --inputbox "Enter new HOST name\nLeave the default value or select something new" 8 60 $newhostname 3>&1 1>&2 2>&3)
  507.  
  508. if [[ $MYMENU == *"modpass"* ]]; then
  509.    
  510.     username=$(whiptail --inputbox "Enter a USER name (example user)\nSpecifically for Node-Red Dashboard" 8 60 $username 3>&1 1>&2 2>&3)
  511.     if [[ -z "${username// }" ]]; then
  512.         printf "No user name given - aborting\r\n"; exit
  513.     fi
  514.    
  515.     userpass=$(whiptail --passwordbox "Enter a user password" 8 60 3>&1 1>&2 2>&3)
  516.     if [[ -z "${userpass// }" ]]; then
  517.         printf "No user password given - aborting${BIWhite}\r\n"; exit
  518.     fi
  519.    
  520.     userpass2=$(whiptail --passwordbox "Confirm user password" 8 60 3>&1 1>&2 2>&3)
  521.     if  [ $userpass2 == "" ]; then
  522.         printf "${BIRed}No password confirmation given - aborting${BIWhite}\r\n"; exit
  523.     fi
  524.     if  [ $userpass != $userpass2 ]
  525.     then
  526.         printf "${BIRed}Passwords don't match - aborting${BIWhite}\r\n"; exit
  527.     fi
  528.    
  529.     adminname=$(whiptail --inputbox "Enter an ADMIN name (example admin)\nFor Node-Red and MQTT" 8 60 $adminname 3>&1 1>&2 2>&3)
  530.     if [[ -z "${adminname// }" ]]; then
  531.         printf "${BIRed}No admin name given - aborting${BIWhite}\r\n"
  532.         exit
  533.     fi
  534.    
  535.     adminpass=$(whiptail --passwordbox "Enter an admin password" 8 60 3>&1 1>&2 2>&3)
  536.     if [[ -z "${adminpass// }" ]]; then
  537.         printf "${BIRed}No user password given - aborting${BIWhite}\r\n"; exit
  538.     fi
  539.    
  540.     adminpass2=$(whiptail --passwordbox "Confirm admin password" 8 60 3>&1 1>&2 2>&3)
  541.     if  [ $adminpass2 == "" ]; then
  542.         printf "${BIRed}No password confirmation given - aborting${BIWhite}\r\n"; exit
  543.     fi
  544.     if  [ $adminpass != $adminpass2 ]; then
  545.         printf "${BIRed}Passwords don't match - aborting${BIWhite}\r\n"; exit
  546.     fi
  547. fi
  548.  
  549. if [[ $MYMENU == *"passwords"* ]]; then
  550.     echo "Update your PI password"
  551.     sudo passwd pi
  552.     echo "Update your ROOT password"
  553.     sudo passwd root
  554. fi
  555.  
  556. if [[ $MYMENU == *"phone"* ]]; then
  557.     echo "en_US.UTF-8 UTF-8" | sudo tee -a /etc/locale.gen > /dev/null
  558.     # echo "service rsyslog stop" | sudo tee -a /etc/init.d/rc.local > /dev/null
  559.     sudo update-rc.d rsyslog disable 2>&1 | tee -a $LOGFILE
  560.     sudo locale-gen 2>&1 | tee -a $LOGFILE
  561.     sudo sed -i -e 's#exit 0##g' /etc/rc.local
  562.     echo "cd /home/pi/habridge" | sudo tee -a /etc/rc.local > /dev/null
  563.     echo "[ -f /home/pi/habridge/habridge-log.txt ] && rm /home/pi/habridge/habridge-log.txt" | sudo tee -a /etc/rc.local > /dev/null
  564.     echo "nohup /usr/bin/java -jar -Dserver.port=82 -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge.jar > /home/pi/habridge/habridge-log.txt 2>&1 &" | sudo tee -a /etc/rc.local > /dev/null
  565.     echo "chmod 777 /home/pi/habridge/habridge-log.txt" | sudo tee -a /etc/rc.local > /dev/null
  566.     echo "exit 0" | sudo tee -a /etc/rc.local > /dev/null
  567. fi
  568.  
  569. if [[ $MYMENU == *"wolfram"* ]]; then
  570.     printstatus "Removing Wolfram"
  571.     sudo apt-get $AQUIET -y purge wolfram-engine 2>&1 | tee -a $LOGFILE
  572. fi
  573.  
  574. if [[ $MYMENU == *"office"* ]]; then
  575.     printstatus "Removing LibreOffice"
  576.     sudo apt-get $AQUIET -y remove --purge libreoffice* 2>&1 | tee -a $LOGFILE
  577. fi
  578.  
  579. if [[ $MYMENU == *"prereq"* ]]; then
  580.     printstatus "Installing pre-requisites (this could take some time)"
  581.     sudo apt-get $AQUIET -y autoremove 2>&1 | tee -a $LOGFILE
  582.     sudo apt-get $AQUIET  update 2>&1 | tee -a $LOGFILE
  583.     sudo apt-get $AQUIET -y upgrade 2>&1 | tee -a $LOGFILE
  584.     # fix for RPI treating PING as a root function - by Dave
  585.     sudo setcap cap_net_raw=ep /bin/ping > /dev/null 2>&1
  586.     sudo setcap cap_net_raw=ep /bin/ping6 > /dev/null 2>&1
  587.     # Prerequisite suggested by Julian and adding in python-dev - and stuff I've added for SAMBA and telnet, and Common utilities
  588.  
  589.     sudo apt install $AQUIET -y sysfsutils
  590.     sudo apt-get install $AQUIET -y apt-utils 2>&1 | tee -a $LOGFILE # a line on its own, as on some boards caused problems on next one...
  591.     sudo apt-get install $AQUIET -y bash-completion unzip build-essential git python-serial scons libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libsqlite3-dev subversion libcurl4-openssl-dev libusb-dev python-dev cmake curl telnet usbutils gawk jq pv samba samba-common samba-common-bin winbind dosfstools parted gcc python-pip htop python-smbus i2c-tools 2>&1 | tee -a $LOGFILE
  592.     sudo pip -q install psutil 2>&1 | tee -a $LOGFILE
  593.     sudo -H pip -q install feedparser 2>&1 | tee -a $LOGFILE
  594.     # This line to ensure name is resolved from hosts FIRST
  595.     sudo sed -i '/\[global\]/a name resolve order = hosts wins bcast' /etc/samba/smb.conf
  596. fi
  597.  
  598. if [[ $MYMENU == *"mosquitto"* ]]; then
  599.     printstatus "Installing Mosquitto with Websockets"
  600.     cd
  601.     if [[ $OPSYS == *"UBUNTU"* ]]; then
  602.         sudo apt-get $AQUIET -y install mosquitto mosquitto-clients 2>&1 | tee -a $LOGFILE
  603.         [ $? -eq 0 ] && mosquitto=1 # mosquitto installed
  604.     else
  605.         if [[ $OPSYS == *"BIAN"* ]] && [[ $DISTRO == *"9."* ]]; then
  606.             printl "${IRed}!!!! Installing stock Mosquitto from Debian 9! ${IWhite}\r\n"
  607.         else
  608.             wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key -a $LOGFILE -O - | sudo apt-key add -
  609.             echo "deb http://repo.mosquitto.org/debian jessie main" |sudo tee /etc/apt/sources.list.d/mosquitto-jessie.list
  610.         fi
  611.         sudo apt-get $AQUIET -y update && sudo apt-get $AQUIET -y install mosquitto mosquitto-clients 2>&1 | tee -a $LOGFILE
  612.         [ $? -eq 0 ] && mosquitto=1 # mosquitto installed
  613.     fi
  614.     # add mosquitto mods+pass ONLY if it was installed...
  615.     if [ $mosquitto -eq 1 ]; then
  616.         sudo bash -c "echo -e \"listener 9001\nprotocol websockets\nlistener 1883\nallow_anonymous false\npassword_file /etc/mosquitto/passwords\" > /etc/mosquitto/conf.d/websockets.conf"
  617.         sudo touch /etc/mosquitto/passwords
  618.         sudo mosquitto_passwd  -b /etc/mosquitto/passwords $adminname $adminpass
  619.         if [[ $OPSYS == *"RASPBIAN"* ]]; then
  620.             echo -e "[Unit]\n\
  621. Description=Mosquitto MQTT Broker daemon\n\
  622. ConditionPathExists=/etc/mosquitto/mosquitto.conf\n\
  623. After=network.target\n\
  624. Requires=network.target\n\
  625. \n\
  626. [Service]\n\
  627. Type=forking\n\
  628. RemainAfterExit=no\n\
  629. StartLimitInterval=0\n\
  630. PIDFile=/var/run/mosquitto.pid\n\
  631. ExecStart=/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf -d\n\
  632. ExecReload=/bin/kill -HUP $MAINPID\n\
  633. Restart=on-failure\n\
  634. RestartSec=2\n\
  635. \n\
  636. [Install]\n\
  637. WantedBy=multi-user.target\n" | sudo tee /lib/systemd/system/mosquitto
  638.             sudo systemctl  start mosquitto 2>&1 | tee -a $LOGFILE
  639.             sudo systemctl enable mosquitto 2>&1 | tee -a $LOGFILE
  640.         fi
  641.     echo "alias mqttlog='tail -f /var/log/mosquitto/mosquitto.log | ccze -A'" | sudo tee -a /etc/bash.bashrc > /dev/null 2>&1
  642.     else
  643.         printl "${IRed}!!!! Mosquitto not installed! ${IWhite}\r\n"
  644.     fi
  645. fi
  646.  
  647. if [[ $MYMENU == *"wiringpi"* ]]; then
  648.     printstatus "Installing WiringPi"
  649.     cd
  650.     git clone git://git.drogon.net/wiringPi 2>&1 | tee -a $LOGFILE
  651.     # if git fails or folder does not exist, abort+report
  652.     if [ $? -eq 0 ] && [ -d wiringPi ]; then
  653.         cd ~/wiringPi
  654.         ./build 2>&1 | tee -a $LOGFILE
  655.     else
  656.         printl "${IRed}!!!! Wiringpi not installed! ${IWhite}\r\n"
  657.     fi
  658. fi
  659.  
  660. # Moved sqlite3 so that node-red sql node will install
  661. # use back facing quotes in here - no idea why.
  662. # Changed the order of installation of Apache etc to solve issues with ARMBIAN
  663. #
  664. if [[ $MYMENU == *"apache"* ]]; then
  665.     printstatus "Installing Apache/PHP and Sqlite"
  666.     cd
  667.     sudo groupadd -f -g33 www-data
  668.    
  669.     if [[ $OPSYS != *"UBUNTU"* ]]; then
  670.         if [[ $OPSYS == *"BIAN"* ]] && [[ $DISTRO == *"9."* ]]; then
  671.             sudo apt-get $AQUIET -y install apache2 libapache2-mod-php7.0 sqlite3 php-sqlite3 php-xml php-mbstring 2>&1 | tee -a $LOGFILE
  672.         else
  673.             sudo apt-get $AQUIET -y install apache2 libapache2-mod-php5 sqlite3 php5-sqlite 2>&1 | tee -a $LOGFILE
  674.         fi
  675.         [ $? -eq 0 ] && apache=1 # apache installed
  676.     else
  677.         sudo apt-get $AQUIET -y install apache2 libapache2-mod-php7.0 sqlite3 php-sqlite3 php-xml php-mbstring 2>&1 | tee -a $LOGFILE
  678.         [ $? -eq 0 ] && apache=1 # apache installed
  679.     fi
  680.     # if apache installed and /var/www/html exists, go on...
  681.     if [ $apache -eq 1 ] && [ -d /var/www/html ]; then
  682.         cd /var/www/html
  683.         sudo mkdir phpliteadmin
  684.         cd phpliteadmin
  685.         sudo wget --no-check-certificate http://bitbucket.org/phpliteadmin/public/downloads/phpLiteAdmin_v1-9-7-1.zip -a $LOGFILE
  686.         if [ $? -eq 0 ]; then
  687.             sudo unzip phpLiteAdmin_v1-9-7-1.zip 2>&1 | tee -a $LOGFILE
  688.             sudo mv phpliteadmin.php index.php
  689.             sudo mv phpliteadmin.config.sample.php phpliteadmin.config.php
  690.             sudo rm *.zip
  691.             sudo mkdir themes
  692.             cd themes
  693.             sudo wget --no-check-certificate http://bitbucket.org/phpliteadmin/public/downloads/phpliteadmin_themes_2013-12-26.zip -a $LOGFILE
  694.             sudo unzip phpliteadmin_themes_2013-12-26.zip 2>&1 | tee -a $LOGFILE
  695.             sudo rm *.zip
  696.             sudo sed -i -e 's#\$directory = \x27.\x27;#\$directory = \x27/home/pi/dbs/\x27;#g' /var/www/html/phpliteadmin/phpliteadmin.config.php
  697.             sudo sed -i -e "s#\$password = \x27admin\x27;#\$password = \x27$adminpass\x27;#g" /var/www/html/phpliteadmin/phpliteadmin.config.php
  698.             sudo sed -i -e "s#\$subdirectories = false;#\$subdirectories = true;#g" /var/www/html/phpliteadmin/phpliteadmin.config.php
  699.             cd
  700.         else
  701.             printl "${IRed}!!!! PHPLITEADMIN not installed! ${IWhite}\r\n"
  702.             cd ; rm -rf /var/www/html/phpliteadmin
  703.         fi
  704.        
  705.         mkdir dbs
  706.         sqlite3 /home/pi/dbs/iot.db << EOF
  707.         CREATE TABLE IF NOT EXISTS \`pinDescription\` (
  708.          \`pinID\` INTEGER PRIMARY KEY NOT NULL,
  709.          \`pinNumber\` varchar(2) NOT NULL,
  710.          \`pinDescription\` varchar(255) NOT NULL
  711.         );
  712.         CREATE TABLE IF NOT EXISTS \`pinDirection\` (
  713.          \`pinID\` INTEGER PRIMARY KEY NOT NULL,
  714.          \`pinNumber\` varchar(2) NOT NULL,
  715.          \`pinDirection\` varchar(3) NOT NULL
  716.         );
  717.         CREATE TABLE IF NOT EXISTS \`pinStatus\` (
  718.          \`pinID\` INTEGER PRIMARY KEY NOT NULL,
  719.          \`pinNumber\` varchar(2)  NOT NULL,
  720.          \`pinStatus\` varchar(1) NOT NULL
  721.         );
  722.         CREATE TABLE IF NOT EXISTS \`users\` (
  723.          \`userID\` INTEGER PRIMARY KEY NOT NULL,
  724.          \`username\` varchar(28) NOT NULL,
  725.          \`password\` varchar(64) NOT NULL,
  726.          \`salt\` varchar(8) NOT NULL
  727.         );
  728.         CREATE TABLE IF NOT EXISTS \`device_list\` (
  729.          \`device_name\` varchar(80) NOT NULL DEFAULT '',
  730.          \`device_description\` varchar(80) DEFAULT NULL,
  731.          \`device_attribute\` varchar(80) DEFAULT NULL,
  732.          \`logins\` int(11) DEFAULT NULL,
  733.          \`creation_date\` datetime DEFAULT NULL,
  734.          \`last_update\` datetime DEFAULT NULL,
  735.          PRIMARY KEY (\`device_name\`)
  736.         );
  737.  
  738.         CREATE TABLE IF NOT EXISTS \`readings\` (
  739.          \`recnum\` INTEGER PRIMARY KEY,
  740.          \`location\` varchar(20),
  741.          \`value\` int(11) NOT NULL,
  742.          \`logged\` timestamp not NULL DEFAULT CURRENT_TIMESTAMP ,
  743.          \`device_name\` varchar(40) not null,
  744.          \`topic\` varchar(40) not null
  745.         );
  746.  
  747.  
  748.         CREATE TABLE IF NOT EXISTS \`pins\` (
  749.          \`gpio0\` int(11) NOT NULL DEFAULT '0',
  750.          \`gpio1\` int(11) NOT NULL DEFAULT '0',
  751.          \`gpio2\` int(11) NOT NULL DEFAULT '0',
  752.          \`gpio3\` int(11) NOT NULL DEFAULT '0'
  753.         );
  754.         INSERT INTO PINS VALUES(0,0,0,0);
  755.         CREATE TABLE IF NOT EXISTS \`temperature_record\` (
  756.          \`device_name\` varchar(64) NOT NULL,
  757.          \`rec_num\` INTEGER PRIMARY KEY,
  758.          \`temperature\` float NOT NULL,
  759.          \`date_time\` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
  760.         );
  761.         CREATE TABLE IF NOT EXISTS \`Device\` (
  762.          \`DeviceID\` INTEGER PRIMARY KEY,
  763.          \`DeviceName\` TEXT NOT NULL
  764.         );
  765.         CREATE TABLE IF NOT EXISTS \`DeviceData\` (
  766.          \`DataID\` INTEGER PRIMARY KEY,
  767.         DeviceID INTEGER,
  768.          \`DataName\` TEXT, FOREIGN KEY(DeviceID ) REFERENCES Device(DeviceID)
  769.         );
  770.         CREATE TABLE IF NOT EXISTS \`Data\` (
  771.         SequenceID INTEGER PRIMARY KEY,
  772.          \`DeviceID\` INTEGER NOT NULL,
  773.          \`DataID\` INTEGER NOT NULL,
  774.          \`DataValue\` NUMERIC NOT NULL,
  775.          \`epoch\` NUMERIC NOT NULL,
  776.          \`timestamp\` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP , FOREIGN KEY(DataID, DeviceID ) REFERENCES DeviceData(DAtaID, DeviceID )
  777.         );
  778. EOF
  779.        
  780.         cd
  781.         chmod 777 /home/pi/dbs
  782.         chmod 666 /home/pi/dbs/iot.db
  783.         cd
  784.     else
  785.         printl "${IRed}!!!! Apache+PHP+SQLITE+PHPLITEADMIN NOT INSTALLED! ${IWhite}\r\n"
  786.     fi
  787. fi
  788.  
  789. if [[ $MYMENU == *"nodejs"* ]]; then
  790.     printstatus "Installing NodeJS"
  791.     LATESTNODE="v8.11.3"
  792.     if [[ $(uname -m) == *"armv6"* ]]; then
  793.         printstatus "Installing ARM6 version"
  794.         wget --no-check-certificate https://nodejs.org/dist/$LATESTNODE/node-$LATESTNODE-linux-armv6l.tar.xz -a $LOGFILE
  795.         [ $? -eq 0 ] && nodejs=1
  796.         pv node-$LATESTNODE-linux-armv6l.tar.xz | tar -xJf -
  797.         cd node-$LATESTNODE-linux-armv6l
  798.         sudo cp -R * /usr/local/
  799.         rm -f node-$LATESTNODE-linux-armv6l.tar.xz
  800.     else
  801.         if [[ $CHECK64 == *"aarch64"* ]]; then
  802.             printstatus "Installing ARM64 version"
  803.             wget --no-check-certificate https://nodejs.org/dist/$LATESTNODE/node-$LATESTNODE-linux-arm64.tar.xz -a $LOGFILE
  804.             [ $? -eq 0 ] && nodejs=1
  805.             pv node-$LATESTNODE-linux-arm64.tar.xz | tar -xJf -
  806.             cd node-$LATESTNODE-linux-arm64
  807.             sudo cp -R * /usr/local/
  808.             rm -f node-$LATESTNODE-linux-arm64.tar.xz
  809.         else
  810.             curl -sL https://deb.nodesource.com/setup_8.x > nodesetup.sh
  811.             sudo bash nodesetup.sh 2>&1 | tee -a $LOGFILE
  812.             sudo apt-get $AQUIET -y install nodejs 2>&1 | tee -a $LOGFILE
  813.             [ $? -eq 0 ] && nodejs=1
  814.         fi
  815.     fi
  816.     if [ $nodejs -ne 1 ]; then
  817.         printl "${IRed}!!!! NodeJS not installed! ${IWhite}\r\n"
  818.     fi
  819. fi
  820.  
  821. if [[ $MYMENU == *"nodered"* ]]; then
  822.     #sudo npm cache clean
  823.     printstatus "Installing Node-Red"
  824.     # if nodejs does not exist, abort node-red install
  825.     if [ -f /usr/bin/node ] || [ -f /usr/local/bin/node ]; then
  826.         # prevent double additions to settings.js if it exists and is already modified
  827.         if [ $(grep public ~/.node-red/settings.js 2> /dev/null | wc -l) -ne 1 ]; then
  828.             sudo npm $NQUIET install -g --unsafe-perm node-red 2>&1 | tee -a $LOGFILE
  829.             if [[ $MYMENU == *"phone"* ]]; then
  830.                 sudo wget -a $LOGFILE -O /etc/init.d/nodered https://gist.githubusercontent.com/bigmonkeyboy/9962293/raw/0fe19671b1aef8e56cbcb20f6677173f8495e539/nodered
  831.                 sudo chmod 755 /etc/init.d/nodered && sudo update-rc.d nodered defaults 2>&1 | tee -a $LOGFILE
  832.             else
  833.                 echo | openssl s_client -showcerts -servername raw.githubusercontent.com -connect raw.githubusercontent.com:443 2>/dev/null | openssl x509 -inform pem -noout -text > /dev/null 2>&1
  834.                 [[ $? -ne 0 ]] && echo 151.101.128.133 raw.githubusercontent.com | sudo tee -a /etc/hosts
  835.                 sudo wget -a $LOGFILE --no-check-certificate https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/nodered.service -O /lib/systemd/system/nodered.service
  836.                 sudo wget -a $LOGFILE --no-check-certificate https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/node-red-start -O /usr/bin/node-red-start
  837.                 sudo wget -a $LOGFILE --no-check-certificate https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/node-red-stop -O /usr/bin/node-red-stop
  838.                 #sudo sed -i -e 's#=pi#=%USER#g' /lib/systemd/system/nodered.service
  839.                 sudo chmod +x /usr/bin/node-red-st*
  840.                 sudo systemctl daemon-reload 2>&1 | tee -a $LOGFILE
  841.             fi
  842.            
  843.             cd
  844.             mkdir .node-red
  845.             cd .node-red
  846.             printstatus "Installing Nodes (could take some time)"
  847.             npm $NQUIET install moment node-red-contrib-config node-red-contrib-grove node-red-contrib-diode node-red-contrib-bigtimer \
  848.             node-red-contrib-esplogin node-red-contrib-timeout node-red-node-openweathermap node-red-node-google node-red-node-sqlite \
  849.             node-red-node-emoncms node-red-node-geofence node-red-contrib-moment node-red-contrib-particle \
  850.             node-red-contrib-web-worldmap node-red-contrib-sqldbs node-red-contrib-ramp-thermostat node-red-contrib-graphs i2c-bus \
  851.             node-red-contrib-isonline node-red-node-ping node-red-node-random node-red-node-smooth node-red-contrib-npm node-red-node-arduino \
  852.             node-red-contrib-file-function node-red-contrib-boolean-logic node-red-contrib-blynk-ws node-red-contrib-chatbot \
  853.             node-red-dashboard node-red-node-darksky node-red-node-serialport node-red-contrib-owntracks node-red-contrib-opi-gpio node-red-contrib-alexa-local 2>&1 | tee -a $LOGFILE
  854.             sudo npm $NQUIET install bcryptjs 2>&1 | tee -a $LOGFILE
  855.  
  856.             ## this last bit of code is to ensure that node-red-contrib-opi-gpio can gain access to port bits!!
  857.             getent group gpio || sudo groupadd gpio 2>&1 | tee -a $LOGFILE
  858.             getent group gpio | grep -w -l pi || sudo adduser pi gpio 2>&1 | tee -a $LOGFILE
  859.             [ ! -f /etc/udev/rules.d/99-com.rules ] && echo "KERNEL==\"gpio*\", RUN=\"/bin/sh -c 'chgrp -R gpio /sys/%p /sys/class/gpio && chmod -R g+w /sys/%p /sys/class/gpio'\"" | sudo tee -a /etc/udev/rules.d/99-com.rules > /dev/null
  860.            
  861.             if [[ $OPSYS == *"RASPBIAN"* ]]; then
  862.                 sudo sed -i -e 's#exit 0#chmod 777 /dev/ttyAMA0\nexit 0#g' /etc/rc.local
  863.                 sudo apt-get -y install python{,3}-rpi.gpio 2>&1 | tee -a $LOGFILE
  864.                 #npm $NQUIET install node-red-contrib-gpio 2>&1 | tee -a $LOGFILE
  865.                 #npm $NQUIET install raspi-io 2>&1 | tee -a $LOGFILE
  866.             fi
  867.            
  868.             cd ~/.node-red/
  869.             sudo service nodered start 2>&1 | tee -a $LOGFILE
  870.             while [ ! -f settings.js ] ; do sudo sleep 1 ; done
  871.             sudo service nodered stop  2>&1 | tee -a $LOGFILE
  872.             echo " "
  873.             bcryptadminpass=$(node -e "console.log(require('bcryptjs').hashSync(process.argv[1], 8));" $adminpass)
  874.             bcryptuserpass=$(node -e "console.log(require('bcryptjs').hashSync(process.argv[1], 8));" $userpass)
  875.             # echo Encrypted password: $bcryptpass
  876.             cp settings.js settings.js.bak-pre-crypt
  877.            
  878.             datetimestamp=`date +%Y-%m-%d_%Hh%Mm`
  879.             cd ~/.node-red
  880.             # this will add the TOP piece of code for non-vol variables in settings.js
  881.             gawk -i inplace -v INPLACE_SUFFIX=-$datetimestamp '!found && /module.exports/ { print " var mySettings;\n try {\n mySettings = require(\"/home/pi/.node-red/redvars.js\");\n } catch(err) {\n mySettings = {};\n }\n"; found=1 } 1' settings.js
  882.            
  883.             sudo sed -i -e 's#functionGlobalContext: {#\/\/ functionGlobalContext: {#g' settings.js
  884.             sudo sed -i -e 's#\s\s\s\s\},#    \/\/ },#g' settings.js
  885.             sudo sed -i -e 's#^\}#,#g' settings.js
  886.             sudo echo " " > tmpfile
  887.             sudo echo "    httpStatic: '/home/pi/.node-red/public'," >> tmpfile
  888.             sudo echo "    functionGlobalContext: {" >> tmpfile
  889.             sudo echo "        os:require('os')," >> tmpfile
  890.             sudo echo "        moment:require('moment'), " >> tmpfile
  891.             sudo echo "        fs:require('fs'), " >> tmpfile
  892.             sudo echo "        i2c:require('i2c-bus'), " >> tmpfile
  893.             sudo echo "        mySettings:mySettings " >> tmpfile
  894.             sudo echo "    }," >> tmpfile
  895.             sudo echo " " >> tmpfile
  896.             sudo echo "    adminAuth: {" >> tmpfile
  897.             sudo echo "        type: \"credentials\"," >> tmpfile
  898.             sudo echo "        users: [{" >> tmpfile
  899.             sudo echo "            username: \"$adminname\"," >> tmpfile
  900.             sudo echo "            password: \"$bcryptadminpass\"," >> tmpfile
  901.             sudo echo "            permissions: \"*\"" >> tmpfile
  902.             sudo echo "        }]" >> tmpfile
  903.             sudo echo "    }," >> tmpfile
  904.             sudo echo " " >> tmpfile
  905.             sudo echo "    httpNodeAuth: {user:\"$username\", pass:\"$bcryptuserpass\"}" >> tmpfile
  906.             sudo echo "}" >> tmpfile
  907.             sudo cat tmpfile >> settings.js
  908.             sudo rm -f tmpfile
  909.         else
  910.             printl "${IRed}!!!! Settings.JS already present and modified, skipping! ${IWhite}\r\n"
  911.         fi
  912.         sed -i -e 's#\/\/\s*var fs = require("fs");#var fs = require("fs");\nvar i2c = require("i2c-bus");#' /home/pi/.node-red/settings.js
  913.         ## The next two lines are new (Sept 2017) and change the flows files to non-host-specific names - good for copying
  914.         sed -i -e 's#\/\/flowFile#flowFile#' /home/pi/.node-red/settings.js
  915.         sed -i -e 's#\/\/flowFilePretty#flowFilePretty#' /home/pi/.node-red/settings.js
  916.         sed -i -e 's#\/\/ Customising#},\n\n    \/\/ Customising#' /home/pi/.node-red/settings.js
  917.         if [[ $MYMENU == *"phone"* ]]; then
  918.             cd && sudo mv /etc/init.d/sendsigs .
  919.         else
  920.             sudo systemctl enable nodered.service 2>&1 | tee -a $LOGFILE
  921.         fi
  922.         ## add a nice little command line utility (nrlog) for showing and tailing Node-Red scripts in colour
  923.         echo "alias nrlog='sudo journalctl -f -n 50 -u nodered -o cat | ccze -A'" | sudo tee -a /etc/bash.bashrc > /dev/null 2>&1
  924.     else
  925.         printl "${IRed}!!!! Node-Red not installed! ${IWhite}\r\n"
  926.     fi
  927. fi
  928.  
  929. if [[ $OPSYS != *"RASPBIAN"* ]]; then
  930.     if [[ $MYMENU == *"odroid"* ]]; then
  931.         printstatus "Installing Odroid GPIO"
  932.         git clone https://github.com/hardkernel/wiringPi.git 2>&1 | tee -a $LOGFILE
  933.         cd wiringPi
  934.         ./build 2>&1 | tee -a $LOGFILE
  935.         sudo chmod a+s /usr/local/bin/gpio
  936.     fi
  937.     if [[ $MYMENU == *"generich3"* ]]; then
  938.         printstatus "Installing H3 GPIO"
  939.         # Install NanoPi H3 based IO library
  940.         git clone https://github.com/zhaolei/WiringOP.git -b h3 2>&1 | tee -a $LOGFILE
  941.         cd WiringOP
  942.         chmod +x ./build
  943.         sudo ./build 2>&1 | tee -a $LOGFILE
  944.         cd
  945.     fi
  946. fi
  947.  
  948. if [[ $MYMENU == *"webmin"* ]]; then
  949.     printstatus "Installing Webmin at port 10000 (could take some time)"
  950.     #cd
  951.     #mkdir webmin
  952.     #cd webmin
  953.     #wget --no-check-certificate http://prdownloads.sourceforge.net/webadmin/webmin-1.831.tar.gz
  954.     #sudo gunzip -q webmin-1.831.tar.gz
  955.     #tar -xf webmin-1.831.tar
  956.     #sudo rm *.tar
  957.     #cd webmin-1.831
  958.     #sudo ./setup.sh /usr/local/Webmin
  959.     wget -a $LOGFILE http://www.webmin.com/jcameron-key.asc -O - | sudo apt-key add -
  960.     echo "deb http://download.webmin.com/download/repository sarge contrib" | sudo tee /etc/apt/sources.list.d/webmin.list > /dev/null
  961.     sudo apt-get $AQUIET -y update 2>&1 | tee -a $LOGFILE
  962.     sudo apt-get $AQUIET -y install webmin 2>&1 | tee -a $LOGFILE
  963.     # http vs https: if you want unsecure http access on port 10000 instead of https, uncomment next line
  964.     sudo sed -i -e 's#ssl=1#ssl=0#g' /etc/webmin/miniserv.conf
  965. fi
  966.  
  967. if [[ $MYMENU == *"mpg123"* ]]; then
  968.     printstatus "Installing MPG123"
  969.     sudo apt-get $AQUIET -y install mpg123 2>&1 | tee -a $LOGFILE
  970. fi
  971.  
  972. #
  973. # This works a treat on the NanoPi NEO using H3 and Armbian - should not do any harm on other systems as it's not installed!
  974. #
  975. if [[ $MYMENU == *"opimonitor"* ]]; then
  976.     printstatus "Installing Armbian Monitor"
  977.     sudo armbianmonitor -r 2>&1 | tee -a $LOGFILE
  978. fi
  979.  
  980. if [[ $MYMENU == *"screen"* ]]; then
  981.     printstatus "Installing Screen"
  982.     sudo apt-get -y $AQUIET install screen 2>&1 | tee -a $LOGFILE
  983. fi
  984.  
  985. if [[ $MYMENU == *"habridge"* ]]; then
  986.     printstatus "Installing HA-Bridge on port 82"
  987.     #sudo sed -i -e 's#80#81#g' /etc/apache2/ports.conf
  988.     #sudo sed -i -e 's#80#81#g' /etc/apache2/sites-enabled/000-default.conf
  989.     #sudo service apache2 restart
  990.     ## now to install HA-Bridge on port 82 and get it running from power up.
  991.     cd ~
  992.     mkdir habridge
  993.     cd habridge
  994.     #wget https://github.com/bwssytems/ha-bridge/releases/download/v3.5.1/ha-bridge-3.5.1.jar -O ~/habridge/ha-bridge.jar
  995.     curl -s https://api.github.com/repos/bwssytems/ha-bridge/releases/latest | jq --raw-output '.assets[0] | .browser_download_url' | wget -a $LOGFILE -i - -O ~/habridge/ha-bridge.jar
  996.     echo -e "[Unit]\n\
  997. Description=HA Bridge\n\
  998. Wants=network.target\n\
  999. After=network.target\n\
  1000. \n\
  1001. [Service]\n\
  1002. Type=simple\n\
  1003. ExecStart=/usr/bin/java -jar -Dserver.port=82 -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge.jar\n\
  1004. \n\
  1005. [Install]\n\
  1006.    WantedBy=multi-user.target\n" | sudo tee /lib/systemd/system/habridge.service
  1007.     sudo systemctl  start habridge.service 2>&1 | tee -a $LOGFILE
  1008.     sudo systemctl enable habridge.service 2>&1 | tee -a $LOGFILE
  1009. fi
  1010.  
  1011. if [[ $MYMENU == *"java"* ]]; then
  1012.     printstatus "Installing/Updating Java"
  1013.     if [[ $OPSYS == *"BIAN"* ]] && [[ $DISTRO == *"9."* ]]; then
  1014.         sudo apt-get $AQUIET -y install software-properties-common dirmngr 2>&1 | tee -a $LOGFILE
  1015.         sudo add-apt-repository "deb http://ppa.launchpad.net/webupd8team/java/ubuntu yakkety main" 2>&1 | tee -a $LOGFILE
  1016.         sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C2518248EEA14886 2>&1 | tee -a $LOGFILE
  1017.     else
  1018.         echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | sudo tee /etc/apt/sources.list.d/webupd8team-java.list
  1019.         echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu xenial main" | sudo tee -a /etc/apt/sources.list.d/webupd8team-java.list
  1020.         sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886 2>&1 | tee -a $LOGFILE
  1021.     fi
  1022.     sudo apt-get $AQUIET update 2>&1 | tee -a $LOGFILE
  1023.     echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections
  1024.     echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections
  1025.     sudo apt-get $AQUIET -y install oracle-java8-installer 2>&1 | tee -a $LOGFILE
  1026. fi
  1027.  
  1028. if [[ $MYMENU == *"phpsysinfo"* ]]; then
  1029.     printstatus "Installing PHPSysInfo"
  1030.     #   sudo apt-get $AQUIET -y install phpsysinfo
  1031.     #   sudo ln -s /usr/share/phpsysinfo /var/www/html
  1032.     if [ -d /var/www/html ]; then
  1033.         cd /var/www/html
  1034.         sudo git clone https://github.com/phpsysinfo/phpsysinfo.git 2>&1 | tee -a $LOGFILE
  1035.         sudo cp /var/www/html/phpsysinfo/phpsysinfo.ini.new /var/www/html/phpsysinfo/phpsysinfo.ini
  1036.     else
  1037.         printl "${IRed}!!!! Apache+PHP not installed! ${IWhite}\r\n"
  1038.     fi
  1039. fi
  1040.  
  1041. # you may want to use these on a Pi or elsewhere to force either a graphical or command line environment
  1042. #sudo systemctl set-default multi-user.target
  1043. #sudo systemctl set-default graphical.target
  1044.  
  1045. if [[ $MYMENU == *"upgradenpm"* ]]; then
  1046.     printstatus "Upgrading NPM to the latest version"
  1047.     sudo npm $NQUIET install npm@latest -g 2>&1 | tee -a $LOGFILE
  1048. fi
  1049.  
  1050. # Add CU to enable serial VT100 mode for terminals
  1051. if [[ $MYMENU == *"installcu"* ]]; then
  1052.     printstatus "Installing CU"
  1053.     sudo apt-get $AQUIET -y install cu 2>&1 | tee -a $LOGFILE
  1054. fi
  1055.  
  1056. if [[ $MYMENU == *"installmc"* ]]; then
  1057.     printstatus "Installing MC File manager and editor"
  1058.     sudo apt-get -y $AQUIET install mc 2>&1 | tee -a $LOGFILE
  1059. fi
  1060.  
  1061. if [[ $MYMENU == *"rpiclone"* ]]; then
  1062.     printstatus "Installing RPI-Clone"
  1063.     cd
  1064.     sudo git clone https://github.com/billw2/rpi-clone.git
  1065.     cd rpi-clone
  1066.     sudo cp rpi-clone /usr/local/sbin
  1067.     cd
  1068.     sudo rm -r rpi-clone
  1069. fi
  1070.  
  1071. if [[ $MYMENU == *"log2ram"* ]]; then
  1072.     printstatus "Installing Log2Ram"
  1073.     cd
  1074.     git clone https://github.com/azlux/log2ram.git 2>&1 | tee -a $LOGFILE
  1075.     cd log2ram
  1076.     chmod +x install.sh
  1077.     sudo ./install.sh 2>&1 | tee -a $LOGFILE
  1078.     cd
  1079. fi
  1080.  
  1081. # Drop in an index file and css for a menu page
  1082. if [[ $MYMENU == *"addindex"* ]]; then
  1083.     printstatus "Adding index page and CSS"
  1084.     if [ -d /var/www/html ]; then
  1085.         sudo wget -a $LOGFILE $AQUIET http://www.scargill.net/iot/index.html -O /var/www/html/index.html
  1086.         sudo wget -a $LOGFILE $AQUIET http://www.scargill.net/iot/reset.css -O /var/www/html/reset.css
  1087.     else
  1088.         printl "${IRed}!!!! Apache+PHP not installed! ${IWhite}\r\n"
  1089.     fi
  1090. fi
  1091.  
  1092. if [[ $MYMENU == *"grafana"* ]]; then
  1093.     printstatus "Installing Grafana and Influxdb"
  1094.     cd
  1095.     sudo apt-get $AQUIET -y update 2>&1 | tee -a $LOGFILE
  1096.     sudo apt-get $AQUIET install -y apt-transport-https curl 2>&1 | tee -a $LOGFILE
  1097.     curl -sL https://repos.influxdata.com/influxdb.key | sudo apt-key add -
  1098.     test $VERSION_ID = "8" && echo "deb https://repos.influxdata.com/debian jessie stable" | sudo tee -a /etc/apt/sources.list.d/influxdb.list
  1099.     test $VERSION_ID = "9" && echo "deb https://repos.influxdata.com/debian jessie stable" | sudo tee -a /etc/apt/sources.list.d/influxdb.list
  1100.     test $VERSION_ID = "16.04" && echo "deb https://repos.influxdata.com/ubuntu xenial stable" | sudo tee -a /etc/apt/sources.list.d/influxdb.list
  1101.     curl -sL https://bintray.com/user/downloadSubjectPublicKey?username=bintray | sudo apt-key add -
  1102.     curl -sL https://packagecloud.io/gpg.key | sudo apt-key add -
  1103.     [[ $OPSYS == *"BIAN"* ]] && [[ $(uname -m) == *"armv6"* ]] && echo "deb https://dl.bintray.com/fg2it/deb-rpi-1b jessie main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
  1104.     [[ $OPSYS == *"BIAN"* ]] && [[ $(uname -m) == *"armv7l"* ]] && echo "deb https://dl.bintray.com/fg2it/deb jessie main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
  1105.     [[ $OPSYS == *"UBUNTU"* ]] && [[ $(uname -m) == *"aarch64"* ]] && echo "deb https://dl.bintray.com/fg2it/deb-arm64 stretch main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
  1106.     [[ $OPSYS == *"UBUNTU"* ]] && [[ $(uname -m) != *"aarch64"* ]] && echo "deb https://packagecloud.io/grafana/testing/debian/ stretch main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
  1107.     sudo apt-get $AQUIET -y remove --purge grafana grafana-data 2>&1 | tee -a $LOGFILE
  1108.     sudo rm -rf /var/log/grafana /etc/grafana
  1109.     sudo apt-get $AQUIET -y autoremove 2>&1 | tee -a $LOGFILE
  1110.     sudo apt-get $AQUIET -y update 2>&1 | tee -a $LOGFILE
  1111.     sudo apt-get install $AQUIET -y influxdb grafana chronograf 2>&1 | tee -a $LOGFILE
  1112.     [ $? -eq 0 ] && grafana=1 # grafana installed
  1113.     if [ $grafana -eq 1 ]; then
  1114.         #sudo sed -i -e 's/.*auth-enabled = false/  auth-enabled = true/g' /etc/influxdb/influxdb.conf
  1115.         sudo systemctl daemon-reload 2>&1 | tee -a $LOGFILE
  1116.         sudo systemctl enable influxdb 2>&1 | tee -a $LOGFILE
  1117.         sudo systemctl start influxdb 2>&1 | tee -a $LOGFILE
  1118.         sudo systemctl enable grafana-server 2>&1 | tee -a $LOGFILE
  1119.         sudo systemctl start grafana-server 2>&1 | tee -a $LOGFILE
  1120.         sudo systemctl enable chronograf 2>&1 | tee -a $LOGFILE
  1121.         sudo systemctl start chronograf 2>&1 | tee -a $LOGFILE
  1122.     else
  1123.         printl "${IRed}!!!! GRAFANA AND INFLUXDB NOT INSTALLED! ${IWhite}\r\n"
  1124.     fi
  1125. fi
  1126.  
  1127. sudo rm -rf /var/cache/apt/archives/apt-fast
  1128. sudo apt-get $AQUIET -y clean 2>&1 | tee -a $LOGFILE
  1129.  
  1130. myip=$(hostname -I)
  1131. thehostname=$(hostname)
  1132. echo $newhostname | sudo tee /etc/hostname > /dev/null 2>&1
  1133. sudo sed -i '/^127.0.1.1/ d' /etc/hosts > /dev/null 2>&1
  1134. echo 127.0.1.1 $newhostname | sudo tee -a /etc/hosts > /dev/null 2>&1
  1135. sudo /etc/init.d/hostname.sh > /dev/null 2>&1
  1136.  
  1137. printstatus "Installing Glances"
  1138. sudo apt-get -y install python{,3}-setuptools 2>&1 | tee -a $LOGFILE
  1139. sudo pip install glances 2>&1 | tee -a $LOGFILE
  1140. sudo pip install bottle 2>&1 | tee -a $LOGFILE
  1141.  
  1142. printstatus "All done."
  1143. printf "${BIGreen}== ${BIYELLOW}When complete, remove the script from the /home/pi directory.\r\n"
  1144. printf "${BIGreen}==\r\n"
  1145. printf "${BIGreen}== ${BIPurple}Current IP: %s${BIWhite}\r\n" "$myip"
  1146. printf "${BIGreen}== ${BIPurple}Existing Hostname: %s  New Hostname: %s${BIWhite}\r\n\r\n" "$thehostname" "$newhostname"
  1147. echo -e Current IP: $myip  Hostname: $thehostname >> $LOGFILE
  1148. echo -e Hostname: $newhostname >> $LOGFILE
  1149. echo -e NPM: $(npm -v) >> $LOGFILE
  1150. echo -e PHP: $(php -v) >> $LOGFILE
  1151. echo -e NODE: $(node -v) >> $LOGFILE
  1152. echo -e MQTT: $(/usr/sbin/mosquitto --help | grep version) >> $LOGFILE
  1153. sudo grep -h ^deb /etc/apt/sources.list /etc/apt/sources.list.d/* 2>&1 >> $LOGFILE
  1154. printstatus  "ALL DONE - PLEASE REBOOT NOW THEN TEST"
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top