#!/bin/bash shopt -s extglob # +(expr) syntax { # Created by MichaIng / micha@dietpi.com / dietpi.com # Prevent concurrent executions (( $(pgrep -cf 'dietpi-survey_report') > 1 )) && { echo 'Concurrent execution detected. Exiting...'; exit 1; } #----------------------------------------------------------- # Globals - benchmarks #----------------------------------------------------------- # NB: PLEASE ENSURE HW_MODEL INDEX ENTRIES MATCH : PREP, dietpi-obtain_hw_model, dietpi-survey_results, # NBB: DO NOT REORDER INDEX's. These are now fixed and will never change (due to survey results etc) aHW_NAME=( [0]='Raspberry Pi 1 256M' [1]='Raspberry Pi 1/Zero 512M' [2]='Raspberry Pi 2' [3]='Raspberry Pi 3/3+/Zero 2' [4]='Raspberry Pi 4' [5]='Raspberry Pi 5' [10]='Odroid C1' [11]='Odroid XU3/XU4/MC1/HC1/HC2' [12]='Odroid C2' [13]='Odroid U3' # until v10.0 [15]='Odroid N2' [16]='Odroid C4' [17]='Odroid HC4' [20]='x86_64 VM' [21]='x86_64 PC' [22]='Generic Device' [23]='Generic Rockchip RK3328' [24]='Generic Rockchip RK3399' [25]='Generic Allwinner H3' [26]='Generic Allwinner H5' [27]='Generic Allwinner H6' [28]='Generic Amlogic S905' [29]='Generic Amlogic S922X' [40]='PINE A64' [42]='ROCKPro64' [43]='ROCK64' [44]='Pinebook' [45]='PINE H64' [46]='Pinebook Pro' [47]='NanoPi R4S' [48]='NanoPi R1' [49]='Quartz64' [52]='ASUS Tinker Board' [54]='NanoPi K2' [55]='NanoPi R2S' [56]='NanoPi NEO3' [57]='NanoPi NEO Plus2' [58]='NanoPi M4V2' [59]='ZeroPi' [60]='NanoPi NEO' [61]='NanoPi M2/T2' # until v10.0 [62]='NanoPi M3/T3/Fire3' # until v10.0 [63]='NanoPi M1' [64]='NanoPi NEO Air' [65]='NanoPi NEO2' [66]='NanoPi M1 Plus' [67]='NanoPi K1 Plus' [68]='NanoPi M4/T4/NEO4' [70]='Sparky SBC' # until v10.0 [72]='ROCK 4' [73]='ROCK Pi S' [74]='Radxa Zero' [75]='Container' [76]='NanoPi R5S/R5C' [77]='ROCK 3A' [78]='ROCK 5B' [79]='NanoPi 6 series' [80]='Orange Pi 5' [81]='StarFive VisionFive 2' [82]='Orange Pi 5 Plus' [83]='Orange Pi Zero 3' [84]='Star64' [85]='ROCK 5A' [86]='ASUS Tinker Board 2' [87]='Orange Pi 3B' [88]='Orange Pi Zero 2W' [89]='Orange Pi 3 LTS' [90]='Radxa ZERO 3' [91]='Orange Pi 5 Max' [92]='NanoPi M6' [93]='Orange Pi 5 Pro' [94]='Orange Pi 5 Ultra' [95]='Orange Pi CM5' [96]='Orange Pi 4A' [97]='Orange Pi RV' [98]='Orange Pi RV2' [99]='Orange Pi 3' [100]='NanoPi R3S' [101]='NanoPi R3S LTS' [102]='NanoPi R76S' [103]='NanoPi M5' [104]='NanoPi Zero2' ) ## Benchmark data arrays: aBENCH_XX[$HW_MODEL,${aBENCH_XX_INDEX[$HW_MODEL]}] # Core benchmarks # - CPU time in x.xx seconds aBENCH_CPU_INDEX=() declare -A aBENCH_CPU # - CPU temp in integer °C aBENCH_CPU_TEMP_INDEX=() declare -A aBENCH_CPU_TEMP_START declare -A aBENCH_CPU_TEMP_END # - I/O in integer MiB/s aBENCH_RAM_INDEX=() declare -A aBENCH_RAM_WRITE declare -A aBENCH_RAM_READ aBENCH_ROOTFS_INDEX=() declare -A aBENCH_ROOTFS_WRITE declare -A aBENCH_ROOTFS_READ # Optional benchmarks aBENCH_CUSTOMFS_INDEX=() declare -A aBENCH_CUSTOMFS_WRITE declare -A aBENCH_CUSTOMFS_READ aBENCH_LAN_INDEX=() declare -A aBENCH_NET_LAN_SPEED # Benchmark result arrays: min, max, average aBENCH_RESULT_CPU_MIN=() aBENCH_RESULT_CPU_MAX=() aBENCH_RESULT_CPU_AVG=() aBENCH_RESULT_CPU_TEMP_START_MIN=() aBENCH_RESULT_CPU_TEMP_START_MAX=() aBENCH_RESULT_CPU_TEMP_START_AVG=() aBENCH_RESULT_CPU_TEMP_END_MIN=() aBENCH_RESULT_CPU_TEMP_END_MAX=() aBENCH_RESULT_CPU_TEMP_END_AVG=() aBENCH_RESULT_RAM_READ_MIN=() aBENCH_RESULT_RAM_READ_MAX=() aBENCH_RESULT_RAM_READ_AVG=() aBENCH_RESULT_RAM_WRITE_MIN=() aBENCH_RESULT_RAM_WRITE_MAX=() aBENCH_RESULT_RAM_WRITE_AVG=() aBENCH_RESULT_ROOTFS_READ_MIN=() aBENCH_RESULT_ROOTFS_READ_MAX=() aBENCH_RESULT_ROOTFS_READ_AVG=() aBENCH_RESULT_ROOTFS_WRITE_MIN=() aBENCH_RESULT_ROOTFS_WRITE_MAX=() aBENCH_RESULT_ROOTFS_WRITE_AVG=() aBENCH_RESULT_CUSTOMFS_READ_MIN=() aBENCH_RESULT_CUSTOMFS_READ_MAX=() aBENCH_RESULT_CUSTOMFS_READ_AVG=() aBENCH_RESULT_CUSTOMFS_WRITE_MIN=() aBENCH_RESULT_CUSTOMFS_WRITE_MAX=() aBENCH_RESULT_CUSTOMFS_WRITE_AVG=() aBENCH_RESULT_NET_LAN_SPEED_MIN=() aBENCH_RESULT_NET_LAN_SPEED_MAX=() aBENCH_RESULT_NET_LAN_SPEED_AVG=() #----------------------------------------------------------- # Globals - Survey #----------------------------------------------------------- DATE_NOW= SURVEY_COUNT_TOTAL=0 SURVEY_COUNT_OPTIN=0 SURVEY_COUNT_OPTOUT=0 SURVEY_COUNT_INACTIVE=0 SURVEY_COUNT_REACTIVE=0 declare -A aDIETPI_VERSION declare -A aDEVICE_NAME declare -A aCPU_ARCH aCPU_COUNT=() declare -A aDISTRO_VERSION declare -A aAUTOSTART_OPTION declare -A aSOFTWARE aAUTO_SETUP_AUTOMATED=(0 0) declare -A aNETWORK_INTERFACE declare -A aGIT_BRANCH aRASPBIAN=(0 0) aMMC=(0 0) # Convert autostart index to name array # shellcheck disable=SC2034 aAUTOSTART_NAME=( [0]='Console manual login' [1]='Kodi' [2]='Desktop auto login' [3]='RetroPie' [4]='OpenTyrian' [5]='DietPi-CloudShell' [6]='Amiberry fast boot' [7]='Console auto login' [8]='Amiberry standard boot' [9]='DXX-Rebirth' [10]='CAVA Spectrum' [11]='Chromium' [14]='Custom (background)' [15]='JRiver' [16]='Desktop LightDM login' [17]='Custom (foreground)' ) # Convert software index to title array # - Start with v8.8 state, the oldest version which uses the correct SSH port to upload reports. aSOFTWARE_NAME8_8=( [0]='OpenSSH Client' [1]='Samba Client' [2]='Folding@Home' [3]='MC' [4]='ViFM' [5]='ALSA' [6]='X11' [7]='FFmpeg' [8]='Java JDK' [9]='Node.js' [10]='iftop' [11]='IPTraf' [12]='Iperf' [13]='MTR-Tiny' [14]='nLoad' [15]='tcpdump' [16]='Build-Essential' [17]='Git Client' [18]='Emacs' [19]='Jed' [20]='Vim' [21]='Vim-Tiny' [22]='QuiteRSS' [23]='LXDE' [24]='MATE' [25]='Xfce' [26]='GNUstep' [27]='TasmoAdmin' [28]='TigerVNC Server' [29]='XRDP' [30]='NoMachine' [31]='Kodi' [32]='ympd' [33]='Airsonic-Advanced' [34]='PHP Composer' [35]='Lyrion Music Server' [36]='Squeezelite' [37]='Shairport Sync' [38]='FreshRSS' [39]='ReadyMedia' [40]='Ampache' [41]='Emby Server' [42]='Plex Media Server' [43]='Mumble Server' [44]='Transmission' [45]='Deluge' [46]='qBittorrent' [47]='ownCloud' [48]='Pydio' [49]='Gogs' [50]='Syncthing' [51]='OpenTyrian' [52]='Cuberite' [53]='MineOS' [54]='phpBB' [55]='WordPress' [56]='Single File PHP Gallery' [57]='Baïkal' [58]='Tailscale' [59]='RPi Cam Web Interface' [60]='WiFi Hotspot' [61]='Tor Hotspot' [62]='Box86' [63]='LinuxDash' [64]='phpSysInfo' [65]='Netdata' [66]='RPi-Monitor' [67]='Firefox' [68]='Remote.It' [69]='RPi.GPIO' [70]='WiringPi' [71]='WebIOPi' [72]='I2C' [73]='Fail2Ban' [74]='InfluxDB' [75]='LASP' [76]='LAMP' [77]='Grafana' [78]='LESP' [79]='LEMP' [80]='Ubooquity' [81]='LLSP' [82]='LLMP' [83]='Apache' [84]='Lighttpd' [85]='Nginx' [86]='Roon Extension Manager' [87]='SQLite' [88]='MariaDB' [89]='PHP' [90]='phpMyAdmin' [91]='Redis' [92]='Certbot' [93]='Pi-hole' [94]='ProFTPD' [95]='vsftpd' [96]='Samba Server' [97]='OpenVPN' [98]='HAProxy' [99]='Prometheus Node Exporter' [100]='PiJuice' [101]='Logrotate' [102]='Rsyslog' [103]='DietPi-RAMlog' [104]='Dropbear' [105]='OpenSSH Server' [106]='Lidarr' [107]='rTorrent' [108]='Amiberry' [109]='NFS Server' [110]='NFS Client' [111]='UrBackup Server' [112]='DXX-Rebirth' [113]='Chromium' [114]='Nextcloud' [115]='Webmin' [116]='Medusa' [117]='PiVPN' [118]='Mopidy' [119]='CAVA' [120]='RealVNC Server' [121]='Roon Bridge' [122]='Node-RED' [123]='Mosquitto' [124]='NAA Daemon' [125]='Synapse Server' [126]='AdGuard Home' [127]='NeoVim' [128]='MPD' [129]='O!MPD' [130]='Python pip' [131]='Blynk Server' [132]='Aria2' [133]='YaCy' [134]='Docker Compose' [135]='Icecast' [136]='motionEye' [137]='mjpg-streamer' [138]='VirtualHere' [139]='SABnzbd' [140]='Domoticz' [141]='Spotify Connect Web' [142]='MicroK8s' [143]='Koel' [144]='Sonarr' [145]='Radarr' [146]='Tautulli' [147]='Jackett' [148]='myMPD' [149]='NZBGet' [150]='Mono' [151]='Prowlarr' [152]='Avahi-Daemon' [153]='OctoPrint' [154]='Roon Server' [155]='HTPC Manager' [156]='Steam' [157]='Home Assistant' [158]='MinIO' [159]='Allo' [160]='Allo_update' [161]='FuguHub' [162]='Docker' [163]='GMediaRender' [164]='Nukkit' [165]='Gitea' [166]='PI-SPC' [167]='Raspotify' [168]='Nextcloud Talk' [169]='Google AIY' [170]='UnRAR' [171]='frp' [172]='WireGuard' [173]='LXQt' [174]='GIMP' [175]='Xfce Power Manager' [176]='Mycroft AI' [177]='Firefox Sync Server' [178]='Jellyfin' [179]='Komga' [180]='Bazarr' [181]='PaperMC' [182]='Unbound' [183]='vaultwarden' [184]='Tor Relay' [185]='Portainer' [186]='Kubo' [187]='CUPS' [188]='Go' [189]='VSCodium' [190]='Beets' [191]='Snapcast Server' [192]='Snapcast Client' [193]='K3s' [194]='PostgreSQL' [195]='youtube-dl' [196]='Java JRE' [197]='Box64' [198]='File Browser' [199]='Spotifyd' [200]='DietPi-Dashboard' [201]='ZeroTier' [202]='Rclone' [203]='Readarr' [204]='Navidrome' ) aSOFTWARE_NAME8_9=() aSOFTWARE_NAME8_10=() aSOFTWARE_NAME8_11=() for i in "${!aSOFTWARE_NAME8_8[@]}" do aSOFTWARE_NAME8_9[i]=${aSOFTWARE_NAME8_8[i]} aSOFTWARE_NAME8_10[i]=${aSOFTWARE_NAME8_9[i]} aSOFTWARE_NAME8_11[i]=${aSOFTWARE_NAME8_10[i]} done aSOFTWARE_NAME8_11[205]='Homer' aSOFTWARE_NAME8_12=() aSOFTWARE_NAME8_13=() aSOFTWARE_NAME8_14=() aSOFTWARE_NAME8_15=() for i in "${!aSOFTWARE_NAME8_11[@]}" do aSOFTWARE_NAME8_12[i]=${aSOFTWARE_NAME8_11[i]} aSOFTWARE_NAME8_13[i]=${aSOFTWARE_NAME8_12[i]} aSOFTWARE_NAME8_14[i]=${aSOFTWARE_NAME8_13[i]} aSOFTWARE_NAME8_15[i]=${aSOFTWARE_NAME8_14[i]} done unset -v 'aSOFTWARE_NAME8_15[16]' # Build-Essential aSOFTWARE_NAME8_16=() for i in "${!aSOFTWARE_NAME8_15[@]}" do aSOFTWARE_NAME8_16[i]=${aSOFTWARE_NAME8_15[i]} done aSOFTWARE_NAME8_16[16]='microblog.pub' aSOFTWARE_NAME8_17=() for i in "${!aSOFTWARE_NAME8_16[@]}" do aSOFTWARE_NAME8_17[i]=${aSOFTWARE_NAME8_16[i]} done aSOFTWARE_NAME8_17[206]='openHAB' aSOFTWARE_NAME8_17[207]='Moonlight (CLI)' aSOFTWARE_NAME8_17[208]='Moonlight (GUI)' aSOFTWARE_NAME8_17[209]='Restic' aSOFTWARE_NAME8_18=() aSOFTWARE_NAME8_19=() for i in "${!aSOFTWARE_NAME8_17[@]}" do aSOFTWARE_NAME8_18[i]=${aSOFTWARE_NAME8_17[i]} aSOFTWARE_NAME8_19[i]=${aSOFTWARE_NAME8_18[i]} done unset -v 'aSOFTWARE_NAME8_19[141]' # Spotify Connect Web unset -v 'aSOFTWARE_NAME8_19[177]' # Firefox Sync Server aSOFTWARE_NAME8_19[210]='MediaWiki' aSOFTWARE_NAME8_20=() for i in "${!aSOFTWARE_NAME8_19[@]}" do aSOFTWARE_NAME8_20[i]=${aSOFTWARE_NAME8_19[i]} done aSOFTWARE_NAME8_20[211]='Homebridge' aSOFTWARE_NAME8_21=() aSOFTWARE_NAME8_22=() for i in "${!aSOFTWARE_NAME8_20[@]}" do aSOFTWARE_NAME8_21[i]=${aSOFTWARE_NAME8_20[i]} aSOFTWARE_NAME8_22[i]=${aSOFTWARE_NAME8_21[i]} done aSOFTWARE_NAME8_22[141]='ADS-B Feeder' aSOFTWARE_NAME8_22[212]='Kavita' aSOFTWARE_NAME8_23=() aSOFTWARE_NAME8_24=() aSOFTWARE_NAME8_25=() aSOFTWARE_NAME9_0=() aSOFTWARE_NAME9_1=() aSOFTWARE_NAME9_2=() for i in "${!aSOFTWARE_NAME8_22[@]}" do aSOFTWARE_NAME8_23[i]=${aSOFTWARE_NAME8_22[i]} aSOFTWARE_NAME8_24[i]=${aSOFTWARE_NAME8_23[i]} aSOFTWARE_NAME8_25[i]=${aSOFTWARE_NAME8_24[i]} aSOFTWARE_NAME9_0[i]=${aSOFTWARE_NAME8_25[i]} aSOFTWARE_NAME9_1[i]=${aSOFTWARE_NAME9_0[i]} aSOFTWARE_NAME9_2[i]=${aSOFTWARE_NAME9_1[i]} aSOFTWARE_NAME9_3[i]=${aSOFTWARE_NAME9_2[i]} aSOFTWARE_NAME9_4[i]=${aSOFTWARE_NAME9_3[i]} aSOFTWARE_NAME9_5[i]=${aSOFTWARE_NAME9_4[i]} done aSOFTWARE_NAME9_5[177]='Forgejo' aSOFTWARE_NAME9_6=() for i in "${!aSOFTWARE_NAME9_5[@]}" do aSOFTWARE_NAME9_6[i]=${aSOFTWARE_NAME9_5[i]} done aSOFTWARE_NAME9_6[213]='soju' aSOFTWARE_NAME9_7=() aSOFTWARE_NAME9_8=() aSOFTWARE_NAME9_9=() aSOFTWARE_NAME9_10=() for i in "${!aSOFTWARE_NAME9_6[@]}" do aSOFTWARE_NAME9_7[i]=${aSOFTWARE_NAME9_6[i]} aSOFTWARE_NAME9_8[i]=${aSOFTWARE_NAME9_7[i]} aSOFTWARE_NAME9_9[i]=${aSOFTWARE_NAME9_8[i]} aSOFTWARE_NAME9_10[i]=${aSOFTWARE_NAME9_9[i]} done unset -v 'aSOFTWARE_NAME9_10[4]' # ViFM unset -v 'aSOFTWARE_NAME9_10[10]' # iftop unset -v 'aSOFTWARE_NAME9_10[11]' # IPTraf unset -v 'aSOFTWARE_NAME9_10[12]' # Iperf unset -v 'aSOFTWARE_NAME9_10[13]' # MTR-Tiny unset -v 'aSOFTWARE_NAME9_10[14]' # nLoad unset -v 'aSOFTWARE_NAME9_10[15]' # tcpdump unset -v 'aSOFTWARE_NAME9_10[18]' # Emacs unset -v 'aSOFTWARE_NAME9_10[19]' # Jed unset -v 'aSOFTWARE_NAME9_10[20]' # Vim unset -v 'aSOFTWARE_NAME9_10[21]' # Vim-Tiny unset -v 'aSOFTWARE_NAME9_10[127]' # NeoVim aSOFTWARE_NAME9_11=() aSOFTWARE_NAME9_12=() for i in "${!aSOFTWARE_NAME9_10[@]}" do aSOFTWARE_NAME9_11[i]=${aSOFTWARE_NAME9_10[i]} aSOFTWARE_NAME9_12[i]=${aSOFTWARE_NAME9_11[i]} done aSOFTWARE_NAME9_12[4]='fish' aSOFTWARE_NAME9_12[10]='Amiberry-Lite' aSOFTWARE_NAME9_13=() for i in "${!aSOFTWARE_NAME9_12[@]}" do aSOFTWARE_NAME9_13[i]=${aSOFTWARE_NAME9_12[i]} done unset -v 'aSOFTWARE_NAME9_13[169]' # Google AIY unset -v 'aSOFTWARE_NAME9_13[176]' # Mycroft AI aSOFTWARE_NAME9_14=() for i in "${!aSOFTWARE_NAME9_13[@]}" do aSOFTWARE_NAME9_14[i]=${aSOFTWARE_NAME9_13[i]} done aSOFTWARE_NAME9_14[11]='GZDoom' aSOFTWARE_NAME9_15=() for i in "${!aSOFTWARE_NAME9_14[@]}" do aSOFTWARE_NAME9_15[i]=${aSOFTWARE_NAME9_14[i]} done aSOFTWARE_NAME9_16=() aSOFTWARE_NAME9_17=() aSOFTWARE_NAME9_18=() for i in "${!aSOFTWARE_NAME9_15[@]}" do aSOFTWARE_NAME9_16[i]=${aSOFTWARE_NAME9_15[i]} aSOFTWARE_NAME9_17[i]=${aSOFTWARE_NAME9_16[i]} aSOFTWARE_NAME9_18[i]=${aSOFTWARE_NAME9_17[i]} done aSOFTWARE_NAME9_18[169]='LazyLibrarian' aSOFTWARE_NAME9_19=() for i in "${!aSOFTWARE_NAME9_18[@]}" do aSOFTWARE_NAME9_19[i]=${aSOFTWARE_NAME9_18[i]} done aSOFTWARE_NAME9_19[127]='BirdNET-Go' aSOFTWARE_NAME9_20=() for i in "${!aSOFTWARE_NAME9_19[@]}" do aSOFTWARE_NAME9_20[i]=${aSOFTWARE_NAME9_19[i]} done aSOFTWARE_NAME9_20[12]='RustDesk Server' aSOFTWARE_NAME10_0=() for i in "${!aSOFTWARE_NAME9_20[@]}" do aSOFTWARE_NAME10_0[i]=${aSOFTWARE_NAME9_20[i]} done unset -v 'aSOFTWARE_NAME10_0[59]' # RPi Cam Web Interface aSOFTWARE_NAME10_0[176]='Uptime Kuma' unset -v 'aSOFTWARE_NAME10_0[48]' # Pydio aSOFTWARE_NAME10_0[47]='ownCloud Infinite Scale' aSOFTWARE_NAME10_1=() for i in "${!aSOFTWARE_NAME10_0[@]}" do aSOFTWARE_NAME10_1[i]=${aSOFTWARE_NAME10_0[i]} done aSOFTWARE_NAME10_1[214]='WhoDB' aSOFTWARE_NAME10_2=() for i in "${!aSOFTWARE_NAME10_1[@]}" do aSOFTWARE_NAME10_2[i]=${aSOFTWARE_NAME10_1[i]} done aSOFTWARE_NAME10_2[215]='Immich' aSOFTWARE_NAME10_2[216]='Immich Machine Learning' aSOFTWARE_NAME10_2[217]='uv' aSOFTWARE_NAME10_2[13]='RustDesk Client' # Pre-create software counter array so that we can see also software (available in newest version) with 0 installs for i in "${aSOFTWARE_NAME10_2[@]}" do aSOFTWARE[$i]=0 done # $1 = File name Process_File() { local file=$1 version branch device arch cpu_count distro autostart automated iface raspbian software_id software_name asoftware=() mmc local BENCH_VERSION BENCH_HW_MODEL BENCH_CPU BENCH_ROOTFS_WRITE BENCH_ROOTFS_READ BENCH_RAM_WRITE BENCH_RAM_READ BENCH_CUSTOMFS_WRITE BENCH_CUSTOMFS_READ BENCH_CPU_TEMP_START BENCH_CPU_TEMP_END BENCH_NET_LAN_SPEED while read -r line do # shellcheck disable=SC2016 case "$line" in '#!/bin/bash') :;; # Pre-v9.12 '# '*) :;; # Pre-v7.9 dietpi-benchmark executions '((aDIETPI_VERSION['+([[:digit:]]).+([[:digit:]])']++))') version=${line#*'['} version=${version%']'*};; '((aGIT_BRANCH['+([[:graph:]])']++))') branch=${line#*'['} branch=${branch%']'*};; '((aDEVICE_NAME['+([[:print:]])']++))') device=${line#*'['} device=${device%']'*};; '((aCPU_ARCH['+([[:graph:]])']++))') arch=${line#*'['} arch=${arch%']'*};; '((aCPU_COUNT['+([[:digit:]])']++))') cpu_count=${line#*'['} cpu_count=${cpu_count%']'*};; '((aDISTRO_VERSION['+([[:alpha:]])']++))') distro=${line#*'['} distro=${distro%']'*};; '((aAUTOSTART_OPTION[${aAUTOSTART_NAME['+([[:digit:]])']:='+([[:digit:]])'}]++))') autostart=${line##*'['} autostart=${autostart%%']'*};; '((aAUTO_SETUP_AUTOMATED['[01]']++))') automated=${line#*'['} automated=${automated%']'*};; '((aNETWORK_INTERFACE['+([[:graph:]])']++))') iface=${line#*'['} iface=${iface%']'*};; '((aRASPBIAN['[01]']++))') raspbian=${line#*'['} raspbian=${raspbian%']'*};; 'MMC='[01]) mmc=${line#*'='};; '((aSOFTWARE[${aSOFTWARE_NAME'${version/./_}'['+([[:digit:]])']:='+([[:digit:]])'}]++))') software_id=${line##*'['} software_id=${software_id%%']'*};; 'BENCH_VERSION='[12]) BENCH_VERSION=${line#*'='};; # 1 until v6.23, 2 afterwards 'BENCH_HW_MODEL='+([[:digit:]])) BENCH_HW_MODEL=${line#*'='};; 'BENCH_CPU='*) BENCH_CPU=${line#*\'} BENCH_CPU=${BENCH_CPU%\'};; 'BENCH_ROOTFS_WRITE='*) BENCH_ROOTFS_WRITE=${line#*\'} BENCH_ROOTFS_WRITE=${BENCH_ROOTFS_WRITE%\'};; 'BENCH_ROOTFS_READ='*) BENCH_ROOTFS_READ=${line#*\'} BENCH_ROOTFS_READ=${BENCH_ROOTFS_READ%\'};; 'BENCH_RAM_WRITE='*) BENCH_RAM_WRITE=${line#*\'} BENCH_RAM_WRITE=${BENCH_RAM_WRITE%\'};; 'BENCH_RAM_READ='*) BENCH_RAM_READ=${line#*\'} BENCH_RAM_READ=${BENCH_RAM_READ%\'};; 'BENCH_CUSTOMFS_WRITE='*) BENCH_CUSTOMFS_WRITE=${line#*\'} BENCH_CUSTOMFS_WRITE=${BENCH_CUSTOMFS_WRITE%\'};; 'BENCH_CUSTOMFS_READ='*) BENCH_CUSTOMFS_READ=${line#*\'} BENCH_CUSTOMFS_READ=${BENCH_CUSTOMFS_READ%\'};; 'BENCH_CPU_TEMP_START='*) BENCH_CPU_TEMP_START=${line#*\'} BENCH_CPU_TEMP_START=${BENCH_CPU_TEMP_START%\'};; 'BENCH_CPU_TEMP_END='*) BENCH_CPU_TEMP_END=${line#*\'} BENCH_CPU_TEMP_END=${BENCH_CPU_TEMP_END%\'};; 'BENCH_NET_LAN_SPEED='*) BENCH_NET_LAN_SPEED=${line#*\'} BENCH_NET_LAN_SPEED=${BENCH_NET_LAN_SPEED%\'};; *) echo "Invalid line: $line" mv -v "/home/dietpi-survey/survey/$file" /home/dietpi-survey/invalid/ return 1 ;; esac # Validate and process software name if present [[ $software_id ]] || continue eval "software_name=\${aSOFTWARE_NAME${version/./_}[$software_id]}" if [[ $software_name ]] then asoftware+=("$software_name") else echo "Invalid software ID \"$software_id\" for DietPi version $version - /home/dietpi-survey/survey/$file" #mv -v "/home/dietpi-survey/survey/$file" /home/dietpi-survey/invalid/ #return 1 fi unset -v software_id software_name done < "$file" # Values that must exist if ! [[ $version && $device && $arch && $cpu_count && $distro && $autostart && ${aAUTOSTART_NAME[$autostart]} && $automated && $iface ]] then echo 'Missing survey value' mv -v "/home/dietpi-survey/survey/$file" /home/dietpi-survey/invalid/ return 1 fi # Sort out files that are > 6 months old (( $DATE_NOW - $(date -u '+%s' -r "$file") < 15724800 )) || { mv "/home/dietpi-survey/survey/$file" /home/dietpi-survey/old/; ((SURVEY_COUNT_INACTIVE++)); return 0; } # Valid content ((SURVEY_COUNT_OPTIN++)) # Count re-activated systems which didn't show activity for at least 6 months but uploaded a new survey file if [[ -f /home/dietpi-survey/old/$file ]] then ((SURVEY_COUNT_REACTIVE++)) # Remove old file rm "/home/dietpi-survey/old/$file" fi # Add to global arrays ((aDIETPI_VERSION["$version"]++)) [[ $branch ]] && ((aGIT_BRANCH["$branch"]++)) ((aDEVICE_NAME["$device"]++)) ((aCPU_ARCH["$arch"]++)) ((aCPU_COUNT["$cpu_count"]++)) ((aDISTRO_VERSION["$distro"]++)) ((aAUTOSTART_OPTION[${aAUTOSTART_NAME["$autostart"]}]++)) ((aAUTO_SETUP_AUTOMATED["$automated"]++)) ((aNETWORK_INTERFACE["$iface"]++)) [[ $raspbian ]] && ((aRASPBIAN["$raspbian"]++)) [[ $mmc ]] && ((aMMC["$mmc"]++)) for i in "${asoftware[@]}" do ((aSOFTWARE[$i]++)) done # Process benchmark results if present, dietpi-benchmark v2, and hardware ID valid [[ $BENCH_VERSION == 2 ]] || return 0 [[ $BENCH_HW_MODEL =~ ^[0-9]+$ && ${aHW_NAME[$BENCH_HW_MODEL]} ]] || { echo "Invalid hardware ID: \"$BENCH_HW_MODEL\""; return 1; } # CPU if [[ $BENCH_CPU == *[1-9]* && $BENCH_CPU =~ ^[0-9]+\.[0-9]{2}$ ]] then # CPU time: Remove decimal point, equals times 100 since it's always in x.xx BENCH_CPU=${BENCH_CPU/.} # - Remove leading zeros to support machines with <1s CPU time: One case with 0.94s was just spotted. while [[ $BENCH_CPU == 0* ]]; do BENCH_CPU=${BENCH_CPU#0}; done aBENCH_CPU[$BENCH_HW_MODEL,${aBENCH_CPU_INDEX[$BENCH_HW_MODEL]:=0}]=$BENCH_CPU # CPU temps: Patch for millidegree: https://github.com/MichaIng/DietPi/issues/2715 if [[ $BENCH_CPU_TEMP_START =~ ^[0-9]+$ && $BENCH_CPU_TEMP_END =~ ^[0-9]+$ ]] then (( $BENCH_CPU_TEMP_START > 200 )) && (( BENCH_CPU_TEMP_START /= 1000 )) (( $BENCH_CPU_TEMP_END > 200 )) && (( BENCH_CPU_TEMP_END /= 1000 )) aBENCH_CPU_TEMP_START[$BENCH_HW_MODEL,${aBENCH_CPU_TEMP_INDEX[$BENCH_HW_MODEL]:=0}]=$BENCH_CPU_TEMP_START aBENCH_CPU_TEMP_END[$BENCH_HW_MODEL,${aBENCH_CPU_TEMP_INDEX[$BENCH_HW_MODEL]}]=$BENCH_CPU_TEMP_END ((aBENCH_CPU_TEMP_INDEX[$BENCH_HW_MODEL]++)) fi ((aBENCH_CPU_INDEX[$BENCH_HW_MODEL]++)) fi # RootFS if [[ $BENCH_ROOTFS_WRITE =~ ^[0-9]+$ && $BENCH_ROOTFS_READ =~ ^[0-9]+$ ]] then aBENCH_ROOTFS_WRITE[$BENCH_HW_MODEL,${aBENCH_ROOTFS_INDEX[$BENCH_HW_MODEL]:=0}]=$BENCH_ROOTFS_WRITE aBENCH_ROOTFS_READ[$BENCH_HW_MODEL,${aBENCH_ROOTFS_INDEX[$BENCH_HW_MODEL]}]=$BENCH_ROOTFS_READ ((aBENCH_ROOTFS_INDEX[$BENCH_HW_MODEL]++)) fi # RAM # - Skip results prior to DietPi-Benchmark v2 (DietPi v6.23): https://github.com/MichaIng/DietPi/issues/2715 if (( $BENCH_VERSION > 1 )) && [[ $BENCH_RAM_WRITE =~ ^[0-9]+$ && $BENCH_RAM_READ =~ ^[0-9]+$ ]] then aBENCH_RAM_WRITE[$BENCH_HW_MODEL,${aBENCH_RAM_INDEX[$BENCH_HW_MODEL]:=0}]=$BENCH_RAM_WRITE aBENCH_RAM_READ[$BENCH_HW_MODEL,${aBENCH_RAM_INDEX[$BENCH_HW_MODEL]}]=$BENCH_RAM_READ ((aBENCH_RAM_INDEX[$BENCH_HW_MODEL]++)) fi # Custom FS if [[ $BENCH_CUSTOMFS_WRITE =~ ^[0-9]+$ && $BENCH_CUSTOMFS_READ =~ ^[0-9]+$ ]] then aBENCH_CUSTOMFS_WRITE[$BENCH_HW_MODEL,${aBENCH_CUSTOMFS_INDEX[$BENCH_HW_MODEL]:=0}]=$BENCH_CUSTOMFS_WRITE aBENCH_CUSTOMFS_READ[$BENCH_HW_MODEL,${aBENCH_CUSTOMFS_INDEX[$BENCH_HW_MODEL]}]=$BENCH_CUSTOMFS_READ ((aBENCH_CUSTOMFS_INDEX[$BENCH_HW_MODEL]++)) fi # LAN if [[ $BENCH_NET_LAN_SPEED =~ ^[0-9]+$ ]] then aBENCH_NET_LAN_SPEED[$BENCH_HW_MODEL,${aBENCH_LAN_INDEX[$BENCH_HW_MODEL]:=0}]=$BENCH_NET_LAN_SPEED ((aBENCH_LAN_INDEX[$BENCH_HW_MODEL]++)) fi } Main() { # Copy files to RAM to speed up sourcing #mkdir -p /tmp/dietpi-survey_report #cp /home/dietpi-survey/survey/*.txt /tmp/dietpi-survey_report/ # cp: Argument list too long rm -Rf /tmp/dietpi-survey_report || exit 1 DATE_NOW=$(date -u '+%s') # Store date of last possible upload cp -a /home/dietpi-survey/survey /tmp/dietpi-survey_report || exit 1 cd /tmp/dietpi-survey_report || exit 1 # Loop through files, including dot files, so that we can detect and sort out invalid file names shopt -s dotglob for file in * do # Skip and move away match with invalid name or when not a file if ! [[ $file =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.txt$ && -f $file ]] then echo 'Invalid file name' mv -v "/home/dietpi-survey/survey/$file" /home/dietpi-survey/invalid/ continue fi # Optout files if [[ ! -s $file ]] then # Sort out files that are > 6 months old (( $DATE_NOW - $(date -u '+%s' -r "$file") < 15724800 )) || { mv "/home/dietpi-survey/survey/$file" /home/dietpi-survey/old/; ((SURVEY_COUNT_INACTIVE++)); continue; } ((SURVEY_COUNT_OPTOUT++)) # Count re-activated systems which didn't show activity for at least 6 months but uploaded a new survey file if [[ -f /home/dietpi-survey/old/$file ]] then ((SURVEY_COUNT_REACTIVE++)) # Remove old file rm "/home/dietpi-survey/old/$file" fi continue fi # Process file Process_File "$file" done shopt -u dotglob extglob # Navigate to parent /tmp cd /tmp || exit 1 # Clean up reports dir rm -R /tmp/dietpi-survey_report || exit 1 # Total count SURVEY_COUNT_TOTAL=$(( $SURVEY_COUNT_OPTOUT + $SURVEY_COUNT_OPTIN )) # Merge old and new hardware model names for i in "${!aDEVICE_NAME[@]}" do [[ $i == 'NanoPi M1/T1 (armv7l)' ]] && ((aDEVICE_NAME['NanoPi M1 (armv7l)']+=aDEVICE_NAME[$i])) && unset -v "aDEVICE_NAME[$i]" # v8.11 [[ $i == 'NanoPi R5S (aarch64)' ]] && ((aDEVICE_NAME['NanoPi R5S/R5C (aarch64)']+=aDEVICE_NAME[$i])) && unset -v "aDEVICE_NAME[$i]" # v8.13 [[ $i == 'NanoPi R6S (aarch64)' ]] && ((aDEVICE_NAME['NanoPi 6 series (aarch64)']+=aDEVICE_NAME[$i])) && unset -v "aDEVICE_NAME[$i]" # v8.17 [[ $i == 'ROCK Pi 4 (aarch64)' ]] && ((aDEVICE_NAME['ROCK 4 (aarch64)']+=aDEVICE_NAME[$i])) && unset -v "aDEVICE_NAME[$i]" # v8.17 [[ $i == 'NanoPi R6S/R6C (aarch64)' ]] && ((aDEVICE_NAME['NanoPi 6 series (aarch64)']+=aDEVICE_NAME[$i])) && unset -v "aDEVICE_NAME[$i]" # v8.19 done # Process all results, for later use in HTML printout # - NB: HW_MODEL array based # CPU for i in "${!aBENCH_CPU_INDEX[@]}" do aBENCH_RESULT_CPU_MIN[i]=${aBENCH_CPU[$i,0]} aBENCH_RESULT_CPU_MAX[i]=${aBENCH_CPU[$i,0]} aBENCH_RESULT_CPU_AVG[i]=0 # CPU time for (( j=0; j<${aBENCH_CPU_INDEX[i]}; j++ )) do (( ${aBENCH_CPU[$i,$j]} < ${aBENCH_RESULT_CPU_MIN[i]} )) && aBENCH_RESULT_CPU_MIN[i]=${aBENCH_CPU[$i,$j]} (( ${aBENCH_CPU[$i,$j]} > ${aBENCH_RESULT_CPU_MAX[i]} )) && aBENCH_RESULT_CPU_MAX[i]=${aBENCH_CPU[$i,$j]} (( aBENCH_RESULT_CPU_AVG[i] += ${aBENCH_CPU[$i,$j]} )) done # Work out averages # - Divide CPU times by 100 and scale to revert decimal point removal aBENCH_RESULT_CPU_MIN[i]=$(printf '%.2f' "${aBENCH_RESULT_CPU_MIN[i]}e-2") aBENCH_RESULT_CPU_MAX[i]=$(printf '%.2f' "${aBENCH_RESULT_CPU_MAX[i]}e-2") aBENCH_RESULT_CPU_AVG[i]=$(printf '%.2f' "$((${aBENCH_RESULT_CPU_AVG[i]}*10/${aBENCH_CPU_INDEX[i]}+1))e-3") # CPU temps if available aBENCH_RESULT_CPU_TEMP_START_MIN[i]='N/A' aBENCH_RESULT_CPU_TEMP_START_MAX[i]='N/A' aBENCH_RESULT_CPU_TEMP_START_AVG[i]='N/A' aBENCH_RESULT_CPU_TEMP_END_MIN[i]='N/A' aBENCH_RESULT_CPU_TEMP_END_MAX[i]='N/A' aBENCH_RESULT_CPU_TEMP_END_AVG[i]='N/A' (( ${aBENCH_CPU_TEMP_INDEX[i]} )) || continue aBENCH_RESULT_CPU_TEMP_START_MIN[i]=${aBENCH_CPU_TEMP_START[$i,0]} aBENCH_RESULT_CPU_TEMP_START_MAX[i]=${aBENCH_CPU_TEMP_START[$i,0]} aBENCH_RESULT_CPU_TEMP_START_AVG[i]=0 aBENCH_RESULT_CPU_TEMP_END_MIN[i]=${aBENCH_CPU_TEMP_END[$i,0]} aBENCH_RESULT_CPU_TEMP_END_MAX[i]=${aBENCH_CPU_TEMP_END[$i,0]} aBENCH_RESULT_CPU_TEMP_END_AVG[i]=0 for (( j=0; j<${aBENCH_CPU_TEMP_INDEX[i]}; j++ )) do (( ${aBENCH_CPU_TEMP_START[$i,$j]} < ${aBENCH_RESULT_CPU_TEMP_START_MIN[i]} )) && aBENCH_RESULT_CPU_TEMP_START_MIN[i]=${aBENCH_CPU_TEMP_START[$i,$j]} (( ${aBENCH_CPU_TEMP_START[$i,$j]} > ${aBENCH_RESULT_CPU_TEMP_START_MAX[i]} )) && aBENCH_RESULT_CPU_TEMP_START_MAX[i]=${aBENCH_CPU_TEMP_START[$i,$j]} (( aBENCH_RESULT_CPU_TEMP_START_AVG[i] += ${aBENCH_CPU_TEMP_START[$i,$j]} )) (( ${aBENCH_CPU_TEMP_END[$i,$j]} < ${aBENCH_RESULT_CPU_TEMP_END_MIN[i]} )) && aBENCH_RESULT_CPU_TEMP_END_MIN[i]=${aBENCH_CPU_TEMP_END[$i,$j]} (( ${aBENCH_CPU_TEMP_END[$i,$j]} > ${aBENCH_RESULT_CPU_TEMP_END_MAX[i]} )) && aBENCH_RESULT_CPU_TEMP_END_MAX[i]=${aBENCH_CPU_TEMP_END[$i,$j]} (( aBENCH_RESULT_CPU_TEMP_END_AVG[i] += ${aBENCH_CPU_TEMP_END[$i,$j]} )) done # Work out averages aBENCH_RESULT_CPU_TEMP_START_AVG[i]=$(( ${aBENCH_RESULT_CPU_TEMP_START_AVG[i]} / ${aBENCH_CPU_TEMP_INDEX[i]} )) aBENCH_RESULT_CPU_TEMP_END_AVG[i]=$(( ${aBENCH_RESULT_CPU_TEMP_END_AVG[i]} / ${aBENCH_CPU_TEMP_INDEX[i]} )) done # RootFS for i in "${!aBENCH_ROOTFS_INDEX[@]}" do aBENCH_RESULT_ROOTFS_WRITE_MIN[i]=${aBENCH_ROOTFS_WRITE[$i,0]} aBENCH_RESULT_ROOTFS_WRITE_MAX[i]=${aBENCH_ROOTFS_WRITE[$i,0]} aBENCH_RESULT_ROOTFS_WRITE_AVG[i]=0 aBENCH_RESULT_ROOTFS_READ_MIN[i]=${aBENCH_ROOTFS_READ[$i,0]} aBENCH_RESULT_ROOTFS_READ_MAX[i]=${aBENCH_ROOTFS_READ[$i,0]} aBENCH_RESULT_ROOTFS_READ_AVG[i]=0 for (( j=0; j<${aBENCH_ROOTFS_INDEX[i]}; j++ )) do (( ${aBENCH_ROOTFS_WRITE[$i,$j]} < ${aBENCH_RESULT_ROOTFS_WRITE_MIN[i]} )) && aBENCH_RESULT_ROOTFS_WRITE_MIN[i]=${aBENCH_ROOTFS_WRITE[$i,$j]} (( ${aBENCH_ROOTFS_WRITE[$i,$j]} > ${aBENCH_RESULT_ROOTFS_WRITE_MAX[i]} )) && aBENCH_RESULT_ROOTFS_WRITE_MAX[i]=${aBENCH_ROOTFS_WRITE[$i,$j]} (( aBENCH_RESULT_ROOTFS_WRITE_AVG[i] += ${aBENCH_ROOTFS_WRITE[$i,$j]} )) (( ${aBENCH_ROOTFS_READ[$i,$j]} < ${aBENCH_RESULT_ROOTFS_READ_MIN[i]} )) && aBENCH_RESULT_ROOTFS_READ_MIN[i]=${aBENCH_ROOTFS_READ[$i,$j]} (( ${aBENCH_ROOTFS_READ[$i,$j]} > ${aBENCH_RESULT_ROOTFS_READ_MAX[i]} )) && aBENCH_RESULT_ROOTFS_READ_MAX[i]=${aBENCH_ROOTFS_READ[$i,$j]} (( aBENCH_RESULT_ROOTFS_READ_AVG[i] += ${aBENCH_ROOTFS_READ[$i,$j]} )) done # Work out averages aBENCH_RESULT_ROOTFS_WRITE_AVG[i]=$(( ${aBENCH_RESULT_ROOTFS_WRITE_AVG[i]} / ${aBENCH_ROOTFS_INDEX[i]} )) aBENCH_RESULT_ROOTFS_READ_AVG[i]=$(( ${aBENCH_RESULT_ROOTFS_READ_AVG[i]} / ${aBENCH_ROOTFS_INDEX[i]} )) done # RAM for i in "${!aBENCH_RAM_INDEX[@]}" do aBENCH_RESULT_RAM_WRITE_MIN[i]=${aBENCH_RAM_WRITE[$i,0]} aBENCH_RESULT_RAM_WRITE_MAX[i]=${aBENCH_RAM_WRITE[$i,0]} aBENCH_RESULT_RAM_WRITE_AVG[i]=0 aBENCH_RESULT_RAM_READ_MIN[i]=${aBENCH_RAM_READ[$i,0]} aBENCH_RESULT_RAM_READ_MAX[i]=${aBENCH_RAM_READ[$i,0]} aBENCH_RESULT_RAM_READ_AVG[i]=0 for (( j=0; j<${aBENCH_RAM_INDEX[i]}; j++ )) do (( ${aBENCH_RAM_WRITE[$i,$j]} < ${aBENCH_RESULT_RAM_WRITE_MIN[i]} )) && aBENCH_RESULT_RAM_WRITE_MIN[i]=${aBENCH_RAM_WRITE[$i,$j]} (( ${aBENCH_RAM_WRITE[$i,$j]} > ${aBENCH_RESULT_RAM_WRITE_MAX[i]} )) && aBENCH_RESULT_RAM_WRITE_MAX[i]=${aBENCH_RAM_WRITE[$i,$j]} (( aBENCH_RESULT_RAM_WRITE_AVG[i] += ${aBENCH_RAM_WRITE[$i,$j]} )) (( ${aBENCH_RAM_READ[$i,$j]} < ${aBENCH_RESULT_RAM_READ_MIN[i]} )) && aBENCH_RESULT_RAM_READ_MIN[i]=${aBENCH_RAM_READ[$i,$j]} (( ${aBENCH_RAM_READ[$i,$j]} > ${aBENCH_RESULT_RAM_READ_MAX[i]} )) && aBENCH_RESULT_RAM_READ_MAX[i]=${aBENCH_RAM_READ[$i,$j]} (( aBENCH_RESULT_RAM_READ_AVG[i] += ${aBENCH_RAM_READ[$i,$j]} )) done # Work out averages aBENCH_RESULT_RAM_WRITE_AVG[i]=$(( ${aBENCH_RESULT_RAM_WRITE_AVG[i]} / ${aBENCH_RAM_INDEX[i]} )) aBENCH_RESULT_RAM_READ_AVG[i]=$(( ${aBENCH_RESULT_RAM_READ_AVG[i]} / ${aBENCH_RAM_INDEX[i]} )) done # LAN for i in "${!aBENCH_LAN_INDEX[@]}" do aBENCH_RESULT_NET_LAN_SPEED_MIN[i]=${aBENCH_NET_LAN_SPEED[$i,0]} aBENCH_RESULT_NET_LAN_SPEED_MAX[i]=${aBENCH_NET_LAN_SPEED[$i,0]} aBENCH_RESULT_NET_LAN_SPEED_AVG[i]=0 for (( j=0; j<${aBENCH_LAN_INDEX[i]}; j++ )) do (( ${aBENCH_NET_LAN_SPEED[$i,$j]} < ${aBENCH_RESULT_NET_LAN_SPEED_MIN[i]} )) && aBENCH_RESULT_NET_LAN_SPEED_MIN[i]=${aBENCH_NET_LAN_SPEED[$i,$j]} (( ${aBENCH_NET_LAN_SPEED[$i,$j]} > ${aBENCH_RESULT_NET_LAN_SPEED_MAX[i]} )) && aBENCH_RESULT_NET_LAN_SPEED_MAX[i]=${aBENCH_NET_LAN_SPEED[$i,$j]} (( aBENCH_RESULT_NET_LAN_SPEED_AVG[i] += ${aBENCH_NET_LAN_SPEED[$i,$j]} )) done # Work out averages aBENCH_RESULT_NET_LAN_SPEED_AVG[i]=$(( ${aBENCH_RESULT_NET_LAN_SPEED_AVG[i]} / ${aBENCH_LAN_INDEX[i]} )) done # Custom FS for i in "${!aBENCH_CUSTOMFS_INDEX[@]}" do aBENCH_RESULT_CUSTOMFS_WRITE_MIN[i]=${aBENCH_CUSTOMFS_WRITE[$i,0]} aBENCH_RESULT_CUSTOMFS_WRITE_MAX[i]=${aBENCH_CUSTOMFS_WRITE[$i,0]} aBENCH_RESULT_CUSTOMFS_WRITE_AVG[i]=0 aBENCH_RESULT_CUSTOMFS_READ_MIN[i]=${aBENCH_CUSTOMFS_READ[$i,0]} aBENCH_RESULT_CUSTOMFS_READ_MAX[i]=${aBENCH_CUSTOMFS_READ[$i,0]} aBENCH_RESULT_CUSTOMFS_READ_AVG[i]=0 for (( j=0; j<${aBENCH_CUSTOMFS_INDEX[i]}; j++ )) do (( ${aBENCH_CUSTOMFS_WRITE[$i,$j]} < ${aBENCH_RESULT_CUSTOMFS_WRITE_MIN[i]} )) && aBENCH_RESULT_CUSTOMFS_WRITE_MIN[i]=${aBENCH_CUSTOMFS_WRITE[$i,$j]} (( ${aBENCH_CUSTOMFS_WRITE[$i,$j]} > ${aBENCH_RESULT_CUSTOMFS_WRITE_MAX[i]} )) && aBENCH_RESULT_CUSTOMFS_WRITE_MAX[i]=${aBENCH_CUSTOMFS_WRITE[$i,$j]} (( aBENCH_RESULT_CUSTOMFS_WRITE_AVG[i] += ${aBENCH_CUSTOMFS_WRITE[$i,$j]} )) (( ${aBENCH_CUSTOMFS_READ[$i,$j]} < ${aBENCH_RESULT_CUSTOMFS_READ_MIN[i]} )) && aBENCH_RESULT_CUSTOMFS_READ_MIN[i]=${aBENCH_CUSTOMFS_READ[$i,$j]} (( ${aBENCH_CUSTOMFS_READ[$i,$j]} > ${aBENCH_RESULT_CUSTOMFS_READ_MAX[i]} )) && aBENCH_RESULT_CUSTOMFS_READ_MAX[i]=${aBENCH_CUSTOMFS_READ[$i,$j]} (( aBENCH_RESULT_CUSTOMFS_READ_AVG[i] += ${aBENCH_CUSTOMFS_READ[$i,$j]} )) done # Work out averages aBENCH_RESULT_CUSTOMFS_WRITE_AVG[i]=$(( ${aBENCH_RESULT_CUSTOMFS_WRITE_AVG[i]} / ${aBENCH_CUSTOMFS_INDEX[i]} )) aBENCH_RESULT_CUSTOMFS_READ_AVG[i]=$(( ${aBENCH_RESULT_CUSTOMFS_READ_AVG[i]} / ${aBENCH_CUSTOMFS_INDEX[i]} )) done # Create HTML file cat << _EOF_ > index.html DietPi-Survey statistics

DietPi-Survey statistics

Below data is based on DietPi systems which have shown activity between $(date -u -d "@$(( $DATE_NOW - 15724800 ))" '+%Y-%m-%d') and $(date -u -d "@$DATE_NOW" '+%Y-%m-%d %T %Z'), i.e. either did a dietpi-update or a dietpi-software installation.

Total system count$SURVEY_COUNT_TOTAL
Systems sending survey data$SURVEY_COUNT_OPTIN$(( $SURVEY_COUNT_OPTIN * 100 / $SURVEY_COUNT_TOTAL ))%
Systems opted out DietPi-Survey$SURVEY_COUNT_OPTOUT$(( $SURVEY_COUNT_OPTOUT * 100 / $SURVEY_COUNT_TOTAL ))%

DietPi versions ¶

$(for i in "${!aDIETPI_VERSION[@]}"; do echo ""; done | sort -Vr)
DietPi v$i${aDIETPI_VERSION[$i]}$(( ${aDIETPI_VERSION[$i]} * 100 / $SURVEY_COUNT_OPTIN ))%

Git branches ¶

$(for i in "${!aGIT_BRANCH[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
$i ${aGIT_BRANCH[$i]}$(( ${aGIT_BRANCH[$i]} * 100 / $SURVEY_COUNT_OPTIN ))%

Devices ¶

$(for i in "${!aDEVICE_NAME[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
$i ${aDEVICE_NAME[$i]}$(( ${aDEVICE_NAME[$i]} * 100 / $SURVEY_COUNT_OPTIN ))%

CPU architectures ¶

$(for i in "${!aCPU_ARCH[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
$i ${aCPU_ARCH[$i]}$(( ${aCPU_ARCH[$i]} * 100 / $SURVEY_COUNT_OPTIN ))%

CPU core counts ¶

$(for i in "${!aCPU_COUNT[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
$i Core(s) ${aCPU_COUNT[i]}$(( ${aCPU_COUNT[i]} * 100 / $SURVEY_COUNT_OPTIN ))%

Distro versions ¶

$(for i in "${!aDISTRO_VERSION[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
$i ${aDISTRO_VERSION[$i]}$(( ${aDISTRO_VERSION[$i]} * 100 / $SURVEY_COUNT_OPTIN ))%

RPi Debian vs Raspbian ¶

Debian is used by${aRASPBIAN[0]} of $(( ${aRASPBIAN[0]} + ${aRASPBIAN[1]} )) RPi systems$(( ${aRASPBIAN[0]} * 100 / ( ${aRASPBIAN[0]} + ${aRASPBIAN[1]} ) ))%

SD card/eMMC used ¶

SD card or eMMC used as rootfs by${aMMC[1]} of $(( ${aMMC[0]} + ${aMMC[1]} )) systems$(( ${aMMC[1]} * 100 / ( ${aMMC[0]} + ${aMMC[1]} ) ))%

Autostart options ¶

$(for i in "${!aAUTOSTART_OPTION[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
$i ${aAUTOSTART_OPTION[$i]}$(( ${aAUTOSTART_OPTION[$i]} * 100 / $SURVEY_COUNT_OPTIN ))%

DietPi-Automation ¶

Used by${aAUTO_SETUP_AUTOMATED[1]} of $SURVEY_COUNT_OPTIN systems$(( ${aAUTO_SETUP_AUTOMATED[1]} * 100 / $SURVEY_COUNT_OPTIN ))%

Network interfaces ¶

$(for i in "${!aNETWORK_INTERFACE[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
$i ${aNETWORK_INTERFACE[$i]}$(( ${aNETWORK_INTERFACE[$i]} * 100 / $SURVEY_COUNT_OPTIN ))%

Installed software titles ¶

$(for i in "${!aSOFTWARE[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
$i ${aSOFTWARE[$i]}$(( ${aSOFTWARE[$i]} * 100 / $SURVEY_COUNT_OPTIN ))%

DietPi-Benchmarks | CPU ¶

$(for i in "${!aBENCH_CPU_INDEX[@]}"; do echo ""; done | sort -nk 2 -t ' ')
CPU time (seconds, lower is faster) CPU idle temp [°C] CPU load temp [°C]
Device Count Average Fastest Slowest Average Lowest Highest Average Lowest Highest
${aHW_NAME[i]}${aBENCH_CPU_INDEX[i]} ${aBENCH_RESULT_CPU_AVG[i]}${aBENCH_RESULT_CPU_MIN[i]}${aBENCH_RESULT_CPU_MAX[i]}${aBENCH_RESULT_CPU_TEMP_START_AVG[i]}${aBENCH_RESULT_CPU_TEMP_START_MIN[i]}${aBENCH_RESULT_CPU_TEMP_START_MAX[i]}${aBENCH_RESULT_CPU_TEMP_END_AVG[i]}${aBENCH_RESULT_CPU_TEMP_END_MIN[i]}${aBENCH_RESULT_CPU_TEMP_END_MAX[i]}

DietPi-Benchmarks | RAM I/O ¶

$(for i in "${!aBENCH_RAM_INDEX[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
RAM write [MiB/s] RAM read [MiB/s]
Device Count Average Fastest Slowest Average Fastest Slowest
${aHW_NAME[i]}${aBENCH_RAM_INDEX[i]} ${aBENCH_RESULT_RAM_WRITE_AVG[i]}${aBENCH_RESULT_RAM_WRITE_MAX[i]}${aBENCH_RESULT_RAM_WRITE_MIN[i]}${aBENCH_RESULT_RAM_READ_AVG[i]}${aBENCH_RESULT_RAM_READ_MAX[i]}${aBENCH_RESULT_RAM_READ_MIN[i]}

DietPi-Benchmarks | RootFS I/O ¶

$(for i in "${!aBENCH_ROOTFS_INDEX[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
RootFS write [MiB/s] RootFS read [MiB/s]
Device Count Average Fastest Slowest Average Fastest Slowest
${aHW_NAME[i]}${aBENCH_ROOTFS_INDEX[i]} ${aBENCH_RESULT_ROOTFS_WRITE_AVG[i]}${aBENCH_RESULT_ROOTFS_WRITE_MAX[i]}${aBENCH_RESULT_ROOTFS_WRITE_MIN[i]}${aBENCH_RESULT_ROOTFS_READ_AVG[i]}${aBENCH_RESULT_ROOTFS_READ_MAX[i]}${aBENCH_RESULT_ROOTFS_READ_MIN[i]}

DietPi-Benchmarks | Custom FS I/O ¶

$(for i in "${!aBENCH_CUSTOMFS_INDEX[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
Custom FS write [MiB/s] Custom FS read [MiB/s]
Device Count Average Fastest Slowest Average Fastest Slowest
${aHW_NAME[i]}${aBENCH_CUSTOMFS_INDEX[i]} ${aBENCH_RESULT_CUSTOMFS_WRITE_AVG[i]}${aBENCH_RESULT_CUSTOMFS_WRITE_MAX[i]}${aBENCH_RESULT_CUSTOMFS_WRITE_MIN[i]}${aBENCH_RESULT_CUSTOMFS_READ_AVG[i]}${aBENCH_RESULT_CUSTOMFS_READ_MAX[i]}${aBENCH_RESULT_CUSTOMFS_READ_MIN[i]}

DietPi-Benchmarks | LAN I/O ¶

$(for i in "${!aBENCH_LAN_INDEX[@]}"; do echo ""; done | sort -nrk 2 -t ' ')
Transfer rate [MiB/s]
Device Count Average Fastest Slowest
${aHW_NAME[i]}${aBENCH_LAN_INDEX[i]} ${aBENCH_RESULT_NET_LAN_SPEED_AVG[i]}${aBENCH_RESULT_NET_LAN_SPEED_MAX[i]}${aBENCH_RESULT_NET_LAN_SPEED_MIN[i]}
_EOF_ # Move HTML page in place mv index.html /var/www/survey/index.html # Get current total system count and calculate new system count local total=$(influx -database 'survey' -execute 'select total from systems order by desc limit 1' | mawk 'END{print $2}') local new=$(( $SURVEY_COUNT_TOTAL - $total + $SURVEY_COUNT_INACTIVE - $SURVEY_COUNT_REACTIVE )) # Create InfluxDB query query=("insert systems total=$SURVEY_COUNT_TOTAL") query+=("insert systems optin=$SURVEY_COUNT_OPTIN") query+=("insert systems optout=$SURVEY_COUNT_OPTOUT") query+=("insert systems inactive=$SURVEY_COUNT_INACTIVE") query+=("insert systems reactive=$SURVEY_COUNT_REACTIVE") query+=("insert systems new=$new") for i in "${!aDIETPI_VERSION[@]}" do query+=("insert version $i=${aDIETPI_VERSION[$i]}") done for i in "${!aGIT_BRANCH[@]}" do query+=("insert branch $i=${aGIT_BRANCH[$i]}") done for i in "${!aDISTRO_VERSION[@]}" do query+=("insert distro $i=${aDISTRO_VERSION[$i]}") done for i in "${!aDEVICE_NAME[@]}" do query+=("insert device ${i// /_}=${aDEVICE_NAME[$i]}") done for i in "${!aCPU_ARCH[@]}" do query+=("insert arch $i=${aCPU_ARCH[$i]}") done for i in "${!aCPU_COUNT[@]}" do query+=("insert cores $i=${aCPU_COUNT[i]}") done query+=("insert raspbian raspbian=${aRASPBIAN[1]}") query+=("insert raspbian debian=${aRASPBIAN[0]}") for i in "${!aAUTOSTART_OPTION[@]}" do query+=("insert autostart ${i// /_}=${aAUTOSTART_OPTION[$i]}") done query+=("insert automation enabled=${aAUTO_SETUP_AUTOMATED[1]}") query+=("insert automation disabled=${aAUTO_SETUP_AUTOMATED[0]}") query+=("insert mmc yes=${aMMC[1]}") query+=("insert mmc no=${aMMC[0]}") for i in "${!aNETWORK_INTERFACE[@]}" do query+=("insert network $i=${aNETWORK_INTERFACE[$i]}") done for i in "${!aSOFTWARE[@]}" do query+=("insert software ${i// /_}=${aSOFTWARE[$i]}") done # Write to InfluxDB influx -database 'survey' -precision 'h' -execute "$(printf '%s\n' "${query[@]}")" } #----------------------------------------------------------- # Main #----------------------------------------------------------- Main #----------------------------------------------------------- exit 0 #----------------------------------------------------------- } &>> /var/log/dietpi-survey_report.log