hostname_linux.go 1.6 KB

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