diff --git a/docs/changelog.md b/docs/changelog.md index f449f3a..6d1a9db 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,64 @@ This document covers possible important changes to KIAUH. +### 2022-10-31 +Some functions got updated, though not all of them. + +The following functions are still currently unavailable: +- Installation of: MJPG-Streamer +- All backup functions and the Log-Upload + +### 2022-10-20 +KIAUH has now reached major version 5 ! + +Recently Moonraker introduced some changes which makes it necessary to change the folder structure of printer setups. +If you are interested in the details, check out this PR: https://github.com/Arksine/moonraker/pull/491 \ +Although Moonraker has some mechanics available to migrate existing setups to the new file structure with the use of symlinks, fresh and clean installs +should be considered. + +The version jump of KIAUH to v5 is a breaking change due to those major changes! That means v4 and v5 are not compatible with each other! +This is also the reason why you will currently be greeted by a yellow notification in the main menu of KIAUH leading to this changelog. +I decided to disable a few functions of the script and focus on releasing the required changes to the core components of this script. +I will work on updating the other parts of the script piece by piece during the next days/weeks. +So I am already sorry in advance if one of your desired components you wanted to install or use temporarily cannot be installed or used right now. + +The following functions are currently unavailable: +- Installation of: KlipperScreen, Obico, Octoprint, MJPG-Streamer, Telegram Bot and PrettyGCode +- All backup functions and the Log-Upload + +**So what is working?**\ +Installation of Klipper, Moonraker, Mainsail and Fluidd. Both, single and multi-instance setups work!\ +As already said, the rest will follow in the near future. Updating and removal of already installed components should continue to work. + +**What was removed?**\ +The option to change Klippers configuration directory got removed. From now on it will not be possible anymore to change +the configuration directory from within KIAUH and the new filestructure is enforced. + +**What if I don't have an existing Klipper/Moonraker install right now?**\ +Nothing important to think about, install Klipper and Moonraker. KIAUH will install both of them with the new filestructure. + +**What if I have an existing Klipper/Moonraker install?**\ +First of all: Backups! Please copy all of your config files and the Moonraker database (it is a hidden folder, usually `~/.moonraker_database`) to a safe location. +After that, uninstall Klipper and Moonraker with KIAUH. You can then proceed and re-install both of them with KIAUH again. It is important that you are on KIAUH v5 for that! +Once everything is installed again, you need to manually copy your configuration files from the old `~/klipper_config` folder to the new `~/printer_data/config` folder. +Previous, by Moonraker created symlinks to folder of the old filestructure will not work anymore, you need to move the files to their new location now! +Do the same with the two files inside of `~/.moonraker_database`. Move/copy them into `~/printer_data/database`. If `~/printer_data/database` is already populated with a `data.mdb` and `lock.mdb` +delete them or simply overwrite them. Nothing should be lost as those should be empty database files. Anyway, you made backups, right? +You can now proceed and restart Moonraker. Either from within Mainsail or Fluidd, or use SSH and execute `sudo systemctl restart moonraker`. +If everything went smooth, you should be good to go again. If you see some Moonraker warnings about deprecated options in the `moonraker.conf`, go ahead and resolve them. +I will not cover them in detail here. A good source is the Moonraker documentation: https://moonraker.readthedocs.io/en/latest/configuration/ + +**What if I have an existing Klipper/Moonraker multi-instance install?**\ +Pretty much the same steps that are required for single instance installs apply to multi-instance setups. So please go ahead and read the previous paragraph if you didn't already. +Make backups of everything first. Then remove and install the desired amount of Klipper and Moonraker instances again. +Now you need to move all config and database files to their new locations.\ +Example with an instance called `printer_1`:\ +The config files go from `~/klipper_config/printer_1` to `~/printer_1_data/config`. +The database files go from `~/.moonraker_database_1` to `~/printer_1_data/database`. +Now restart all Moonraker services. You can restart all of them at once if you launch KIAUH, and in the main menu type `restart moonraker` and hit Enter. + +I hope I have covered the most important things. In case you need further support, the official Klipper Discord is a good place to ask for help. + ### 2022-08-15 Support for "Obico for Klipper" was added! Huge thanks to [kennethjiang](https://github.com/kennethjiang) for helping me with the implementation! diff --git a/kiauh.sh b/kiauh.sh index b01b5d9..8d40d98 100755 --- a/kiauh.sh +++ b/kiauh.sh @@ -9,6 +9,15 @@ # This file may be distributed under the terms of the GNU GPLv3 license # #=======================================================================# +# TODO: mjpg-streamer +# TODO: moonraker-telegram-bot +# TODO: obico +# TODO: pretty_gcode +# TODO: upload_log +# TODO: all backup functions +# TODO: octoprint +# TODO: doublecheck that nothing got missed! + set -e clear diff --git a/resources/printer.cfg b/resources/example.printer.cfg similarity index 100% rename from resources/printer.cfg rename to resources/example.printer.cfg diff --git a/resources/klipper.env b/resources/klipper.env new file mode 100644 index 0000000..1f16a6e --- /dev/null +++ b/resources/klipper.env @@ -0,0 +1 @@ +KLIPPER_ARGS="/home/%USER%/klipper/klippy/klippy.py %CFG% -I %PRINTER% -l %LOG% -a %UDS%" \ No newline at end of file diff --git a/resources/klipper.service b/resources/klipper.service index 5bf8f5a..8c74cd4 100644 --- a/resources/klipper.service +++ b/resources/klipper.service @@ -1,22 +1,18 @@ -#Systemd Klipper Service - [Unit] -Description=Systemd Klipper Service for instance klipper-%INST% +Description=Klipper 3D Printer Firmware SV1 Documentation=https://www.klipper3d.org/ -After=network.target +After=network-online.target Wants=udev.target [Install] WantedBy=multi-user.target [Service] -Environment=KLIPPER_CONFIG=%CFG% -Environment=KLIPPER_LOG=%LOG% -Environment=KLIPPER_SOCKET=%UDS% -Environment=KLIPPER_PRINTER=%PRINTER% Type=simple User=%USER% RemainAfterExit=yes -ExecStart=%ENV%/bin/python %DIR%/klippy/klippy.py ${KLIPPER_CONFIG} -I ${KLIPPER_PRINTER} -l ${KLIPPER_LOG} -a ${KLIPPER_SOCKET} +WorkingDirectory=/home/%USER%/klipper +EnvironmentFile=%ENV_FILE% +ExecStart=%ENV%/bin/python $KLIPPER_ARGS Restart=always -RestartSec=10 \ No newline at end of file +RestartSec=10 diff --git a/resources/moonraker-telegram-bot.env b/resources/moonraker-telegram-bot.env new file mode 100644 index 0000000..aaa7547 --- /dev/null +++ b/resources/moonraker-telegram-bot.env @@ -0,0 +1 @@ +TELEGRAM_BOT_ARGS="/home/%USER%/moonraker-telegram-bot/bot/main.py -c %CFG% -l %LOG%" \ No newline at end of file diff --git a/resources/moonraker-telegram-bot.service b/resources/moonraker-telegram-bot.service index 3581f18..28cf88f 100644 --- a/resources/moonraker-telegram-bot.service +++ b/resources/moonraker-telegram-bot.service @@ -1,19 +1,17 @@ -#Systemd service file for Moonraker Telegram Bot - [Unit] -Description=Starts Moonraker Telegram Bot instance %INST% on startup +Description=Moonraker Telegram Bot SV1 %INST% Documentation=https://github.com/nlef/moonraker-telegram-bot/wiki -After=network.target +After=network-online.target [Install] WantedBy=multi-user.target [Service] -Environment=TELEGRAM_CONF=%CFG% -Environment=TELEGRAM_LOG=%LOG% Type=simple User=%USER% RemainAfterExit=yes -ExecStart=%ENV%/bin/python %DIR%/bot/main.py -c ${TELEGRAM_CONF} -l ${TELEGRAM_LOG} +WorkingDirectory=/home/%USER%/moonraker-telegram-bot +EnvironmentFile=%ENV_FILE% +ExecStart=%ENV%/bin/python $TELEGRAM_BOT_ARGS Restart=always RestartSec=10 \ No newline at end of file diff --git a/resources/moonraker.conf b/resources/moonraker.conf index f819c5a..bdca99a 100644 --- a/resources/moonraker.conf +++ b/resources/moonraker.conf @@ -1,7 +1,6 @@ [server] host: 0.0.0.0 port: %PORT% -enable_debug_logging: False klippy_uds_address: %UDS% [authorization] @@ -22,13 +21,6 @@ cors_domains: https://app.fluidd.xyz http://app.fluidd.xyz -[database] -database_path: %DB% - -[file_manager] -config_path: %CFG% -log_path: %LOG% - [octoprint_compat] [history] diff --git a/resources/moonraker.env b/resources/moonraker.env new file mode 100644 index 0000000..065ca7e --- /dev/null +++ b/resources/moonraker.env @@ -0,0 +1 @@ +MOONRAKER_ARGS="/home/%USER%/moonraker/moonraker/moonraker.py -d %PRINTER_DATA%" \ No newline at end of file diff --git a/resources/moonraker.service b/resources/moonraker.service index 0ef771f..ac8000f 100644 --- a/resources/moonraker.service +++ b/resources/moonraker.service @@ -1,20 +1,19 @@ -#Systemd Moonraker Service - [Unit] -Description=Systemd Moonraker Service for instance moonraker-%INST% +Description=API Server for Klipper SV1 %INST% Documentation=https://moonraker.readthedocs.io/ -After=network.target +Requires=network-online.target +After=network-online.target [Install] WantedBy=multi-user.target [Service] -Environment=MOONRAKER_CONF=%CFG% -Environment=MOONRAKER_LOG=%LOG% Type=simple -SupplementaryGroups=moonraker-admin User=%USER% +SupplementaryGroups=moonraker-admin RemainAfterExit=yes -ExecStart=%ENV%/bin/python %DIR%/moonraker/moonraker.py -c ${MOONRAKER_CONF} -l ${MOONRAKER_LOG} +WorkingDirectory=/home/%USER%/moonraker +EnvironmentFile=%ENV_FILE% +ExecStart=%ENV%/bin/python $MOONRAKER_ARGS Restart=always RestartSec=10 \ No newline at end of file diff --git a/scripts/fluidd.sh b/scripts/fluidd.sh index 41e7838..55f2e2e 100644 --- a/scripts/fluidd.sh +++ b/scripts/fluidd.sh @@ -39,29 +39,29 @@ function install_fluidd() { ### check if another site already listens to port 80 fluidd_port_check - ### ask user to install mjpg-streamer - local install_mjpg_streamer - if [[ ! -f "${SYSTEMD}/webcamd.service" ]]; then - while true; do - echo - top_border - echo -e "| Install MJPG-Streamer for webcam support? |" - bottom_border - read -p "${cyan}###### Please select (y/N):${white} " yn - case "${yn}" in - Y|y|Yes|yes) - select_msg "Yes" - install_mjpg_streamer="true" - break;; - N|n|No|no|"") - select_msg "No" - install_mjpg_streamer="false" - break;; - *) - error_msg "Invalid command!";; - esac - done - fi +# ### ask user to install mjpg-streamer +# local install_mjpg_streamer +# if [[ ! -f "${SYSTEMD}/webcamd.service" ]]; then +# while true; do +# echo +# top_border +# echo -e "| Install MJPG-Streamer for webcam support? |" +# bottom_border +# read -p "${cyan}###### Please select (y/N):${white} " yn +# case "${yn}" in +# Y|y|Yes|yes) +# select_msg "Yes" +# install_mjpg_streamer="true" +# break;; +# N|n|No|no|"") +# select_msg "No" +# install_mjpg_streamer="false" +# break;; +# *) +# error_msg "Invalid command!";; +# esac +# done +# fi ### download fluidd download_fluidd @@ -83,7 +83,7 @@ function install_fluidd() { patch_fluidd_update_manager ### install mjpg-streamer - [[ ${install_mjpg_streamer} == "true" ]] && install_mjpg-streamer +# [[ ${install_mjpg_streamer} == "true" ]] && install_mjpg-streamer fetch_webui_ports #WIP @@ -124,9 +124,11 @@ function install_fluidd_macros() { } function download_fluidd_macros() { - local fluidd_cfg="https://raw.githubusercontent.com/fluidd-core/FluiddPI/master/src/modules/fluidd/filesystem/home/pi/klipper_config/fluidd.cfg" - local configs path - configs=$(find "${KLIPPER_CONFIG}" -type f -name "printer.cfg" | sort) + local fluidd_cfg path configs regex + + fluidd_cfg="https://raw.githubusercontent.com/fluidd-core/FluiddPI/master/src/modules/fluidd/filesystem/home/pi/klipper_config/fluidd.cfg" + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/config\/printer\.cfg" + configs=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" | sort) if [[ -n ${configs} ]]; then for config in ${configs}; do @@ -214,8 +216,23 @@ function remove_fluidd_logs() { } function remove_fluidd_log_symlinks() { + local files regex + + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/logs\/fluidd-.*" + files=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" 2> /dev/null | sort) + + if [[ -n ${files} ]]; then + for file in ${files}; do + status_msg "Removing ${file} ..." + rm -f "${file}" + ok_msg "${file} removed!" + done + fi +} + +function remove_legacy_fluidd_log_symlinks() { local files - files=$(find "${KLIPPER_LOGS}" -name "fluidd*" 2> /dev/null | sort) + files=$(find "${HOME}/klipper_logs" -name "fluidd*" 2> /dev/null | sort) if [[ -n ${files} ]]; then for file in ${files}; do @@ -231,6 +248,7 @@ function remove_fluidd() { remove_fluidd_config remove_fluidd_logs remove_fluidd_log_symlinks + remove_legacy_fluidd_log_symlinks ### remove fluidd_port from ~/.kiauh.ini sed -i "/^fluidd_port=/d" "${INI_FILE}" @@ -395,12 +413,13 @@ function select_fluidd_port() { } function patch_fluidd_update_manager() { - local patched="false" - local moonraker_configs - moonraker_configs=$(find "${KLIPPER_CONFIG}" -type f -name "moonraker.conf" | sort) + local patched moonraker_configs regex + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/config\/moonraker\.conf" + moonraker_configs=$(find "${HOME}" -maxdepth 3 -type f -regextype posix-extended -regex "${regex}" | sort) + patched="false" for conf in ${moonraker_configs}; do - if ! grep -Eq "^\[update_manager fluidd\]$" "${conf}"; then + if ! grep -Eq "^\[update_manager fluidd\]\s*$" "${conf}"; then ### add new line to conf if it doesn't end with one [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}" diff --git a/scripts/gcode_shell_command.sh b/scripts/gcode_shell_command.sh index d546839..3ddb3f3 100644 --- a/scripts/gcode_shell_command.sh +++ b/scripts/gcode_shell_command.sh @@ -105,10 +105,11 @@ function create_example_shell_command() { ### create a backup of the config folder backup_klipper_config_dir - local printer_cfgs path - printer_cfgs=$(find "$(get_klipper_cfg_dir)" -type f -name "printer.cfg" | sort) + local configs regex path + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/config\/printer\.cfg" + configs=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" | sort) - for cfg in ${printer_cfgs}; do + for cfg in ${configs}; do path=$(echo "${cfg}" | rev | cut -d"/" -f2- | rev) if [[ ! -f "${path}/shell_command.cfg" ]]; then diff --git a/scripts/globals.sh b/scripts/globals.sh index 5eb327b..56b3cd5 100644 --- a/scripts/globals.sh +++ b/scripts/globals.sh @@ -34,8 +34,6 @@ function set_globals() { KLIPPY_ENV="${HOME}/klippy-env" KLIPPER_DIR="${HOME}/klipper" KLIPPER_REPO="https://github.com/Klipper3d/klipper.git" - KLIPPER_LOGS="${HOME}/klipper_logs" - KLIPPER_CONFIG="$(get_klipper_cfg_dir)" # default: ${HOME}/klipper_config #================= MOONRAKER ==================# MOONRAKER_ENV="${HOME}/moonraker-env" diff --git a/scripts/klipper.sh b/scripts/klipper.sh index 0ce70bc..c611d98 100644 --- a/scripts/klipper.sh +++ b/scripts/klipper.sh @@ -11,36 +11,31 @@ set -e +#TODO (multi instance): +# if the klipper installer is started another time while other klipper +# instances are detected, ask if new instances should be added + #=================================================# #================ INSTALL KLIPPER ================# #=================================================# -### check for existing klipper service installations -function klipper_initd() { - local services - services=$(find "${INITD}" -maxdepth 1 -regextype posix-extended -regex "${INITD}/klipper(-[^0])?[0-9]*" | sort) - echo "${services}" -} - -function klipper_systemd() { - local services - services=$(find "${SYSTEMD}" -maxdepth 1 -regextype posix-extended -regex "${SYSTEMD}/klipper(-[0-9a-zA-Z]+)?.service" | sort) - echo "${services}" -} - -function klipper_setup_dialog() { - status_msg "Initializing Klipper installation ..." - +function start_klipper_setup() { local klipper_initd_service local klipper_systemd_services - local python_version="${1}" user_input=() + local python_version + local instance_count + local instance_names + local use_custom_names + local input + local regex local error - klipper_initd_service=$(klipper_initd) - klipper_systemd_services=$(klipper_systemd) - user_input+=("${python_version}") + status_msg "Initializing Klipper installation ...\n" ### return early if klipper already exists + klipper_initd_service=$(find_klipper_initd) + klipper_systemd_services=$(find_klipper_systemd) + if [[ -n ${klipper_initd_service} ]]; then error="Unsupported Klipper SysVinit service detected:" error="${error}\n ➔ ${klipper_initd_service}" @@ -54,10 +49,116 @@ function klipper_setup_dialog() { error="${error}\n ➔ ${s}" done fi - [[ -n ${error} ]] && print_error "${error}" && return - ### ask for amount of instances to create + ### user selection for python version + print_dialog_user_select_python_version + while true; do + read -p "${cyan}###### Select Python version:${white} " input + case "${input}" in + 1) + select_msg "Python 2.7\n" + python_version=2 + break;; + 2) + select_msg "Python 3.x\n" + python_version=3 + break;; + B|b) + clear; install_menu; break;; + *) + error_msg "Invalid Input!\n";; + esac + done && input="" + + ### user selection for instance count + print_dialog_user_select_instance_count + regex="^[1-9][0-9]*$" + while [[ ! ${input} =~ ${regex} ]]; do + read -p "${cyan}###### Number of Klipper instances to set up:${white} " -i "1" -e input + + if [[ ${input} =~ ${regex} ]]; then + instance_count="${input}" + select_msg "Instance count: ${instance_count}\n" + break + elif [[ ${input} == "B" || ${input} == "b" ]]; then + install_menu + else + error_msg "Invalid Input!\n" + fi + done && input="" + + ### user selection for custom names + use_custom_names="false" + if (( instance_count > 1 )); then + print_dialog_user_select_custom_name_bool + while true; do + read -p "${cyan}###### Assign custom names? (y/N):${white} " input + case "${input}" in + Y|y|Yes|yes) + select_msg "Yes\n" + use_custom_names="true" + break;; + N|n|No|no|"") + select_msg "No\n" + break;; + B|b) + clear; install_menu; break;; + *) + error_msg "Invalid Input!\n";; + esac + done && input="" + else + instance_names+=("printer") + fi + + ### user selection for setting the actual custom names + if (( instance_count > 1 )) && [[ ${use_custom_names} == "true" ]]; then + local i + + i=1 + regex="^[0-9a-zA-Z]+$" + while [[ ! ${input} =~ ${regex} || ${i} -le ${instance_count} ]]; do + read -p "${cyan}###### Name for instance #${i}:${white} " input + + if [[ ${input} =~ ${regex} ]]; then + select_msg "Name: ${input}\n" + if [[ ${input} =~ ^[0-9]+$ ]]; then + instance_names+=("printer_${input}") + else + instance_names+=("${input}") + fi + i=$(( i + 1 )) + else + error_msg "Invalid Input!\n" + fi + done && input="" + elif (( instance_count > 1 )) && [[ ${use_custom_names} == "false" ]]; then + for (( i=1; i <= instance_count; i++ )); do + instance_names+=("printer_${i}") + done + fi + + (( instance_count > 1 )) && status_msg "Installing ${instance_count} Klipper instances ..." + (( instance_count == 1 )) && status_msg "Installing single Klipper instance ..." + + run_klipper_setup "${python_version}" "${instance_names[@]}" +} + +function print_dialog_user_select_python_version() { + top_border + echo -e "| Please select the preferred Python version. | " + echo -e "| The recommended version is Python 2.7. | " + blank_line + echo -e "| Installing Klipper with Python 3 is officially not | " + echo -e "| recommended and should be considered as experimental. | " + hr + echo -e "| 1) [Python 2.7] (recommended) | " + echo -e "| 2) [Python 3.x] ${yellow}(experimental)${white} | " + back_footer +} + +function print_dialog_user_select_instance_count() { top_border echo -e "| Please select the number of Klipper instances to set |" echo -e "| up. The number of Klipper instances will determine |" @@ -65,89 +166,107 @@ function klipper_setup_dialog() { blank_line echo -e "| ${yellow}WARNING:${white} |" echo -e "| ${yellow}Setting up too many instances may crash your system.${white} |" - bottom_border + back_footer +} - ### ask for amount of instances - local klipper_count re="^[1-9][0-9]*$" - while [[ ! ${klipper_count} =~ ${re} ]]; do - read -p "${cyan}###### Number of Klipper instances to set up:${white} " -i "1" -e klipper_count - ### break if input is valid - [[ ${klipper_count} =~ ${re} ]] && break - ### error messages on invalid input - error_msg "Input not a number" - done && select_msg "${klipper_count}" +function print_dialog_user_select_custom_name_bool() { + top_border + echo -e "| You can now assign a custom name to each instance. |" + echo -e "| If skipped, each instance will get an index assigned |" + echo -e "| in ascending order, starting at index '1'. |" + blank_line + echo -e "| Info: |" + echo -e "| Only alphanumeric characters for names are allowed! |" + back_footer +} - user_input+=("${klipper_count}") +function run_klipper_setup() { + read_kiauh_ini "${FUNCNAME[0]}" - ### confirm instance amount - local yn - while true; do - read -p "${cyan}###### Install ${klipper_count} instance(s)? (Y/n):${white} " yn - case "${yn}" in - Y|y|Yes|yes|"") - select_msg "Yes" - break;; - N|n|No|no) - select_msg "No" - abort_msg "Exiting Klipper setup ...\n" - return;; - *) - error_msg "Invalid Input!";; - esac + local python_version=${1} + local instance_names + local confirm + local custom_repo + local custom_branch + local dep + + shift 1 + read -r -a instance_names <<< "${@}" + + custom_repo="${custom_klipper_repo}" + custom_branch="${custom_klipper_repo_branch}" + dep=(git) + + ### checking dependencies + dependency_check "${dep[@]}" + + ### step 1: clone klipper + clone_klipper "${custom_repo}" "${custom_branch}" + + ### step 2: install klipper dependencies and create python virtualenv + install_klipper_packages "${python_version}" + create_klipper_virtualenv "${python_version}" + + ### step 3: create klipper instances + for instance in "${instance_names[@]}"; do + create_klipper_service "${instance}" done - ### ask for custom names - if (( klipper_count > 1 )); then - local custom_names="false" - top_border - echo -e "| You can give each instance a custom name or skip. |" - echo -e "| If skipped, KIAUH will automatically assign an index |" - echo -e "| to each instance in ascending order, starting at '1'. |" - blank_line - echo -e "| Info: |" - echo -e "| Only alphanumeric characters will be allowed. |" - bottom_border - while true; do - read -p "${cyan}###### Use custom names? (y/N):${white} " yn - case "${yn}" in - Y|y|Yes|yes) - select_msg "Yes" - custom_names="true" - break;; - N|n|No|no|"") - select_msg "No" - break;; - *) - error_msg "Invalid Input!";; - esac - done + ### step 4: enable and start all instances + do_action_service "enable" "klipper" + do_action_service "start" "klipper" - ### get user input for custom names - if [[ ${custom_names} == "true" ]]; then - local i=1 name re="^[0-9a-zA-Z]+$" - while [[ ! ${name} =~ ${re} || ${i} -le ${klipper_count} ]]; do - read -p "${cyan}###### Name for instance #${i}:${white} " name - if [[ ${name} =~ ${re} ]]; then - select_msg "Name: ${name}" - user_input+=("${name}") - i=$(( i + 1 )) - else - error_msg "Invalid Input!" - fi - done - else - ### if no custom names are used, add the respective amount of indices to the user_input array - for (( i=1; i <= klipper_count; i++ )); do - user_input+=("${i}") - done - fi + ### step 5: check for dialout group membership + check_usergroups + + ### confirm message + (( ${#instance_names[@]} == 1 )) && confirm="Klipper has been set up!" + (( ${#instance_names[@]} > 1 )) && confirm="${#instance_names[@]} Klipper instances have been set up!" + + ### finalizing the setup with writing instance names to the kiauh.ini + set_multi_instance_names + + print_confirm "${confirm}" && return +} + +function clone_klipper() { + local repo=${1} branch=${2} + + [[ -z ${repo} ]] && repo="${KLIPPER_REPO}" + repo=$(echo "${repo}" | sed -r "s/^(http|https):\/\/github\.com\///i; s/\.git$//") + repo="https://github.com/${repo}" + + [[ -z ${branch} ]] && branch="master" + + ### force remove existing klipper dir and clone into fresh klipper dir + [[ -d ${KLIPPER_DIR} ]] && rm -rf "${KLIPPER_DIR}" + + status_msg "Cloning Klipper from ${repo} ..." + + cd "${HOME}" || exit 1 + if git clone "${repo}" "${KLIPPER_DIR}"; then + cd "${KLIPPER_DIR}" && git checkout "${branch}" + else + print_error "Cloning Klipper from\n ${repo}\n failed!" + exit 1 fi +} +function create_klipper_virtualenv() { + local python_version="${1}" - (( klipper_count > 1 )) && status_msg "Installing ${klipper_count} Klipper instances ..." - (( klipper_count == 1 )) && status_msg "Installing single Klipper instance ..." + [[ -d ${KLIPPY_ENV} ]] && rm -rf "${KLIPPY_ENV}" - klipper_setup "${user_input[@]}" + status_msg "Installing $("python${python_version}" -V) virtual environment..." + + if virtualenv -p "python${python_version}" "${KLIPPY_ENV}"; then + (( python_version == 3 )) && "${KLIPPY_ENV}"/bin/pip install -U pip + "${KLIPPY_ENV}"/bin/pip install -r "${KLIPPER_DIR}"/scripts/klippy-requirements.txt + else + log_error "failure while creating python3 klippy-env" + error_msg "Creation of Klipper virtualenv failed!" + exit 1 + fi } ### @@ -168,10 +287,10 @@ function install_klipper_packages() { ### add dbus requirement for DietPi distro [[ -e "/boot/dietpi/.version" ]] && packages+=" dbus" - if [[ ${python_version} == "python3" ]]; then + if (( python_version == 3 )); then ### replace python-dev with python3-dev if python3 was selected packages="${packages//python-dev/python3-dev}" - elif [[ ${python_version} == "python2" ]]; then + elif (( python_version == 2 )); then ### package name 'python-dev' is deprecated (-> no installation candidate) on more modern linux distros packages="${packages//python-dev/python2-dev}" else @@ -200,181 +319,68 @@ function install_klipper_packages() { fi } -function create_klipper_virtualenv() { - local python_version="${1}" +function create_klipper_service() { + local instance_name=${1} - [[ ${python_version} == "python2" ]] && \ - status_msg "Installing $(python2 -V) virtual environment..." + local printer_data + local cfg_dir + local cfg + local log + local klippy_serial + local klippy_socket + local env_file + local service + local service_template + local env_template + local suffix - [[ ${python_version} == "python3" ]] && \ - status_msg "Installing $(python3 -V) virtual environment..." + printer_data="${HOME}/${instance_name}_data" + cfg_dir="${printer_data}/config" + cfg="${cfg_dir}/printer.cfg" + log="${printer_data}/logs/klippy.log" + klippy_serial="${printer_data}/comms/klippy.serial" + klippy_socket="${printer_data}/comms/klippy.sock" + env_file="${printer_data}/systemd/klipper.env" - ### remove klippy-env if it already exists - [[ -d ${KLIPPY_ENV} ]] && rm -rf "${KLIPPY_ENV}" - - if [[ ${python_version} == "python2" ]]; then - if virtualenv -p python2 "${KLIPPY_ENV}"; then - "${KLIPPY_ENV}"/bin/pip install -r "${KLIPPER_DIR}"/scripts/klippy-requirements.txt - else - log_error "failure while creating python2 klippy-env" - error_msg "Creation of Klipper virtualenv failed!" - exit 1 - fi - fi - - if [[ ${python_version} == "python3" ]]; then - if virtualenv -p python3 "${KLIPPY_ENV}"; then - "${KLIPPY_ENV}"/bin/pip install -U pip - "${KLIPPY_ENV}"/bin/pip install -r "${KLIPPER_DIR}"/scripts/klippy-requirements.txt - else - log_error "failure while creating python3 klippy-env" - error_msg "Creation of Klipper virtualenv failed!" - exit 1 - fi - fi - - return -} - -function klipper_setup() { - read_kiauh_ini "${FUNCNAME[0]}" - ### index 0: python version, index 1: instance count, index 2-n: instance names (optional) - local user_input=("${@}") - local python_version="${user_input[0]}" && unset "user_input[0]" - local instance_arr=("${user_input[@]}") && unset "user_input[@]" - local custom_repo="${custom_klipper_repo}" - local custom_branch="${custom_klipper_repo_branch}" - ### checking dependencies - local dep=(git) - dependency_check "${dep[@]}" - - ### step 1: clone klipper - clone_klipper "${custom_repo}" "${custom_branch}" - - ### step 2: install klipper dependencies and create python virtualenv - install_klipper_packages "${python_version}" - create_klipper_virtualenv "${python_version}" - - ### step 3: create gcode_files and logs folder - [[ ! -d "${HOME}/gcode_files" ]] && mkdir -p "${HOME}/gcode_files" - [[ ! -d ${KLIPPER_LOGS} ]] && mkdir -p "${KLIPPER_LOGS}" - - ### step 4: create klipper instances - create_klipper_service "${instance_arr[@]}" - - ### step 5: enable and start all instances - do_action_service "enable" "klipper" - do_action_service "start" "klipper" - - ### step 6: check for dialout group membership - check_usergroups - - ### confirm message - local confirm="" - (( instance_arr[0] == 1 )) && confirm="Klipper has been set up!" - (( instance_arr[0] > 1 )) && confirm="${instance_arr[0]} Klipper instances have been set up!" - - print_confirm "${confirm}" && return -} - -function clone_klipper() { - local repo=${1} branch=${2} - - [[ -z ${repo} ]] && repo="${KLIPPER_REPO}" - repo=$(echo "${repo}" | sed -r "s/^(http|https):\/\/github\.com\///i; s/\.git$//") - repo="https://github.com/${repo}" - - [[ -z ${branch} ]] && branch="master" - - ### force remove existing klipper dir and clone into fresh klipper dir - [[ -d ${KLIPPER_DIR} ]] && rm -rf "${KLIPPER_DIR}" - - status_msg "Cloning Klipper from ${repo} ..." - - cd "${HOME}" || exit 1 - if git clone "${repo}" "${KLIPPER_DIR}"; then - cd "${KLIPPER_DIR}" && git checkout "${branch}" + if [[ ${instance_name} == "printer" ]]; then + suffix="${instance_name//printer/}" else - print_error "Cloning Klipper from\n ${repo}\n failed!" - exit 1 + suffix="-${instance_name//printer_/}" fi -} -function write_klipper_service() { - local i=${1} cfg=${2} log=${3} printer=${4} uds=${5} service=${6} - local service_template="${KIAUH_SRCDIR}/resources/klipper.service" + create_required_folders "${printer_data}" + + service_template="${KIAUH_SRCDIR}/resources/klipper.service" + env_template="${KIAUH_SRCDIR}/resources/klipper.env" + service="${SYSTEMD}/klipper${suffix}.service" - ### replace all placeholders if [[ ! -f ${service} ]]; then - status_msg "Creating Klipper Service ${i} ..." + status_msg "Create Klipper service file ..." + sudo cp "${service_template}" "${service}" - [[ -z ${i} ]] && sudo sed -i "s| for instance klipper-%INST%||" "${service}" - [[ -n ${i} ]] && sudo sed -i "s|%INST%|${i}|" "${service}" - sudo sed -i "s|%USER%|${USER}|; s|%ENV%|${KLIPPY_ENV}|; s|%DIR%|${KLIPPER_DIR}|" "${service}" - sudo sed -i "s|%LOG%|${log}|; s|%CFG%|${cfg}|; s|%PRINTER%|${printer}|; s|%UDS%|${uds}|" "${service}" + sudo cp "${env_template}" "${env_file}" + sudo sed -i "s|%USER%|${USER}|g; s|%ENV%|${KLIPPY_ENV}|; s|%ENV_FILE%|${env_file}|" "${service}" + sudo sed -i "s|%USER%|${USER}|; s|%LOG%|${log}|; s|%CFG%|${cfg}|; s|%PRINTER%|${klippy_serial}|; s|%UDS%|${klippy_socket}|" "${env_file}" + + ok_msg "Klipper service file created!" + fi + + if [[ ! -f ${cfg} ]]; then + write_example_printer_cfg "${cfg}" fi } function write_example_printer_cfg() { - local cfg_dir=${1} cfg=${2} - local cfg_template="${KIAUH_SRCDIR}/resources/printer.cfg" + local cfg=${1} + local cfg_template - ### create a config directory if it doesn't exist - if [[ ! -d ${cfg_dir} ]]; then - status_msg "Creating '${cfg_dir}' ..." - mkdir -p "${cfg_dir}" - fi - - ### create a minimal config if there is no printer.cfg - if [[ ! -f ${cfg} ]]; then - status_msg "Creating minimal example printer.cfg ..." - cp "${cfg_template}" "${cfg}" - fi -} - -function create_klipper_service() { - local input=("${@}") - local klipper_count=${input[0]} && unset "input[0]" - local names=("${input[@]}") && unset "input[@]" - local cfg_dir cfg log printer uds service - - if (( klipper_count == 1 )) && [[ ${#names[@]} -eq 0 ]]; then - cfg_dir="${KLIPPER_CONFIG}" - cfg="${cfg_dir}/printer.cfg" - log="${KLIPPER_LOGS}/klippy.log" - printer="/tmp/printer" - uds="/tmp/klippy_uds" - service="${SYSTEMD}/klipper.service" - ### write single instance service - write_klipper_service "" "${cfg}" "${log}" "${printer}" "${uds}" "${service}" - write_example_printer_cfg "${cfg_dir}" "${cfg}" - ok_msg "Klipper instance created!" - - elif (( klipper_count >= 1 )) && [[ ${#names[@]} -gt 0 ]]; then - local j=0 re="^[1-9][0-9]*$" - - for (( i=1; i <= klipper_count; i++ )); do - ### overwrite config folder if name is only a number - if [[ ${names[j]} =~ ${re} ]]; then - cfg_dir="${KLIPPER_CONFIG}/printer_${names[${j}]}" - else - cfg_dir="${KLIPPER_CONFIG}/${names[${j}]}" - fi - - cfg="${cfg_dir}/printer.cfg" - log="${KLIPPER_LOGS}/klippy-${names[${j}]}.log" - printer="/tmp/printer-${names[${j}]}" - uds="/tmp/klippy_uds-${names[${j}]}" - service="${SYSTEMD}/klipper-${names[${j}]}.service" - ### write multi instance service - write_klipper_service "${names[${j}]}" "${cfg}" "${log}" "${printer}" "${uds}" "${service}" - write_example_printer_cfg "${cfg_dir}" "${cfg}" - ok_msg "Klipper instance 'klipper-${names[${j}]}' created!" - j=$(( j + 1 )) - done && unset j + cfg_template="${KIAUH_SRCDIR}/resources/example.printer.cfg" + status_msg "Creating minimal example printer.cfg ..." + if cp "${cfg_template}" "${cfg}"; then + ok_msg "Minimal example printer.cfg created!" else - return 1 + error_msg "Couldn't create minimal example printer.cfg!" fi } @@ -382,71 +388,61 @@ function create_klipper_service() { #================ REMOVE KLIPPER ================# #================================================# -function remove_klipper_sysvinit() { - [[ ! -e "${INITD}/klipper" ]] && return +function remove_klipper_service() { + if [[ ! -e "${INITD}/klipper" ]] && [[ -z $(find_klipper_systemd) ]]; then + return + fi - status_msg "Removing Klipper SysVinit service ..." - sudo systemctl stop klipper - sudo update-rc.d -f klipper remove - sudo rm -f "${INITD}/klipper" "${ETCDEF}/klipper" - ok_msg "Klipper SysVinit service removed!" -} + status_msg "Removing Klipper services ..." -function remove_klipper_systemd() { - [[ -z $(klipper_systemd) ]] && return - - status_msg "Removing Klipper Systemd Services ..." - for service in $(klipper_systemd | cut -d"/" -f5); do - status_msg "Removing ${service} ..." - sudo systemctl stop "${service}" - sudo systemctl disable "${service}" - sudo rm -f "${SYSTEMD}/${service}" - ok_msg "Done!" - done - - ### reloading units - sudo systemctl daemon-reload - sudo systemctl reset-failed - ok_msg "Klipper Service removed!" -} - -function remove_klipper_logs() { - local files regex="klippy(-[0-9a-zA-Z]+)?\.log(.*)?" - files=$(find "${KLIPPER_LOGS}" -maxdepth 1 -regextype posix-extended -regex "${KLIPPER_LOGS}/${regex}" 2> /dev/null | sort) - - if [[ -n ${files} ]]; then - for file in ${files}; do - status_msg "Removing ${file} ..." - rm -f "${file}" - ok_msg "${file} removed!" + if [[ -e "${INITD}/klipper" ]]; then + sudo systemctl stop klipper + sudo update-rc.d -f klipper remove + sudo rm -f "${INITD}/klipper" "${ETCDEF}/klipper" + else + for service in $(find_klipper_systemd | cut -d"/" -f5); do + status_msg "Removing ${service} ..." + sudo systemctl stop "${service}" + sudo systemctl disable "${service}" + sudo rm -f "${SYSTEMD}/${service}" + sudo systemctl daemon-reload + sudo systemctl reset-failed done fi + + ok_msg "All Klipper services removed!" } -function remove_klipper_uds() { - local files - files=$(find /tmp -maxdepth 1 -regextype posix-extended -regex "/tmp/klippy_uds(-[0-9a-zA-Z]+)?" | sort) - - if [[ -n ${files} ]]; then - for file in ${files}; do - status_msg "Removing ${file} ..." - rm -f "${file}" - ok_msg "${file} removed!" - done - fi -} - -function remove_klipper_printer() { +function find_instance_files() { + local target_folder=${1} + local target_name=${2} local files - files=$(find /tmp -maxdepth 1 -regextype posix-extended -regex "/tmp/printer(-[0-9a-zA-Z]+)?" | sort) - if [[ -n ${files} ]]; then - for file in ${files}; do - status_msg "Removing ${file} ..." - rm -f "${file}" - ok_msg "${file} removed!" - done - fi + readarray -t files < <(find "${HOME}" -regex "${HOME}/[A-Za-z0-9_]+_data/${target_folder}/${target_name}" | sort) + + echo -e "${files[@]}" +} + +function find_legacy_klipper_logs() { + local files + local regex="klippy(-[0-9a-zA-Z]+)?\.log(.*)?" + + readarray -t files < <(find "${HOME}/klipper_logs" -maxdepth 1 -regextype posix-extended -regex "${HOME}/klipper_logs/${regex}" 2> /dev/null | sort) + echo -e "${files[@]}" +} + +function find_legacy_klipper_uds() { + local files + + readarray -t files < <(find /tmp -maxdepth 1 -regextype posix-extended -regex "/tmp/klippy_uds(-[0-9a-zA-Z]+)?" | sort) + echo -e "${files[@]}" +} + +function find_legacy_klipper_printer() { + local files + + readarray -t files < <(find /tmp -maxdepth 1 -regextype posix-extended -regex "/tmp/printer(-[0-9a-zA-Z]+)?" | sort) + echo -e "${files[@]}" } function remove_klipper_dir() { @@ -465,17 +461,38 @@ function remove_klipper_env() { ok_msg "Directory removed!" } +### +# takes in a string of space separated absolute +# filepaths and removes those files one after another +# +function remove_files() { + local files + read -r -a files <<< "${@}" + + if (( ${#files[@]} > 0 )); then + for file in "${files[@]}"; do + status_msg "Removing ${file} ..." + rm -f "${file}" + ok_msg "${file} removed!" + done + fi +} + function remove_klipper() { - remove_klipper_sysvinit - remove_klipper_systemd - remove_klipper_logs - remove_klipper_uds - remove_klipper_printer + remove_klipper_service + remove_files "$(find_instance_files "systemd" "klipper.env")" + remove_files "$(find_instance_files "logs" "klippy.log.*")" + remove_files "$(find_instance_files "comms" "klippy.sock")" + remove_files "$(find_instance_files "comms" "klippy.serial")" + + remove_files "$(find_legacy_klipper_logs)" + remove_files "$(find_legacy_klipper_uds)" + remove_files "$(find_legacy_klipper_printer)" + remove_klipper_dir remove_klipper_env - local confirm="Klipper was successfully removed!" - print_confirm "${confirm}" && return + print_confirm "Klipper was successfully removed!" && return } #================================================# @@ -493,7 +510,7 @@ function update_klipper() { local custom_repo="${custom_klipper_repo}" local custom_branch="${custom_klipper_repo_branch}" - py_ver="python$(get_klipper_python_ver)" + py_ver=$(get_klipper_python_ver) do_action_service "stop" "klipper" @@ -520,11 +537,11 @@ function update_klipper() { function get_klipper_status() { local sf_count status py_ver - sf_count="$(klipper_systemd | wc -w)" + sf_count="$(find_klipper_systemd | wc -w)" ### detect an existing "legacy" klipper init.d installation - if [[ $(klipper_systemd | wc -w) -eq 0 ]] \ - && [[ $(klipper_initd | wc -w) -ge 1 ]]; then + if [[ $(find_klipper_systemd | wc -w) -eq 0 ]] \ + && [[ $(find_klipper_initd | wc -w) -ge 1 ]]; then sf_count=1 fi @@ -595,19 +612,6 @@ function compare_klipper_versions() { #=================== HELPERS ====================# #================================================# -function get_klipper_cfg_dir() { - local cfg_dir - read_kiauh_ini "${FUNCNAME[0]}" - - if [[ -z ${custom_klipper_cfg_loc} ]]; then - cfg_dir="${HOME}/klipper_config" - else - cfg_dir="${custom_klipper_cfg_loc}" - fi - - echo "${cfg_dir}" -} - ### # reads the python version from the klipper virtual environment # diff --git a/scripts/klipperscreen.sh b/scripts/klipperscreen.sh index 945f98b..7c302fe 100644 --- a/scripts/klipperscreen.sh +++ b/scripts/klipperscreen.sh @@ -207,7 +207,7 @@ function patch_klipperscreen_update_manager() { moonraker_configs=$(find "${KLIPPER_CONFIG}" -type f -name "moonraker.conf" | sort) for conf in ${moonraker_configs}; do - if ! grep -Eq "^\[update_manager KlipperScreen\]$" "${conf}"; then + if ! grep -Eq "^\[update_manager KlipperScreen\]\s*$" "${conf}"; then ### add new line to conf if it doesn't end with one [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}" diff --git a/scripts/mainsail.sh b/scripts/mainsail.sh index bb4c282..b3c1f95 100644 --- a/scripts/mainsail.sh +++ b/scripts/mainsail.sh @@ -39,29 +39,29 @@ function install_mainsail() { ### check if another site already listens to port 80 mainsail_port_check - ### ask user to install mjpg-streamer - local install_mjpg_streamer - if [[ ! -f "${SYSTEMD}/webcamd.service" ]]; then - while true; do - echo - top_border - echo -e "| Install MJPG-Streamer for webcam support? |" - bottom_border - read -p "${cyan}###### Please select (y/N):${white} " yn - case "${yn}" in - Y|y|Yes|yes) - select_msg "Yes" - install_mjpg_streamer="true" - break;; - N|n|No|no|"") - select_msg "No" - install_mjpg_streamer="false" - break;; - *) - error_msg "Invalid command!";; - esac - done - fi +# ### ask user to install mjpg-streamer +# local install_mjpg_streamer +# if [[ ! -f "${SYSTEMD}/webcamd.service" ]]; then +# while true; do +# echo +# top_border +# echo -e "| Install MJPG-Streamer for webcam support? |" +# bottom_border +# read -p "${cyan}###### Please select (y/N):${white} " yn +# case "${yn}" in +# Y|y|Yes|yes) +# select_msg "Yes" +# install_mjpg_streamer="true" +# break;; +# N|n|No|no|"") +# select_msg "No" +# install_mjpg_streamer="false" +# break;; +# *) +# error_msg "Invalid command!";; +# esac +# done +# fi ### download mainsail download_mainsail @@ -83,7 +83,7 @@ function install_mainsail() { patch_mainsail_update_manager ### install mjpg-streamer - [[ ${install_mjpg_streamer} == "true" ]] && install_mjpg-streamer +# [[ ${install_mjpg_streamer} == "true" ]] && install_mjpg-streamer fetch_webui_ports #WIP @@ -124,9 +124,11 @@ function install_mainsail_macros() { } function download_mainsail_macros() { - local ms_cfg="https://raw.githubusercontent.com/mainsail-crew/MainsailOS/master/src/modules/mainsail/filesystem/home/pi/klipper_config/mainsail.cfg" - local configs path - configs=$(find "${KLIPPER_CONFIG}" -type f -name "printer.cfg" | sort) + local ms_cfg path configs regex + + ms_cfg="https://raw.githubusercontent.com/mainsail-crew/MainsailOS/master/src/modules/mainsail/filesystem/home/pi/klipper_config/mainsail.cfg" + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/config\/printer\.cfg" + configs=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" | sort) if [[ -n ${configs} ]]; then for config in ${configs}; do @@ -219,8 +221,23 @@ function remove_mainsail_logs() { } function remove_mainsail_log_symlinks() { + local files regex + + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/logs\/mainsail-.*" + files=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" 2> /dev/null | sort) + + if [[ -n ${files} ]]; then + for file in ${files}; do + status_msg "Removing ${file} ..." + rm -f "${file}" + ok_msg "${file} removed!" + done + fi +} + +function remove_legacy_mainsail_log_symlinks() { local files - files=$(find "${KLIPPER_LOGS}" -name "mainsail*" 2> /dev/null | sort) + files=$(find "${HOME}/klipper_logs" -name "mainsail*" 2> /dev/null | sort) if [[ -n ${files} ]]; then for file in ${files}; do @@ -236,6 +253,7 @@ function remove_mainsail() { remove_mainsail_config remove_mainsail_logs remove_mainsail_log_symlinks + remove_legacy_mainsail_log_symlinks ### remove mainsail_port from ~/.kiauh.ini sed -i "/^mainsail_port=/d" "${INI_FILE}" @@ -397,13 +415,13 @@ function ms_theme_install() { for folder in "${folder_arr[@]}"; do ### instance names/identifier of only numbers need to be prefixed with 'printer_' if [[ ${folder} =~ ^[0-9]+$ ]]; then - target_folders+=("${KLIPPER_CONFIG}/printer_${folder}") + target_folders+=("${HOME}/printer_${folder}_data/config") else - target_folders+=("${KLIPPER_CONFIG}/${folder}") + target_folders+=("${HOME}/${folder}_data/config") fi done else - target_folders+=("${KLIPPER_CONFIG}") + target_folders+=("${HOME}/printer_data/config") fi if (( ${#target_folders[@]} > 1 )); then @@ -411,7 +429,7 @@ function ms_theme_install() { echo -e "| Please select the printer you want to apply the theme |" echo -e "| installation to: |" for (( i=0; i < ${#target_folders[@]}; i++ )); do - folder=$(echo "${target_folders[${i}]}" | rev | cut -d "/" -f1 | rev) + folder=$(echo "${target_folders[${i}]}" | rev | cut -d "/" -f2 | cut -d"_" -f2- | rev) printf "|${cyan}%-55s${white}|\n" " ${i}) ${folder}" done bottom_border @@ -440,8 +458,11 @@ function ms_theme_install() { } function ms_theme_delete() { - local theme_folders target_folders=() - theme_folders=$(find "${KLIPPER_CONFIG}" -mindepth 1 -type d -name ".theme" | sort) + local regex theme_folders target_folders=() + + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/config\/\.theme" + theme_folders=$(find "${HOME}" -maxdepth 3 -type d -regextype posix-extended -regex "${regex}" | sort) +# theme_folders=$(find "${KLIPPER_CONFIG}" -mindepth 1 -type d -name ".theme" | sort) ### build target folder array for folder in ${theme_folders}; do @@ -570,12 +591,13 @@ function enable_mainsail_remotemode() { } function patch_mainsail_update_manager() { - local patched="false" - local moonraker_configs - moonraker_configs=$(find "${KLIPPER_CONFIG}" -type f -name "moonraker.conf" | sort) + local patched moonraker_configs regex + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/config\/moonraker\.conf" + moonraker_configs=$(find "${HOME}" -maxdepth 3 -type f -regextype posix-extended -regex "${regex}" | sort) + patched="false" for conf in ${moonraker_configs}; do - if ! grep -Eq "^\[update_manager mainsail\]$" "${conf}"; then + if ! grep -Eq "^\[update_manager mainsail\]\s*$" "${conf}"; then ### add new line to conf if it doesn't end with one [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}" diff --git a/scripts/moonraker-telegram-bot.sh b/scripts/moonraker-telegram-bot.sh index d10c5e1..423e8a3 100644 --- a/scripts/moonraker-telegram-bot.sh +++ b/scripts/moonraker-telegram-bot.sh @@ -203,29 +203,40 @@ function create_telegram_conf() { local input=("${@}") local telegram_bot_count=${input[0]} && unset "input[0]" local names=("${input[@]}") && unset "input[@]" - local log="${KLIPPER_LOGS}" - local cfg cfg_dir + local printer_data log_dir cfg cfg_dir if (( telegram_bot_count == 1 )); then - cfg_dir="${KLIPPER_CONFIG}" + printer_data="${HOME}/printer_data" + log_dir="${printer_data}/logs" + cfg_dir="${printer_data}/config" cfg="${cfg_dir}/telegram.conf" + + ### create required folder structure + create_required_folders "${printer_data}" + ### write single instance config - write_telegram_conf "${cfg_dir}" "${cfg}" "${log}" + write_telegram_conf "${cfg_dir}" "${cfg}" elif (( telegram_bot_count > 1 )); then local j=0 re="^[1-9][0-9]*$" for (( i=1; i <= telegram_bot_count; i++ )); do - ### overwrite config folder if name is only a number - if [[ ${names[j]} =~ ${re} ]]; then - cfg_dir="${KLIPPER_CONFIG}/printer_${names[${j}]}" - else - cfg_dir="${KLIPPER_CONFIG}/${names[${j}]}" - fi + + printer_data="${HOME}/${names[${j}]}_data" + ### prefix instance name with "printer_" if it is only a number + [[ ${names[j]} =~ ${re} ]] && printer_data="${HOME}/printer_${names[${j}]}_data" + + + cfg_dir="${printer_data}/config" cfg="${cfg_dir}/telegram.conf" + log_dir="${printer_data}/logs" + + ### create required folder structure + create_required_folders "${printer_data}" ### write multi instance config - write_telegram_conf "${cfg_dir}" "${cfg}" "${log}" + write_telegram_conf "${cfg_dir}" "${cfg}" + j=$(( j + 1 )) done && unset j @@ -235,17 +246,15 @@ function create_telegram_conf() { } function write_telegram_conf() { - local cfg_dir=${1} cfg=${2} log=${3} + local cfg_dir=${1} cfg=${2} local conf_template="${TELEGRAM_BOT_DIR}/scripts/base_install_template" - [[ ! -d ${cfg_dir} ]] && mkdir -p "${cfg_dir}" if [[ ! -f ${cfg} ]]; then status_msg "Creating telegram.conf in ${cfg_dir} ..." cp "${conf_template}" "${cfg}" - sed -i "s|some_log_path|${log}|g" "${cfg}" ok_msg "telegram.conf created!" else - status_msg "File '${cfg}' already exists!\nSkipping..." + ok_msg "File '${cfg}' already exists! Skipping..." fi } @@ -253,16 +262,22 @@ function create_telegram_bot_service() { local input=("${@}") local instances=${input[0]} && unset "input[0]" local names=("${input[@]}") && unset "input[@]" - local cfg_dir cfg log service + local printer_data cfg_dir cfg log service env_file if (( instances == 1 )); then - cfg_dir="${KLIPPER_CONFIG}" + printer_data="${HOME}/printer_data" + cfg_dir="${printer_data}/config" cfg="${cfg_dir}/telegram.conf" - log="${KLIPPER_LOGS}/telegram.log" + log="${printer_data}/logs/telegram.log" service="${SYSTEMD}/moonraker-telegram-bot.service" + env_file="${printer_data}/systemd/moonraker-telegram-bot.env" + + ### create required folder structure + create_required_folders "${printer_data}" + ### write single instance service - write_telegram_bot_service "" "${cfg}" "${log}" "${service}" - ok_msg "Single Telegram Bot instance created!" + write_telegram_bot_service "" "${cfg}" "${log}" "${service}" "${env_file}" + ok_msg "Telegram Bot instance created!" elif (( instances > 1 )); then local j=0 re="^[1-9][0-9]*$" @@ -270,17 +285,27 @@ function create_telegram_bot_service() { for (( i=1; i <= instances; i++ )); do ### overwrite config folder if name is only a number if [[ ${names[j]} =~ ${re} ]]; then - cfg_dir="${KLIPPER_CONFIG}/printer_${names[${j}]}" + printer_data="${HOME}/printer_${names[${j}]}_data" else - cfg_dir="${KLIPPER_CONFIG}/${names[${j}]}" + printer_data="${HOME}/${names[${j}]}_data" fi + cfg_dir="${printer_data}/config" cfg="${cfg_dir}/telegram.conf" - log="${KLIPPER_LOGS}/telegram-${names[${j}]}.log" + log="${printer_data}/logs/telegram.log" service="${SYSTEMD}/moonraker-telegram-bot-${names[${j}]}.service" + env_file="${printer_data}/systemd/moonraker-telegram-bot.env" + + ### create required folder structure + create_required_folders "${printer_data}" + ### write multi instance service - write_telegram_bot_service "${names[${j}]}" "${cfg}" "${log}" "${service}" - ok_msg "Telegram Bot instance moonraker-telegram-bot-${names[${j}]} created!" + if write_telegram_bot_service "${names[${j}]}" "${cfg}" "${log}" "${service}" "${env_file}"; then + ok_msg "Telegram Bot instance moonraker-telegram-bot-${names[${j}]} created!" + else + error_msg "An error occured during creation of instance moonraker-telegram-bot-${names[${j}]}!" + fi + j=$(( j + 1 )) done && unset j @@ -290,17 +315,24 @@ function create_telegram_bot_service() { } function write_telegram_bot_service() { - local i=${1} cfg=${2} log=${3} service=${4} + local i=${1} cfg=${2} log=${3} service=${4} env_file=${5} local service_template="${KIAUH_SRCDIR}/resources/moonraker-telegram-bot.service" + local env_template="${KIAUH_SRCDIR}/resources/moonraker-telegram-bot.env" ### replace all placeholders if [[ ! -f ${service} ]]; then - status_msg "Creating Telegram Bot Service ${i} ..." + status_msg "Creating service file for instance ${i} ..." sudo cp "${service_template}" "${service}" - [[ -z ${i} ]] && sudo sed -i "s|instance %INST% ||" "${service}" - [[ -n ${i} ]] && sudo sed -i "s|%INST%|${i}|" "${service}" - sudo sed -i "s|%USER%|${USER}|; s|%ENV%|${TELEGRAM_BOT_ENV}|; s|%DIR%|${TELEGRAM_BOT_DIR}|" "${service}" - sudo sed -i "s|%CFG%|${cfg}|; s|%LOG%|${log}|" "${service}" + if [[ -z ${i} ]]; then + sudo sed -i "s| %INST%||" "${service}" + else + sudo sed -i "s|%INST%|${i}|" "${service}" + fi + sudo sed -i "s|%USER%|${USER}|g; s|%ENV%|${TELEGRAM_BOT_ENV}|; s|%ENV_FILE%|${env_file}|" "${service}" + + status_msg "Creating environment file for instance ${i} ..." + cp "${env_template}" "${env_file}" + sed -i "s|%USER%|${USER}|; s|%CFG%|${cfg}|; s|%LOG%|${log}|" "${env_file}" fi } @@ -343,9 +375,35 @@ function remove_telegram_bot_env() { ok_msg "Directory removed!" } +function remove_telegram_bot_env_file() { + local files regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/systemd\/moonraker-telegram-bot\.env" + files=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" | sort) + + if [[ -n ${files} ]]; then + for file in ${files}; do + status_msg "Removing ${file} ..." + rm -f "${file}" + ok_msg "${file} removed!" + done + fi +} + function remove_telegram_bot_logs() { + local files regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/logs\/telegram\.log.*" + files=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" | sort) + + if [[ -n ${files} ]]; then + for file in ${files}; do + status_msg "Removing ${file} ..." + rm -f "${file}" + ok_msg "${file} removed!" + done + fi +} + +function remove_legacy_telegram_bot_logs() { local files regex="telegram(-[0-9a-zA-Z]+)?\.log(.*)?" - files=$(find "${KLIPPER_LOGS}" -maxdepth 1 -regextype posix-extended -regex "${KLIPPER_LOGS}/${regex}" | sort) + files=$(find "${HOME}/klipper_logs" -maxdepth 1 -regextype posix-extended -regex "${HOME}/klipper_logs/${regex}" 2> /dev/null | sort) if [[ -n ${files} ]]; then for file in ${files}; do @@ -360,7 +418,9 @@ function remove_telegram_bot() { remove_telegram_bot_systemd remove_telegram_bot_dir remove_telegram_bot_env + remove_telegram_bot_env_file remove_telegram_bot_logs + remove_legacy_telegram_bot_logs local confirm="Moonraker-Telegram-Bot was successfully removed!" print_confirm "${confirm}" && return @@ -458,12 +518,13 @@ function compare_telegram_bot_versions() { #================================================# function patch_telegram_bot_update_manager() { - local patched="false" - local moonraker_configs - moonraker_configs=$(find "${KLIPPER_CONFIG}" -type f -name "moonraker.conf" | sort) + local patched moonraker_configs regex + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/config\/moonraker\.conf" + moonraker_configs=$(find "${HOME}" -maxdepth 3 -type f -regextype posix-extended -regex "${regex}" | sort) + patched="false" for conf in ${moonraker_configs}; do - if ! grep -Eq "^\[update_manager moonraker-telegram-bot\]$" "${conf}"; then + if ! grep -Eq "^\[update_manager moonraker-telegram-bot\]\s*$" "${conf}"; then ### add new line to conf if it doesn't end with one [[ $(tail -c1 "${conf}" | wc -l) -eq 0 ]] && echo "" >> "${conf}" diff --git a/scripts/moonraker.sh b/scripts/moonraker.sh index a345d28..707b27d 100644 --- a/scripts/moonraker.sh +++ b/scripts/moonraker.sh @@ -60,7 +60,7 @@ function moonraker_setup_dialog() { ### return early if klipper is not installed local klipper_services - klipper_services=$(klipper_systemd) + klipper_services=$(find_klipper_systemd) if [[ -z ${klipper_services} ]]; then local error="Klipper not installed! Please install Klipper first!" log_error "Moonraker setup started without Klipper being installed. Aborting setup." @@ -205,7 +205,7 @@ function moonraker_setup() { create_moonraker_conf "${instance_arr[@]}" ### step 4: create moonraker instances - create_moonraker_service "${instance_arr[@]}" + configure_moonraker_service "${instance_arr[@]}" ### step 5: create polkit rules for moonraker install_moonraker_polkit || true @@ -240,18 +240,19 @@ function create_moonraker_conf() { local input=("${@}") local moonraker_count=${input[0]} && unset "input[0]" local names=("${input[@]}") && unset "input[@]" - local log="${KLIPPER_LOGS}" - local lan + local port lan printer_data cfg_dir cfg uds + + port=7125 lan="$(hostname -I | cut -d" " -f1 | cut -d"." -f1-2).0.0/16" - local port=7125 cfg_dir cfg db uds if (( moonraker_count == 1 )); then - cfg_dir="${KLIPPER_CONFIG}" + printer_data="${HOME}/printer_data" + cfg_dir="${printer_data}/config" cfg="${cfg_dir}/moonraker.conf" - db="${HOME}/.moonraker_database" - uds="/tmp/klippy_uds" + uds="${printer_data}/comms/klippy.sock" + ### write single instance config - write_moonraker_conf "${cfg_dir}" "${cfg}" "${port}" "${log}" "${db}" "${uds}" "${lan}" + write_moonraker_conf "${cfg_dir}" "${cfg}" "${port}" "${uds}" "${lan}" elif (( moonraker_count > 1 )); then local j=0 re="^[1-9][0-9]*$" @@ -259,16 +260,17 @@ function create_moonraker_conf() { for (( i=1; i <= moonraker_count; i++ )); do ### overwrite config folder if name is only a number if [[ ${names[j]} =~ ${re} ]]; then - cfg_dir="${KLIPPER_CONFIG}/printer_${names[${j}]}" + printer_data="${HOME}/printer_${names[${j}]}_data" else - cfg_dir="${KLIPPER_CONFIG}/${names[${j}]}" + printer_data="${HOME}/${names[${j}]}_data" fi + cfg_dir="${printer_data}/config" cfg="${cfg_dir}/moonraker.conf" - uds="/tmp/klippy_uds-${names[${j}]}" - db="${HOME}/.moonraker_database_${names[${j}]}" + uds="${printer_data}/comms/klippy.sock" + ### write multi instance config - write_moonraker_conf "${cfg_dir}" "${cfg}" "${port}" "${log}" "${db}" "${uds}" "${lan}" + write_moonraker_conf "${cfg_dir}" "${cfg}" "${port}" "${uds}" "${lan}" port=$(( port + 1 )) j=$(( j + 1 )) done && unset j @@ -279,7 +281,7 @@ function create_moonraker_conf() { } function write_moonraker_conf() { - local cfg_dir=${1} cfg=${2} port=${3} log=${4} db=${5} uds=${6} lan=${7} + local cfg_dir=${1} cfg=${2} port=${3} uds=${4} lan=${5} local conf_template="${KIAUH_SRCDIR}/resources/moonraker.conf" [[ ! -d ${cfg_dir} ]] && mkdir -p "${cfg_dir}" @@ -287,8 +289,7 @@ function write_moonraker_conf() { if [[ ! -f ${cfg} ]]; then status_msg "Creating moonraker.conf in ${cfg_dir} ..." cp "${conf_template}" "${cfg}" - sed -i "s|%USER%|${USER}|g" "${cfg}" - sed -i "s|%CFG%|${cfg_dir}|; s|%PORT%|${port}|; s|%LOG%|${log}|; s|%DB%|${db}|; s|%UDS%|${uds}|" "${cfg}" + sed -i "s|%USER%|${USER}|g; s|%PORT%|${port}|; s|%UDS%|${uds}|" "${cfg}" # if host ip is not in the default ip ranges replace placeholder, # otherwise remove placeholder from config if ! grep -q "${lan}" "${cfg}"; then @@ -302,20 +303,24 @@ function write_moonraker_conf() { fi } -function create_moonraker_service() { +function configure_moonraker_service() { local input=("${@}") local moonraker_count=${input[0]} && unset "input[0]" local names=("${input[@]}") && unset "input[@]" - local cfg_dir cfg log service + local printer_data cfg_dir service env_file if (( moonraker_count == 1 )) && [[ ${#names[@]} -eq 0 ]]; then i="" - cfg_dir="${KLIPPER_CONFIG}" - cfg="${cfg_dir}/moonraker.conf" - log="${KLIPPER_LOGS}/moonraker.log" + printer_data="${HOME}/printer_data" + cfg_dir="${printer_data}/config" service="${SYSTEMD}/moonraker.service" + env_file="${printer_data}/systemd/moonraker.env" + + ### create required folder structure + create_required_folders "${printer_data}" + ### write single instance service - write_moonraker_service "" "${cfg}" "${log}" "${service}" + write_moonraker_service "" "${printer_data}" "${service}" "${env_file}" ok_msg "Moonraker instance created!" elif (( moonraker_count > 1 )) && [[ ${#names[@]} -gt 0 ]]; then @@ -324,16 +329,20 @@ function create_moonraker_service() { for (( i=1; i <= moonraker_count; i++ )); do ### overwrite config folder if name is only a number if [[ ${names[j]} =~ ${re} ]]; then - cfg_dir="${KLIPPER_CONFIG}/printer_${names[${j}]}" + printer_data="${HOME}/printer_${names[${j}]}_data" else - cfg_dir="${KLIPPER_CONFIG}/${names[${j}]}" + printer_data="${HOME}/${names[${j}]}_data" fi - cfg="${cfg_dir}/moonraker.conf" - log="${KLIPPER_LOGS}/moonraker-${names[${j}]}.log" + cfg_dir="${printer_data}/config" service="${SYSTEMD}/moonraker-${names[${j}]}.service" + env_file="${printer_data}/systemd/moonraker.env" + + ### create required folder structure + create_required_folders "${printer_data}" + ### write multi instance service - write_moonraker_service "${names[${j}]}" "${cfg}" "${log}" "${service}" + write_moonraker_service "${names[${j}]}" "${printer_data}" "${service}" "${env_file}" ok_msg "Moonraker instance 'moonraker-${names[${j}]}' created!" j=$(( j + 1 )) done && unset i @@ -349,18 +358,20 @@ function create_moonraker_service() { } function write_moonraker_service() { - local i=${1} cfg=${2} log=${3} service=${4} + local i=${1} printer_data=${2} service=${3} env_file=${4} local service_template="${KIAUH_SRCDIR}/resources/moonraker.service" + local env_template="${KIAUH_SRCDIR}/resources/moonraker.env" ### replace all placeholders if [[ ! -f ${service} ]]; then status_msg "Creating Moonraker Service ${i} ..." sudo cp "${service_template}" "${service}" + sudo cp "${env_template}" "${env_file}" - [[ -z ${i} ]] && sudo sed -i "s| for instance moonraker-%INST%||" "${service}" + [[ -z ${i} ]] && sudo sed -i "s| %INST%||" "${service}" [[ -n ${i} ]] && sudo sed -i "s|%INST%|${i}|" "${service}" - sudo sed -i "s|%USER%|${USER}|; s|%ENV%|${MOONRAKER_ENV}|; s|%DIR%|${MOONRAKER_DIR}|" "${service}" - sudo sed -i "s|%CFG%|${cfg}|; s|%LOG%|${log}|" "${service}" + sudo sed -i "s|%USER%|${USER}|g; s|%ENV%|${MOONRAKER_ENV}|; s|%ENV_FILE%|${env_file}|" "${service}" + sudo sed -i "s|%USER%|${USER}|; s|%PRINTER_DATA%|${printer_data}|" "${env_file}" fi } @@ -453,9 +464,35 @@ function remove_moonraker_systemd() { ok_msg "Moonraker Services removed!" } +function remove_moonraker_env_file() { + local files regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/systemd\/moonraker\.env" + files=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" | sort) + + if [[ -n ${files} ]]; then + for file in ${files}; do + status_msg "Removing ${file} ..." + rm -f "${file}" + ok_msg "${file} removed!" + done + fi +} + function remove_moonraker_logs() { + local files regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/logs\/moonraker\.log.*" + files=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" | sort) + + if [[ -n ${files} ]]; then + for file in ${files}; do + status_msg "Removing ${file} ..." + rm -f "${file}" + ok_msg "${file} removed!" + done + fi +} + +function remove_legacy_moonraker_logs() { local files regex="moonraker(-[0-9a-zA-Z]+)?\.log(.*)?" - files=$(find "${KLIPPER_LOGS}" -maxdepth 1 -regextype posix-extended -regex "${KLIPPER_LOGS}/${regex}" 2> /dev/null | sort) + files=$(find "${HOME}/klipper_logs" -maxdepth 1 -regextype posix-extended -regex "${HOME}/klipper_logs/${regex}" 2> /dev/null | sort) if [[ -n ${files} ]]; then for file in ${files}; do @@ -509,7 +546,9 @@ function remove_moonraker_polkit() { function remove_moonraker() { remove_moonraker_sysvinit remove_moonraker_systemd + remove_moonraker_env_file remove_moonraker_logs + remove_legacy_moonraker_logs remove_moonraker_api_key remove_moonraker_polkit remove_moonraker_dir diff --git a/scripts/nginx.sh b/scripts/nginx.sh index dfff521..3a9215f 100644 --- a/scripts/nginx.sh +++ b/scripts/nginx.sh @@ -74,23 +74,29 @@ function set_upstream_nginx_cfg() { } function symlink_webui_nginx_log() { - local interface=${1} path="${KLIPPER_LOGS}" - local access_log="/var/log/nginx/${interface}-access.log" - local error_log="/var/log/nginx/${interface}-error.log" + local interface path access_log error_log regex logpaths - [[ ! -d ${path} ]] && mkdir -p "${path}" + interface=${1} + access_log="/var/log/nginx/${interface}-access.log" + error_log="/var/log/nginx/${interface}-error.log" + regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/logs" + logpaths=$(find "${HOME}" -maxdepth 2 -type d -regextype posix-extended -regex "${regex}" | sort) - if [[ -f ${access_log} && ! -L "${path}/${interface}-access.log" ]]; then - status_msg "Creating symlink for ${access_log} ..." - ln -s "${access_log}" "${path}" - ok_msg "Done!" - fi + for path in ${logpaths}; do + [[ ! -d ${path} ]] && mkdir -p "${path}" - if [[ -f ${error_log} && ! -L "${path}/${interface}-error.log" ]]; then - status_msg "Creating symlink for ${error_log} ..." - ln -s "${error_log}" "${path}" - ok_msg "Done!" - fi + if [[ -f ${access_log} && ! -L "${path}/${interface}-access.log" ]]; then + status_msg "Creating symlink for ${access_log} ..." + ln -s "${access_log}" "${path}" + ok_msg "Symlink created: ${path}/${interface}-access.log" + fi + + if [[ -f ${error_log} && ! -L "${path}/${interface}-error.log" ]]; then + status_msg "Creating symlink for ${error_log} ..." + ln -s "${error_log}" "${path}" + ok_msg "Symlink created: ${path}/${interface}-error.log" + fi + done } function match_nginx_configs() { diff --git a/scripts/obico.sh b/scripts/obico.sh index 5ccca70..1b0b393 100644 --- a/scripts/obico.sh +++ b/scripts/obico.sh @@ -24,7 +24,7 @@ function moonraker_obico_systemd() { function moonraker_obico_config() { local moonraker_cfg_dirs - read -r -a moonraker_cfg_dirs <<< "$(get_config_folders)" + read -r -a moonraker_cfg_dirs <<< "$(get_instance_folder_path "config")" if (( ${#moonraker_cfg_dirs[@]} > 0 )); then echo "${moonraker_cfg_dirs[${1}]}/moonraker-obico.cfg" @@ -65,7 +65,6 @@ function obico_server_url_prompt() { function moonraker_obico_setup_dialog() { status_msg "Initializing Moonraker-obico installation ..." - local moonraker_count local moonraker_names @@ -103,7 +102,6 @@ function moonraker_obico_setup_dialog() { if (( existing_moonraker_obico_count > 0 )); then printf "|${green}%-55s${white}|\n" " ${existing_moonraker_obico_count} Moonraker-obico instances already installed!" for svc in ${moonraker_obico_services}; do -# printf "|${cyan}%-57s${white}|\n" " ● moonraker-obco-$(get_instance_name "${svc}" moonraker-obico)" printf "|${cyan}%-57s${white}|\n" " ● moonraker-obco-$(get_instance_name "${svc}")" done fi @@ -179,17 +177,29 @@ function moonraker_obico_setup_dialog() { ### step 6: call moonrake-obico/install.sh with the correct params local port=7125 - local moonraker_cfg_dirs + local instance_cfg_dirs + local instance_log_dirs - read -r -a moonraker_cfg_dirs <<< "$(get_config_folders)" + read -r -a instance_cfg_dirs <<< "$(get_instance_folder_path "config")" + read -r -a instance_log_dirs <<< "$(get_instance_folder_path "logs")" if (( moonraker_count == 1 )); then - "${MOONRAKER_OBICO_DIR}/install.sh" -C "${moonraker_cfg_dirs[0]}/moonraker.conf" -p "${port}" -H 127.0.0.1 -l "${KLIPPER_LOGS}" -s -L -S "${obico_server_url}" + "${MOONRAKER_OBICO_DIR}/install.sh"\ + -C "${instance_cfg_dirs[0]}/moonraker.conf"\ + -p "${port}" -H 127.0.0.1 -l\ + "${instance_log_dirs[0]}"\ + -s -L -S "${obico_server_url}" elif (( moonraker_count > 1 )); then local j=${existing_moonraker_obico_count} for (( i=1; i <= new_moonraker_obico_count; i++ )); do - "${MOONRAKER_OBICO_DIR}/install.sh" -n "${moonraker_names[${j}]}" -C "${moonraker_cfg_dirs[${j}]}/moonraker.conf" -p $((port+j)) -H 127.0.0.1 -l "${KLIPPER_LOGS}" -s -L -S "${obico_server_url}" + "${MOONRAKER_OBICO_DIR}/install.sh"\ + -n "${moonraker_names[${j}]}"\ + -C "${instance_cfg_dirs[${j}]}/moonraker.conf"\ + -p $((port+j))\ + -H 127.0.0.1\ + -l "${instance_log_dirs[${j}]}"\ + -s -L -S "${obico_server_url}" j=$(( j + 1 )) done && unset j fi # (( moonraker_count == 1 )) @@ -301,8 +311,21 @@ function remove_moonraker_obico_systemd() { } function remove_moonraker_obico_logs() { + local files regex="\/home\/${USER}\/([A-Za-z0-9_]+)\/logs\/moonraker-obico(-[0-9a-zA-Z]+)?\.log(.*)?" + files=$(find "${HOME}" -maxdepth 3 -regextype posix-extended -regex "${regex}" | sort) + + if [[ -n ${files} ]]; then + for file in ${files}; do + status_msg "Removing ${file} ..." + rm -f "${file}" + ok_msg "${file} removed!" + done + fi +} + +function remove_legacy_moonraker_obico_logs() { local files regex="moonraker-obico(-[0-9a-zA-Z]+)?\.log(.*)?" - files=$(find "${KLIPPER_LOGS}" -maxdepth 1 -regextype posix-extended -regex "${KLIPPER_LOGS}/${regex}" 2> /dev/null | sort) + files=$(find "${HOME}/klipper_logs" -maxdepth 1 -regextype posix-extended -regex "${HOME}/klipper_logs/${regex}" 2> /dev/null | sort) if [[ -n ${files} ]]; then for file in ${files}; do @@ -372,7 +395,7 @@ function get_moonraker_obico_status() { is_linked="true" if [[ -n ${moonraker_obico_services} ]]; then - for cfg_dir in $(get_config_folders); do + for cfg_dir in $(get_instance_folder_path "config"); do if moonraker_obico_needs_linking "${cfg_dir}/moonraker-obico.cfg"; then is_linked="false" fi diff --git a/scripts/octoprint.sh b/scripts/octoprint.sh index db118fe..dee4851 100644 --- a/scripts/octoprint.sh +++ b/scripts/octoprint.sh @@ -25,7 +25,7 @@ function octoprint_setup_dialog() { status_msg "Initializing OctoPrint installation ..." local klipper_services - klipper_services=$(klipper_systemd) + klipper_services=$(find_klipper_systemd) if [[ -z ${klipper_services} ]]; then local error="Klipper not installed! Please install Klipper first!" log_error "OctoPrint setup started without Klipper being installed. Aborting setup." @@ -227,21 +227,30 @@ function create_octoprint_service() { local octoprint_count=${input[0]} && unset "input[0]" local names=("${input[@]}") && unset "input[@]" local j=0 port=5000 - local octo_env service basedir tmp_printer config_yaml restart_cmd + local printer_data octo_env service basedir printer config_yaml restart_cmd for (( i=1; i <= octoprint_count; i++ )); do if (( octoprint_count == 1 )); then + printer_data="${HOME}/printer_data" octo_env="${HOME}/OctoPrint" service="${SYSTEMD}/octoprint.service" basedir="${HOME}/.octoprint" - tmp_printer="/tmp/printer" + printer="${printer_data}/comms/klippy.serial" config_yaml="${basedir}/config.yaml" restart_cmd="sudo service octoprint restart" elif (( octoprint_count > 1 )); then + + local re="^[1-9][0-9]*$" + if [[ ${names[j]} =~ ${re} ]]; then + printer_data="${HOME}/printer_${names[${j}]}_data" + else + printer_data="${HOME}/${names[${j}]}_data" + fi + octo_env="${HOME}/OctoPrint_${names[${j}]}" service="${SYSTEMD}/octoprint-${names[${j}]}.service" basedir="${HOME}/.octoprint_${names[${j}]}" - tmp_printer="/tmp/printer-${names[${j}]}" + printer="${printer_data}/comms/klippy.serial" config_yaml="${basedir}/config.yaml" restart_cmd="sudo service octoprint-${names[${j}]} restart" fi @@ -280,9 +289,9 @@ OCTOPRINT /bin/sh -c "cat > ${basedir}/config.yaml" << CONFIGYAML serial: additionalPorts: - - ${tmp_printer} + - ${printer} disconnectOnErrors: false - port: ${tmp_printer} + port: ${printer} server: commands: serverRestartCommand: ${restart_cmd} diff --git a/scripts/ui/install_menu.sh b/scripts/ui/install_menu.sh index 9f60e7f..78e4f03 100755 --- a/scripts/ui/install_menu.sh +++ b/scripts/ui/install_menu.sh @@ -47,7 +47,7 @@ function install_menu() { read -p "${cyan}####### Perform action:${white} " action case "${action}" in 1) - do_action "select_klipper_python_version" "install_ui";; + do_action "start_klipper_setup" "install_ui";; 2) do_action "moonraker_setup_dialog" "install_ui";; 3) @@ -65,7 +65,10 @@ function install_menu() { 9) do_action "moonraker_obico_setup_dialog" "install_ui";; 10) - do_action "install_mjpg-streamer" "install_ui";; + #do_action "install_mjpg-streamer" "install_ui";; + clear && print_header + print_error "Function currently disabled! Sorry!" + install_ui;; B|b) clear; main_menu; break;; *) @@ -74,33 +77,3 @@ function install_menu() { done install_menu } - -function select_klipper_python_version() { - top_border - echo -e "| Please select the preferred Python version. | " - echo -e "| The recommended version is Python 2.7. | " - blank_line - echo -e "| Installing Klipper with Python 3 is officially not | " - echo -e "| recommended and should be considered as experimental. | " - hr - echo -e "| 1) [Python 2.7] (recommended) | " - echo -e "| 2) [Python 3.x] ${yellow}(experimental)${white} | " - back_footer - while true; do - read -p "${cyan}###### Select Python version:${white} " action - case "${action}" in - 1) - select_msg "Python 2.7" - klipper_setup_dialog "python2" - break;; - 2) - select_msg "Python 3.x" - klipper_setup_dialog "python3" - break;; - B|b) - clear; install_menu; break;; - *) - error_msg "Invalid Input!\n";; - esac - done -} diff --git a/scripts/ui/main_menu.sh b/scripts/ui/main_menu.sh index 925fca6..00e3989 100755 --- a/scripts/ui/main_menu.sh +++ b/scripts/ui/main_menu.sh @@ -12,6 +12,10 @@ set -e function main_ui() { + echo -e "${yellow}/=======================================================\\" + echo -e "| Please read the newest changelog carefully: |" + echo -e "| https://git.io/JnmlX |" + echo -e "\=======================================================/${white}" top_border echo -e "| $(title_msg "~~~~~~~~~~~~~~~ [ Main Menu ] ~~~~~~~~~~~~~~~") |" hr @@ -83,7 +87,8 @@ function print_klipper_repo() { function main_menu() { - print_header && main_ui + clear && print_header + main_ui ### initialize kiauh.ini init_ini @@ -103,8 +108,9 @@ function main_menu() { "restart octoprint") do_action_service "restart" "octoprint"; main_ui;; update) do_action "update_kiauh" "main_ui";; 0)clear && print_header - upload_selection - break;; + #upload_selection + print_error "Function currently disabled! Sorry!" + main_ui;; 1)clear && print_header install_menu break;; @@ -118,8 +124,9 @@ function main_menu() { advanced_menu break;; 5)clear && print_header - backup_menu - break;; + #backup_menu + print_error "Function currently disabled! Sorry!" + main_ui;; 6)clear && print_header settings_menu break;; @@ -130,5 +137,5 @@ function main_menu() { deny_action "main_ui";; esac done - clear; main_menu + main_menu } diff --git a/scripts/ui/settings_menu.sh b/scripts/ui/settings_menu.sh index bb10bb6..3146102 100755 --- a/scripts/ui/settings_menu.sh +++ b/scripts/ui/settings_menu.sh @@ -14,20 +14,12 @@ set -e function settings_ui() { read_kiauh_ini "${FUNCNAME[0]}" - local custom_cfg_loc="${custom_klipper_cfg_loc}" local custom_repo="${custom_klipper_repo}" local custom_branch="${custom_klipper_repo_branch}" local ms_pre_rls="${mainsail_install_unstable}" local fl_pre_rls="${fluidd_install_unstable}" local bbu="${backup_before_update}" - ### config location - if [[ -z ${custom_cfg_loc} ]]; then - custom_cfg_loc="${cyan}${KLIPPER_CONFIG}${white}" - else - custom_cfg_loc="${cyan}${custom_cfg_loc}${white}" - fi - ### custom repository custom_repo=$(echo "${custom_repo}" | sed "s/https:\/\/github\.com\///" | sed "s/\.git$//" ) if [[ -z ${custom_repo} ]]; then @@ -67,8 +59,6 @@ function settings_ui() { echo -e "| $(title_msg "~~~~~~~~~~~~ [ KIAUH Settings ] ~~~~~~~~~~~~~") |" hr echo -e "| Klipper: |" - echo -e "| ● Config folder: |" - printf "| %-60s|\n" "${custom_cfg_loc}" echo -e "| ● Repository: |" printf "| %-70s|\n" "${custom_repo} (${custom_branch})" hr @@ -77,24 +67,23 @@ function settings_ui() { hr printf "| Backup before updating: %-42s|\n" "${bbu}" hr - echo -e "| 1) Change Klipper config folder location |" - echo -e "| 2) Set custom Klipper repository |" + echo -e "| 1) Set custom Klipper repository |" blank_line if [[ ${mainsail_install_unstable} == "false" ]]; then - echo -e "| 3) ${green}Allow${white} unstable Mainsail releases |" + echo -e "| 2) ${green}Allow${white} unstable Mainsail releases |" else - echo -e "| 3) ${red}Disallow${white} unstable Mainsail releases |" + echo -e "| 2) ${red}Disallow${white} unstable Mainsail releases |" fi if [[ ${fluidd_install_unstable} == "false" ]]; then - echo -e "| 4) ${green}Allow${white} unstable Fluidd releases |" + echo -e "| 3) ${green}Allow${white} unstable Fluidd releases |" else - echo -e "| 4) ${red}Disallow${white} unstable Fluidd releases |" + echo -e "| 3) ${red}Disallow${white} unstable Fluidd releases |" fi blank_line if [[ ${backup_before_update} == "false" ]]; then - echo -e "| 5) ${green}Enable${white} automatic backups before updates |" + echo -e "| 4) ${green}Enable${white} automatic backups before updates |" else - echo -e "| 5) ${red}Disable${white} automatic backups before updates |" + echo -e "| 4) ${red}Disable${white} automatic backups before updates |" fi back_help_footer } @@ -105,16 +94,6 @@ function show_settings_help() { top_border echo -e "| ~~~~~~ < ? > Help: KIAUH Settings < ? > ~~~~~~ |" hr - echo -e "| ${cyan}Klipper config folder:${white} |" - echo -e "| The location of your printer.cfg and all other config |" - echo -e "| files that gets used during installation of Klipper |" - echo -e "| and all other components which need that location. |" - echo -e "| It is not recommended to change this location. |" - echo -e "| Be advised, that negative side effects could occur. |" - blank_line - printf "| Default: %-55s|\n" "${default_cfg}" - blank_line - hr echo -e "| ${cyan}Install unstable releases:${white} |" echo -e "| If set to ${green}true${white}, KIAUH installs/updates the software |" echo -e "| with the latest, currently available release. |" @@ -160,20 +139,16 @@ function settings_menu() { read -p "${cyan}####### Perform action:${white} " action case "${action}" in 1) - clear && print_header - change_klipper_cfg_folder - settings_ui;; - 2) clear && print_header change_klipper_repo_menu settings_ui;; - 3) + 2) switch_mainsail_releasetype settings_menu;; - 4) + 3) switch_fluidd_releasetype settings_menu;; - 5) + 4) toggle_backup_before_update settings_menu;; B|b) diff --git a/scripts/utilities.sh b/scripts/utilities.sh index 88d83e3..5c3a6ed 100644 --- a/scripts/utilities.sh +++ b/scripts/utilities.sh @@ -156,10 +156,6 @@ function init_ini() { echo -e "\nlogupload_accepted=false\c" >> "${INI_FILE}" fi - if ! grep -Eq "^custom_klipper_cfg_loc=" "${INI_FILE}"; then - echo -e "\ncustom_klipper_cfg_loc=\c" >> "${INI_FILE}" - fi - if ! grep -Eq "^custom_klipper_repo=" "${INI_FILE}"; then echo -e "\ncustom_klipper_repo=\c" >> "${INI_FILE}" fi @@ -184,157 +180,6 @@ function init_ini() { sed -i "/^[[:blank:]]*$/ d" "${INI_FILE}" } -function change_klipper_cfg_folder() { - local current_cfg_loc example_loc recommended_loc new_cfg_loc - current_cfg_loc="$(get_klipper_cfg_dir)" - example_loc=$(printf "%s/" "${HOME}") - recommended_loc=$(printf "%s/klipper_config" "${HOME}") - - local yn - while true; do - top_border - echo -e "| ${yellow}IMPORTANT:${white} |" - echo -e "| Please enter the new path in the following format: |" - printf "| ${cyan}%-51s${white} |\n" "${example_loc}" - blank_line - echo -e "| ${red}WARNING: ${white} |" - echo -e "| ${red}There will be no validation checks! Make sure to set${white} |" - echo -e "| ${red}a valid directory to prevent possible problems!${white} |" - blank_line - printf "| Recommended: ${cyan}%-38s${white} |\n" "${recommended_loc}" - bottom_border - echo - echo -e "${cyan}###### Please set the new Klipper config directory:${white} " - read -e -i "${current_cfg_loc}" -e new_cfg_loc - echo - read -p "${cyan}###### Set config directory to '${yellow}${new_cfg_loc}${cyan}' ? (Y/n):${white} " yn - case "${yn}" in - Y|y|Yes|yes|"") - select_msg "Yes" - set_klipper_cfg_path "${current_cfg_loc}" "${new_cfg_loc}" - print_confirm "New config directory set!" - break;; - N|n|No|no) - select_msg "No" - break;; - *) - print_error "Invalid command!";; - esac - done -} - -function set_klipper_cfg_path() { - local current_cfg_loc="${1}" new_cfg_loc="${2}" - local instance klipper_services moonraker_services moonraker_configs - - log_info "Function set_klipper_cfg_path invoked\nCurrent location: ${1}\nNew location: ${2}" - ### backup the old config dir - backup_klipper_config_dir - ### write new location to .kiauh.ini - sed -i "/^custom_klipper_cfg_loc=/d" "${INI_FILE}" - sed -i '$a'"custom_klipper_cfg_loc=${new_cfg_loc}" "${INI_FILE}" - status_msg "New directory was set to '${new_cfg_loc}'!" - - ### stop services - do_action_service "stop" "klipper" - do_action_service "stop" "moonraker" - - ### copy config files to new klipper config folder - if [[ -n ${current_cfg_loc} && -d ${current_cfg_loc} ]]; then - status_msg "Copy config files to '${new_cfg_loc}' ..." - - if [[ ! -d ${new_cfg_loc} ]]; then - log_info "Copy process started" - mkdir -p "${new_cfg_loc}" - cd "${current_cfg_loc}" - cp -r -v ./* "${new_cfg_loc}" - ok_msg "Done!" - else - log_warning "Copy process skipped, new config directory already exists and may not be empty!" - warn_msg "New config directory already exists! Copy process skipped!" - fi - fi - - klipper_services=$(klipper_systemd) - - if [[ -n ${klipper_services} ]]; then - status_msg "Re-writing Klipper services to use new config file location ..." - - for service in ${klipper_services}; do - if [[ ${service} = "/etc/systemd/system/klipper.service" ]]; then - - if grep -q "Environment=KLIPPER_CONFIG=" "${service}"; then - ### single instance klipper service installed by kiauh v4 / MainsailOS > 0.5.0 - sudo sed -i -r "/KLIPPER_CONFIG=/ s|CONFIG=(.+)\/printer\.cfg|CONFIG=${new_cfg_loc}/printer\.cfg|" "${service}" - else - ### single instance klipper service installed by kiauh v3 - sudo sed -i -r "/ExecStart=/ s|klippy\.py (.+)\/printer\.cfg|klippy\.py ${new_cfg_loc}\/printer\.cfg|" "${service}" - fi - - else - instance=$(echo "${service}" | cut -d"-" -f2 | cut -d"." -f1) - - if grep -q "Environment=KLIPPER_CONFIG=" "${service}"; then - ### multi instance klipper service installed by kiauh v4 / MainsailOS > 0.5.0 - sudo sed -i -r "/KLIPPER_CONFIG=/ s|CONFIG=(.+)\/printer_${instance}\/printer\.cfg|CONFIG=${new_cfg_loc}\/printer_${instance}\/printer\.cfg|" "${service}" - else - ### multi instance klipper service installed by kiauh v3 - sudo sed -i -r "/ExecStart=/ s|klippy\.py (.+)\/printer_${instance}\/printer\.cfg|klippy\.py ${new_cfg_loc}\/printer_${instance}\/printer\.cfg|" "${service}" - fi - fi - done - ok_msg "OK!" - fi - - moonraker_services=$(moonraker_systemd) - - if [[ -n ${moonraker_services} ]]; then - ### handle multi moonraker instance service file - status_msg "Re-writing Moonraker services to use new config file location ..." - - for service in ${moonraker_services}; do - if [[ ${service} = "/etc/systemd/system/moonraker.service" ]]; then - - if grep -q "Environment=MOONRAKER_CONF=" "${service}"; then - ### single instance moonraker service installed by kiauh v4 / MainsailOS > 0.5.0 - sudo sed -i -r "/MOONRAKER_CONF=/ s|_CONF=(.+)\/moonraker\.conf|_CONF=${new_cfg_loc}\/moonraker\.conf|" "${service}" - else - ### single instance moonraker service installed by kiauh v3 - sudo sed -i -r "/ExecStart=/ s| -c (.+)\/moonraker\.conf| -c ${new_cfg_loc}\/moonraker\.conf|" "${service}" - fi - - else - instance=$(echo "${service}" | cut -d"-" -f2 | cut -d"." -f1) - - if grep -q "Environment=MOONRAKER_CONF=" "${service}"; then - ### multi instance moonraker service installed by kiauh v4 / MainsailOS > 0.5.0 - sudo sed -i -r "/MOONRAKER_CONF=/ s|_CONF=(.+)\/printer_${instance}\/moonraker\.conf|_CONF=${new_cfg_loc}\/printer_${instance}\/moonraker\.conf|" "${service}" - else - ### multi instance moonraker service installed by kiauh v3 - sudo sed -i -r "/ExecStart=/ s| -c (.+)\/printer_${instance}\/moonraker\.conf| -c ${new_cfg_loc}\/printer_${instance}\/moonraker\.conf|" "${service}" - fi - fi - done - - moonraker_configs=$(find "${new_cfg_loc}" -type f -name "moonraker.conf" | sort) - - ### replace old file path with new one in moonraker.conf - local loc - for conf in ${moonraker_configs}; do - loc=$(echo "${conf}" | rev | cut -d"/" -f2- | rev) - sed -i -r "/config_path:/ s|config_path:.*|config_path: ${loc}|" "${conf}" - done - ok_msg "OK!" - fi - - ### reloading units - sudo systemctl daemon-reload - - ### restart services - do_action_service "restart" "klipper" - do_action_service "restart" "moonraker" -} - function switch_mainsail_releasetype() { read_kiauh_ini "${FUNCNAME[0]}" local state="${mainsail_install_unstable}" @@ -493,6 +338,38 @@ function fetch_webui_ports() { #=================== SYSTEM =====================# #================================================# +function find_klipper_initd() { + local services + services=$(find "${INITD}" -maxdepth 1 -regextype posix-extended -regex "${INITD}/klipper(-[^0])?[0-9]*" | sort) + echo "${services}" +} + +function find_klipper_systemd() { + local services + services=$(find "${SYSTEMD}" -maxdepth 1 -regextype posix-extended -regex "${SYSTEMD}/klipper(-[0-9a-zA-Z]+)?.service" | sort) + echo "${services}" +} + +function create_required_folders() { + local printer_data=${1} folders + folders=("backup" "certs" "config" "database" "gcodes" "comms" "logs" "systemd") + + for folder in "${folders[@]}"; do + local dir="${printer_data}/${folder}" + + ### remove possible symlink created by moonraker + if [[ -L "${dir}" && -d "${dir}" ]]; then + rm "${dir}" + fi + + if [[ ! -d "${dir}" ]]; then + status_msg "Creating folder '${dir}' ..." + mkdir -p "${dir}" + ok_msg "Folder '${dir}' created!" + fi + done +} + function check_system_updates() { local updates_avail info_msg updates_avail=$(apt list --upgradeable 2>/dev/null | sed "1d") @@ -720,7 +597,9 @@ function set_multi_instance_names() { local name local names="" - local services=$(klipper_systemd) + local services + + services=$(find_klipper_systemd) ### # if value of 'multi_instance_names' is not an empty @@ -780,16 +659,60 @@ function get_config_folders() { # by KIAUH convention, all instance names of only numbers # need to be prefixed with 'printer_' if [[ ${name} =~ ^[0-9]+$ ]]; then - cfg_dirs+=("${KLIPPER_CONFIG}/printer_${name}") + cfg_dirs+=("${HOME}/printer_${name}_data/config") else - cfg_dirs+=("${KLIPPER_CONFIG}/${name}") + cfg_dirs+=("${HOME}/${name}_data/config") fi done - elif [[ -z ${instance_names} && $(klipper_systemd | wc -w) -gt 0 ]]; then - cfg_dirs+=("${KLIPPER_CONFIG}") + elif [[ -z ${instance_names} && $(find_klipper_systemd | wc -w) -gt 0 ]]; then + cfg_dirs+=("${HOME}/printer_data/config") else cfg_dirs=() fi echo "${cfg_dirs[@]}" } + +### +# helper function that returns all available absolute directory paths +# based on their instance name and specified target folder +# +# @param {string}: folder name - target instance folder name (e.g. config) +# +# => return an empty string if klipper is not installed +# => return space-separated string of absolute directory paths +# +function get_instance_folder_path() { + local folder_name=${1} + local folder_paths=() + local instance_names + local path + + instance_names=$(get_multi_instance_names) + + if [[ -n ${instance_names} ]]; then + for name in ${instance_names}; do + ### + # by KIAUH convention, all instance names of only numbers + # need to be prefixed with 'printer_' + if [[ ${name} =~ ^[0-9]+$ ]]; then + path="${HOME}/printer_${name}_data/${folder_name}" + if [[ -d ${path} ]]; then + folder_paths+=("${path}") + fi + else + path="${HOME}/${name}_data/${folder_name}" + if [[ -d ${path} ]]; then + folder_paths+=("${path}") + fi + fi + done + elif [[ -z ${instance_names} && $(find_klipper_systemd | wc -w) -gt 0 ]]; then + path="${HOME}/printer_data/${folder_name}" + if [[ -d ${path} ]]; then + folder_paths+=("${path}") + fi + fi + + echo "${folder_paths[@]}" +}