对于我正在 dockerized python3 模块内进行的项目。我遇到了socket.gethostname()
总是返回随机 docker 名称的问题。由于这些实例是临时的,并且在重新生成之前只存在很短的时间,因此随机名称的积累速度非常快,我希望有一种方法来全面标准化这些名称。
我的限制是:
- 我无法控制上游源代码,因此修改它或维护我自己的版本是绝对不行的。
- 我无法控制 docker 容器的配置方式,因此在 docker 运行时设置名称是不可行的。
我的问题是:
- 数据从哪里
socket.gethostname()
获取?显然是从系统获取的,但具体从哪里获取,又是如何获取的?如果你更改/etc/hosts
,它仍然会提取先前的值。 - 有没有办法直接告诉你的 python 环境,我想将主机名值设置为
x
无论系统设置的主机名如何(如果可能的话,这可能是理想的)? - 处理这个问题最明智的方法是什么?
此外,如果有人愿意指出实际的源代码,以便socket.gethostname()
我可以亲自了解它是如何工作的,我将不胜感激!
答案1
我期望 Pythonsocket.gethostname()
只是一个薄包装系统gethostname
调用, 哪个在 Ubuntu 上(使用 glibc)反过来又包装了系统uname
调用:
C library/kernel differences
The GNU C library does not employ the gethostname() system call; instead, it implements
gethostname() as a library function that calls uname(2) and copies up to len bytes from
the returned nodename field into name.
对于uname(2)
:
This is a system call, and the operating system presumably knows its name, release, and
version. It also knows what hardware it runs on. So, four of the fields of the struct
are meaningful. On the other hand, the field nodename is meaningless: it gives the name
of the present machine in some undefined network, but typically machines are in more than
one network and have several names. Moreover, the kernel has no way of knowing about such
things, so it has to be told what to answer here. The same holds for the additional
domainname field.
To this end, Linux uses the system calls sethostname(2) and setdomainname(2). Note that
there is no standard that says that the hostname set by sethostname(2) is the same string
as the nodename field of the struct returned by uname() (indeed, some systems allow a
256-byte hostname and an 8-byte nodename), but this is true on Linux. The same holds for
setdomainname(2) and the domainname field.
所以:
这取决于做什么
sethostname()
。对于 Docker 容器来说,那就是 Docker 本身。我不知道。
只是要求 Docker 设置任意主机名你想要的容器:
% docker run --rm -it python:3.9 python -c 'import socket; print(socket.gethostname())' dd247ca179da % docker run --rm -it --hostname my-own-hostname python:3.9 python -c 'import socket; print(socket.gethostname())' my-own-hostname
以下是源代码的相关部分,Python 3.11.3:
#ifdef HAVE_GETHOSTNAME
/* Python interface to gethostname(). */
/*ARGSUSED*/
static PyObject *
socket_gethostname(PyObject *self, PyObject *unused)
{
if (PySys_Audit("socket.gethostname", NULL) < 0) {
return NULL;
}
#ifdef MS_WINDOWS
// snip
#else
char buf[1024];
int res;
Py_BEGIN_ALLOW_THREADS
res = gethostname(buf, (int) sizeof buf - 1);
Py_END_ALLOW_THREADS
if (res < 0)
return set_error();
buf[sizeof buf - 1] = '\0';
return PyUnicode_DecodeFSDefault(buf);
#endif
}