Python docker 容器内的程序 运行 依赖于 'uname -r'
Python program running inside docker container relies upon 'uname -r'
我有一个 Python 程序,该程序仅在 Linux 的某些发行版(即 CentOS、Ubuntu 等)中被设计为 运行。我想在 CentOS7 容器中 运行ning 得到它,但它失败了,因为下面是 returning '4.9.49-moby':
import platform
platform.release()
该程序期望找到 linux 内核版本,即“3.10.0-327.el7.x86_64”。
假设我无法修改程序的源代码。
我可以做些什么来解决这个问题?
我尝试围绕 'uname -r' 编写一个包装脚本到 return 我想要的。但这无济于事,因为显然 Python 直接从内核中获取它。
Python 只需调用 uname
系统调用来获取该信息,该信息总是会 return 有关当前 运行ning 内核的信息。在不修改源代码的情况下覆盖 return 值将很棘手。
您可以使用函数插入来完成此操作,例如如上所述 here。这需要修改图像以包含包装器库和必要的环境设置,或者需要您在 Docker 运行 命令行上传递一些附加参数。
这是一个简单的例子。我从原始图像开始,然后在 Python:
中调用 os.uname()
$ docker run -it --rm fedora python3
Python 3.6.2 (default, Sep 1 2017, 12:03:48)
[GCC 7.1.1 20170802 (Red Hat 7.1.1-7)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.uname()
posix.uname_result(sysname='Linux', nodename='fd2d40cb028b', release='4.13.15-100.fc25.x86_64', version='#1 SMP Tue Nov 21 22:45:32 UTC 2017', machine='x86_64')
>>>
我希望 release
字段显示 1.0.0
。我首先为 uname
系统调用创建一个包装器:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <sys/utsname.h>
/* Function pointers to hold the value of the glibc functions */
static int (*real_uname)(struct utsname *name) = NULL;
/* wrapping write function call */
int uname(struct utsname *name) {
int res;
real_uname = dlsym(RTLD_NEXT, "uname");
res = real_uname(name);
if (res == 0) {
memset(name->release, 0, _UTSNAME_RELEASE_LENGTH);
strncpy(name->release, "1.0.0", 5);
}
return res;
}
然后我编译共享库:
$ gcc -fPIC -shared -o wrap_uname.so wrap_uname.c -ldl
现在我可以将其注入 docker 图像并预加载共享库。关键的添加是 -v
注入库和 -e LD_PRELOAD
使链接器预加载它:
$ docker run -it --rm \
-v $PWD/wrap_uname.so:/lib/wrap_uname.so \
-e LD_PRELOAD=/lib/wrap_uname.so fedora python3
如您所见,这给了我们想要的结果:
Python 3.6.2 (default, Sep 1 2017, 12:03:48)
[GCC 7.1.1 20170802 (Red Hat 7.1.1-7)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.uname()
posix.uname_result(sysname='Linux', nodename='dd88d697fb65', release='1.0.0', version='#1 SMP Tue Nov 21 22:45:32 UTC 2017', machine='x86_64')
>>>
您可以在 CentOS 容器内使用 docker:dind 到 运行 一个 Ubuntu 容器(或任何其他兼容的发行版)。
我有一个 Python 程序,该程序仅在 Linux 的某些发行版(即 CentOS、Ubuntu 等)中被设计为 运行。我想在 CentOS7 容器中 运行ning 得到它,但它失败了,因为下面是 returning '4.9.49-moby':
import platform
platform.release()
该程序期望找到 linux 内核版本,即“3.10.0-327.el7.x86_64”。
假设我无法修改程序的源代码。
我可以做些什么来解决这个问题?
我尝试围绕 'uname -r' 编写一个包装脚本到 return 我想要的。但这无济于事,因为显然 Python 直接从内核中获取它。
Python 只需调用 uname
系统调用来获取该信息,该信息总是会 return 有关当前 运行ning 内核的信息。在不修改源代码的情况下覆盖 return 值将很棘手。
您可以使用函数插入来完成此操作,例如如上所述 here。这需要修改图像以包含包装器库和必要的环境设置,或者需要您在 Docker 运行 命令行上传递一些附加参数。
这是一个简单的例子。我从原始图像开始,然后在 Python:
中调用os.uname()
$ docker run -it --rm fedora python3
Python 3.6.2 (default, Sep 1 2017, 12:03:48)
[GCC 7.1.1 20170802 (Red Hat 7.1.1-7)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.uname()
posix.uname_result(sysname='Linux', nodename='fd2d40cb028b', release='4.13.15-100.fc25.x86_64', version='#1 SMP Tue Nov 21 22:45:32 UTC 2017', machine='x86_64')
>>>
我希望 release
字段显示 1.0.0
。我首先为 uname
系统调用创建一个包装器:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <sys/utsname.h>
/* Function pointers to hold the value of the glibc functions */
static int (*real_uname)(struct utsname *name) = NULL;
/* wrapping write function call */
int uname(struct utsname *name) {
int res;
real_uname = dlsym(RTLD_NEXT, "uname");
res = real_uname(name);
if (res == 0) {
memset(name->release, 0, _UTSNAME_RELEASE_LENGTH);
strncpy(name->release, "1.0.0", 5);
}
return res;
}
然后我编译共享库:
$ gcc -fPIC -shared -o wrap_uname.so wrap_uname.c -ldl
现在我可以将其注入 docker 图像并预加载共享库。关键的添加是 -v
注入库和 -e LD_PRELOAD
使链接器预加载它:
$ docker run -it --rm \
-v $PWD/wrap_uname.so:/lib/wrap_uname.so \
-e LD_PRELOAD=/lib/wrap_uname.so fedora python3
如您所见,这给了我们想要的结果:
Python 3.6.2 (default, Sep 1 2017, 12:03:48)
[GCC 7.1.1 20170802 (Red Hat 7.1.1-7)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.uname()
posix.uname_result(sysname='Linux', nodename='dd88d697fb65', release='1.0.0', version='#1 SMP Tue Nov 21 22:45:32 UTC 2017', machine='x86_64')
>>>
您可以在 CentOS 容器内使用 docker:dind 到 运行 一个 Ubuntu 容器(或任何其他兼容的发行版)。