From 525a1a9f4272479c0cd555c5e016124ff524c24c Mon Sep 17 00:00:00 2001 From: Mark Date: Sun, 2 Aug 2026 13:41:26 +0800 Subject: [PATCH] Make Zabbix agent argument errors say which fix is needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running the Linux Zabbix agent script from TacticalRMM against a newly onboarded site failed with 'ERROR: ZabbixProxy and ZabbixServer are required', which does not say what to do — and fires for three different causes needing three different fixes. Traced through the TacticalRMM source: parse_script_args passes an argument through unaltered when the resolved value is falsy, and get_db_value falls back to the custom field's default_value when the site has no saved value. So the failure modes reach the script differently: - empty value -> the custom field exists but is blank for this site - literal {{...}} -> no custom field / Key Store entry is defined at all - no arguments -> the script's Arguments field was never populated Each is now reported separately with the exact TacticalRMM UI path to fix it, including that global variables come from the Key Store rather than Custom Fields. No behaviour change for a correctly configured run. --- install-zabbix-agent-linux-tactical-rmm.sh | 48 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/install-zabbix-agent-linux-tactical-rmm.sh b/install-zabbix-agent-linux-tactical-rmm.sh index ace20de..8f247d2 100644 --- a/install-zabbix-agent-linux-tactical-rmm.sh +++ b/install-zabbix-agent-linux-tactical-rmm.sh @@ -32,13 +32,57 @@ AGENT_CONF_D="/etc/zabbix/zabbix_agent2.d" # --- Input validation -------------------------------------------------------- # SECURITY: Validate all arguments before use in URLs, config files, or commands. +# TacticalRMM leaves an argument completely untouched when it cannot resolve the +# variable, so a literal "{{...}}" arriving here means the custom field or Key +# Store entry does not exist at all. An empty value means the opposite: the +# field exists but has no value for this agent's site. The two need different +# fixes, so report them differently rather than as one generic "required". +unresolved_var() { [[ "$1" == *'{{'*'}}'* ]]; } + +if [[ $# -eq 0 ]]; then + echo "ERROR: No arguments were passed." + echo " In TacticalRMM the script's Arguments field must be populated, in order:" + echo " {{site.ZabbixProxy}} {{site.ZabbixServer}} {{global.DiscordWebhook}} \\" + echo " {{global.ZabbixVersion}} {{global.ZabbixMSSQLPassword}} {{site.MSSQLSAPassword}} \\" + echo " {{agent.ZabbixHostName}}" + exit 1 +fi + +for pair in "ZabbixProxy:${ZABBIX_PROXY}:Site" \ + "ZabbixServer:${ZABBIX_SERVER}:Site" \ + "ZabbixVersion:${ZABBIX_VERSION}:Global"; do + var_name="${pair%%:*}" + var_rest="${pair#*:}" + var_value="${var_rest%:*}" + var_scope="${var_rest##*:}" + + if unresolved_var "$var_value"; then + echo "ERROR: TacticalRMM did not substitute ${var_name} — it arrived as: ${var_value}" + if [[ "$var_scope" == "Global" ]]; then + echo " That means no '${var_name}' entry exists in the Key Store." + echo " Create it in: Settings -> Global Settings -> Key Store" + else + echo " That means no '${var_name}' custom field is defined for ${var_scope}s." + echo " Create it in: Settings -> Global Settings -> Custom Fields (model: ${var_scope})" + fi + exit 1 + fi +done + if [[ -z "$ZABBIX_PROXY" || -z "$ZABBIX_SERVER" ]]; then - echo "ERROR: ZabbixProxy and ZabbixServer are required." + [[ -z "$ZABBIX_PROXY" ]] && echo "ERROR: ZabbixProxy is empty." + [[ -z "$ZABBIX_SERVER" ]] && echo "ERROR: ZabbixServer is empty." + echo " The Site custom field exists but has no value for this agent's site," + echo " so TacticalRMM substituted an empty string." + echo " Set it in: Clients -> -> Sites -> -> Edit -> Custom Fields" + echo " Both ZabbixProxy and ZabbixServer must be set on every site you deploy to." exit 1 fi if [[ -z "$ZABBIX_VERSION" ]]; then - echo "ERROR: ZabbixVersion global variable is not set." + echo "ERROR: ZabbixVersion is empty." + echo " Set it in: Settings -> Global Settings -> Key Store (e.g. 7.4)" + echo " Linux takes major.minor only — 7.4, not 7.4.13." exit 1 fi