16

I do not understand this:

Python 2.7.3 (default, Apr 14 2012, 08:58:41) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> socket.getfqdn()
'SR-MW001'
>>> socket.gethostname()
'sr-mw001.foo-domain.de'

What is wrong here?

According to the docs of socket.getfqdn() the "a fully qualified domain name" should get returned.

Update

More infos:

/etc/hosts

sr-mw001:~ # grep -iP 'SR-MW001|localhost|foo-domain' /etc/hosts
127.0.0.1       localhost
::1             localhost ipv6-localhost ipv6-loopback
10.189.217.11   SR-MW001 foo-work

IPs

sr-mw001:~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:50:56:a8:6e:eb brd ff:ff:ff:ff:ff:ff
    inet 10.189.217.11/24 brd 10.189.217.255 scope global eth0
       valid_lft forever preferred_lft forever

socket.gethostbyaddr()

>>> socket.gethostbyaddr('sr-mw001.stadtwerke-gt.de')
('SR-MW001', ['foo-work'], ['10.189.217.11'])

More details:

> uname -n
sr-mw001.foo-domain.de

> hostname
sr-mw001.foo-domain.de

> domainname
(none)

> nisdomainname
-bash: nisdomainname: command not found

> dnsdomainname
foo-domain.de

> ypdomainname
-bash: ypdomainname: command not found

Related question: /etc/HOSTNAME on SuSE: short name or FQDN?

guettli
  • 25,042
  • 81
  • 346
  • 663
  • Did you modified your files (e.g. *socket.py*) in your *Python* installation? *getfqdn* should return the result of *gethostname* if anything goes wrong. Based on the outputs, you shouldn't get here using a pristine version.Could you paste the *getfqdn* implementation (you can find the file by: `print(socket)`)? Any reason for using this ancient version? – CristiFati Jun 11 '19 at 17:39
  • Also is it possible to share */etc/hosts* content? Is this reproducible on one machine only or is it general? Your machine is in a domain? If yes what are you using? *nis*, *ldap*, ... ? Is the machine *IPv6* or 4? – CristiFati Jun 11 '19 at 17:46
  • @CristiFati I updated the question. You ask "Your machine is in a domain?" how can I check this? – guettli Jun 12 '19 at 07:58
  • @guettli So your question now has become "Why does socket.gethostbyaddr() not return a domain name?" That sounds more like a DNS configuration issue than a Python question. And the returned values look suspiciously like what's defined in /etc/hosts. – Roland Weber Jun 13 '19 at 09:31
  • Run the following commands in the shell and also place their output: `uname -n`, `hostname`, `domainname`, `nisdomainname`, `dnsdomainname`, `ypdomainname`. Also could you also extend the *grep* search in */etc/hosts* to `grep -iP 'SR-MW001|localhost|foo-domain\.de' /etc/hosts`? – CristiFati Jun 13 '19 at 09:52
  • @CristiFati I updated the question according to your wish. – guettli Jun 13 '19 at 10:52
  • 1
    Unfortunately I can't figure out why the functions behave the way they do. If I could reproduce the problem locally, maybe I could come up with an answer, but I imagine, you got tired of updating the question every time I need a new detail. As a workaround (to get the *fqdn*) you could call `socket.getfqdn()` and if that doesn't contain any dots, call `socket.gethostname()`. Or you could do `subprocess.check_output(["hostname", "--fqdn"]).split("\n")[0]`. – CristiFati Jun 13 '19 at 12:13
  • @CristiFati in my current context we auto-detected the hostname up to now. But in the future this will be set by configuration management. This is more predictable. It is 100% that the real root of this issue is still unknown. – guettli Jun 13 '19 at 12:42
  • Yes, the issue it's still unknown, that's what I kind of said in my previous comment (but without being able to reproduce the problem, it's hard to figure out what that could be). – CristiFati Jun 13 '19 at 14:37

2 Answers2

4

Check what socket.gethostbyaddr('sr-mw001.foo-domain.de') returns on your machine.

The implementation of getfqdn() relies on that:
https://github.com/python/cpython/blob/2.7/Lib/socket.py#L128-L151

If gethostbyaddr() returns a hostname without domain, and no aliases, then that hostname is returned by getfqdn().


The updated information in the question indicates that my guess was close. It's the entries without domain in your /etc/hosts that cause this behavior. The following Q&A shows a way to fix it, I believe: https://unix.stackexchange.com/a/77924


Also consider to upgrade your Python installation. Version 2.7.3 is from 2012, the latest fixlevel for 2.7 is 2.7.16. There's no change in getfqdn(), but I haven't checked gethostbyaddr() or what other functions might get called.

Roland Weber
  • 3,395
  • 12
  • 26
3

/etc/hostname should have the short (unqualified) name (sr-mw00). The name from file is pushed into the kernel at boot, and should be seen in uname.

Then /etc/hosts should have an entry like this:

127.0.1.1    sr-mw001.foo-domain.de sr-mw001

This sets sr-mw001.foo-domain.de as the canonical name with sr-mw001 being an alias.

hostname should output the short name. hostname --fqdn should output the full canonical name.

Using 127.0.1.1 is the convention used by the Debian installer when the system has a DHCP-assigned IP address.

If the system has a static IP address, you should use that address instead. That will ensure the system can also determine its FQDN from its IP address (a reverse lookup).

Ensure that these are working before checking from python.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • Thank you very much for your answer. Is there a reference or name for this "best practice" guide? – guettli Jun 14 '19 at 08:52
  • 2
    The [`hostname(1)`](http://man7.org/linux/man-pages/man1/hostname.1.html) man page vaguely suggests this route. I essentially learned this after many attempts. – Jonathon Reinhart Jun 14 '19 at 13:06