Ad Widget

Collapse

UserParameter and shell commands

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • joke
    Junior Member
    • Jan 2010
    • 10

    #1

    UserParameter and shell commands

    hi,

    I'm trying to setup some user parameters within the agent to monitor some parameters.

    But zabbix always seems to run user parameters like
    Code:
    UserParameter=dpkg.updates,/usr/lib/update-notifier/apt-check 2>&1 | IFS=';' read -A; print ${reply[2]}
    within the shell /bin/sh.

    Recent ubuntu systems configure dash (a minimal sh compatible shell) as default shell which is fine because all init scripts are sh compatible but I would really like to use advanced bash or zsh scripts for all my users parameters.

    How can I tell zabbix to use /bin/bash or /bin/zsh rather than /bin/sh?

    Thanks.
  • richlv
    Senior Member
    Zabbix Certified Trainer
    Zabbix Certified SpecialistZabbix Certified Professional
    • Oct 2005
    • 3112

    #2
    you could set up a wrapper script and specify bash in shebang
    Zabbix 3.0 Network Monitoring book

    Comment

    • alixen
      Senior Member
      • Apr 2006
      • 474

      #3
      Hi,

      You could explicitly call bash:
      Code:
      UserParameter=dpkg.updates,bash -c "/usr/lib/update-notifier/apt-check 2>&1 | IFS=';' read -A; print ${reply[2]}"
      This is not my prefered solution, I would instead rewrite this command to run within any shell as it is more portable to other Linux/Unix systems:
      Code:
      UserParameter=dpkg.updates,/usr/lib/update-notifier/apt-check 2>&1 | awk -F';'  '{print $2}'
      However, if you are sure that you will always have bash or zsh, it is up to you

      Regards,
      Alixen
      http://www.alixen.fr/zabbix.html

      Comment

      • joke
        Junior Member
        • Jan 2010
        • 10

        #4
        The whole concept of using bash or zsh is to benefit from the advanced scripting capabilities and to reduce process invocation and resource consumption.

        - Using separate scripts would require to maintain them.
        - Using a more sh portable way like using awk or cut would require additional forking.

        The user parameters are added to a local zabbix_agent configuration file. So there is really no need to be portable. The client doesn't fetch it's user parameter commands from the server. Which would be really nice by the way.

        A simple totally sh compliant user parameter like
        Code:
        [ -e /etc/passwd ] && echo 1 || echo 0
        would require a total of three processes to check if /etc/passwd is present while a bash compliant version
        Code:
        [[ -e /etc/passwd ]] && echo 1 || echo 0
        would require only one process to check the file.

        Using only bash scripting and installing a bash on every host is as portable as using sh compliant scripts but it's way more efficient. Especially if the command is executed every few seconds.

        Comment

        • alixen
          Senior Member
          • Apr 2006
          • 474

          #5
          Sorry, I did not want to start a flame war on shell selection.

          There is always a tradeoff between performance and portability.
          Obviously, your environment allows you to favour performance; this is not always the case (I have worked on some Unix systems where installing a new shell was not an option).

          I have provided two ways to define your UserParameter. Both work and one of them uses bash.

          Regards,
          Alixen
          http://www.alixen.fr/zabbix.html

          Comment

          • richlv
            Senior Member
            Zabbix Certified Trainer
            Zabbix Certified SpecialistZabbix Certified Professional
            • Oct 2005
            • 3112

            #6
            i wouldn't call this a flamewar, i think all arguments provided were very reasonable
            quick, grouphug.
            Zabbix 3.0 Network Monitoring book

            Comment

            • joke
              Junior Member
              • Jan 2010
              • 10

              #7
              Originally posted by alixen
              I have provided two ways to define your UserParameter. Both work and one of them uses bash.
              Of cause they both work. But I would really like a way to just start bash without invoking sh first. The zabbix agent doesn't seem to respect the users default shell as specified in /etc/passwd. I changed the shell entry to /bin/bash but the agent doesn't seem to care.

              I don't think I favor performance over portability. If I've got a host which doesn't have a bash installed I only need to provide a different set of UserParameter. This can easily be done by distributing the correct set of UserParameter definitions via zabbix server.


              By the way using
              Code:
              exec bash -c 'some command'
              rather than
              Code:
              bash -c 'some command'
              is more efficient because it doesn't fork an extra process.
              Last edited by joke; 27-01-2010, 11:14.

              Comment

              • joke
                Junior Member
                • Jan 2010
                • 10

                #8
                Originally posted by joke
                The zabbix agent doesn't seem to respect the users default shell as specified in /etc/passwd.
                I think this may be a bug. The agent doesn't respect the default shell as specified in /etc/passwd and it doesn't respect the SHELL environmental variable.

                Every program should respect these settings. If a user specifies them it's for a good reason. It's default unix behavior.

                Comment

                • alixen
                  Senior Member
                  • Apr 2006
                  • 474

                  #9
                  Hi,

                  Originally posted by joke
                  I think this may be a bug. The agent doesn't respect the default shell as specified in /etc/passwd and it doesn't respect the SHELL environmental variable.

                  Every program should respect these settings. If a user specifies them it's for a good reason. It's default unix behavior.
                  I have checked zabbix agent source code and it uses popen() function from libc library to execute UserParameter command.

                  According to popen man page:
                  The command argument is a pointer to a null-terminated string containing a shell command line. This command is passed to /bin/sh using the -c flag; interpretation, if any, is performed by the shell. The type argument is a pointer to a null-terminated string which must be either 'r' for reading or 'w' for writing.
                  So, if SHELL environment variable is not used, it seems to be a bug in popen, not Zabbix.
                  I have also checked popen in glibc source code:
                  Code:
                  _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
                  Obviously, /bin/sh is hardcoded in popen.

                  In order to respect SHELL variable in Zabbix agent, popen call has to be replaced in agent code by some new code that will have to be tested on all platforms currently supported.

                  Regards,
                  Alixen
                  http://www.alixen.fr/zabbix.html

                  Comment

                  • joke
                    Junior Member
                    • Jan 2010
                    • 10

                    #10
                    Originally posted by alixen
                    I have checked zabbix agent source code and it uses popen() function from libc library to execute UserParameter command.
                    I didn't have the time to check the sources to verify zabbix uses popen() but you are probably right.

                    Originally posted by alixen
                    In order to respect SHELL variable in Zabbix agent, popen call has to be replaced in agent code by some new code that will have to be tested on all platforms currently supported.
                    As far as I remember popen() isn't a function defined in ISO C but a normal posix compliant function which is a wrapper around fork() and co itself. It should be possible to replace it with fork(), pipe(), fopen() and execv(). The shell could be queried with getenv() and getpwuid().

                    Doing a popen() manually would be as portable as using popen() but of cause it's a little more code as using the popen() wrapper.

                    Comment

                    • markkrj
                      Junior Member
                      • Jun 2017
                      • 2

                      #11
                      /etc/default/zabbix-agent

                      DISCLAIMER: I'm posting this to a few old threads because google got me there and it might help other people.

                      If you wanna set environment variables for your UserParameters or any other things that is run by the zabbix-agent, place them in /etc/default/zabbix-agent. The default systemd's zabbix-agent service unit has an parameter for sourcing it (EnvironmentFile=-/etc/default/zabbix-agent). The file doesn't exist by default, hence the minus (-) before the path (in systemd, an minus in front of the file avoid error if the files doesn't exist).

                      If you're still using SysVinit (/etc/init.d scripts), then take a look at zabbix-agent's script (/etc/init.d/zabbix-agent) search for the following lines:
                      Code:
                      [ -r /etc/default/zabbix-agent ]
                      if it's not there, add it.

                      After that, restart the service. Profit.

                      PS: You can try your zabbix-agent environment this way:
                      add this to your agent's config:
                      Code:
                      UserParameter=test.env,export
                      Restart your zabbix-agent and run
                      Code:
                      zabbix_get -s localhost -k test.env

                      Comment

                      Working...