github.com/newrelic/go-agent@v3.26.0+incompatible/internal/sysinfo/hostname_linux.go (about)

     1  // Copyright 2020 New Relic Corporation. All rights reserved.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package sysinfo
     5  
     6  import (
     7  	"os"
     8  	"syscall"
     9  )
    10  
    11  // Hostname returns the host name.
    12  func Hostname() (string, error) {
    13  	// Try the builtin API first, which is designed to match the output of
    14  	// /bin/hostname, and fallback to uname(2) if that fails to match the
    15  	// behavior of gethostname(2) as implemented by glibc. On Linux, all
    16  	// these method should result in the same value because sethostname(2)
    17  	// limits the hostname to 64 bytes, the same size of the nodename field
    18  	// returned by uname(2). Note that is correspondence is not true on
    19  	// other platforms.
    20  	//
    21  	// os.Hostname failures should be exceedingly rare, however some systems
    22  	// configure SELinux to deny read access to /proc/sys/kernel/hostname.
    23  	// Redhat's OpenShift platform for example. os.Hostname can also fail if
    24  	// some or all of /proc has been hidden via chroot(2) or manipulation of
    25  	// the current processes' filesystem namespace via the cgroups APIs.
    26  	// Docker is an example of a tool that can configure such an
    27  	// environment.
    28  	name, err := os.Hostname()
    29  	if err == nil {
    30  		return name, nil
    31  	}
    32  
    33  	var uts syscall.Utsname
    34  	if err2 := syscall.Uname(&uts); err2 != nil {
    35  		// The man page documents only one possible error for uname(2),
    36  		// suggesting that as long as the buffer given is valid, the
    37  		// call will never fail. Return the original error in the hope
    38  		// it provides more relevant information about why the hostname
    39  		// can't be retrieved.
    40  		return "", err
    41  	}
    42  
    43  	// Convert Nodename to a Go string.
    44  	buf := make([]byte, 0, len(uts.Nodename))
    45  	for _, c := range uts.Nodename {
    46  		if c == 0 {
    47  			break
    48  		}
    49  		buf = append(buf, byte(c))
    50  	}
    51  
    52  	return string(buf), nil
    53  }