How to reliably get FQDN (Fully Qualified Domain Name) in bash scripts across Unix/Linux systems


2 views

When working with server automation, getting the correct FQDN (Fully Qualified Domain Name) is crucial for many operations - from certificate generation to service discovery. However, common methods like hostname -f often fail to deliver consistent results across different Unix/Linux distributions.

The hostname -f command relies on system configuration files to determine the FQDN, but its behavior varies:


# On some systems (properly configured):
$ hostname -f
server1.example.com

# On others (misconfigured or different implementations):
$ hostname -f
server1

Here are several robust methods to extract the FQDN:

Method 1: Using getent with hosts

This uses system name resolution:


FQDN=$(getent hosts $(hostname) | awk '{print $2}')
echo $FQDN

Method 2: Using dnsdomainname

Combine with hostname:


FQDN=$(hostname --short).$(dnsdomainname)
echo $FQDN

Method 3: Python Alternative

For systems with Python available:


FQDN=$(python -c 'import socket; print(socket.getfqdn())')
echo $FQDN

This combines multiple approaches with fallbacks:


get_fqdn() {
  local fqdn=""

  # Try hostname -f first
  fqdn=$(hostname -f 2>/dev/null)
  
  # If that fails or returns short name, try alternatives
  if [[ -z "$fqdn" || "$fqdn" == "$(hostname -s)" ]]; then
    # Try getent method
    fqdn=$(getent hosts $(hostname -s) | awk '{print $2}')
    
    if [[ -z "$fqdn" ]]; then
      # Try dnsdomainname combination
      fqdn="$(hostname -s).$(dnsdomainname 2>/dev/null)"
      
      if [[ "$fqdn" == "$(hostname -s)." ]]; then
        # Final fallback to hostname only
        fqdn=$(hostname -s)
      fi
    fi
  fi
  
  echo "$fqdn"
}

FQDN=$(get_fqdn)
echo "System FQDN: $FQDN"

To verify your FQDN detection works across different scenarios:


# Test short name responses
hostname -s > /etc/hostname
./your_script.sh

# Test with proper FQDN
echo "server1.example.com" > /etc/hostname
./your_script.sh

# Test with multiple aliases
echo "server1" > /etc/hostname
echo "127.0.0.1 server1 server1.example.com server1-alias" >> /etc/hosts
./your_script.sh
  • Systems with multiple network interfaces
  • Servers in different DNS domains
  • Containers with minimal hostname configuration
  • Cloud instances with provider-specific naming

For production scripts, consider this enhanced version that handles more edge cases:


get_system_fqdn() {
  local shortname=$(hostname -s)
  local fqdn=""
  
  # Try DNS first
  if type dig &>/dev/null; then
    fqdn=$(dig +short -x $(dig +short $(hostname -s)) | sed 's/\.$//')
  fi
  
  # Fallback to host commands
  [[ -z "$fqdn" ]] && fqdn=$(hostname -f 2>/dev/null)
  
  # Fallback to getent
  [[ -z "$fqdn" ]] && fqdn=$(getent hosts $(hostname -s) | awk '{print $2}')
  
  # Final fallback to short name
  [[ -z "$fqdn" ]] && fqdn=$shortname
  
  # Ensure we don't return just the shortname if we have domain parts
  if [[ "$fqdn" == "$shortname" ]]; then
    local domain=$(dnsdomainname 2>/dev/null)
    [[ -n "$domain" ]] && fqdn="${shortname}.${domain}"
  fi
  
  echo "$fqdn"
}

export FQDN=$(get_system_fqdn)

When working with Unix/Linux servers, getting the fully qualified domain name (FQDN) through standard commands like hostname -f can be unreliable. As noted in various community discussions (including this ServerFault thread), different distributions handle this differently:

# Common but unreliable approach
fqdn=$(hostname -f)
echo $fqdn  # Might return short name on some systems

Here are several more robust methods to obtain the FQDN:

Method 1: Using DNS Lookup

# Get IP first, then reverse lookup
ip=$(hostname -I | awk '{print $1}')
fqdn=$(dig +short -x $ip | sed 's/\.$//')
echo $fqdn

Method 2: Using Host Command

# Using hostname with domain search
fqdn=$(host $(hostname) | awk '{print $1}' | sed 's/\.$//')
echo $fqdn

Method 3: Python Alternative

For systems with Python available:

fqdn=$(python -c 'import socket; print(socket.getfqdn())')
echo $fqdn

Consider these additional checks for production environments:

# Fallback chain for maximum reliability
get_fqdn() {
  # Try hostname -f first
  fqdn=$(hostname -f 2>/dev/null)
  [[ -n "$fqdn" ]] && echo "$fqdn" && return
  
  # Try DNS method
  fqdn=$(dig +short $(hostname -I | awk '{print $1}') | sed 's/\.$//' 2>/dev/null)
  [[ -n "$fqdn" ]] && echo "$fqdn" && return
  
  # Final fallback
  echo $(hostname)
}

FQDN=$(get_fqdn)
  • Cache the FQDN if your script runs multiple times
  • Handle cases where DNS might be unavailable
  • Consider multi-homed systems (multiple IPs/interfaces)
  • Test across different distributions (RHEL, Ubuntu, etc.)

Here's how you might use this in a configuration script:

#!/bin/bash

# Get reliable FQDN
get_fqdn() {
  # Implementation from above
  ...
}

FQDN=$(get_fqdn)

# Use in configuration
cat < /etc/app/config
server_fqdn=$FQDN
server_ip=$(hostname -I | awk '{print $1}')
EOF