2017-12-12 10 views
0

私はLinuxの特定のディストリビューション(CentOS、Ubuntuなど)でのみ動作するように設計されたPythonプログラムを持っています。以下は「4.9.49-モビー」返しているので、私はそれがCentOS7コンテナ内で実行されている取得したいが、その失敗たい:dockerコンテナ内で動作するPythonプログラムは、 'uname -r'に依存しています

import platform 
platform.release() 

プログラムはLinuxカーネルのリリースを見つけることを期待している、すなわち、「3.10を.0-327.el7.x86_64 '。

プログラムのソースコードを変更できないとします。

この問題を回避する方法はありますか?

「uname -r」の周りにラッパースクリプトを書いてみました。しかし、これは明らかにPythonがこれを直接カーネルから調達しているので、役に立たない。

+0

なぜディストリビューションを検出してスクリプトを実行するbashスクリプトを使用しますか?あなたがそれに興味があるなら私は答えを書くことができます;-) –

+0

残念ながら、unameの周りのラッパースクリプトはそれを(私が説明したように)カットするつもりはありません。あなたが別のアプローチを意味していない限り。いずれにせよ、私は@ larsksが提供したソリューションが本当に好きです。 –

答えて

3

Pythonは単にその情報を取得するためにunameシステムコールを呼び出します。これは常に現在実行中のカーネルに関する情報を返します。ソースを変更せずに戻り値をオーバーライドするのは難しいでしょう。

お客様は、機能の介入を使用してこれを実行します。記載の通り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') 
>>> 

私が代わりに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 

は、今私はドッキングウィンドウのイメージにそれを注入し、共有ライブラリをプリロードすることができます。キーの追加は、リンカがそれをプリロードさせるライブラリと -e LD_PRELOADを注入する -vされている。

$ 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

することができますがドッカーを使う:あなたのCentOSコンテナの中にUbuntuのコンテナ(または他の互換性のあるディストリビューション)を走らせないでください。

+0

... 'uname'システムコールは、あなたのホスト上で動作しているカーネルに関連する情報を報告し続けるので、同じ問題が残ります。 – larsks

関連する問題