From 531b3c31f684a1e56fef687de785cb0214dfa4a4 Mon Sep 17 00:00:00 2001 From: Lukas Macura Date: Tue, 12 Apr 2016 10:36:17 +0200 Subject: [PATCH] Switched working flow to trunk --- Makefile | 35 ++++++---- README.md | 100 +++++++++++++++++++++------ files/changelog.template | 2 +- files/postinst.template | 2 +- install.sh | 146 ++++++++++++++++++++++++++------------- lib/ctrl.lib.sh | 9 +-- lib/os.lib.sh | 18 ++--- lib/zaf.lib.sh | 62 ++++++++++++++--- zaf | 123 ++++++++++++++++++++++++--------- 9 files changed, 361 insertions(+), 136 deletions(-) diff --git a/Makefile b/Makefile index 3209a61..cadc4f4 100644 --- a/Makefile +++ b/Makefile @@ -4,14 +4,29 @@ CONTROLFILES=$(foreach p,$(PLUGINS),$(p)/control.zaf) ZAF_EXPORT_OPTS=$(foreach o,$(ZAF_OPTIONS),$(shell echo $(o)|cut -d '=' -f 1)) DEBIAN_DIR=tmp/deb DEBIAN_CTRL=$(DEBIAN_DIR)/DEBIAN -DEBIAN_PKG=out/zaf.deb +DEBIAN_PKG=$(shell . lib/zaf.lib.sh; echo out/zaf-$$ZAF_VERSION.deb) + +ifeq ($(ZAF_OPTIONS),) + ZAF_OPTIONS = ZAF_GIT=0 +endif +ifeq ($(IPLUGINS),) + IPLUGINS = zaf +endif all: help help: - @echo make '{deb|ipk|rpm}' '[PLUGINS="/dir/plg1 /dir/plg2] [ZAF_OPTIONS="ZAF_cfg=val ..."] [AGENT_OPTIONS="Z_Server=host ..."]' + @echo make '{deb|ipk|rpm}' '[PLUGINS="/dir/plg1 [/dir2]...] [IPLUGINS="plg1 [plg2]..."] [ZAF_OPTIONS="ZAF_cfg=val ..."] [AGENT_OPTIONS="Z_Server=host ..."]' + @echo PLUGINS are embedded into package. Has to be local directories accessible during build. + @echo IPLUGINS will be downloaded and installed after package is installed. Can be name or url accessible after package installation. + @echo -deb: deb-clean deb-init deb-deps deb-control deb-scripts deb-cp deb-package +deb: $(DEBIAN_PKG) + +$(DEBIAN_PKG): deb-clean deb-init deb-deps deb-control deb-scripts deb-cp deb-package + +clean: + @rm -rf tmp/* out/* deb-clean: @rm -rf $(DEBIAN_DIR) $(DEBIAN_PKG) @@ -29,22 +44,17 @@ deb-control: for p in $(PLUGINS); do \ DEPENDS="$$DEPENDS,$$(zaf_ctrl_get_global_option $$p/control.zaf Depends-dpkg | tr ' ' ',')"; \ done; \ - zaf_far '{ZAF_VERSION}' "0.1" $(DEBIAN_CTRL)/control + zaf_far '{ZAF_VERSION}' "$$ZAF_VERSION" $(DEBIAN_CTRL)/control deb-scripts: -ifneq ($(PLUGINS),) @. lib/zaf.lib.sh; \ . lib/ctrl.lib.sh; \ - for p in $(PLUGINS); do \ - plugins="$$plugins "$$(zaf_ctrl_get_global_option $$p/control.zaf Plugin) ; \ - done; \ - cat files/postinst.template | zaf_far '{PLUGINS}' "$$plugins" | zaf_far '{ZAF_LIB_DIR}' "/usr/lib/zaf" >$(DEBIAN_CTRL)/postinst + cat files/postinst.template | zaf_far '{PLUGINS}' "$(PLUGINS)" | zaf_far "{IPLUGINS}" "$(IPLUGINS)" | zaf_far '{ZAF_LIB_DIR}' "/usr/lib/zaf" >$(DEBIAN_CTRL)/postinst @chmod +x $(DEBIAN_CTRL)/postinst @cp files/preinst.template $(DEBIAN_CTRL)/preinst @chmod +x $(DEBIAN_CTRL)/preinst @cp files/prerm.template $(DEBIAN_CTRL)/prerm @chmod +x $(DEBIAN_CTRL)/prerm -endif deb-cp: @mkdir -p $(DEBIAN_DIR) @@ -66,13 +76,12 @@ ifneq ($(AGENT_OPTIONS),) @echo "ZAF_AGENT_OPTIONS=\"$(AGENT_OPTIONS)\"" >>$(DEBIAN_DIR)/etc/zaf.conf endif -deb-changelog: - @cp files/changelog.template $(DEBIAN_CTRL)/changelog - deb-package: @dpkg-deb -b $(DEBIAN_DIR) $(DEBIAN_PKG) @echo "\nCheck configuration:" @cat $(DEBIAN_DIR)/etc/zaf.conf + @echo PLUGINS embedded: $(PLUGINS) + @echo PLUGINS in postinst: $(IPLUGINS) @echo diff --git a/README.md b/README.md index 5e327f4..0b786eb 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ If you are maintainer of some external check, it is enough to create zaf file in ## Motivation -Did you install lot of zabbix agents? Do you want to setup them all? Do you want to change some zabbix agent options on lot of system? Do you want to write your own simple check or discovery rule for zabbix and it is nightmare to deploy same script on more zabbix agents? Are you tired searching some system specific agent check and setup them individualy? +Did you install lot of zabbix agents and try to setup similar common user parameters? Do you want to setup them all? Do you want to change some zabbix agent options on lot of system? Do you want to write your own simple check or discovery rule for zabbix and it is nightmare to deploy same script on more zabbix agents? Are you tired searching some system specific agent check and setup them individualy? So zaf is here for you :) ## Features @@ -21,60 +21,121 @@ So zaf is here for you :) * Zabbix discovery simplification. Creating zabbix item for discovery is not so easy in shell based system and result is not nice. But you can use framework function to do so. * OS packaging support (in future). * Zabbix agent autoinstallation and autoconfiguration suitable to use in puppet or another tool +* OS packaging support ## Installing Zaf You need to be root and you must have curl installed on your system. Depending on your system, github certificates may not be available so you have to use *-k* option for curl (insecure). Default installation type is silent. So there will be no questions and everything will be autodetected. This simple command should be used on most systems: ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh +curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | sh ``` ### Install options and autoconfiguration General parameters for install.sh on any system (simplest way how to install) ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | \ +curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | \ sh -s {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] ``` or use git version: ``` -git clone https://github.com/limosek/zaf.git +git clone https://github.com/limosek/zaf.git; cd zaf; git checkout 1.0 ./install.sh {auto|interactive|debug-auto|debug-interactive} [Agent-Options] [Zaf-Options] - Agent-Options: A_Option=value [...] + Agent-Options: Z_Option=value [...] Zaf-Options: ZAF_OPT=value [...] + To unset Agent-Option use Z_Option='' ``` So you can pass ANY configuration of your zabbix agent directly to installer prefixing it with *Z_*. Please note that options are *Case Sensitive*! -Next to this, you can pass ANY zaf config options by *ZAF_* prefix. Yes, we need some more documentation of ZAF options. Please look at least here: https://github.com/limosek/zaf/blob/master/install.sh#L160 +Next to this, you can pass ANY zaf config options by *ZAF_* prefix. Interresting ZAF options: +``` + # If we want to use GIT and local GIT repository + ZAF_GIT='1'# Default + + # Git repository. Can be your local version + ZAF_REPO_GITURL='https://github.com/limosek/zaf-plugins.git' + + # Where to install plugins + ZAF_PLUGINS_DIR='/usr/lib/zaf/plugins' + + # Plugins can be downloaded from http[s] too + ZAF_REPO_URL='https://raw.githubusercontent.com/limosek/zaf-plugins/master/' + +``` + Installer will try to autoguess suitable config options for your system. -Now everything was tested on Debian and OpenWrt. If somebody is interrested in, you can help and test with some rpm specific functions. +Now everything was tested on Debian and OpenWrt. If somebody is interrested in, you can help and test with some rpm specific functions. Remember that on some systems, default zabbix agent config is empty so you *need to* enter essential config options as parameters. ### Example Suppose you want to autoinstall agent on clean system. You need only curl installed. Everything else is one-cmd process. This command will install zaf, install zabbix-agent if necessary and sets zabbix variables on agent to reach server. This command can be automatized by puppet or another deploying system. ``` -curl -k https://raw.githubusercontent.com/limosek/zaf/master/install.sh | sh -s auto \ +curl -k https://raw.githubusercontent.com/limosek/zaf/1.0/install.sh | sh -s auto \ Z_Server=zabbix.server.local \ Z_ServerActive=zabbix.server.local \ Z_HostnameItem=system.hostname Z_RefreshActiveChecks=60 \ - ZAF_PLUGINS_GITURL="git://gitserver.local" + ZAF_REPO_GITURL="git://gitserver.local" +``` + +### Packaged version +You can make your own deb package with preconfigured option. It is up to you to put it to right APT repository and install. +``` +git clone https://github.com/limosek/zaf.git \ + && cd zaf \ + && git checkout 1.0 \ + && git clone https://github.com/limosek/zaf-plugins.git \ + && make deb PLUGINS="./zaf-plugins/fsx" IPLUGINS="zaf" ZAF_OPTIONS="ZAF_GIT=0" AGENT_OPTIONS="Z_Server=zabbix.server Z_ServerActive=zabbix.server Z_StartAgents=8" +sudo dpkg -i out/zaf-1.0.deb +``` +General usage: +``` +make {deb|ipk|rpm} [PLUGINS="/dir/plg1 [/dir2]...] [IPLUGINS="plg1 [plg2]..."] [ZAF_OPTIONS="ZAF_cfg=val ..."] [AGENT_OPTIONS="Z_Server=host ..."] +PLUGINS are embedded into package. Has to be local directories accessible during build. +IPLUGINS will be downloaded and installed after package is installed. Can be name or url accessible after package installation. ``` ## Zaf plugin Zaf plugin is set of configuration options and binaries which are needed for specific checks. For example, to monitor postfix, we need some cron job which is automaticaly run and next ti this, some external items which has to be configured. Do not mix zaf plugin and zabbix plugin. While zaf plugin is set of scripts or binaries external to zabbix agent, zabbix plugin is internal zabbix lodadable module. +### Control file +Control file is main part of zaf plugin. It describes how to install plugin and defines all checks. In fact, simple control file can be enough to create zaf plugin because scripts can be embeded within. There are two kind of options: global and per item. Each option can be singleline: +``` +Plugin: pluginname +``` +or multiline: +``` +Description:: + Zaf plugin for monitoring fail2ban with LLD + Credits + 2014 dron, jiri.slezka@slu.cz + 2016 limo, lukas.macura@slu.cz +:: +``` +Items are enclosed like this: +``` +Item some_item: +Description:: + Returns number of currently banned IPs for jail +:: +Parameters: jail +Cmd: sudo fail2ban-client status $1 | grep "Currently banned:" | grep -o -E "[0-9]*" +/Item +``` +During plugin installation, zaf will check all dependencies, do install binaries and generates apropriate zabbix.conf.d entries. Look into https://github.com/limosek/zaf-plugins repository for more examples. + ## Zaf utility Zaf binary can be installed on any system from openwrt to big system. It has minimal dependencies and is shell based. Is has minimal size (up to 50kb of code). It can be used for installing, removing and testing zaf plugin items. Zaf should be run as root. ``` zaf -/usr/bin/zaf Version trunk. Please use some of this commands: -/usr/bin/zaf update To update repo -/usr/bin/zaf plugins To list installed plugins -/usr/bin/zaf show [plugin] To show installed plugins or plugin info -/usr/bin/zaf items [plugin] To list all suported items [for plugin] -/usr/bin/zaf test [plugin[.item]] To test all suported items [for plugin] -/usr/bin/zaf install plugin To install plugin -/usr/bin/zaf remove plugin To remove plugin -/usr/bin/zaf self-upgrade To self-upgrade zaf -/usr/bin/zaf self-remove To self-remove zaf and its config +zaf Version 1.0. Please use some of this commands: +zaf update To update repo +zaf plugins To list installed plugins +zaf show [plugin] To show installed plugins or plugin info +zaf items [plugin] To list all suported items [for plugin] +zaf test [plugin[.item]] To test [all] suported items by zabbix_agentd [for plugin] +zaf get [plugin[.item]] To test [all] suported items by zabbix_get [for plugin] +zaf install plugin To install plugin +zaf remove plugin To remove plugin +zaf self-upgrade To self-upgrade zaf +zaf self-remove To self-remove zaf and its config ``` @@ -96,7 +157,6 @@ Installer will look into control file, run setup task defined there, fetch binar ## How it works Zaf installer will do most of actions needed to monitor some specific plugin items. Configuration of plugin is very simple and text readable. Anybody can write its own plugin or make its plugin "zafable". It is enough to create *control.zaf" file. For example, look into https://github.com/limosek/zaf-plugins repository. This is default repository for zaf. - ## I want to make my own plugin! Great! Look into https://github.com/limosek/zaf-plugins repository, look to control files and try to create your own. It is easy! You can contact me for help. diff --git a/files/changelog.template b/files/changelog.template index 98bcb73..8057848 100644 --- a/files/changelog.template +++ b/files/changelog.template @@ -1,4 +1,4 @@ -PACKAGE (0.1) zaf; urgency=medium +PACKAGE (1.0) zaf; urgency=medium * Initial release. diff --git a/files/postinst.template b/files/postinst.template index 45e6060..e5abaf1 100644 --- a/files/postinst.template +++ b/files/postinst.template @@ -8,7 +8,7 @@ configure) . /usr/lib/zaf/os.lib.sh . /usr/lib/zaf/ctrl.lib.sh cd /usr/lib/zaf && /usr/lib/zaf/install.sh reconf - zaf reinstall {PLUGINS} + zaf reinstall {PLUGINS} {IPLUGINS} fi ;; esac diff --git a/install.sh b/install.sh index 51269c9..369efb9 100755 --- a/install.sh +++ b/install.sh @@ -1,8 +1,9 @@ #!/bin/sh +[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 if [ -z "$ZAF_URL" ]; then # Runing as standalone install.sh. We have to download rest of files first. - [ -z "$ZAF_VERSION" ] && ZAF_VERSION=master + [ -z "$ZAF_VERSION" ] && ZAF_VERSION=1.0 ZAF_URL="https://github.com/limosek/zaf/" fi @@ -19,7 +20,7 @@ zaf_fetch_url(){ # Download tgz and extract to /tmp/zaf-installer zaf_download_files() { rm -rf /tmp/zaf-installer - zaf_fetch_url $ZAF_URL/archive/$ZAF_VERSION.tar.gz | tar -C /tmp -zx && mv /tmp/zaf-$ZAF_VERSION /tmp/zaf-installer + zaf_fetch_url $ZAF_URL/archive/$ZAF_VERSION.tar.gz | tar -f - -C /tmp -zx && mv /tmp/zaf-$ZAF_VERSION /tmp/zaf-installer } if ! [ -f README.md ]; then @@ -52,7 +53,6 @@ done [ -z "$ZAF_CFG_FILE" ] && ZAF_CFG_FILE=$INSTALL_PREFIX/etc/zaf.conf [ -n "$C_ZAF_DEBUG" ] && ZAF_DEBUG=$C_ZAF_DEBUG -[ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 # Read option. If it is already set in zaf.conf, it is skipped. If env variable is set, it is used instead of default # It sets global variable name on result. @@ -99,9 +99,10 @@ zaf_set_option(){ local description if ! grep -q "^$1=" ${ZAF_CFG_FILE}; then echo "$1='$2'" >>${ZAF_CFG_FILE} - zaf_dbg "Saving $1 to $2 in ${ZAF_CFG_FILE}" >&2 + zaf_dbg "Saving $1 to $2 in ${ZAF_CFG_FILE}" else - zaf_wrn "Preserving $1 to $2 in ${ZAF_CFG_FILE}" >&2 + sed -i "s#^$1=\(.*\)#$1='$2'#" ${ZAF_CFG_FILE} + zaf_dbg "Changing $1 to $2 in ${ZAF_CFG_FILE}" fi } @@ -113,7 +114,20 @@ zaf_set_agent_option() { local value="$2" if grep -q ^$option\= $ZAF_AGENT_CONFIG; then zaf_dbg "Setting option $option in $ZAF_AGENT_CONFIG." - sed -i "s/$option=(.*)/$option=$2/" $ZAF_AGENT_CONFIG + sed -i "s/$option=\(.*\)/$option=$2/" $ZAF_AGENT_CONFIG + else + zaf_move_agent_option "$1" "$2" + fi +} + +# Unset config option in zabbix agent config file +# $1 option +zaf_unset_agent_option() { + local option="$1" + local value="$2" + if grep -q ^$option\= $ZAF_AGENT_CONFIG; then + zaf_dbg "Unsetting option $option in $ZAF_AGENT_CONFIG." + sed -i "s/$option=\(.*\)/#$option=$2/" $ZAF_AGENT_CONFIG fi } @@ -157,27 +171,36 @@ zaf_configure_agent() { echo $pair | grep -q '^Z\_' || continue # Skip non Z_ vars option=$(echo $pair|cut -d '=' -f 1|cut -d '_' -f 2) value=$(echo $pair|cut -d '=' -f 2-) - zaf_set_agent_option "$option" "$value" + if [ -n "$value" ]; then + zaf_set_agent_option "$option" "$value" + else + zaf_unset_agent_option "$option" + fi options="$options Z_$option='$value'" done zaf_set_option ZAF_AGENT_OPTIONS "${options}" } -zaf_configure(){ - +zaf_preconfigure(){ zaf_detect_system zaf_os_specific zaf_configure_os - if ! zaf_is_root; then + if ! zaf_is_root; then [ -z "$INSTALL_PREFIX" ] && zaf_err "We are not root. Use INSTALL_PREFIX or become root." + else + [ "$1" != "reconf" ] && zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot install." fi - zaf_get_option ZAF_PKG "Packaging system to use" "$ZAF_PKG" "$1" - zaf_get_option ZAF_OS "Operating system to use" "$ZAF_OS" "$1" - zaf_get_option ZAF_OS_CODENAME "Operating system codename" "$ZAF_OS_CODENAME" "$1" - zaf_get_option ZAF_AGENT_PKG "Zabbix agent package" "$ZAF_AGENT_PKG" "$1" - zaf_get_option ZAF_AGENT_OPTIONS "Zabbix options to set in cfg" "$ZAF_AGENT_OPTIONS" "$1" +} + +zaf_configure(){ + + zaf_get_option ZAF_PKG "Packaging system to use" "$ZAF_PKG" "$INSTALL_MODE" + zaf_get_option ZAF_OS "Operating system to use" "$ZAF_OS" "$INSTALL_MODE" + zaf_get_option ZAF_OS_CODENAME "Operating system codename" "$ZAF_OS_CODENAME" "$INSTALL_MODE" + zaf_get_option ZAF_AGENT_PKG "Zabbix agent package" "$ZAF_AGENT_PKG" "$INSTALL_MODE" + zaf_get_option ZAF_AGENT_OPTIONS "Zabbix options to set in cfg" "$ZAF_AGENT_OPTIONS" "$INSTALL_MODE" if zaf_is_root && [ -n "$ZAF_AGENT_PKG" ]; then if ! zaf_os_specific zaf_check_deps "$ZAF_AGENT_PKG"; then - if [ "$1" = "auto" ]; then + if [ "$INSTALL_MODE" = "auto" ]; then zaf_os_specific zaf_install_agent fi fi @@ -187,20 +210,20 @@ zaf_configure(){ else ZAF_GIT=0 fi - zaf_get_option ZAF_GIT "Git is installed" "$ZAF_GIT" "$1" - zaf_get_option ZAF_CURL_INSECURE "Insecure curl (accept all certificates)" "1" "$1" - zaf_get_option ZAF_TMP_BASE "Tmp directory prefix (\$USER will be added)" "/tmp/zaf" "$1" - zaf_get_option ZAF_LIB_DIR "Libraries directory" "/usr/lib/zaf" "$1" - zaf_get_option ZAF_BIN_DIR "Directory to put binaries" "/usr/bin" "$1" - zaf_get_option ZAF_PLUGINS_DIR "Plugins directory" "${ZAF_LIB_DIR}/plugins" "$1" - [ "${ZAF_GIT}" = 1 ] && zaf_get_option ZAF_PLUGINS_GITURL "Git plugins repository" "https://github.com/limosek/zaf-plugins.git" "$1" - zaf_get_option ZAF_PLUGINS_URL "Plugins http[s] repository" "https://raw.githubusercontent.com/limosek/zaf-plugins/master/" "$1" - zaf_get_option ZAF_REPO_DIR "Plugins directory" "${ZAF_LIB_DIR}/repo" "$1" - zaf_get_option ZAF_AGENT_CONFIG "Zabbix agent config" "/etc/zabbix/zabbix_agentd.conf" "$1" + zaf_get_option ZAF_GIT "Git is installed" "$ZAF_GIT" "$INSTALL_MODE" + zaf_get_option ZAF_CURL_INSECURE "Insecure curl (accept all certificates)" "1" "$INSTALL_MODE" + zaf_get_option ZAF_TMP_BASE "Tmp directory prefix (\$USER will be added)" "/tmp/zaf" "$INSTALL_MODE" + zaf_get_option ZAF_LIB_DIR "Libraries directory" "/usr/lib/zaf" "$INSTALL_MODE" + zaf_get_option ZAF_BIN_DIR "Directory to put binaries" "/usr/bin" "$INSTALL_MODE" + zaf_get_option ZAF_PLUGINS_DIR "Plugins directory" "${ZAF_LIB_DIR}/plugins" "$INSTALL_MODE" + [ "${ZAF_GIT}" = 1 ] && zaf_get_option ZAF_REPO_GITURL "Git plugins repository" "https://github.com/limosek/zaf-plugins.git" "$INSTALL_MODE" + zaf_get_option ZAF_REPO_URL "Plugins http[s] repository" "https://raw.githubusercontent.com/limosek/zaf-plugins/master/" "$INSTALL_MODE" + zaf_get_option ZAF_REPO_DIR "Plugins directory" "${ZAF_LIB_DIR}/repo" "$INSTALL_MODE" + zaf_get_option ZAF_AGENT_CONFIG "Zabbix agent config" "/etc/zabbix/zabbix_agentd.conf" "$INSTALL_MODE" ! [ -d "${ZAF_AGENT_CONFIGD}" ] && [ -d "/etc/zabbix/zabbix_agentd.d" ] && ZAF_AGENT_CONFIGD="/etc/zabbix/zabbix_agentd.d" - zaf_get_option ZAF_AGENT_CONFIGD "Zabbix agent config.d" "/etc/zabbix/zabbix_agentd.conf.d/" "$1" - zaf_get_option ZAF_AGENT_BIN "Zabbix agent binary" "/usr/sbin/zabbix_agentd" "$1" - zaf_get_option ZAF_AGENT_RESTART "Zabbix agent restart cmd" "service zabbix-agent restart" "$1" + zaf_get_option ZAF_AGENT_CONFIGD "Zabbix agent config.d" "/etc/zabbix/zabbix_agentd.conf.d/" "$INSTALL_MODE" + zaf_get_option ZAF_AGENT_BIN "Zabbix agent binary" "/usr/sbin/zabbix_agentd" "$INSTALL_MODE" + zaf_get_option ZAF_AGENT_RESTART "Zabbix agent restart cmd" "service zabbix-agent restart" "$INSTALL_MODE" if zaf_is_root && ! [ -x $ZAF_AGENT_BIN ]; then zaf_err "Zabbix agent ($ZAF_AGENT_BIN) not installed? Use ZAF_AGENT_BIN env variable to specify location. Exiting." @@ -221,15 +244,14 @@ zaf_configure(){ zaf_set_option ZAF_LIB_DIR "$ZAF_LIB_DIR" zaf_set_option ZAF_BIN_DIR "$ZAF_BIN_DIR" zaf_set_option ZAF_PLUGINS_DIR "$ZAF_PLUGINS_DIR" - zaf_set_option ZAF_PLUGINS_URL "$ZAF_PLUGINS_URL" - [ "${ZAF_GIT}" = 1 ] && zaf_set_option ZAF_PLUGINS_GITURL "$ZAF_PLUGINS_GITURL" + zaf_set_option ZAF_REPO_URL "$ZAF_REPO_URL" + [ "${ZAF_GIT}" = 1 ] && zaf_set_option ZAF_REPO_GITURL "$ZAF_REPO_GITURL" zaf_set_option ZAF_REPO_DIR "$ZAF_REPO_DIR" zaf_set_option ZAF_AGENT_CONFIG "$ZAF_AGENT_CONFIG" zaf_set_option ZAF_AGENT_CONFIGD "$ZAF_AGENT_CONFIGD" zaf_set_option ZAF_AGENT_BIN "$ZAF_AGENT_BIN" zaf_set_option ZAF_AGENT_RESTART "$ZAF_AGENT_RESTART" [ -n "$ZAF_PREPACKAGED_DIR" ] && zaf_set_option ZAF_PREPACKAGED_DIR "$ZAF_PREPACKAGED_DIR" - ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}-$$" if zaf_is_root; then zaf_configure_agent $ZAF_AGENT_OPTIONS "$@" @@ -252,11 +274,12 @@ zaf_install_all() { zaf_install_bin $i ${ZAF_BIN_DIR}/ done zaf_install_dir ${ZAF_PLUGINS_DIR} - zaf_install_dir ${ZAF_TMP_DIR}/p/zaf zaf_install_dir ${ZAF_PLUGINS_DIR} zaf_install_dir ${ZAF_BIN_DIR} - export INSTALL_PREFIX ZAF_CFG_FILE ZAF_DEBUG - if zaf_is_root; then +} + +zaf_postconfigure() { + if zaf_is_root; then [ "${ZAF_GIT}" = 1 ] && ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf update ${INSTALL_PREFIX}/${ZAF_BIN_DIR}/zaf reinstall zaf || zaf_err "Error installing zaf plugin." if zaf_is_root && ! zaf_test_item zaf.framework_version; then @@ -267,62 +290,91 @@ zaf_install_all() { exit 1 fi else - [ "${ZAF_GIT}" = 1 ] && [ -n "${INSTALL_PREFIX}" ] && git clone "${ZAF_PLUGINS_GITURL}" "${INSTALL_PREFIX}/${ZAF_REPO_DIR}" + [ "${ZAF_GIT}" = 1 ] && [ -n "${INSTALL_PREFIX}" ] && git clone "${ZAF_REPO_GITURL}" "${INSTALL_PREFIX}/${ZAF_REPO_DIR}" fi - rm -rif ${ZAF_TMP_DIR} - echo "Install OK. Use 'zaf' without parameters to continue." + zaf_wrn "Install done. Use 'zaf' to get started. Do not forget to do 'zaf upgrade' to upgrade plugins too!" + true } if [ -f "${ZAF_CFG_FILE}" ]; then . "${ZAF_CFG_FILE}" fi -ZAF_TMP_DIR="${ZAF_TMP_BASE-/tmp/zaf}-${USER}-$$" +ZAF_TMP_DIR="/tmp/zaf-installer-tmp/" + +# If debug is on, do not remove tmp dir +if [ "$ZAF_DEBUG" -le 3 ]; then + trap "rm -rif ${ZAF_TMP_DIR}" EXIT + trap "rm -rif /tmp/zaf-installer" EXIT +fi +! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" case $1 in interactive) shift - zaf_configure interactive + INSTALL_MODE=interactive + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; auto) shift - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; debug-auto) shift; ZAF_DEBUG=4 - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; debug-interactive) shift; ZAF_DEBUG=4 - zaf_configure interactive + INSTALL_MODE=interactive + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; debug) shift; ZAF_DEBUG=4 - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; reconf) shift; rm -f $ZAF_CFG_FILE - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure reconf + zaf_configure "$@" + zaf_postconfigure ;; install) - zaf_configure auto + INSTALL_MODE=auto + zaf_preconfigure nor + zaf_configure "$@" zaf_install_all + zaf_postconfigure ;; *) echo echo "Please specify how to install." echo "install.sh {auto|interactive|debug-auto|debug-interactive|reconf} [Agent-Options] [Zaf-Options]" echo "scratch means that config file will be created from scratch" - echo " Agent-Options: A_Option=value [...]" + echo " Agent-Options: Z_Option=value [...]" echo " Zaf-Options: ZAF_OPT=value [...]" + echo " To unset Agent-Option use Z_Option=''" echo echo "Example 1 (default install): install.sh auto" echo 'Example 2 (preconfigure agent options): install.sh auto A_Server=zabbix.server A_ServerActive=zabbix.server A_Hostname=$(hostname)' diff --git a/lib/ctrl.lib.sh b/lib/ctrl.lib.sh index 028404d..05f9b12 100644 --- a/lib/ctrl.lib.sh +++ b/lib/ctrl.lib.sh @@ -71,12 +71,13 @@ zaf_ctrl_get_item_option() { zaf_ctrl_check_deps() { local deps deps=$(zaf_ctrl_get_global_block <$1 | zaf_block_get_option "Depends-${ZAF_PKG}" ) - zaf_os_specific zaf_check_deps $deps + if ! zaf_os_specific zaf_check_deps $deps; then + zaf_err "Missing one of dependend system packages: $deps" + fi deps=$(zaf_ctrl_get_global_block <$1 | zaf_block_get_option "Depends-bin" ) for cmd in $deps; do if ! which $cmd >/dev/null; then - zaf_wrn "Missing binary dependency $cmd. Please install it first." - return 1 + zaf_err "Missing binary dependency $cmd. Please install it first." fi done } @@ -139,7 +140,7 @@ zaf_ctrl_generate_cfg() { fi cmd=$(zaf_ctrl_get_item_option $1 $i "Function") if [ -n "$cmd" ]; then - $(which echo) -E "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; + $(which echo) "UserParameter=$ikey,${ZAF_LIB_DIR}/preload.sh $lock$cmd"; continue; fi cmd=$(zaf_ctrl_get_item_option $1 $i "Script") diff --git a/lib/os.lib.sh b/lib/os.lib.sh index cb5c0ff..48ea6a5 100644 --- a/lib/os.lib.sh +++ b/lib/os.lib.sh @@ -12,28 +12,30 @@ zaf_configure_os_freebsd() { ZAF_AGENT_PKG="zabbix3-agent" ZAF_AGENT_CONFIG="/usr/local/etc/zabbix3/zabbix_agentd.conf" ZAF_AGENT_CONFIGD="/usr/local/etc/zabbix3/zabbix_agentd.conf.d/" + ZAF_AGENT_BIN="/usr/local/sbin/zabbix_agentd" + ZAF_AGENT_RESTART="service zabbix_agentd restart" } zaf_detect_system() { if which dpkg >/dev/null; then ZAF_PKG=dpkg - ZAF_OS=$(lsb_release -is|tr '[:upper:]' '[:lower:]') - ZAF_OS_CODENAME=$(lsb_release -cs|tr '[:upper:]' '[:lower:]') + ZAF_OS=$(lsb_release -is|zaf_tolower) + ZAF_OS_CODENAME=$(lsb_release -cs|zaf_tolower) ZAF_CURL_INSECURE=0 ZAF_AGENT_PKG="zabbix-agent" return else if which rpm >/dev/null; then ZAF_PKG="rpm" - ZAF_OS=$(lsb_release -is|tr '[:upper:]' '[:lower:]') - ZAF_OS_CODENAME=$(lsb_release -cs|tr '[:upper:]' '[:lower:]') + ZAF_OS=$(lsb_release -is|zaf_tolower) + ZAF_OS_CODENAME=$(lsb_release -cs|zaf_tolower) ZAF_CURL_INSECURE=0 ZAF_AGENT_PKG="zabbix-agent" return else if which opkg >/dev/null; then ZAF_PKG="opkg" . /etc/openwrt_release - ZAF_OS="$(echo $DISTRIB_ID|tr '[:upper:]' '[:lower:]')" - ZAF_OS_CODENAME="$(echo $DISTRIB_CODENAME|tr '[:upper:]' '[:lower:]')" + ZAF_OS="$(echo $DISTRIB_ID|zaf_tolower)" + ZAF_OS_CODENAME="$(echo $DISTRIB_CODENAME|zaf_tolower)" return else if which pkg >/dev/null; then ZAF_PKG="pkg" @@ -145,7 +147,7 @@ zaf_check_deps_rpm() { zaf_check_deps_opkg() { local p for p in $*; do - opkg info $p | grep -q 'Package:' || { echo "Missing package $p" >&2; return 1; } + opkg info $p | grep -q 'Package:' || { return 1; } done } @@ -154,7 +156,7 @@ zaf_check_deps_opkg() { zaf_check_deps_pkg() { local p for p in $*; do - pkg query -x "Package: %n" $p| grep -q 'Package:' || { echo "Missing package $p" >&2; return 1; } + pkg query -x "Package: %n" $p| grep -q 'Package:' || { return 1; } done } diff --git a/lib/zaf.lib.sh b/lib/zaf.lib.sh index e08a539..c45716b 100644 --- a/lib/zaf.lib.sh +++ b/lib/zaf.lib.sh @@ -2,6 +2,7 @@ # Hardcoded variables ZAF_VERSION="master" ZAF_URL="https://github.com/limosek/zaf" +ZAF_RAW_URL="https://raw.githubusercontent.com/limosek/zaf" ############################################ Common routines @@ -143,11 +144,11 @@ zaf_check_agent_config() { # Update repo zaf_update_repo() { - [ "$ZAF_GIT" != 1 ] && { zaf_err "Git is not installed. Exiting."; } - if [ -z "${ZAF_PLUGINS_GITURL}" ] || [ -z "${ZAF_REPO_DIR}" ]; then + [ "$ZAF_GIT" != 1 ] && { zaf_err "Git is disabled or is not installed. Exiting."; } + if [ -z "${ZAF_REPO_GITURL}" ] || [ -z "${ZAF_REPO_DIR}" ]; then zaf_err "This system is not configured for git repository." else - [ ! -d "${ZAF_REPO_DIR}" ] && git clone "${ZAF_PLUGINS_GITURL}" "${ZAF_REPO_DIR}" + [ ! -d "${ZAF_REPO_DIR}" ] && git clone "${ZAF_REPO_GITURL}" "${ZAF_REPO_DIR}" (cd ${ZAF_REPO_DIR} && git pull) fi } @@ -171,7 +172,11 @@ zaf_get_plugin_url() { if [ -n "${ZAF_PREPACKAGED_DIR}" ] && [ -d "${ZAF_PREPACKAGED_DIR}/$1" ]; then url="${ZAF_PREPACKAGED_DIR}/$1" else - zaf_err "Plugin $1 not found." + if [ -n "${ZAF_REPO_URL}" ]; then + url="${ZAF_REPO_URL}/$1" + else + zaf_err "Cannot find plugin $1" + fi fi fi fi @@ -183,6 +188,7 @@ zaf_get_plugin_url() { zaf_plugin_info() { local control="$1" + ! [ -f "$control" ] && zaf_err "Control file $control not found." plugin=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_option Plugin) pdescription=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_moption Description) pmaintainer=$(zaf_ctrl_get_global_block <"${control}" | zaf_block_get_option Maintainer) @@ -209,7 +215,7 @@ zaf_prepare_plugin() { local plugindir local control - url=$(zaf_get_plugin_url "$1")/control.zaf + url=$(zaf_get_plugin_url "$1")/control.zaf || exit $? plugindir="$2" control=${plugindir}/control.zaf zaf_install_dir "$plugindir" @@ -217,7 +223,7 @@ zaf_prepare_plugin() { if zaf_fetch_url "$url" >"${control}"; then zaf_ctrl_check_deps "${control}" else - zaf_err "Cannot fetch or write control file!" + zaf_err "prepare_plugin: Cannot fetch or write control file $control from url $url!" fi } @@ -231,7 +237,7 @@ zaf_install_plugin() { url=$(zaf_get_plugin_url "$1") plugin=$(zaf_ctrl_get_global_block <"${ZAF_TMP_DIR}/plugin/control.zaf" | zaf_block_get_option Plugin) plugindir="${ZAF_PLUGINS_DIR}"/$plugin - if zaf_prepare_plugin "$1" $plugindir; then + if [ -n "$plugin" ] && zaf_prepare_plugin "$1" $plugindir; then control=${plugindir}/control.zaf [ "$ZAF_DEBUG" -gt 0 ] && zaf_plugin_info "${control}" zaf_ctrl_check_deps "${control}" @@ -240,7 +246,7 @@ zaf_install_plugin() { | zaf_far '{PLUGINDIR}' "${plugindir}" >${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf zaf_dbg "Generated ${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf" else - zaf_err "Cannot install plugin $plugin to $plugindir!" + zaf_err "Cannot install plugin '$plugin' to $plugindir!" fi else zaf_err "Cannot prepare plugin $1" @@ -266,7 +272,9 @@ zaf_discovery_plugins() { zaf_list_plugins | zaf_discovery '{#PLUGIN}' } -zaf_plugin_version() { +# $1 plugin +# $2 ctrl_option +zaf_plugin_option() { local plugindir local cfile @@ -276,12 +284,28 @@ zaf_plugin_version() { if zaf_is_plugin "$1"; then plugindir="${ZAF_PLUGINS_DIR}/$1" cfile="$plugindir/control.zaf" - zaf_ctrl_get_global_option $cfile Version + zaf_ctrl_get_global_option $cfile $2 else zaf_err "Plugin $1 not installed." fi } +zaf_plugin_version() { + zaf_plugin_option "$1" Version +} +zaf_plugin_maintainer() { + zaf_plugin_option "$1" Maintainer +} +zaf_plugin_url() { + zaf_plugin_option "$1" Url +} +zaf_plugin_web() { + zaf_plugin_option "$1" Web +} +zaf_plugin_template_url() { + echo $(zaf_plugin_option "$1" Url)/template.xml +} + zaf_list_plugin_items() { local items local i @@ -312,7 +336,18 @@ zaf_list_items() { done } +zaf_get_item() { + if which zabbix_get >/dev/null; then + zabbix_get -s localhost -k "$1" || zaf_wrn "Cannot reach agent on localhost. Please localhost to Server list." + return 11 + else + zaf_wrn "Please install zabbix_get binary to check items over network." + return 11 + fi +} + zaf_test_item() { + [ "$USER" != "zabbix" ] && zaf_wrn "You are not zabbix user. Test will be run with your privileges and sudo access!" $ZAF_AGENT_BIN -t "$1" } @@ -323,4 +358,11 @@ zaf_remove_plugin() { rm -f ${ZAF_AGENT_CONFIGD}/zaf_${plugin}.conf } +zaf_tolower() { + tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' +} + +zaf_toupper() { + tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +} diff --git a/zaf b/zaf index 1e2fd88..6c70dda 100755 --- a/zaf +++ b/zaf @@ -18,9 +18,15 @@ done [ -z "$ZAF_TMP_BASE" ] && ZAF_TMP_BASE=/tmp/zaf ZAF_TMP_DIR="${ZAF_TMP_BASE}-${USER}" -trap "rm -rif ${ZAF_TMP_DIR}" EXIT -! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" [ -z "$ZAF_DEBUG" ] && ZAF_DEBUG=1 +export ZAF_DEBUG + +# If debug is on, do not remove tmp dir +if [ "$ZAF_DEBUG" -le 3 ]; then + trap "rm -rif ${ZAF_TMP_DIR}" EXIT +fi + +! [ -d "${ZAF_TMP_DIR}" ] && mkdir "${ZAF_TMP_DIR}" if [ -f ./lib/zaf.lib.sh ]; then . ./lib/zaf.lib.sh @@ -34,6 +40,25 @@ else [ -f ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh ] && . ${ZAF_LIB_DIR}/zaf.${ZAF_OS}.sh fi +zaf_shift(){ + local s + + if echo $1 |grep -q "="; then + if echo $2 |grep -q "="; then + if echo $3 |grep -q "="; then + s=3 + else + s=2 + fi + else + s=1 + fi + else + s=0 + fi + echo $s +} + case $1 in check-agent-config) @@ -41,24 +66,30 @@ check-agent-config) ;; update) - zaf_wrn "Updating repository ${ZAF_PLUGINS_GITURL}..." + zaf_wrn "Updating repository ${ZAF_REPO_GITURL}..." zaf_update_repo ;; - +upgrade) + zaf_list_plugins | while read plugin; do + ZAF_DEBUG=$ZAF_DEBUG $0 reinstall $plugin || zaf_err "Error upgrading $plugin" + done + ;; show) - if [ -z "$2" ]; then + shift; + shift $(zaf_shift "$@") + if [ -z "$1" ]; then zaf_list_plugins | while read plugin; do zaf_plugin_info $ZAF_PLUGINS_DIR/$plugin/control.zaf done - else - if zaf_list_plugins | grep -q "^$2"; then - zaf_plugin_info $ZAF_PLUGINS_DIR/$2/control.zaf + else + if zaf_list_plugins | grep -q "^$1"; then + [ -f $ZAF_PLUGINS_DIR/$1/control.zaf ] && zaf_plugin_info $ZAF_PLUGINS_DIR/$1/control.zaf || zaf_err "Plugin $1 not installed." else - if echo $2 |grep -q ^http; then - zaf_prepare_plugin "$2" "$ZAF_TMP_DIR/plugin" + if echo $1 |grep -q ^http; then + zaf_prepare_plugin "$1" "$ZAF_TMP_DIR/plugin" zaf_plugin_info "$ZAF_TMP_DIR/plugin/control.zaf" else - zaf_err "Plugin $2 not installed." + zaf_err "Plugin $1 not installed." fi fi fi @@ -69,33 +100,55 @@ plugins) ;; items) - if [ -z "$2" ]; then + shift + shift $(zaf_shift "$@") + if [ -z "$1" ]; then zaf_list_items else - zaf_list_plugin_items "$2" + zaf_list_plugin_items "$1" fi ;; test) - if echo $2|grep -q '\.'; then - zaf_test_item "$2" + shift + shift $(zaf_shift "$@") + if echo $1|grep -q '\.'; then + zaf_test_item "$1" exit fi - if [ -n "$2" ]; then - shift + if [ -n "$1" ]; then + plugins="$@" + else + plugins="$(zaf_list_plugins)" + fi + for p in $plugins; do + ! zaf_is_plugin $p && zaf_err "Unknown plugin $p" + for i in $(zaf_list_plugin_items $p); do + echo $i: $(zaf_test_item $i) + done + done + ;; +get) + shift + shift $(zaf_shift "$@") + if echo $1|grep -q '\.'; then + zaf_get_item "$1" + exit + fi + if [ -n "$1" ]; then plugins="$@" else plugins="$(zaf_list_plugins)" fi for p in $plugins; do for i in $(zaf_list_plugin_items $p); do - echo $i: $(zaf_test_item $i) + echo $i: $(zaf_get_item $i) done done ;; - install) - shift; + shift + shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 install plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then @@ -109,7 +162,8 @@ install) ;; reinstall) - shift; + shift + shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 reinstall plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then @@ -123,7 +177,8 @@ reinstall) ;; remove) - shift; + shift + shift $(zaf_shift "$@") [ -z "$1" ] && echo "$0 remove plugin [plugin]..." for p in $@; do if zaf_is_plugin "$p"; then @@ -135,26 +190,25 @@ remove) ;; self-upgrade) + shift + shift $(zaf_shift "$@") + [ -z "$1" ] && auto=auto zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-upgrade." rm -rf /tmp/zaf-installer && mkdir /tmp/zaf-installer if ! which curl >/dev/null; then zaf_err "Curl not found. Cannot continue. Please install it." fi - [ -z "$2" ] && auto=auto - set -e - mkdir -p /tmp/zaf-installer \ - && cd /tmp/zaf-installer \ - && (for i in lib/zaf.lib.sh lib/os.lib.sh lib/ctrl.lib.sh install.sh ; do echo curl -f -k -s -L -o - "$ZAF_URL/$i" >&2; curl -f -k -s -L -o - "$ZAF_URL/$i"; done) >install.sh \ - && chmod +x install.sh \ - && exec ./install.sh $auto "$@" + zaf_fetch_url $ZAF_RAW_URL/$ZAF_VERSION/install.sh | exec sh -s $auto "$@" exit ;; self-remove) + shift + shift $(zaf_shift "$@") zaf_os_specific zaf_check_deps zaf && zaf_err "Zaf is installed as system package. Cannot self-remove." . /etc/zaf.conf - if [ "$2" = "force" ]; then + if [ "$1" = "force" ]; then rm -rf /etc/zaf.conf ${ZAF_PLUGINS_DIR} ${ZAF_REPO_DIR} ${ZAF_LIB_DIR} \ ${ZAF_BIN_DIR}/zaf ${ZAF_AGENT_CONFIGD}/zaf_* else @@ -169,15 +223,20 @@ self-remove) *) echo "$0 Version ${ZAF_VERSION}. Please use some of this commands:" - echo "$0 update To update repo" + echo "$0 Cmd [ZAF_OPTION=value] ..." + echo "Commands:" + echo "$0 update To update repo (not plugins, similar to apt-get update)" + echo "$0 upgrade To upgrade installed plugins from repo" echo "$0 plugins To list installed plugins" echo "$0 show [plugin] To show installed plugins or plugin info" echo "$0 items [plugin] To list all suported items [for plugin]" - echo "$0 test [plugin[.item]] To test all suported items [for plugin]" + echo "$0 test [plugin[.item]] To test [all] suported items by zabbix_agentd [for plugin]" + echo "$0 get [plugin[.item]] To test [all] suported items by zabbix_get [for plugin]" echo "$0 install plugin To install plugin" echo "$0 remove plugin To remove plugin" echo "$0 self-upgrade To self-upgrade zaf" echo "$0 self-remove To self-remove zaf and its config" + echo ;; esac