#!/bin/bash do { #//////////////////////////////////// # DietPi Process Tool # #//////////////////////////////////// # Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com # #//////////////////////////////////// # # Info: # - Menu system that allows users to configure and set system wide process/program attributes: Nice, Affinity, Scheduler Policy/Priority. # - Called from /DietPi/dietpi/dietpi-services start (eg: after all installed dietpi-software has been started) # # Usage: # dietpi-process_tool 0/no input = Menu # dietpi-process_tool 1 = Apply #//////////////////////////////////// #Grab Input setglobal INPUT = '0' if [[ $1 =~ ^-?[0-9]+$ ]] { setglobal INPUT = $1 } #Import DietPi-Globals --------------------------------------------------------------- source /DietPi/dietpi/func/dietpi-globals G_CHECK_ROOT_USER export G_PROGRAM_NAME='DietPi-Process_tool' #Import DietPi-Globals --------------------------------------------------------------- #///////////////////////////////////////////////////////////////////////////////////// # Globals #///////////////////////////////////////////////////////////////////////////////////// setglobal EXIT_CODE = '0' setglobal MAX_PROGRAMS = '0' setglobal aNICE = ''() setglobal aAFFINITY = ''() setglobal aSCHEDULE_POLICY = ''() setglobal aSCHEDULE_PRIORITY = ''() setglobal aPID = ''() setglobal aNAME = ''() setglobal aPROCESS_NAME = ''() setglobal aAVAILABLE = ''() setglobal aSCHEDULE_AVAILABLE_POLICY = ''() setglobal aSCHEDULE_AVAILABLE_PRIORITY_MIN = ''() setglobal aSCHEDULE_AVAILABLE_PRIORITY_MAX = ''() setglobal MAX_SCHEDULE_POLICIES = '0' proc Apply_Process_Tool{ G_DIETPI-NOTIFY 3 DietPi-Process_Tool Apply var status_text = ''"" var status_text_ok = $[G_DIETPI-NOTIFY 0] var status_text_failed = $[G_DIETPI-NOTIFY 1] for ((i=0; i<$MAX_PROGRAMS; i++)) do if (( ${aAVAILABLE[$i]} == 1 )); then # - Find all processes with target name cat "$FP_PS_LIST" | grep "${aPROCESS_NAME[$i]}" | awk '{print $1}' > "$FP_TEMP" while read -r line do #Obtain PID aPID[$i]=$line #info echo -e "${aNAME[$i]} (${aPID[$i]})" # - Check if PID exists (this can occur with programs like netdata that run as root initally, create a new process under a different user, then terminate the original root process. if (( ! $( ps ax | awk '{print $1}' | grep -ci -m1 "${aPID[$i]}") )); then G_DIETPI-NOTIFY 2 PID "${aPID[$i]}" no longer exists else # - nice renice -n ${aNICE[$i]} ${aPID[$i]} &> /dev/null if (( $? == 0 )); then status_text=$status_text_ok else status_text=$status_text_failed EXIT_CODE=1 fi status_text+="\e[90mNice ${aNICE[$i]}\e[0m" echo -e "$status_text" # - Affinity taskset -pc ${aAFFINITY[$i]} ${aPID[$i]} &> /dev/null if (( $? == 0 )); then status_text=$status_text_ok else status_text=$status_text_failed EXIT_CODE=2 fi status_text+="\e[90mAffinity ${aAFFINITY[$i]}\e[0m" echo -e "$status_text" # - schedule # -- Match scheduler policy to array list of available for ((j=0; j<$MAX_SCHEDULE_POLICIES; j++)) do if [ "${aSCHEDULE_POLICY[$i]}" = "${aSCHEDULE_AVAILABLE_POLICY[$j]}" ]; then # -- cap to min/max against array of available if (( ${aSCHEDULE_PRIORITY[$i]} < ${aSCHEDULE_AVAILABLE_PRIORITY_MIN[$j]} )) || (( ${aSCHEDULE_PRIORITY[$i]} > ${aSCHEDULE_AVAILABLE_PRIORITY_MAX[$j]} )); then aSCHEDULE_PRIORITY[$i]=${aSCHEDULE_AVAILABLE_PRIORITY_MIN[$j]} fi break fi done local chrt_mode='' if [ "${aSCHEDULE_POLICY[$i]}" = "SCHED_OTHER" ]; then chrt_mode='-o' elif [ "${aSCHEDULE_POLICY[$i]}" = "SCHED_FIFO" ]; then chrt_mode='-f' elif [ "${aSCHEDULE_POLICY[$i]}" = "SCHED_RR" ]; then chrt_mode='-r' elif [ "${aSCHEDULE_POLICY[$i]}" = "SCHED_BATCH" ]; then chrt_mode='-b' elif [ "${aSCHEDULE_POLICY[$i]}" = "SCHED_IDLE" ]; then chrt_mode='-i' fi # - Apply chrt $chrt_mode -p ${aSCHEDULE_PRIORITY[$i]} ${aPID[$i]} &> /dev/null if (( $? == 0 )); then status_text=$status_text_ok else status_text=$status_text_failed EXIT_CODE=3 fi status_text+="\e[90mScheduler ${aSCHEDULE_POLICY[$i]} ${aSCHEDULE_PRIORITY[$i]}\e[0m" echo -e "$status_text" fi done < "$FP_TEMP" rm "$FP_TEMP" fi done echo -e "" } #///////////////////////////////////////////////////////////////////////////////////// # Init #///////////////////////////////////////////////////////////////////////////////////// proc Init{ #-------------------------------------------------------------------------------- #Init array var index = '0' aNAME[$index]='Aria2';aPROCESS_NAME[$index]='aria2c';sh-expr 'index++' aNAME[$index]='Avahi Daemon';aPROCESS_NAME[$index]='avahi-daemon';sh-expr 'index++' aNAME[$index]='Bluetooth (Service)';aPROCESS_NAME[$index]='bluetooth';sh-expr 'index++' aNAME[$index]='Bluetooth (Hciuart)';aPROCESS_NAME[$index]='hciattach';sh-expr 'index++' aNAME[$index]='Blynk Server';aPROCESS_NAME[$index]='blynkserver';sh-expr 'index++' aNAME[$index]='BruteFIR';aPROCESS_NAME[$index]='brutefir';sh-expr 'index++' aNAME[$index]='CAVA';aPROCESS_NAME[$index]='cava';sh-expr 'index++' aNAME[$index]='Cuberite';aPROCESS_NAME[$index]='Cuberite';sh-expr 'index++' aNAME[$index]='CloudPrint';aPROCESS_NAME[$index]='cloudprintd';sh-expr 'index++' aNAME[$index]='CouchPotato';aPROCESS_NAME[$index]='CouchPotato.py';sh-expr 'index++' aNAME[$index]='Cron';aPROCESS_NAME[$index]='cron';sh-expr 'index++' aNAME[$index]='CUPS';aPROCESS_NAME[$index]='cupsd';sh-expr 'index++' aNAME[$index]='DarkIce';aPROCESS_NAME[$index]='darkice';sh-expr 'index++' aNAME[$index]='Deluge (Daemon)';aPROCESS_NAME[$index]='deluged';sh-expr 'index++' aNAME[$index]='Deluge (Web interface)';aPROCESS_NAME[$index]='deluge-web';sh-expr 'index++' aNAME[$index]='DHCP Client';aPROCESS_NAME[$index]='dhclient';sh-expr 'index++' aNAME[$index]='DHCP Server';aPROCESS_NAME[$index]='dhcpd';sh-expr 'index++' aNAME[$index]='Docker';aPROCESS_NAME[$index]='docker';sh-expr 'index++' aNAME[$index]='Dropbear';aPROCESS_NAME[$index]='dropbear';sh-expr 'index++' aNAME[$index]='Emby Server';aPROCESS_NAME[$index]='emby-server';sh-expr 'index++' aNAME[$index]='EmonHUB';aPROCESS_NAME[$index]='emonhub';sh-expr 'index++' aNAME[$index]='Fail2Ban';aPROCESS_NAME[$index]='fail2ban-server';sh-expr 'index++' aNAME[$index]='FuguHub';aPROCESS_NAME[$index]='bdd';sh-expr 'index++' aNAME[$index]='Gitea';aPROCESS_NAME[$index]='gitea';sh-expr 'index++' aNAME[$index]='Gogs';aPROCESS_NAME[$index]='gogs';sh-expr 'index++' aNAME[$index]='Google AIY';aPROCESS_NAME[$index]='main.py';sh-expr 'index++' aNAME[$index]='Gmediarender';aPROCESS_NAME[$index]='gmediarender';sh-expr 'index++' aNAME[$index]='Home Assistant';aPROCESS_NAME[$index]='hass';sh-expr 'index++' aNAME[$index]='HTPC Manager';aPROCESS_NAME[$index]='Htpc.py';sh-expr 'index++' aNAME[$index]='IceCast';aPROCESS_NAME[$index]='icecast2';sh-expr 'index++' aNAME[$index]='MPD';aPROCESS_NAME[$index]='bin/mpd';sh-expr 'index++' #Tomcat8 triggers 'mpd' aNAME[$index]='YMPD (HiFi)';aPROCESS_NAME[$index]='ympd';sh-expr 'index++' aNAME[$index]='Jackett';aPROCESS_NAME[$index]='JackettConsole.exe';sh-expr 'index++' aNAME[$index]='Jack Server';aPROCESS_NAME[$index]='jackd';sh-expr 'index++' aNAME[$index]='Jconvolver';aPROCESS_NAME[$index]='jconvolver';sh-expr 'index++' aNAME[$index]='Minio';aPROCESS_NAME[$index]='minio';sh-expr 'index++' aNAME[$index]='MiniDLNA';aPROCESS_NAME[$index]='minidlna';sh-expr 'index++' #aNAME[$index]='moOde (worker.php)';aPROCESS_NAME[$index]='worker.php';((index++)) aNAME[$index]='Mopidy';aPROCESS_NAME[$index]='mopidy';sh-expr 'index++' aNAME[$index]='Mosquitto';aPROCESS_NAME[$index]='mosquitto';sh-expr 'index++' aNAME[$index]='MotionEye';aPROCESS_NAME[$index]='motioneye';sh-expr 'index++' aNAME[$index]='Mumble Server';aPROCESS_NAME[$index]='murmurd';sh-expr 'index++' aNAME[$index]='NAA Daemon';aPROCESS_NAME[$index]='networkaudiod';sh-expr 'index++' aNAME[$index]='NetData';aPROCESS_NAME[$index]='netdata';sh-expr 'index++' aNAME[$index]='Nukkit';aPROCESS_NAME[$index]='nukkit.jar';sh-expr 'index++' aNAME[$index]='Node-Red';aPROCESS_NAME[$index]='node-red';sh-expr 'index++' aNAME[$index]='NoIp';aPROCESS_NAME[$index]='noip2';sh-expr 'index++' aNAME[$index]='NZBget';aPROCESS_NAME[$index]='nzbget';sh-expr 'index++' aNAME[$index]='OctoPrint';aPROCESS_NAME[$index]='octoprint';sh-expr 'index++' aNAME[$index]='OpenBazaar';aPROCESS_NAME[$index]='openbazaard.py';sh-expr 'index++' aNAME[$index]='Open Media Vault';aPROCESS_NAME[$index]='omv-engined';sh-expr 'index++' aNAME[$index]='OpenSSH Server';aPROCESS_NAME[$index]='sshd';sh-expr 'index++' aNAME[$index]='OpenVPN Server';aPROCESS_NAME[$index]='openvpn';sh-expr 'index++' aNAME[$index]='Pi-SPC';aPROCESS_NAME[$index]='sds.sh';sh-expr 'index++' aNAME[$index]='Pi-hole';aPROCESS_NAME[$index]='dnsmasq';sh-expr 'index++' aNAME[$index]='Pi-hole FTL';aPROCESS_NAME[$index]='pihole-FTL';sh-expr 'index++' aNAME[$index]='ProFTP';aPROCESS_NAME[$index]='proftpd';sh-expr 'index++' aNAME[$index]='qBitTorrent';aPROCESS_NAME[$index]='qbittorrent-nox';sh-expr 'index++' aNAME[$index]='Radarr';aPROCESS_NAME[$index]='Radarr.exe';sh-expr 'index++' aNAME[$index]='Raspotify';aPROCESS_NAME[$index]='librespot';sh-expr 'index++' aNAME[$index]='RoonBridge';aPROCESS_NAME[$index]='RoonBridge';sh-expr 'index++' aNAME[$index]='RoonBridge (Helper)';aPROCESS_NAME[$index]='RoonBridgeHelper';sh-expr 'index++' aNAME[$index]='RoonBridge/Server (RAATServer)';aPROCESS_NAME[$index]='RAATServer';sh-expr 'index++' aNAME[$index]='RoonBridge/Server (Appliance)';aPROCESS_NAME[$index]='RoonAppliance';sh-expr 'index++' aNAME[$index]='RoonServer';aPROCESS_NAME[$index]='RoonServer';sh-expr 'index++' aNAME[$index]='rTorrent';aPROCESS_NAME[$index]='rtorrent';sh-expr 'index++' aNAME[$index]='SABnzbd';aPROCESS_NAME[$index]='SABnzbd.py';sh-expr 'index++' aNAME[$index]='Samba Server (Daemon)';aPROCESS_NAME[$index]='smbd';sh-expr 'index++' aNAME[$index]='Samba Server (NetBios)';aPROCESS_NAME[$index]='nmbd';sh-expr 'index++' aNAME[$index]='Shairport Sync';aPROCESS_NAME[$index]='shairport-sync';sh-expr 'index++' aNAME[$index]='SickRage';aPROCESS_NAME[$index]='SickBeard.py';sh-expr 'index++' aNAME[$index]='Sonarr';aPROCESS_NAME[$index]='NzbDrone.exe';sh-expr 'index++' aNAME[$index]='Spotify Connect Web';aPROCESS_NAME[$index]='spotify-connect-web';sh-expr 'index++' aNAME[$index]='Supervisor';aPROCESS_NAME[$index]='supervisor';sh-expr 'index++' aNAME[$index]='Squeezebox Server (LMS)';aPROCESS_NAME[$index]='squeezeboxserver';sh-expr 'index++' aNAME[$index]='Squeezelite';aPROCESS_NAME[$index]='squeezelite';sh-expr 'index++' aNAME[$index]='Syncthing';aPROCESS_NAME[$index]='syncthing';sh-expr 'index++' aNAME[$index]='Syncthing-inotify';aPROCESS_NAME[$index]='syncthing-inotify';sh-expr 'index++' aNAME[$index]='Tomcat8';aPROCESS_NAME[$index]='tomcat8';sh-expr 'index++' aNAME[$index]='Tonido';aPROCESS_NAME[$index]='tonidoconsole';sh-expr 'index++' aNAME[$index]='Transmission';aPROCESS_NAME[$index]='transmission-daemon';sh-expr 'index++' aNAME[$index]='AmiBerry';aPROCESS_NAME[$index]='amiberry';sh-expr 'index++' aNAME[$index]='UrBackup Server';aPROCESS_NAME[$index]='urbackupsrv';sh-expr 'index++' aNAME[$index]='Webserver Apache2';aPROCESS_NAME[$index]='apache2';sh-expr 'index++' aNAME[$index]='Webserver Nginx';aPROCESS_NAME[$index]='nginx';sh-expr 'index++' aNAME[$index]='Webserver Lighttpd';aPROCESS_NAME[$index]='lighttpd';sh-expr 'index++' aNAME[$index]='Webserver MariaDB';aPROCESS_NAME[$index]='mariadb';sh-expr 'index++' aNAME[$index]='Webserver MySql';aPROCESS_NAME[$index]='mysqld';sh-expr 'index++' aNAME[$index]='Webserver Php-fpm';aPROCESS_NAME[$index]='php-fpm';sh-expr 'index++' aNAME[$index]='Webserver Redis';aPROCESS_NAME[$index]='redis-server';sh-expr 'index++' aNAME[$index]='WiFi Hotspot';aPROCESS_NAME[$index]='hostapd';sh-expr 'index++' aNAME[$index]='WiFi Monitor';aPROCESS_NAME[$index]='dietpi-wifi-monitor.sh';sh-expr 'index++' aNAME[$index]='VirtualHere';aPROCESS_NAME[$index]='vhusbd';sh-expr 'index++' aNAME[$index]='YaCy search engine';aPROCESS_NAME[$index]='yacy';sh-expr 'index++' setglobal MAX_PROGRAMS = $(#aNAME[@]) # - Find out which programs are running (impies installed) | exclude kernel threads ([]) ps ax | grep -v '\[' > $FP_PS_LIST # - Enable affinity for all cores and all programs by default var init_affinity_value = '0' if sh-expr ' $(nproc --all) > 1 ' { set init_affinity_value = ""0-$shExpr(' $(nproc --all) - 1')"" } # - Init other arrays for ((i=0; i<$MAX_PROGRAMS; i++)) do aNICE[$i]=0 aAFFINITY[$i]=$init_affinity_value aSCHEDULE_POLICY[$i]="SCHED_OTHER" aSCHEDULE_PRIORITY[$i]=0 aPID[$i]=0 aAVAILABLE[$i]=0 # - Obtain list of available programs if (( $(cat "$FP_PS_LIST" | awk '{string=""; for (i=5; i<=NF; i++) string=string $i " "; print string}' | grep -ci -m1 "${aPROCESS_NAME[$i]}") == 1 )); then aAVAILABLE[$i]=1 fi # - Apply default nice to specific programs if [ "${aPROCESS_NAME[$i]}" = "netdata" ]; then aNICE[$i]=19 fi done #Obtain list of available system schedulers/priorites chrt -m > $FP_TEMP set index = '0' while read line { # - available schedulers aSCHEDULE_AVAILABLE_POLICY[$index]=$[echo -e $line | awk '{print $1}] # - available priorities # -- min aSCHEDULE_AVAILABLE_PRIORITY_MIN[$index]=$[echo -e $line | sed 's/.*: //' | sed 's/\// /' | awk '{print $1}] # -- max aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index]=$[echo -e $line | sed 's/.*: //' | sed 's/\// /' | awk '{print $2}] sh-expr 'index++' } < "$FP_TEMP" setglobal MAX_SCHEDULE_POLICIES = $(#aSCHEDULE_AVAILABLE_POLICY[@]) #-------------------------------------------------------------------------------- #Load Settings file. Generate if required. if test ! -f $FP_SETTINGS { Write_Settings_File } else { Read_Settings_File } } #///////////////////////////////////////////////////////////////////////////////////// # Settings File #///////////////////////////////////////////////////////////////////////////////////// #Define Location setglobal FP_SETTINGS = '"/DietPi/dietpi/.dietpi-process_tool'" setglobal FP_TEMP = '"/tmp/.dietpi-process_tool_temp'" # - ps-aux > ram setglobal FP_PS_LIST = '"/tmp/.dietpi-process_tool_ps_list'" proc Read_Settings_File{ var string = ''"" for ((i=0; i<$MAX_PROGRAMS; i++)) do #Match settings against process name local string=$( cat "$FP_SETTINGS" | grep -m1 "^${aPROCESS_NAME[$i]}") if [ -n "$string" ]; then #- nice aNICE[$i]=$( echo -e "$string" | awk '{print $2}') #- affinity aAFFINITY[$i]=$(echo -e "$string" | awk '{print $3}') #- schedule aSCHEDULE_POLICY[$i]=$(echo -e "$string" | awk '{print $4}') aSCHEDULE_PRIORITY[$i]=$(echo -e "$string" | awk '{print $5}') fi done } proc Write_Settings_File{ rm $FP_SETTINGS &> /dev/null for ((i=0; i<$MAX_PROGRAMS; i++)) do if (( ${aAVAILABLE[$i]} == 1 )); then echo -e "${aPROCESS_NAME[$i]} ${aNICE[$i]} ${aAFFINITY[$i]} ${aSCHEDULE_POLICY[$i]} ${aSCHEDULE_PRIORITY[$i]}" >> $FP_SETTINGS fi done } #///////////////////////////////////////////////////////////////////////////////////// # Menu System #///////////////////////////////////////////////////////////////////////////////////// setglobal PROGRAM_NAME = '"DietPi-Process Tool'" setglobal WHIP_QUESTION = '0' setglobal CHOICE = '0' setglobal TARGETMENUID = '0' setglobal LAST_SELECTED_NAME = '0' proc Menu_Exit{ whiptail --title "Exit $PROGRAM_NAME?" --yesno "Exit $PROGRAM_NAME?" --backtitle $PROGRAM_NAME --yes-button "Ok" --no-button "Back" --defaultno 9 55 setglobal CHOICE = $Status if sh-expr ' $CHOICE == 0 ' { #exit setglobal TARGETMENUID = '-1' } else { #Return to Main Menu setglobal TARGETMENUID = '0' } } #TARGETMENUID=0 proc Menu_Main{ setglobal TARGETMENUID = '0' var whiptail_menu_array = ''() for ((i=0; i<$MAX_PROGRAMS; i++)) do if (( ${aAVAILABLE[$i]} == 1 )); then whiptail_menu_array+=("${aNAME[$i]}" ": Nice ${aNICE[$i]} | Affinity ${aAFFINITY[$i]}") fi done setglobal WHIP_QUESTION = ''Select a program:'' setglobal OPTION = $[whiptail --title $PROGRAM_NAME --backtitle $PROGRAM_NAME --menu $WHIP_QUESTION --cancel-button "Exit" --default-item $LAST_SELECTED_NAME 16 70 8 $(whiptail_menu_array[@]) !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status unset whiptail_menu_array if sh-expr ' $CHOICE == 0 ' { setglobal LAST_SELECTED_NAME = $OPTION #Find selected program index var index_current = '0' for ((i=0; i<$MAX_PROGRAMS; i++)) do if [ "${aNAME[$i]}" = "$OPTION" ]; then index_current=$i break fi done #Installed? if sh-expr ' ${aAVAILABLE[$index_current]} == 0 ' { whiptail --title "Not available." --msgbox "$(aNAME[$index_current]) is not running and/or installed." 8 70 #Prompt for nice/affinity/schedule choice } else { #return back to this section. var run_loop = '1' while (( $run_loop == 1 )) { #menu, choose nice/affinity etc setglobal WHIP_QUESTION = ""Select an option for $(aNAME[$index_current]):"" var whiptail_menu_array = ''() set whiptail_menu_array = '('"Nice" ": ${aNICE[$index_current]}") set whiptail_menu_array = '('"Affinity" ": ${aAFFINITY[$index_current]}") set whiptail_menu_array = '('"Schedule Policy" ": ${aSCHEDULE_POLICY[$index_current]}") set whiptail_menu_array = '('"Schedule Priority" ": ${aSCHEDULE_PRIORITY[$index_current]}") setglobal OPTION = $[whiptail --title $(aNAME[$index_current]) --backtitle $PROGRAM_NAME --menu $WHIP_QUESTION --cancel-button "Back" 11 60 4 $(whiptail_menu_array[@]) !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status unset whiptail_menu_array if sh-expr ' $CHOICE == 0 ' { match $OPTION { with Nice #Get existing nice level var nice_current = '0' # - note: Whiptail will not work with negative numbers. The string cannot start with "-" as it throws subscript error. set nice_current = ""Nice : $(aNICE[$index_current])"" var whiptail_menu_array = ''() for ((i=-20; i<20; i++)) do local desc="" if (( $i == -20 )); then desc="(Highest priority)" elif (( $i == -10 )); then desc="(Higher priority)" elif (( $i == -5 )); then desc="(High priority)" elif (( $i == 0 )); then desc="(Default priority)" elif (( $i == 5 )); then desc="(Low priority)" elif (( $i == 10 )); then desc="(Lower priority)" elif (( $i == 19 )); then desc="(Lowest priority)" fi whiptail_menu_array+=("Nice : $i" " $desc") done setglobal WHIP_QUESTION = ""Please select your nice level for:\n$(aNAME[$index_current])\n\nInfo:\n - Negative values have a higher priority (eg: -10).\n - Positive values have a lower priority (eg: 15).\n - The default value is 0."" setglobal OPTION = $[whiptail --title "Nice : $(aNAME[$index_current])" --backtitle $PROGRAM_NAME --menu $WHIP_QUESTION --cancel-button "Back" --default-item $nice_current 19 60 5 $(whiptail_menu_array[@]) !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status unset whiptail_menu_array if sh-expr ' $CHOICE == 0 ' { #Convert back to int aNICE[$index_current]=$[echo $OPTION | sed 's/[A-Za-z :]*//g] #Apply Apply_Process_Tool } with Affinity # - Get existing affinity #NB: currently enables all var whiptail_menu_array = ''() for ((i=0; i<$(nproc --all); i++)) do whiptail_menu_array+=("$i" "CPU " "on") done setglobal WHIP_QUESTION = ""Please select your CPU affinity for:\n$(aNAME[$index_current])\n\n- Use the spacebar to enable/disable access to specific cores, for this program.\n- The default value is to enable all items."" whiptail --title "Affinity : $(aNAME[$index_current])" --backtitle $PROGRAM_NAME --checklist --separate-output $WHIP_QUESTION --cancel-button "Back" 18 65 6 $(whiptail_menu_array[@]) !2 > $FP_TEMP setglobal CHOICE = $Status unset whiptail_menu_array if sh-expr ' $CHOICE == 0 ' { var new_affinity = ''"" var loop_count = '0' while read choice { if test $choice != "" { #taskset requires , (comma) seperated cpu index indexs after 1st entry. if sh-expr ' $loop_count == 0 ' { set new_affinity = $choice #Add comma for future entries } else { set new_affinity = "",$choice"" } sh-expr 'loop_count++' } } < "$FP_TEMP" #Update affinity array with new value, if at least 1 item was selected. if test $new_affinity != "" { aAFFINITY[$index_current]="$new_affinity" } #Apply Apply_Process_Tool } rm $FP_TEMP &> /dev/null with "Schedule Policy" var whiptail_menu_array = ''() var description = '''' for ((i=0; i<$MAX_SCHEDULE_POLICIES; i++)) do # - add descriptions if [ "${aSCHEDULE_AVAILABLE_POLICY[$i]}" = "SCHED_OTHER" ]; then description='Normal (Default)' elif [ "${aSCHEDULE_AVAILABLE_POLICY[$i]}" = "SCHED_FIFO" ]; then description='First In, First Out (Real-time, time-critical)' elif [ "${aSCHEDULE_AVAILABLE_POLICY[$i]}" = "SCHED_RR" ]; then description='Round Robin (Real-time, time-critical)' elif [ "${aSCHEDULE_AVAILABLE_POLICY[$i]}" = "SCHED_BATCH" ]; then description='Batch style execution' elif [ "${aSCHEDULE_AVAILABLE_POLICY[$i]}" = "SCHED_IDLE" ]; then description='Background Jobs (Very low priority)' fi whiptail_menu_array+=("${aSCHEDULE_AVAILABLE_POLICY[$i]}" ": $description") done setglobal WHIP_QUESTION = ""Please select a Schedule Policy for :\n$(aNAME[$index_current])"" setglobal OPTION = $[whiptail --title "Schedule Policy : $(aNAME[$index_current])" --backtitle $PROGRAM_NAME --menu $WHIP_QUESTION --cancel-button "Back" --default-item $(aSCHEDULE_POLICY[$index_current]) 14 70 5 $(whiptail_menu_array[@]) !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status unset whiptail_menu_array if sh-expr ' $CHOICE == 0 ' { aSCHEDULE_POLICY[$index_current]=$OPTION #Apply Apply_Process_Tool } with "Schedule Priority" #Match scheduler policy to array list var index_schedule = '0' for ((i=0; i<$MAX_SCHEDULE_POLICIES; i++)) do if [ "${aSCHEDULE_POLICY[$index_current]}" = "${aSCHEDULE_AVAILABLE_POLICY[$i]}" ]; then index_schedule=$i break fi done #No priority options available if sh-expr ' ( ${aSCHEDULE_AVAILABLE_PRIORITY_MIN[$index_schedule]} + ${aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index_schedule]} ) == 0 ' { whiptail --title $(aSCHEDULE_POLICY[$index_current]) --msgbox "No priority options are available for $(aSCHEDULE_POLICY[$index_current])." 8 60 #List available } else { var whiptail_menu_array = ''() # - 7 step description scale var scale_value_lowest = $(aSCHEDULE_AVAILABLE_PRIORITY_MIN[$index_schedule]) var scale_value_lower = $shExpr(' ${aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index_schedule]} / 6 ') var scale_value_low = $shExpr(' ${aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index_schedule]} / 6 * 2 ') var scale_value_medium = $shExpr(' ${aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index_schedule]} / 6 * 3 ') var scale_value_high = $shExpr(' ${aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index_schedule]} / 6 * 4 ') var scale_value_higher = $shExpr(' ${aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index_schedule]} / 6 * 5 ') var scale_value_highest = $(aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index_schedule]) for ((i=${aSCHEDULE_AVAILABLE_PRIORITY_MIN[$index_schedule]}; i<$(( ${aSCHEDULE_AVAILABLE_PRIORITY_MAX[$index_schedule]} + 1 )); i++)) do local description="" if (( $i == $scale_value_lowest )); then description="(Lowest priority)" elif (( $i == $scale_value_lower )); then description="(Lower priority)" elif (( $i == $scale_value_low )); then description="(Low priority)" elif (( $i == $scale_value_medium )); then description="(Medium priority)" elif (( $i == $scale_value_high )); then description="(High priority)" elif (( $i == $scale_value_higher )); then description="(Higher priority)" elif (( $i == $scale_value_highest )); then description="(Highest priority)" fi whiptail_menu_array+=("$i" ": $description") done setglobal WHIP_QUESTION = ""Please select a Schedule Priority level for :\n$(aNAME[$index_current])\n\n - Lower values are low priority\n - Higher values are high priority"" setglobal OPTION = $[whiptail --title "Schedule Policy : $(aNAME[$index_current])" --backtitle $PROGRAM_NAME --menu $WHIP_QUESTION --cancel-button "Back" --default-item $(aSCHEDULE_PRIORITY[$index_current]) 18 60 5 $(whiptail_menu_array[@]) !3 > !1 !1 > !2 !2 > !3] setglobal CHOICE = $Status unset whiptail_menu_array if sh-expr ' $CHOICE == 0 ' { aSCHEDULE_PRIORITY[$index_current]=$OPTION #Apply Apply_Process_Tool } } } #Return to main menu } else { set run_loop = '0' } } } } else { Menu_Exit } } #///////////////////////////////////////////////////////////////////////////////////// # MAIN #///////////////////////////////////////////////////////////////////////////////////// #----------------------------------------------------------------------------------- #Init Init #----------------------------------------------------------------------------------- #Run config menu if sh-expr ' $INPUT == 0 ' { #Start DietPi Menu while sh-expr ' $TARGETMENUID > -1 ' { clear if sh-expr ' $TARGETMENUID == 0 ' { Menu_Main } } #Save settings Write_Settings_File #Apply Process Tool } elif sh-expr ' $INPUT == 1 ' { Apply_Process_Tool G_DIETPI-NOTIFY -1 $(EXIT_CODE:=0) "$PROGRAM_NAME |" } #----------------------------------------------------------------------------------- #Del tmp files rm $FP_TEMP &> /dev/null rm $FP_PS_LIST &> /dev/null #----------------------------------------------------------------------------------- #Delete[] Global arrays unset aNICE unset aAFFINITY unset aSCHEDULE_POLICY unset aSCHEDULE_PRIORITY unset aPID unset aNAME unset aPROCESS_NAME unset aAVAILABLE unset aSCHEDULE_AVAILABLE_POLICY unset aSCHEDULE_AVAILABLE_PRIORITY_MIN unset aSCHEDULE_AVAILABLE_PRIORITY_MAX #----------------------------------------------------------------------------------- exit #----------------------------------------------------------------------------------- }