#!/bin/bash { #//////////////////////////////////// # DietPi Services Script # #//////////////////////////////////// # Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com # # Info: # - Allows service control for all listed programs used in dietpi-software # - Disable removes the autostart from init.d and systemd. This allows DietPi to control program services below. # # Usage: # - /DietPi/dietpi/dietpi-services $AVAILABLE_OPTIONS #//////////////////////////////////// AVAILABLE_OPTIONS=' - [No Input] (Run Menu) - start/stop/restart/status (all services, known to DietPi) - start/stop/restart (single service, systemd) - systemd_controlled/dietpi_controlled (all services, known to DietPi) - enable/disable all (all services, known to DietPi) - enable/disable (single service, systemd) - mask/unmask all (all services, known to DietPi) - mask/unmask (single service, systemd) - You can include/exclude custom services by editing the following file: /DietPi/dietpi/.dietpi-services_include_exclude' # - Optional input, prevent starting of services, useful for unmask during dietpi-software installs DISABLE_SERVICES_START=${DISABLE_SERVICES_START:-0} #Grab Inputs INPUT_MODE=$1 INPUT_S2=$2 #Import DietPi-Globals --------------------------------------------------------------- . /DietPi/dietpi/func/dietpi-globals (( $G_DIETPI_SERVICES_DISABLE )) && exit 0 G_PROGRAM_NAME='DietPi-Services' G_CHECK_ROOT_USER G_INIT #Import DietPi-Globals --------------------------------------------------------------- FP_TEMP='dietpi-services_installed' aCPU_NICE=() aCPU_AFFINITY=() aCPU_SCHEDULE_POLICY=() aCPU_SCHEDULE_POLICY_TYPE=( 'other' 'fifo' 'rr' 'batch' 'idle' ) aCPU_SCHEDULE_POLICY_DESC=( 'Normal (Default)' 'First In, First Out (Real-time, time-critical)' 'Round Robin (Real-time, time-critical)' 'Batch style execution' 'Background Jobs (Very low priority)' ) aCPU_SCHEDULE_PRIORITY=() aIO_SCHEDULE_POLICY=() aIO_SCHEDULE_POLICY_TYPE=('none' 'best-effort' 'realtime' 'idle') aIO_SCHEDULE_POLICY_DESC=('Unset (Default)' '(Medium Priority)' 'Time-critical (Highest priority)' 'Background Jobs (Very low priority)') aIO_PRIORITY=() aFP_SERVICE=() aSERVICE_MODE=() #Enabled/disabled/masked/unmasked aSERVICE_AVAILABLE=() aSERVICE_RESTART_REQUIRED=() #eg, made changes, prompt to restart this service. aSERVICE_NAME=( #Core ------------------------------------------------------------------ # - Network 'fail2ban' 'avahi-daemon' 'isc-dhcp-server' 'haproxy' # - File servers 'proftpd' 'vsftpd' 'nmbd' 'smbd' 'nfs-kernel-server' #Core ------------------------------------------------------------------ #Backends -------------------------------------------------------------- # - MySQL/Databases 'redis-server' 'mariadb' # 'mysql' applied on Jessie systems during availablility check: https://github.com/MichaIng/DietPi/issues/1000#issuecomment-30776051 # - PHP 'php5-fpm' 'php7.0-fpm' 'php7.1-fpm' 'php7.2-fpm' 'php7.3-fpm' # - Webservers 'apache2' 'nginx' 'lighttpd' 'tomcat8' # - Media 'alsa-init' 'coturn' 'mpd' 'minidlna' 'shairport-sync' 'squeezelite' 'gmrender' 'mumble-server' 'networkaudiod' 'roonbridge' 'roonserver' 'roon-extension-manager' 'icecast2' 'darkice' 'voice-recognizer' # - Download/BitTorrent 'transmission-daemon' 'qbittorrent' 'rtorrent' 'nzbget' 'deluged' #Backends -------------------------------------------------------------- #Frontends / Misc ------------------------------------------------------ # - Media 'ympd' 'mympd' 'logitechmediaserver' 'subsonic' 'airsonic' 'mopidy' 'koel' 'raspotify' 'plexpy' 'plexmediaserver' 'emby-server' 'spotify-connect-web' 'ubooquity' #'moode-worker' # - Download/BitTorrent 'sickrage' # pre-v6.20 compatibility 'medusa' 'aria2' 'sabnzbd' 'couchpotato' 'jackett' 'sonarr' 'radarr' 'lidarr' 'htpc-manager' 'deluge-web' # - Cloud/Backups 'bdd' 'minio' 'syncthing' 'syncthing-inotify' 'urbackupsrv' 'tonido' 'gogs' 'gitea' # - Emulation/Gaming 'supervisor' 'nukkit' 'cuberite' # - Camera/Surveillance 'motioneye' 'raspimjpeg' # - Printing 'cups' 'cloudprintd' 'octoprint' # - Social/Search 'yacy' 'openbazaar' # - Hardware Projects 'pi-spc' 'pijuice' 'mosquitto' 'node-red' 'blynkserver' 'webiopi' 'emonhub' 'influxdb' 'grafana-server' # - Home Automation 'home-assistant' # - Network 'noip2' 'virtualhere' #'pihole-FTL' #: https://github.com/MichaIng/DietPi/issues/1696 'hostapd' # - System stats / Management 'netdata' 'rpimonitor' 'webmin' # - Misc #'openmediavault-engined' 'docker' 'cron' 'fahclient' #Frontends / Misc ------------------------------------------------------ ) #Additional services: https://github.com/MichaIng/DietPi/issues/1869#issuecomment-401017251 [[ -f '/etc/rsyncd.conf' ]] && aSERVICE_NAME+=('rsync') #Hidden/not-controlled services # - Status mode, enable service status if [[ ! $INPUT_MODE || $INPUT_MODE == 'status' ]]; then # - SSH aSERVICE_NAME+=('dropbear') aSERVICE_NAME+=('ssh') #: OpenSSH Server # - Misc #aSERVICE_NAME+=('systemd-timesyncd') #: Timesync. DietPi stops this by default after success, may confuse user/prompt questions. aSERVICE_NAME+=('dnsmasq') #: https://github.com/MichaIng/DietPi/issues/1501 aSERVICE_NAME+=('pihole-FTL') #: https://github.com/MichaIng/DietPi/issues/1696 aSERVICE_NAME+=('openvpn') #: https://github.com/MichaIng/DietPi/issues/1501 aSERVICE_NAME+=('vncserver') #: DietPi vnc server service/script aSERVICE_NAME+=('nxserver') #: Nomachine aSERVICE_NAME+=('xrdp') #: XRDP Server aSERVICE_NAME+=('amiberry') #: DietPi AmiBerry run service # - DietPi aSERVICE_NAME+=('dietpi-nordvpn') #: NordVPN install + client if [[ $INPUT_MODE == 'status' ]]; then aSERVICE_NAME+=('dietpi-ramdisk') aSERVICE_NAME+=('dietpi-ramlog') aSERVICE_NAME+=('dietpi-preboot') aSERVICE_NAME+=('dietpi-boot') aSERVICE_NAME+=('dietpi-postboot') aSERVICE_NAME+=('dietpi-wifi-monitor') #: https://github.com/MichaIng/DietPi/issues/1288#issuecomment-350653480 aSERVICE_NAME+=('dietpi-arr_to_RAM') #: Sonarr/Radarr/Lidarr database to RAM link service fi #aSERVICE_NAME+=('wg-quick@wg0') #: WireGuard fi # - User: read custom services file FP_INCLUDE_CUSTOM_SERVICES='/DietPi/dietpi/.dietpi-services_include_exclude' Process_Includes_Excludes(){ if [[ -f $FP_INCLUDE_CUSTOM_SERVICES ]]; then while read line do if [[ $line != '#'* ]]; then local scrape=${line: +2} # - Include if [[ $line == '+ '* ]]; then local index=${#aSERVICE_NAME[@]} local service_known_already_to_dietpi=0 for ((i=0; i<${#aSERVICE_NAME[@]}; i++)) do if [[ $scrape == ${aSERVICE_NAME[$i]} ]]; then service_known_already_to_dietpi=1 break fi done if (( ! $service_known_already_to_dietpi )); then aSERVICE_NAME[$index]=$scrape G_DIETPI-NOTIFY 2 "Including custom service: $scrape" fi # - Exclude elif [[ $line == '- '* ]]; then for ((i=0; i<${#aSERVICE_NAME[@]}; i++)) do if [[ $scrape == ${aSERVICE_NAME[$i]} ]]; then G_DIETPI-NOTIFY 2 "Excluding service: $scrape" aSERVICE_NAME[$i]='' break fi done fi fi done < $FP_INCLUDE_CUSTOM_SERVICES fi } #$1=index FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF='dietpi-process_tool.conf' Save_Process_Tool(){ local index=$1 #Backwards cap for init.d, create systemd wrapper echo ${aFP_SERVICE[$index]} sleep 1 if [[ ${aFP_SERVICE[$index]} =~ '/etc/init.d/' ]]; then aFP_SERVICE[$index]="/lib/systemd/system/${aSERVICE_NAME[$index]}.service" cat << _EOF_ > /lib/systemd/system/pihole-FTL.service [Unit] Description=${aSERVICE_NAME[$index]} sysinit wrapper (DietPi) [Service] Type=forking ExecStop=/bin/bash -c '/etc/init.d/${aSERVICE_NAME[$index]} stop' ExecStart=/bin/bash -c '/etc/init.d/${aSERVICE_NAME[$index]} start' [Install] WantedBy=multi-user.target _EOF_ G_WHIP_MSG "[INFO] DietPi has created a systemd service wrapper for /etc/init.d/${aSERVICE_NAME[$index]}. This is required to allow support for applying process tool options.\n\nIf you experience any issues with the wrapper, simply remove the file:\n - rm /lib/systemd/system/${aSERVICE_NAME[$index]}.service\n - Then restart the service." fi mkdir -p ${aFP_SERVICE[$index]}.d cat << _EOF_ > ${aFP_SERVICE[$index]}.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF [Service] Nice=${aCPU_NICE[$index]} CPUAffinity=${aCPU_AFFINITY[$index]} CPUSchedulingPolicy=${aCPU_SCHEDULE_POLICY[$index]} CPUSchedulingPriority=${aCPU_SCHEDULE_PRIORITY[$index]} IOSchedulingClass=${aIO_SCHEDULE_POLICY[$index]} IOSchedulingPriority=${aIO_PRIORITY[$index]} _EOF_ G_RUN_CMD systemctl daemon-reload aSERVICE_RESTART_REQUIRED[$index]=1 } #$1=index Load_Process_Tool(){ local index=$1 aCPU_NICE[$index]=$(grep -m1 '^[[:blank:]]*Nice=' $j.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF | sed 's/^[^=]*=//g') aCPU_AFFINITY[$index]=$(grep -m1 '^[[:blank:]]*CPUAffinity=' $j.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF | sed 's/^[^=]*=//g') aCPU_SCHEDULE_POLICY[$index]=$(grep -m1 '^[[:blank:]]*CPUSchedulingPolicy=' $j.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF | sed 's/^[^=]*=//g') aCPU_SCHEDULE_PRIORITY[$index]=$(grep -m1 '^[[:blank:]]*CPUSchedulingPriority=' $j.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF | sed 's/^[^=]*=//g') aIO_SCHEDULE_POLICY[$index]=$(grep -m1 '^[[:blank:]]*IOSchedulingClass=' $j.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF | sed 's/^[^=]*=//g') aIO_PRIORITY[$index]=$(grep -m1 '^[[:blank:]]*IOSchedulingPriority=' $j.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF | sed 's/^[^=]*=//g') } #$1=index Reset_Service_Defaults(){ local index=$1 local fp="${aFP_SERVICE[$index]}.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF" if [[ -f $fp ]]; then G_RUN_CMD rm $fp G_RUN_CMD systemctl unmask ${aSERVICE_NAME[$index]} G_RUN_CMD systemctl daemon-reload aSERVICE_RESTART_REQUIRED[$index]=1 fi } #Check if service name is available on system. Populate_Available_Array(){ Process_Includes_Excludes local default_cpu_affinity="0-$(( $G_HW_CPU_CORES - 1 ))" aSERVICE_AVAILABLE=() aFP_SERVICE=() for i in ${!aSERVICE_NAME[@]} do aSERVICE_AVAILABLE[$i]=0 aFP_SERVICE[$i]='' [[ ! ${aSERVICE_RESTART_REQUIRED[$i]} ]] && aSERVICE_RESTART_REQUIRED[$i]=0 #Static init for menu use if [[ ${aSERVICE_NAME[$i]} ]]; then local fp_service=( /etc/systemd/system/${aSERVICE_NAME[$i]}.service /lib/systemd/system/${aSERVICE_NAME[$i]}.service /usr/lib/systemd/system/${aSERVICE_NAME[$i]}.service /etc/init.d/${aSERVICE_NAME[$i]} ) for j in ${fp_service[@]} do if [[ -f $j ]]; then aSERVICE_AVAILABLE[$i]=1 aFP_SERVICE[$i]=$j aSERVICE_MODE[$i]=$(systemctl is-enabled ${aSERVICE_NAME[$i]} 2>/dev/null) aCPU_NICE[$i]=0 aCPU_AFFINITY[$i]=$default_cpu_affinity aCPU_SCHEDULE_POLICY[$i]='other' aCPU_SCHEDULE_PRIORITY[$i]=0 aIO_SCHEDULE_POLICY[$i]='none' aIO_PRIORITY[$i]='0' if [[ -f $j.d/$FP_DIETPI_PROCESS_TOOL_SYSTEMD_CONF ]]; then Load_Process_Tool $i fi break fi done unset fp_service fi done } Print_Status(){ #$1 = Method #$2 = name #$3 = exit code # NB: systemd exit code 5 = not loaded/active, so don't trigger a failed result. #ok if (( $3 == 0 || $3 == 5 )); then G_DIETPI-NOTIFY 0 "$1 : $2" #failed else G_DIETPI-NOTIFY 1 "$1 : $2" fi } #$1 = mode (eg: start/stop/restart) Set_Running_State(){ local target_state=$1 # Control ownCloud and Nextcloud maintenance mode: if [[ $target_state == 'stop' || $target_state == 'restart' ]]; then [[ -f /var/www/owncloud/config/config.php ]] && grep -q "'maintenance' => false," /var/www/owncloud/config/config.php && G_USER_INPUTS=0 G_ERROR_HANDLER_INFO_ONLY=1 G_RUN_CMD occ maintenance:mode --on [[ -f /var/www/nextcloud/config/config.php ]] && grep -q "'maintenance' => false," /var/www/nextcloud/config/config.php && G_USER_INPUTS=0 G_ERROR_HANDLER_INFO_ONLY=1 G_RUN_CMD ncc maintenance:mode --on fi # - STOP: Reverse service order if [[ $target_state == 'stop' ]]; then for ((i=$(( ${#aSERVICE_NAME[@]} - 1 )); i>=0; i--)) do if (( ${aSERVICE_AVAILABLE[$i]} )); then G_DIETPI-NOTIFY -2 ${aSERVICE_NAME[$i]} systemctl $target_state ${aSERVICE_NAME[$i]} &> /dev/null Print_Status $target_state ${aSERVICE_NAME[$i]} $? aSERVICE_RESTART_REQUIRED[$i]=0 fi done # - EG: START/RESTART: Standard service order elif (( ! $DISABLE_SERVICES_START )); then for i in ${!aSERVICE_NAME[@]} do if (( ${aSERVICE_AVAILABLE[$i]} )); then G_DIETPI-NOTIFY -2 ${aSERVICE_NAME[$i]} systemctl $target_state ${aSERVICE_NAME[$i]} &> /dev/null Print_Status $target_state ${aSERVICE_NAME[$i]} $? aSERVICE_RESTART_REQUIRED[$i]=0 fi done # Control ownCloud and Nextcloud maintenance mode: if [[ $target_state == 'restart' || $target_state == 'start' ]]; then [[ -f /var/www/owncloud/config/config.php ]] && grep -q "'maintenance' => true," /var/www/owncloud/config/config.php && G_USER_INPUTS=0 G_ERROR_HANDLER_INFO_ONLY=1 G_RUN_CMD occ maintenance:mode --off [[ -f /var/www/nextcloud/config/config.php ]] && grep -q "'maintenance' => true," /var/www/nextcloud/config/config.php && G_USER_INPUTS=0 G_ERROR_HANDLER_INFO_ONLY=1 G_RUN_CMD ncc maintenance:mode --off fi fi } #$1=mode Apply_Service_States(){ local mode=$1 local additional_option=$2 local systemd_cmd='disable' #dietpi_controlled/systemd_controlled if [[ $mode == 'dietpi_controlled' || $mode == 'systemd_controlled' ]]; then [[ $mode == 'systemd_controlled' ]] && systemd_cmd='enable' for i in ${!aSERVICE_NAME[@]} do #Apply if (( ${aSERVICE_AVAILABLE[$i]} )); then G_DIETPI-NOTIFY -2 ${aSERVICE_NAME[$i]} systemctl $systemd_cmd ${aSERVICE_NAME[$i]} &> /dev/null Print_Status $mode ${aSERVICE_NAME[$i]} $? fi done systemctl daemon-reload &> /dev/null #mask/unmask/enable/disable elif [[ $mode == 'enable' || $mode == 'disable' || $mode == 'unmask' || $mode == 'mask' ]]; then #Switch to mask, as DietPi_Controlled uses disable to take over from systemd systemd_cmd='mask' [[ $mode == 'enable' || $mode == 'unmask' ]] && systemd_cmd='unmask' # - Process ALL known services if [[ $additional_option == 'all' ]]; then [[ $mode == 'disable' || $mode == 'mask' ]] && Set_Running_State stop for i in ${!aSERVICE_NAME[@]} do if (( ${aSERVICE_AVAILABLE[$i]} )); then G_DIETPI-NOTIFY 0 "$mode $additional_option: ${aSERVICE_NAME[$i]}" systemctl $systemd_cmd ${aSERVICE_NAME[$i]} fi done # - Process user defined single entry via cmd input else [[ $mode == 'disable' || $mode == 'mask' ]] && systemctl stop $additional_option local notify_index=0 ! systemctl $systemd_cmd $additional_option && notify_index=1 G_DIETPI-NOTIFY $notify_index "$mode $additional_option" fi systemctl daemon-reload #status elif [[ $mode == 'status' ]]; then for i in ${!aSERVICE_NAME[@]} do #Apply if (( ${aSERVICE_AVAILABLE[$i]} )); then local status="${aSERVICE_NAME[$i]}\t$(systemctl status ${aSERVICE_NAME[$i]} | grep -m1 'Active' | cut -c12-)" if [[ $status =~ 'failed' ]]; then G_DIETPI-NOTIFY 1 "$status" systemctl -l --no-pager status ${aSERVICE_NAME[$i]} elif [[ $status =~ 'inactive' ]]; then G_DIETPI-NOTIFY 2 "$status" else G_DIETPI-NOTIFY 0 "$status" fi fi done #start/stop/restart elif [[ $mode == 'start' || $mode == 'stop' || $mode == 'restart' ]]; then #Single use case, basically a alias for systemd if [[ $additional_option ]]; then if systemctl $mode $additional_option &> /dev/null; then G_DIETPI-NOTIFY 0 "$mode $additional_option" else G_DIETPI-NOTIFY 1 "$mode $additional_option" fi #All services controlled else Set_Running_State $mode fi else G_DIETPI-NOTIFY 2 "Invalid command\e[0m\nAvailable options:\n$AVAILABLE_OPTIONS\n" fi } #///////////////////////////////////////////////////////////////////////////////////// # Menu System #///////////////////////////////////////////////////////////////////////////////////// MENU_TARGETID=0 MENU_SELECTED_SERVICE_INDEX=0 MENU_LAST_SELECTED_MAIN=0 #Main menu MENU_LAST_SELECTED_SUB_0=0 #Sub menus, level 0 Menu_Exit(){ G_WHIP_SIZE_X_MAX=50 if G_WHIP_YESNO "Exit $G_PROGRAM_NAME?"; then # - Prompt to restart changed services. local service_restart_list_menu='' local service_restart_list_systemd='' for i in ${!aSERVICE_NAME[@]} do if (( ${aSERVICE_RESTART_REQUIRED[$i]} )); then service_restart_list_menu+="\n - ${aSERVICE_NAME[$i]}: Nice=${aCPU_NICE[$i]} | Affinity=${aCPU_AFFINITY[$i]} | CPU Scheduling Policy=${aCPU_SCHEDULE_POLICY[$i]} | CPU Scheduling Priority=${aCPU_SCHEDULE_PRIORITY[$i]} | IO Scheduling Policy=${aIO_SCHEDULE_POLICY[$i]} | IO Scheduling Priority=${aIO_PRIORITY[$i]}" service_restart_list_systemd+="${aSERVICE_NAME[$i]} " fi done if [[ $service_restart_list_systemd ]]; then if G_WHIP_YESNO "[INFO] The following services require a restart, in order to apply your recently modified settings: $service_restart_list_menu\n\nDo you wish to continue, and, restart the above services now?"; then G_RUN_CMD systemctl restart $service_restart_list_systemd fi fi #exit MENU_TARGETID=-1 else #Return to Main Menu MENU_TARGETID=0 fi } #MENU_TARGETID=0 Menu_Main(){ MENU_TARGETID=0 G_WHIP_MENU_ARRAY=('' '●─ Single Service Options ') for i in ${!aSERVICE_NAME[@]} do if (( ${aSERVICE_AVAILABLE[$i]} )); then G_WHIP_MENU_ARRAY+=("${aSERVICE_NAME[$i]}" ": $(systemctl is-active ${aSERVICE_NAME[$i]}) | Nice ${aCPU_NICE[$i]} | Affinity ${aCPU_AFFINITY[$i]}") fi done G_WHIP_MENU_ARRAY+=('' '●─ Global Service Options ') G_WHIP_MENU_ARRAY+=('Stop' ': Stop ALL services') G_WHIP_MENU_ARRAY+=('Restart' ': Start/restart ALL services') G_WHIP_DEFAULT_ITEM=$MENU_LAST_SELECTED_MAIN G_WHIP_BUTTON_CANCEL_TEXT='Exit' if G_WHIP_MENU 'Please select an option or program:'; then MENU_LAST_SELECTED_MAIN=$G_WHIP_RETURNED_VALUE if [[ ${G_WHIP_RETURNED_VALUE,,} == 'restart' || ${G_WHIP_RETURNED_VALUE,,} == 'stop' ]]; then Apply_Service_States ${G_WHIP_RETURNED_VALUE,,} sleep 0.5 else #Find selected program index MENU_SELECTED_SERVICE_INDEX=0 for i in ${!aSERVICE_NAME[@]} do if [[ ${aSERVICE_NAME[$i]} == $G_WHIP_RETURNED_VALUE ]]; then MENU_SELECTED_SERVICE_INDEX=$i break fi done MENU_TARGETID=1 fi else Menu_Exit fi } Menu_Service(){ MENU_TARGETID=1 local service_state=$(systemctl is-active ${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}) local service_mode_print=${aSERVICE_MODE[$MENU_SELECTED_SERVICE_INDEX]} [[ $service_mode_print == 'disabled' ]] && service_mode_print+=' (DietPi default)' G_WHIP_DEFAULT_ITEM=$MENU_LAST_SELECTED_SUB_0 G_WHIP_BUTTON_CANCEL_TEXT='Back' G_WHIP_MENU_ARRAY=( '' '●─ Service Control ' 'State' ": [$service_state]" 'Edit' ": [${aFP_SERVICE[$MENU_SELECTED_SERVICE_INDEX]}]" 'Mode' ": [$service_mode_print]" '' '●─ CPU Process Tool ' 'Nice' ": [${aCPU_NICE[$MENU_SELECTED_SERVICE_INDEX]}]" 'Affinity' ": [${aCPU_AFFINITY[$MENU_SELECTED_SERVICE_INDEX]}]" 'Schedule Policy' ": [${aCPU_SCHEDULE_POLICY[$MENU_SELECTED_SERVICE_INDEX]}]" 'Schedule Priority' ": [${aCPU_SCHEDULE_PRIORITY[$MENU_SELECTED_SERVICE_INDEX]}]" '' '●─ IO Process Tool ' 'IO Scheduling Policy' ": [${aIO_SCHEDULE_POLICY[$MENU_SELECTED_SERVICE_INDEX]}]" 'IO Scheduling Priority' ": [${aIO_PRIORITY[$MENU_SELECTED_SERVICE_INDEX]}]" '' '●─ Misc Options ' 'Reset' ': Reset all options to default' ) if G_WHIP_MENU "Please select an option for ${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}:"; then MENU_LAST_SELECTED_SUB_0=$G_WHIP_RETURNED_VALUE case "$G_WHIP_RETURNED_VALUE" in 'Reset') Reset_Service_Defaults $MENU_SELECTED_SERVICE_INDEX ;; 'Mode') G_WHIP_MENU_ARRAY=( 'disable' ': Recommended (DietPi controls service order)' 'enable' ': Systemd controls service order' 'mask' ': Hide service from system and prevent use' 'unmask' ': Un-hide service from system and allow use' ) G_WHIP_DEFAULT_ITEM='disable' if G_WHIP_MENU "Please select the desired Service Mode for :\n${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}"; then [[ $G_WHIP_RETURNED_VALUE == 'enable' || $G_WHIP_RETURNED_VALUE == 'disable' ]] && systemctl unmask ${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]} &> /dev/null G_ERROR_HANDLER_INFO_ONLY=1 G_RUN_CMD systemctl $G_WHIP_RETURNED_VALUE ${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]} #Dont start service... #Apply_Service_States $G_WHIP_RETURNED_VALUE ${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]} fi ;; 'IO Scheduling Policy') G_WHIP_MENU_ARRAY=() for i in ${!aIO_SCHEDULE_POLICY_TYPE[@]} do G_WHIP_MENU_ARRAY+=("${aIO_SCHEDULE_POLICY_TYPE[$i]}" ": ${aIO_SCHEDULE_POLICY_DESC[$i]}" ) done G_WHIP_DEFAULT_ITEM=${aIO_SCHEDULE_POLICY[$MENU_SELECTED_SERVICE_INDEX]} if G_WHIP_MENU "Please select the desired IO Scheduling Class for :\n${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}"; then aIO_SCHEDULE_POLICY[$MENU_SELECTED_SERVICE_INDEX]=$G_WHIP_RETURNED_VALUE Save_Process_Tool $MENU_SELECTED_SERVICE_INDEX fi ;; 'IO Scheduling Priority') G_WHIP_MENU_ARRAY=() for i in {7..0} do local desc='' if (( $i == 0 )); then desc='(Highest priority)' elif (( $i == 7 )); then desc='(Lowest priority)' fi G_WHIP_MENU_ARRAY+=("IO Priority : $i" " $desc") done G_WHIP_DEFAULT_ITEM=${aIO_PRIORITY[$MENU_SELECTED_SERVICE_INDEX]} G_WHIP_MENU "Please select the desired IO Scheduling Priority level for:\n${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}." if (( ! $? )); then #Convert back to int aIO_PRIORITY[$MENU_SELECTED_SERVICE_INDEX]=${G_WHIP_RETURNED_VALUE##*: } Save_Process_Tool $MENU_SELECTED_SERVICE_INDEX fi ;; 'Edit') nano ${aFP_SERVICE[$MENU_SELECTED_SERVICE_INDEX]} G_ERROR_HANDLER_INFO_ONLY=1 G_RUN_CMD systemctl daemon-reload ;; 'State') local target_mode='restart' [[ ${service_state,,} == 'active' ]] && target_mode='stop' Apply_Service_States $target_mode ${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]} sleep 0.5 ;; 'Nice') #Get existing nice level # - note: Whiptail will not work with negative numbers. The string cannot start with "-" as it throws subscript error. local nice_current="Nice : ${aCPU_NICE[$MENU_SELECTED_SERVICE_INDEX]}" G_WHIP_MENU_ARRAY=() for i in {-20..19} 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 G_WHIP_MENU_ARRAY+=("Nice : $i" " $desc") done G_WHIP_DEFAULT_ITEM=$nice_current G_WHIP_MENU "Please select the desired Nice level for:\n${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}\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." if (( ! $? )); then #Convert back to int aCPU_NICE[$MENU_SELECTED_SERVICE_INDEX]=${G_WHIP_RETURNED_VALUE##*: } Save_Process_Tool $MENU_SELECTED_SERVICE_INDEX fi ;; 'Affinity') # - Get existing affinity #NB: currently enables all G_WHIP_CHECKLIST_ARRAY=() for ((i=0; i<$G_HW_CPU_CORES; i++)) do G_WHIP_CHECKLIST_ARRAY+=($i 'CPU ' 'on') done G_WHIP_CHECKLIST "Please select the desired CPU Affinity for:\n${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}\n\n- Use the spacebar to enable/disable access to specific cores, for this program.\n- The default value is to enable all items." if (( ! $? )); then local new_affinity='' local loop_count=0 for i in ${G_WHIP_RETURNED_VALUE[@]} do #taskset requires , (comma) seperated cpu index indexs after 1st entry. if (( $loop_count == 0 )); then new_affinity+=$i #Add comma for future entries else new_affinity+=",$i" fi ((loop_count++)) done #Update affinity array with new value, if at least 1 item was selected. [[ $new_affinity ]] && aCPU_AFFINITY[$MENU_SELECTED_SERVICE_INDEX]=$new_affinity Save_Process_Tool $MENU_SELECTED_SERVICE_INDEX fi ;; 'Schedule Policy') G_WHIP_MENU_ARRAY=() for i in ${!aCPU_SCHEDULE_POLICY_TYPE[@]} do G_WHIP_MENU_ARRAY+=("${aCPU_SCHEDULE_POLICY_TYPE[$i]}" ": ${aCPU_SCHEDULE_POLICY_DESC[$i]}" ) done G_WHIP_DEFAULT_ITEM=${aCPU_SCHEDULE_POLICY[$MENU_SELECTED_SERVICE_INDEX]} if G_WHIP_MENU "Please select the desired CPU Scheduling Policy for :\n${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}"; then aCPU_SCHEDULE_POLICY[$MENU_SELECTED_SERVICE_INDEX]=$G_WHIP_RETURNED_VALUE Save_Process_Tool $MENU_SELECTED_SERVICE_INDEX fi ;; 'Schedule Priority') G_WHIP_MENU_ARRAY=() # - 7 step description scale local scale_value_lowest=0 local scale_value_highest=99 local scale_value_lower=$(( $scale_value_highest / 6 )) local scale_value_low=$(( $scale_value_highest / 6 * 2 )) local scale_value_medium=$(( $scale_value_highest / 6 * 3 )) local scale_value_high=$(( $scale_value_highest / 6 * 4 )) local scale_value_higher=$(( $scale_value_highest / 6 * 5 )) for ((i=0; i<$(( $scale_value_highest + 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 G_WHIP_MENU_ARRAY+=($i ": $description") done G_WHIP_DEFAULT_ITEM=${aCPU_SCHEDULE_PRIORITY[$MENU_SELECTED_SERVICE_INDEX]} G_WHIP_MENU "Please select the desired CPU Scheduling Priority level for :\n${aSERVICE_NAME[$MENU_SELECTED_SERVICE_INDEX]}\n\n - Lower values are low priority\n - Higher values are high priority" if (( ! $? )); then aCPU_SCHEDULE_PRIORITY[$MENU_SELECTED_SERVICE_INDEX]=$G_WHIP_RETURNED_VALUE Save_Process_Tool $MENU_SELECTED_SERVICE_INDEX fi ;; esac #Return to main menu else MENU_TARGETID=0 fi } #///////////////////////////////////////////////////////////////////////////////////// # Main #///////////////////////////////////////////////////////////////////////////////////// #Info G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" "$INPUT_MODE" if [[ ! -f $FP_INCLUDE_CUSTOM_SERVICES ]]; then cat << _EOF_ > $FP_INCLUDE_CUSTOM_SERVICES #DietPi-Services Include/Exclude configuration #Include custom service (Use '+ servicename' without the comments to enable DietPi control of that service) # Once completed, for DietPi to control the service, please run the following command, without quotes (') # 'dietpi-services dietpi_controlled' #+ myservice1 #+ myservice2 #Exclude DietPi from controlling known services (Use '- servicename' without the comments to disable DietPi control for that service) # The service will be in disabled form, and, you can start and stop it manually #- cron #- transmission-daemon _EOF_ fi #Obtain an array of available services installed on system. Populate_Available_Array #----------------------------------------------------------------------------------- #Direct service control mode if [[ $INPUT_MODE ]]; then Apply_Service_States $INPUT_MODE $INPUT_S2 #----------------------------------------------------------------------------------- #Men You! elif [[ ! $INPUT_MODE ]]; then while (( $MENU_TARGETID > -1 )) do if (( $MENU_TARGETID == 0 )); then Menu_Main elif (( $MENU_TARGETID == 1 )); then Menu_Service fi Populate_Available_Array done fi #----------------------------------------------------------------------------------- exit #----------------------------------------------------------------------------------- }