Sunday, August 22, 2010

MySQL installation error - Neither host nor 'localhost' could be looked up

While trying to install MySQL 5.1 on my Ubuntu system recently, I ran into an annoying error. I call it annoying because the error message turned out to be a bit misleading. I'll first mention the steps that I followed to install MySQL and the error that I ran into and finally the "fix" to get past the error.

System details:

- Ubuntu 10.04 Operating System

- MySQL 5.1.x downloaded from the official site here http://dev.mysql.com/downloads/mysql/ and selected the "Compressed TAR Archive" (mysql-5.1.50-linux-i686-glibc23.tar.gz to be precise) under the "Linux - Generic" platform

Installation steps:

- Extracted the .tar.gz locally to /home/jpai/MySQL/mysql-5.1.50-linux-i686-glibc23. In the rest of this article, I'll refer to this path as MYSQL_DOWNLOAD_HOME

- From the command prompt, "cd" to
MYSQL_DOWNLOAD_HOME

(Some steps mentioned in the /INSTALL-BINARY file are skipped in this article, since they aren't relevant here)

- Run the scripts/mysql_install_db command from the command prompt:

jpai@jpai-laptop:mysql-5.1.50-linux-i686-glibc23$ scripts/mysql_install_db 



Error:

Running that above command threw up the following error message:

jpai@jpai-laptop:mysql-5.1.50-linux-i686-glibc23$ scripts/mysql_install_db 
Neither host 'jpai-laptop' nor 'localhost' could be looked up with
/usr/bin/resolveip
Please configure the 'hostname' command to return a correct
hostname.
If you want to solve this at a later stage, restart this script
with the --force option



That message looked strange because I was able to ping those hostnames and was sure that I had my hostname setup properly. So I decided to see why "usr/bin/resolveip" can't resolve those hostnames. So from the command prompt, I tried running the following command:

jpai@jpai-laptop:~$ /usr/bin/resolveip --help



This threw up an error:

jpai@jpai-laptop:~$ /usr/bin/resolveip --help
bash: /usr/bin/resolveip: No such file or directory



So obviously, /usr/bin/resolveip command doesn't exist at all. So why was the MySQL installation trying to use this non-existent command? I then decided to take a look at the scripts/mysql_install_db script under . The lines, in that script, from where this error is being thrown are as follows:
# Check if hostname is valid
if test "$cross_bootstrap" -eq 0 -a "$in_rpm" -eq 0 -a "$force" -eq 0
then
  resolved=`$extra_bindir/resolveip $hostname 2>&1`
  if test $? -ne 0
  then
    resolved=`$extra_bindir/resolveip localhost 2>&1`
    if test $? -ne 0
    then
      echo "Neither host '$hostname' nor 'localhost' could be looked up with"
      echo "$extra_bindir/resolveip"
      echo "Please configure the 'hostname' command to return a correct"
      echo "hostname."
      echo "If you want to solve this at a later stage, restart this script"
      echo "with the --force option"
      exit 1
    fi
    echo "WARNING: The host '$hostname' could not be looked up with resolveip."
    echo "This probably means that your libc libraries are not 100 % compatible"
    echo "with this binary MySQL version. The MySQL daemon, mysqld, should work"
    echo "normally with the exception that host name resolving will not work."
    echo "This means that you should use IP addresses instead of hostnames"
    echo "when specifying MySQL privileges !"
  fi
fi


The important part from those lines are:

resolved=`$extra_bindir/resolveip $hostname 2>&1`


and

resolved=`$extra_bindir/resolveip localhost 2>&1`


As can be seen the script tries to infer the location of "resolveip" command through the $extra_bindir variable. This variable gets set earlier in that script, based on various conditions. Some of the relevant lines are these:

# Now we can get arguments from the groups [mysqld] and [mysql_install_db]
# in the my.cfg file, then re-run to merge with command line arguments.
parse_arguments `$print_defaults $defaults mysqld mysql_install_db`
parse_arguments PICK-ARGS-FROM-ARGV "$@"

# Configure paths to support files
if test -n "$srcdir"
then
  basedir="$builddir"
  bindir="$basedir/client"
  extra_bindir="$basedir/extra"
  mysqld="$basedir/sql/mysqld"
  langdir="$srcdir/sql/share/english"
  pkgdatadir="$srcdir/scripts"
  scriptdir="$srcdir/scripts"
elif test -n "$basedir"
then
  bindir="$basedir/bin"
  extra_bindir="$bindir"
  mysqld=`find_in_basedir mysqld libexec sbin bin`
  if test -z "$mysqld"
  then
    cannot_find_file mysqld $basedir/libexec $basedir/sbin $basedir/bin
    exit 1
  fi
  langdir=`find_in_basedir --dir errmsg.sys share/english share/mysql/english`
  if test -z "$langdir"
  then
    cannot_find_file errmsg.sys $basedir/share/english $basedir/share/mysql/english
    exit 1
  fi
  pkgdatadir=`find_in_basedir --dir fill_help_tables.sql share share/mysql`
  if test -z "$pkgdatadir"
  then
    cannot_find_file fill_help_tables.sql $basedir/share $basedir/share/mysql
    exit 1
  fi
  scriptdir="$basedir/scripts"
else
  basedir="."
  bindir="./bin"
  extra_bindir="$bindir"
  mysqld="./bin/mysqld"
  pkgdatadir="./share"
  scriptdir="./bin"
fi


In short, those lines check for the presence of "default" values for some variables like "basedir" in MySQL configuration files (from earlier installations) under some known locations like /etc/my.cnf or the /etc/mysql. Incidentally, I had one such file /etc/mysql/my.cnf with one of the lines being:

...
basedir  = /usr
...


So effectively, MySQL ended up picking up "basedir" as /usr and ultimately the following lines in the script:

...
  bindir="$basedir/bin"
  extra_bindir="$bindir"
...


set extra_bindir to /usr/bin.

Now that explained why the MySQL installation ending up using /usr/bin/resolveip while resolving the hostname:

resolved=`$extra_bindir/resolveip $hostname 2>&1`


Solution:

For those who are just looking for a solution to get past this error, I'll just quickly explain what needs to be done. The scripts/mysql_install_db script allows for explicitly specifying the basedir to use during the installation. So the solution is to pass the as the value of basedir from the command prompt while running that script. Here's how you do it:
jpai@jpai-laptop:mysql-5.1.50-linux-i686-glibc23$ scripts/mysql_install_db --basedir=.



(Remember that we are running this command from the  MYSQL_DOWNLOAD_HOME, so the relative path "." works fine for the basedir).

By passing the value for basedir we have now made sure that MySQL picks up the "resolveip" command from the correct location, which is 
MYSQL_DOWNLOAD_HOME/bin/resolveip. Yes, "resolveip" is indeed shipped as part of the MySQL download.


What's annoying about this error:

I earlier mentioned that I found this error annoying because of the misleading error message. As we saw, the real problem was that the installation script was trying to use an non-existent command (due to incorrect path). The reason why it used the incorrect path was mainly my fault, because I ignored a part in the INSTALL_BINARY file which mentioned:

Warning

   If you have previously installed a MySQL installation using your
   operating system native package management system, such as yum or
   apt-get, you may experience problems installing using a native
   binary. Make sure your previous MySQL previous installation has
   been removed entirely (using your package management system), and
   that any additional files, such as old versions of your data
   files, have also been removed. You should also check the existence
   of configuration files such as /etc/my.cnf or the /etc/mysql
   directory have been deleted.


*But* the error message should really have printed out a message which could probably have said:

"/usr/bin/resolveip" command not found. 
Make sure basedir (and other variables) point to the right location. 
Tip: resolveip can be located in the bin folder of MySQL download location.


This would have made it real easy for the user to fix the issue instead of trying to figure out what's wrong with their hostname.

Update: I've brought this up in the MySQL mailing list here http://lists.mysql.com/mysql/222638.