文章目录

  • 1 简单Python代码示例
  • 2 安装PyInstaller
  • 3 不加密直接编译exe
  • 4 对PyInstaller打包的不加密编译exe进行反编译
  • 5 加密编译exe
    • 5.1 注意事项
    • 5.2 加密编译
  • 6 将外部数据打包到exe中
    • 6.1 如果不需要加密编译
    • 6.2 如果需要加密编译
  • 7 为exe添加图标

1 简单Python代码示例

TestAdd.py

#__author__ = 'StubbornHuang'
#coding = utf-8import io
import os
import sysdef addTest(a,b):print ("a+b={}".format(a+b))if __name__ == '__main__':addTest(1,5)

2 安装PyInstaller

输入以下命令安装pyinstaller:

pip install pyinstaller

验证是否安装成功,输入以下命令:

pyinstaller

3 不加密直接编译exe

在需要打包的py文件目录下启动cmd.exe,或者PowerShell.exe,我自己用的是Cmder.exe。

输入以下命令:

pyinstaller TestAdd.py



打包的exe在py文件所在目录的dist子目录下

如果直接运行TestAdd.exe会一闪而过,最好在当前exe所在目录下执行命令运行:

./TestAdd.exe

我们可以看到直接运行成功。

4 对PyInstaller打包的不加密编译exe进行反编译

使用pyinstxtractor.py 对上述不加密的exe进行反编译,其中pyinstxtractor.py文件内容如下:

"""
PyInstaller Extractor v1.9 (Supports pyinstaller 3.3, 3.2, 3.1, 3.0, 2.1, 2.0)
Author : Extreme Coders
E-mail : extremecoders(at)hotmail(dot)com
Web    : https://0xec.blogspot.com
Date   : 29-November-2017
Url    : https://sourceforge.net/projects/pyinstallerextractor/For any suggestions, leave a comment on
https://forum.tuts4you.com/topic/34455-pyinstaller-extractor/This script extracts a pyinstaller generated executable file.
Pyinstaller installation is not needed. The script has it all.For best results, it is recommended to run this script in the
same version of python as was used to create the executable.
This is just to prevent unmarshalling errors(if any) while
extracting the PYZ archive.Usage : Just copy this script to the directory where your exe residesand run the script with the exe file name as a parameterC:\path\to\exe\>python pyinstxtractor.py <filename>
$ /path/to/exe/python pyinstxtractor.py <filename>Licensed under GNU General Public License (GPL) v3.
You are free to modify this source.CHANGELOG
================================================Version 1.1 (Jan 28, 2014)
-------------------------------------------------
- First Release
- Supports only pyinstaller 2.0Version 1.2 (Sept 12, 2015)
-------------------------------------------------
- Added support for pyinstaller 2.1 and 3.0 dev
- Cleaned up code
- Script is now more verbose
- Executable extracted within a dedicated sub-directory(Support for pyinstaller 3.0 dev is experimental)Version 1.3 (Dec 12, 2015)
-------------------------------------------------
- Added support for pyinstaller 3.0 final
- Script is compatible with both python 2.x & 3.x (Thanks to Moritz Kroll @ Avira Operations GmbH & Co. KG)Version 1.4 (Jan 19, 2016)
-------------------------------------------------
- Fixed a bug when writing pyc files >= version 3.3 (Thanks to Daniello Alto: https://github.com/Djamana)Version 1.5 (March 1, 2016)
-------------------------------------------------
- Added support for pyinstaller 3.1 (Thanks to Berwyn Hoyt for reporting)Version 1.6 (Sept 5, 2016)
-------------------------------------------------
- Added support for pyinstaller 3.2
- Extractor will use a random name while extracting unnamed files.
- For encrypted pyz archives it will dump the contents as is. Previously, the tool would fail.Version 1.7 (March 13, 2017)
-------------------------------------------------
- Made the script compatible with python 2.6 (Thanks to Ross for reporting)Version 1.8 (April 28, 2017)
-------------------------------------------------
- Support for sub-directories in .pyz files (Thanks to Moritz Kroll @ Avira Operations GmbH & Co. KG)Version 1.9 (November 29, 2017)
-------------------------------------------------
- Added support for pyinstaller 3.3
- Display the scripts which are run at entry (Thanks to Michael Gillespie @ malwarehunterteam for the feature request)"""from __future__ import print_function
import os
import struct
import marshal
import zlib
import sys
import imp
import types
from uuid import uuid4 as uniquenameclass CTOCEntry:def __init__(self, position, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name):self.position = positionself.cmprsdDataSize = cmprsdDataSizeself.uncmprsdDataSize = uncmprsdDataSizeself.cmprsFlag = cmprsFlagself.typeCmprsData = typeCmprsDataself.name = nameclass PyInstArchive:PYINST20_COOKIE_SIZE = 24           # For pyinstaller 2.0PYINST21_COOKIE_SIZE = 24 + 64      # For pyinstaller 2.1+MAGIC = b'MEI\014\013\012\013\016'  # Magic number which identifies pyinstallerdef __init__(self, path):self.filePath = pathdef open(self):try:self.fPtr = open(self.filePath, 'rb')self.fileSize = os.stat(self.filePath).st_sizeexcept:print('[*] Error: Could not open {0}'.format(self.filePath))return Falsereturn Truedef close(self):try:self.fPtr.close()except:passdef checkFile(self):print('[*] Processing {0}'.format(self.filePath))# Check if it is a 2.0 archiveself.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)magicFromFile = self.fPtr.read(len(self.MAGIC))if magicFromFile == self.MAGIC:self.pyinstVer = 20     # pyinstaller 2.0print('[*] Pyinstaller version: 2.0')return True# Check for pyinstaller 2.1+ before bailing outself.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)magicFromFile = self.fPtr.read(len(self.MAGIC))if magicFromFile == self.MAGIC:print('[*] Pyinstaller version: 2.1+')self.pyinstVer = 21     # pyinstaller 2.1+return Trueprint('[*] Error : Unsupported pyinstaller version or not a pyinstaller archive')return Falsedef getCArchiveInfo(self):try:if self.pyinstVer == 20:self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)# Read CArchive cookie(magic, lengthofPackage, toc, tocLen, self.pyver) = \struct.unpack('!8siiii', self.fPtr.read(self.PYINST20_COOKIE_SIZE))elif self.pyinstVer == 21:self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)# Read CArchive cookie(magic, lengthofPackage, toc, tocLen, self.pyver, pylibname) = \struct.unpack('!8siiii64s', self.fPtr.read(self.PYINST21_COOKIE_SIZE))except:print('[*] Error : The file is not a pyinstaller archive')return Falseprint('[*] Python version: {0}'.format(self.pyver))# Overlay is the data appended at the end of the PEself.overlaySize = lengthofPackageself.overlayPos = self.fileSize - self.overlaySizeself.tableOfContentsPos = self.overlayPos + tocself.tableOfContentsSize = tocLenprint('[*] Length of package: {0} bytes'.format(self.overlaySize))return Truedef parseTOC(self):# Go to the table of contentsself.fPtr.seek(self.tableOfContentsPos, os.SEEK_SET)self.tocList = []parsedLen = 0# Parse table of contentswhile parsedLen < self.tableOfContentsSize:(entrySize, ) = struct.unpack('!i', self.fPtr.read(4))nameLen = struct.calcsize('!iiiiBc')(entryPos, cmprsdDataSize, uncmprsdDataSize, cmprsFlag, typeCmprsData, name) = \struct.unpack( \'!iiiBc{0}s'.format(entrySize - nameLen), \self.fPtr.read(entrySize - 4))name = name.decode('utf-8').rstrip('\0')if len(name) == 0:name = str(uniquename())print('[!] Warning: Found an unamed file in CArchive. Using random name {0}'.format(name))self.tocList.append( \CTOCEntry(                      \self.overlayPos + entryPos, \cmprsdDataSize,             \uncmprsdDataSize,           \cmprsFlag,                  \typeCmprsData,              \name                        \))parsedLen += entrySizeprint('[*] Found {0} files in CArchive'.format(len(self.tocList)))def extractFiles(self):print('[*] Beginning extraction...please standby')extractionDir = os.path.join(os.getcwd(), os.path.basename(self.filePath) + '_extracted')if not os.path.exists(extractionDir):os.mkdir(extractionDir)os.chdir(extractionDir)for entry in self.tocList:basePath = os.path.dirname(entry.name)if basePath != '':# Check if path exists, create if notif not os.path.exists(basePath):os.makedirs(basePath)self.fPtr.seek(entry.position, os.SEEK_SET)data = self.fPtr.read(entry.cmprsdDataSize)if entry.cmprsFlag == 1:data = zlib.decompress(data)# Malware may tamper with the uncompressed size# Comment out the assertion in such a caseassert len(data) == entry.uncmprsdDataSize # Sanity Checkwith open(entry.name, 'wb') as f:f.write(data)if entry.typeCmprsData == b's':print('[+] Possible entry point: {0}'.format(entry.name))elif entry.typeCmprsData == b'z' or entry.typeCmprsData == b'Z':self._extractPyz(entry.name)def _extractPyz(self, name):dirName =  name + '_extracted'# Create a directory for the contents of the pyzif not os.path.exists(dirName):os.mkdir(dirName)with open(name, 'rb') as f:pyzMagic = f.read(4)assert pyzMagic == b'PYZ\0' # Sanity CheckpycHeader = f.read(4) # Python magic valueif imp.get_magic() != pycHeader:print('[!] Warning: The script is running in a different python version than the one used to build the executable')print('    Run this script in Python{0} to prevent extraction errors(if any) during unmarshalling'.format(self.pyver))(tocPosition, ) = struct.unpack('!i', f.read(4))f.seek(tocPosition, os.SEEK_SET)try:toc = marshal.load(f)except:print('[!] Unmarshalling FAILED. Cannot extract {0}. Extracting remaining files.'.format(name))returnprint('[*] Found {0} files in PYZ archive'.format(len(toc)))# From pyinstaller 3.1+ toc is a list of tuplesif type(toc) == list:toc = dict(toc)for key in toc.keys():(ispkg, pos, length) = toc[key]f.seek(pos, os.SEEK_SET)fileName = keytry:# for Python > 3.3 some keys are bytes object some are str objectfileName = key.decode('utf-8')except:pass# Make sure destination directory exists, ensuring we keep inside dirNamedestName = os.path.join(dirName, fileName.replace("..", "__"))destDirName = os.path.dirname(destName)if not os.path.exists(destDirName):os.makedirs(destDirName)try:data = f.read(length)data = zlib.decompress(data)except:print('[!] Error: Failed to decompress {0}, probably encrypted. Extracting as is.'.format(fileName))open(destName + '.pyc.encrypted', 'wb').write(data)continuewith open(destName + '.pyc', 'wb') as pycFile:pycFile.write(pycHeader)      # Write pyc magicpycFile.write(b'\0' * 4)      # Write timestampif self.pyver >= 33:pycFile.write(b'\0' * 4)  # Size parameter added in Python 3.3pycFile.write(data)def main():if len(sys.argv) < 2:print('[*] Usage: pyinstxtractor.py <filename>')else:arch = PyInstArchive(sys.argv[1])if arch.open():if arch.checkFile():if arch.getCArchiveInfo():arch.parseTOC()arch.extractFiles()arch.close()print('[*] Successfully extracted pyinstaller archive: {0}'.format(sys.argv[1]))print('')print('You can now use a python decompiler on the pyc files within the extracted directory')returnarch.close()if __name__ == '__main__':main()

将pyinstxtractor.py文件复制到TestAdd.exe同目录下,运行cmd.exe,输入以下命令进行反编译:

python pyinstxtractor.py TestAdd.exe


反编译的文件在exe所在目录的后缀为exe_extracted文件夹下,示例的提取目录为TestAdd.exe_extracted/PYZ-00.pyz_extracted文件下

在TestAdd.exe_extracted下有从TextAdd.exe提取出来的pyc文件,我们可以使用反编译工具进行反编译。

5 加密编译exe

如果我们要增加反编译pyinstaller打包的exe文件的难度该怎么办?添加key值。
在py目录启动cmd.exe,输入以下命令:

pyinstaller -F --key 123456789 TestAdd.py

其中运行选项:
-F:强制编译为单个exe文件,不要多余的文件;
–key 123456789:使用key123456789进行加密编译;

5.1 注意事项

需要注意的是,在运行上述命令时如果你没有安装pycrypto第三方库,则需要执行下述命令进行安装:

pip install pycrypto

进行安装,在这其中大概率会出现如下错误:

error C2061: 语法错误: 标识符“intmax_t”;error C2059: 语法错误:“;” ;error C2143: 语法错误: 缺少“{”(在“__cdecl”的前面)等等

等。

解决方案:
1 进入电脑VS安装目录下,搜索stdint.h(示例路径:D:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include),将该文件复制到以下路径,示例路径:C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt/
2 然后在C:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt/下找到inttypes.h文件,进行文件编译,
将包含头文件的代码:

#include <stdint.h>

修改为

#include "stdint.h"

3 重新运行

pip install pycrypto

进行安装pycrypto,应该就可以了。

5.2 加密编译



这是dist目录下只有单个的TestAdd.exe文件。

这是我们依然采用pyinstxtractor.py对其进行反编译

可以看到出现了较多的decompress Error 解压错误,TestAdd.exe_extracted/PYZ-00.pyz_extracted文件夹下的文件都是加密的。

这种方式增加了反编译pyinstaller打包的exe文件的难度,在一定程度上增加了python源代码的保护性。

6 将外部数据打包到exe中

将TestAdd.py文件内容修改如下:

#__author__ = 'StubbornHuang'
#coding = utf-8import io
import os
import sysdef resource_path(relative_path):""" Get absolute path to resource, works for dev and for PyInstaller """base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))return os.path.join(base_path, relative_path)def printTestFile1():file = 'Test1.txt'print(resource_path(file))with open(resource_path(file), 'r',encoding='UTF-8') as f:while True:line = f.readline()     # 逐行读取if not line:breakprint(line)def printTestFile2():file = 'data/Test2.txt'print(resource_path(file))with open(resource_path(file), 'r',encoding='UTF-8') as f:while True:line = f.readline()     # 逐行读取if not line:breakprint(line)if __name__ == '__main__':printTestFile1()printTestFile2()

然后在py所在目录新建Test1.txt,并输入以下内容:

pyinstaller外部数据打包测试(单文件)

然后在py所在目录新建data子文件夹,在data文件夹下新建Test2.txt,并输入以下内容:

pyinstaller外部数据打包测试(文件夹下的目录)



好的,将上述准备工作做好之后则开始进行将外部数据增加到exe中

6.1 如果不需要加密编译

则在py文件所在目录输入以下命令

pyi-makespec -F TestAdd.py

执行完命令后,可以看到py所在目录下新增了文件TestAdd.spec


该文件内容为:

# -*- mode: python -*-block_cipher = Nonea = Analysis(['TestAdd.py'],pathex=['C:\\Users\\Administrator\\Desktop\\PythonExe\\Test'],binaries=[],datas=[],hiddenimports=[],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='TestAdd',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,runtime_tmpdir=None,console=True )

将上述文件进行修改,添加外部数据,修改如下:

# -*- mode: python -*-block_cipher = Nonea = Analysis(['TestAdd.py'],pathex=['C:\\Users\\Administrator\\Desktop\\PythonExe\\Test'],binaries=[], datas=[('Test1.txt','.'),('data/Test2.txt','data')],#修改处hiddenimports=[], #填入需要导入的第三方库,例如flaskhookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='TestAdd',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,runtime_tmpdir=None,console=True )

上述修改会将Test1.txt以及/data/Test2.txt文件在运行时复制到可执行程序的临时目录以便可执行程序可以找到相应的文件。
修改后,使用命令:

pyinstaller TestAdd.spec

进行编译。

如果出现找不到Test1.txt或者/data/Test2.txt的错误,是因为运行可执行文件时,会先将可执行文件进行压缩,压缩的位置在 /tmp 下,再执行,所以被打包进去的数据文件在被解压的路径下,而,程序是在运行的路径下搜索,即可执行文件的目录下,所以找不到数据文件。
所以我们在编写TestAdd.py文件时,添加了如下函数

def resource_path(relative_path):""" Get absolute path to resource, works for dev and for PyInstaller """base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))return os.path.join(base_path, relative_path)

用于寻找pyinstaller临时文件目录。

6.2 如果需要加密编译

如果需要加密编译,参照第5节,运行以下命令:

pyinstaller -F --key 123456789 TestAdd.py

生成TestAdd.spec,其文件内容如下:

# -*- mode: python -*-block_cipher = pyi_crypto.PyiBlockCipher(key='123456789')a = Analysis(['TestAdd.py'],pathex=['C:\\Users\\Administrator\\Desktop\\PythonExe\\Test'],binaries=[],datas=[],hiddenimports=[],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='TestAdd',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,runtime_tmpdir=None,console=True )

将其修改为:

# -*- mode: python -*-block_cipher = pyi_crypto.PyiBlockCipher(key='123456789')a = Analysis(['TestAdd.py'],pathex=['C:\\Users\\Administrator\\Desktop\\PythonExe\\Test'],binaries=[],datas=[('Test1.txt','.'),('data/Test2.txt','data')],hiddenimports=[],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='TestAdd',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,runtime_tmpdir=None,console=True )

保存之后,执行命令:

pyinstaller TestAdd.spec

编译文件,这样,编译出来的exe既是加密后的也是引入外部数据的。

7 为exe添加图标

找一个在线生成图标ico的网站,生成自己想要的图标,我用的是http://www.faviconico.org/favicon,然后将图标放在py同目录下。

然后修改TestAdd.spec文件,源文件内容如下:

# -*- mode: python -*-block_cipher = pyi_crypto.PyiBlockCipher(key='123456789')a = Analysis(['TestAdd.py'],pathex=['C:\\Users\\Administrator\\Desktop\\PythonExe\\Test'],binaries=[],datas=[],hiddenimports=[],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='TestAdd',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,runtime_tmpdir=None,console=True)

修改为:

# -*- mode: python -*-block_cipher = pyi_crypto.PyiBlockCipher(key='123456789')a = Analysis(['TestAdd.py'],pathex=['C:\\Users\\Administrator\\Desktop\\PythonExe\\Test'],binaries=[],datas=[('Test1.txt','.'),('data/Test2.txt','data')],hiddenimports=[],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,cipher=block_cipher)
exe = EXE(pyz,a.scripts,a.binaries,a.zipfiles,a.datas,[],name='TestAdd',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,runtime_tmpdir=None,console=True,icon='ico.ico') #增加的图标

然后使用命令

pyinstaller TestAdd.spec

生成exe文件,我们可以看到exe是带图标的了

如果您觉得这篇博文有用,请访问我的个人站:http://www.stubbornhuang.com/,更多博文干货等着您。

PyInstaller:编译exe与反编译相关推荐

  1. pyinstaller 打包exe 防反编译(加密)

    如果对安全性要求不高,可以选择直接将py文件,打包成exe即可,解压出来的是pyc文件,pyc文件还原成源码,也是有一定复杂度的,相对而言也是有一定的安全性的 在源文件同级目录下创建build文件 b ...

  2. 【干货】Python文件打包 .exe文件反编译

    一.Python文件 打包 成 .exe 可执行文件 第一步:安装pyinstaller 首先安装pyinstall,使用命令:pip3 install pyinstaller,当然有可能报错,如下图 ...

  3. Python代码封装的可执行exe文件反编译为Py脚本

    起因是笔者有个课,教图形图像学,作业的代码调不出老师的效果,于是就又有了hack的想法,把老师给的用来演示的exe文件反编译.主要是根据这篇文章的方法来的.将 exe 文件反编译成 Python 脚本 ...

  4. 初识Ildasm.exe——IL反编译的实用工具(转自Youngman)

    Ildasm.exe 概要: 一.前言: 微软的IL反编译实用程序--Ildasm.exe,可以对可执行文件(ex,经典的控制台Hello World 的 exe 可执行文件)抽取出 IL 代码,并且 ...

  5. 如何反编译,防止反编译,常见问题总结

    本文对如何反编译,防止反编译,和常遇到的问题做了个总结,并略有修改. 资源来自:http://blog.csdn.net/sunboy_2050/article/details/6727581 htt ...

  6. 【反编译系列】反编译so文件(IDA_Pro)

    概述 安卓应用程序的开发语言是java,但是由于java层的代码很容易被反编译,而反编译c/c++程序的难度比较大,所以现在很多安卓应用程序的核心部分都使用NDK进行开发.使用NDK开发能够编译c/c ...

  7. 超详细!apk安装包快速反编译,多种反编译及失败的解决方案(包含classes.dex的反编译,新增加快速反编译)

    如要转载,请贴出原地址:https://blog.csdn.net/Nobody_else_/article/details/83996441 众所周知,我们开发所用的手机App安装包都是apk文件, ...

  8. unity3D 如何提取游戏资源 (反编译)+代码反编译【P.M.出品】

    转自:https://blog.csdn.net/LANGZI7758521/article/details/52291564 首先感谢 雨松MOMO 的一篇帖子 教我们怎么提取 .ipa 中的游戏资 ...

  9. 对python3.7打包而成的exe进行反编译

    记一次对pyinstaller打包的,无加壳exe程序的反编译.之前,有位朋友写了有关学校充电费的程序,打包成了exe,现在学校充电费的网站更新了,我就想把这位朋友写的程序反编译一下,然后进行代码修改 ...

  10. 将exe4j打包的java exe程序反编译过程

    开始,我用了http://blog.csdn.net/lanximu/article/details/16879545的方法,但十六进制文件看着有乱码,试着截了几次进行压缩,但都不对,不管是用ultr ...

最新文章

  1. 括号匹配(栈和队列)
  2. linux 复制包括子目录_【Linux分享】Linux常用命令+教程分享
  3. 在windows上搭建redis集群(Redis-Sentinel)
  4. matlab打开时总闪一下才打开_大家装窗帘轨道时,是不是多数都是下面这样的: 打开网易新闻 查看更多图片 或者做个窗帘盒,遮盖一下?...
  5. 4.Java JSON使用
  6. visio之图案填充
  7. Mac无法打开“XX”,因为Apple无法检查其是否包含恶意软件。”的解决办法
  8. 模板字符串+JS模板引擎+vue,三者之间的字符串比较
  9. 关于gitlab报错 would clobber existing tag 的解决办法
  10. PHP加密解密方法 阿星小栈
  11. Idea使用起来反应比较慢
  12. 圆周率一千万亿位_目前圆周率已经达到十万亿位了,为何还要算?有什么用处?...
  13. python打印数组的全部元素
  14. 什么是好人,什么是坏人,你有标准答案吗
  15. 小丸子学Docker系列之——实战Dockerfile
  16. 基于kmeans聚类算法的微博舆情热点事件分析系统
  17. Linux笔记----ln -s,>, >>, cat, more, less, head, tail, sed
  18. 安卓手机文件系统 roots recovery bootimg
  19. 汇源福利社——青龙脚本
  20. 税务会计实务【11】

热门文章

  1. 响铃:创业三年即IPO,拼多多不应该被质疑
  2. 若依框架----代码生成(详解)
  3. matlab画图函数之plot【matlab图行绘制一】
  4. stc流水灯c语言程序,求51单片机流水灯跑马灯程序设计 (STC89C52RC)??
  5. 网关报错:Load balancer does not have available server for client: xxx
  6. Linux常用远程连接工具介绍,总有一款适合你
  7. jdk安装好了怎么使用_安装jdk怎么打开
  8. cad填充图案乱理石_CAD教程:CAD填充图案管理技巧
  9. Grid Search 网格搜索 介绍
  10. ICESat2学习笔记4 :Windows下使用HDFView查看ICESat-2 hdf5文件