2017-12-12 13 views
0

Linux (즉, CentOS, Ubuntu 등)의 특정 배포판에서만 실행되도록 설계된 Python 프로그램이 있습니다. 나는 그것이 CentOS7 컨테이너 내에서 실행하지만, '- 모비 4.9.49'를 반환하는 다음 때문에 실패 좀하고 싶습니다 :이 프로그램은 리눅스 커널 버전을 찾으려는도커 컨테이너 내에서 실행되는 Python 프로그램은 'uname -r'을 사용합니다.

import platform 
platform.release() 

, 즉 '3.10 .0-327.el7.x86_64 '.

프로그램의 소스 코드를 수정할 수 없다고 가정 해보십시오.

이 문제를 해결할 수있는 방법은 무엇입니까?

'uname -r'주위에 래퍼 스크립트를 작성하여 원하는 것을 반환하려고했습니다. 그러나 이것은 파이썬이 커널에서 이것을 직접 소싱하고 있기 때문에 도움이되지 않습니다.

+0

왜 배포판을 발견하고 스크립트를 실행하는 bash 스크립트를 사용합니까? 그 일에 관심이 있다면 대답을 쓸 수 있습니다 ;-) –

+0

불행히도 uname 주위의 래퍼 스크립트는 그것을 잘라내지 않을 것입니다 (필자가 설명했듯이). 다른 접근법을 의미하지 않는 한. 어쨌든 @larsks가 제공 한 솔루션이 정말 마음에 든다. –

답변

3

파이썬은 단순히 uname 시스템 호출을 호출하여 정보를 얻습니다.이 정보는 항상 현재 실행중인 커널에 대한 정보를 반환합니다. 소스를 수정하지 않고 리턴 값을 오버라이드하는 것은 까다로울 것입니다.

고객 은 함수 삽입을 사용하여이를 수행합니다. here. 래퍼 라이브러리와 필요한 환경 설정을 모두 포함하도록 이미지를 수정해야하거나 Docker 실행 명령 줄에 여러 매개 변수를 추가로 전달해야합니다.

다음은 간단한 예입니다. 나는 바닐라 이미지로 시작하고 파이썬에서 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') 
>>> 

내가 대신 1.0.0을 표시하는 release 필드를 싶습니다. 나는 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 

가 지금은 고정 표시기 이미지로 저를 주입하고 공유 라이브러리를 미리로드 할 수 있습니다. 주요 추가는 링커가 미리로드하게하기 위해 라이브러리를 주입 -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') 
>>> 
+0

굉장한 답변! 그래,이 속임수를했다. 감사! –

+0

젠장! 내가 upvote 한 번만 칠 수있는 것은 부끄러운 일입니다! –

+0

@AliM 이것은 재미있는 하나였습니다! :) – larsks

-1

당신은 할 수 있습니다 docker를 사용하여 CentOS 컨테이너 내부에서 우분투 컨테이너 (또는 다른 호환 가능한 배포판)를 실행하십시오.

+0

...'uname' 시스템 콜이 계속해서 당신의 호스트에서 돌아가고있는 커널과 관련된 정보를보고 할 것이기 때문에 여전히 같은 문제가 있습니다. – larsks