Zabbix: Rename all hosts to the inventory hostname via JSON API (Perl script)

When you monitor a high number of hosts in Zabbix, mass updates can be a pain (for 1000 hosts with 100 hosts displayed per page you still have to go through 10 pages and click select all on each one).

You probably want to use the API and script things. Thats what I do.

Here is a quick Perl script I wrote (requires JSON::RPC::Client) which changes the host name of all monitored hosts to the one which the host inventory has discovered (if you happen to use this functionality). Pretty nifty if you imported hosts by IP addresses.

You can use this script as template for various API operations. The Zabbix API is documented (v2.2) and pretty easy to work with, especially with Perl and JSON.

#!/usr/bin/env perl

use utf8;
use strict;
use warnings;

use JSON::RPC::Client;

my ($aid, $res);

my $url  = 'http://zabbix.ip/zabbix/api_jsonrpc.php';
my $user = 'admin';
my $pass = 'pass';

my $json = {
   jsonrpc => '2.0',
   method  => 'user.login',
   params  => {
      user     => $user,
      password => $pass,
   id => 1,

my $z = JSON::RPC::Client->new;

$res = $z->call($url, $json);
die "Could not authenticate.\n" unless ($res->content->{result});

$aid = $res->content->{'result'};
print "Authentication successful, Auth ID: $aid\n\n";

$json = {
   jsonrpc => '2.0',
   method  => 'host.get',
   params  => {
      output          => ['hostid', 'host', 'name'],
      selectInventory => ['name'],
      sortfield       => 'hostid',
   id   => 2,
   auth => $aid,

$res = $z->call($url, $json);
die "$$json{method} failed\n" unless ($res->content->{result});

my $count = 0;
my $crapcount = 0;
my @crap;

foreach my $host (@{$res->content->{result}}) {
   unless (ref $host->{inventory} eq 'ARRAY' || $host->{inventory}->{name} =~ /^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/ || $host->{inventory}->{name} eq '') {
      print "Now updating #$host->{hostid} | Old hostname: $host->{host} | New hostname: $host->{inventory}->{name}\n";

      $json = {
         jsonrpc => '2.0',
         method  => 'host.update',
         params  => {
            hostid => $host->{hostid}, 
            host   => $host->{inventory}->{name},
         id   => $count+3,
         auth => $aid,

      $res = $z->call($url, $json);
      warn "$$json{method} failed\n" unless ($res->content->{result});

      unless ($res->content->{result}) {
         warn "$$json{method} failed\n";
         push(@crap, $host->{hostid});
      else {

if (@crap) {
   print "\nCrap ($crapcount):\n";
   print "$_\n" for (@crap);

printf("\nUpdated %u hosts.\n", $count - $crapcount);


Happy monitoring!



  • Eric

    Thanks for the post! I’m trying to figure out how to get this to run on a single host group (e.g. Discovered hosts). Think you could point me in the right direction?

    • nico

      I’m not sure as we don’t use host discovery but you can check if any of the methods can help you. Discovered hosts seem different than manually added ones. Also you can always use output=>’extend’ with all .get methods and print $res with Data::Dumper to nicely show the data scructure of the returned information. Form there you just need to figure what you need and put together some lines to get the desired values for the host.update method.

Leave a Reply

Your email address will not be published. Required fields are marked *