git –version 查看git版本
which -a git
git-cmd.exe
git-bash.exe
工程准备
git init 用于在本地目录下新建git 项目仓库
//处理子仓
git submodule update –init –recursive
工程克隆:git clone
查看工作区
查看工作区的修改内容:git diff
查看工作区文件状态:git status
文件修改后提交推送
新增/删除/移动文件到暂存区:git add/ git rm/ git mv
提交更改的文件:git commit
推送远端仓库:git push origin branch_name:new_branch_name
查看日志
查看当前分支上的提交日志:git log
分支管理
列出本地分支:git branch
新建分支:git branch / git checkout -b
删除分支:git branch -d
切换分支:git checkout
更新分支:git pull
合并分支:git merge
撤销操作
强制回退到历史节点:git reset
回退本地所有修改而未提交的:git checkout
撤销commit: git reset –soft HEAD^
撤销add: git reset –hard HEAD^
清理:git reset –hard; git clean -df
分支合并
合并目标分支内容到当前分支: git merge/ git rebase
本地仓特性分支:feat
远端仓master指定commit:123456
将特性rebase到指定commit:
1.git checkout 123456
2.git checkout -b newmaster(该分支的最新commitid为:123456)
3.git checkout feat
4.git rebase 123456
5.git push origin feat –force
git status 查看当前状态,本地是否有更改的文件
git checkout master 切换分支
git pull –rebase 远程拉取代码
git checkout . && git clean -xdf 丢弃本地所有修改
git blame 小乌龟->Blame previous revision
git pull –rebase
git add .
git commit –m ”Bug: BUG”
如果需要覆盖提交,则:git commit –amend
git review
指定分支提交:
git push origin develop:dev_codecheck
git config –global user.name lzy
git config –global user.email lzy@***
///默认git的日志时区是 UTC +0000,设置为中国的时区 UTC +8000
git config –global log.date local
git config –global credential.helper store
(保存git的用户名和密码,只要输入一次以后就不用输了
git config –system –unset credential.helper 清一下缓存密码
) git config –list
\1. git branch 查看本地分支
\2. git branch -a (查看所有分支)
其中有remotes/的为远程分支
\3. git checkout –b(创建新的分支)
git add .
git stash
git checkout ***
Git status
Git stash list
git stash drop stash@{0}
git status
git checkout [filepath/filename]
git reset HEAD [filepath/filename]
git rebase –abort
git reflog
git reset commitid
撤销已修改的文件 git reset HEAD
撤销未跟踪文件 git checkout
清除所有未跟踪文件 git clean -dxf
删除当前目录下没有被track过的文件和文件夹git clean -df
git log 查看有哪些commit
git log -m 查看merged的commit
git reset –hard [commitid]
(强制转换,修改的内容会被丢弃)
git cherry-pick [commitid] (git update-ref -d CHERRY_PICK_HEAD)
git reset –soft HEAD~1
(修改的内容会在缓存区)
git commit
cat .git/HEAD 查看当前 HEAD 指向哪儿
git reflog
git reset –soft HEAD~1
git reset file
git checkout file
git checkout origin/master
git checkout –b new 创建并切换到分支new
git cherry-pick commit-id
git commit –m “Bug: BUG***** ”
git review
当前分支所有超前master的提交: git format-patch -M master
某两次提交之间的所有patch: git format-patch 365a..4e16 –365a和4e16分别对应两次提交的名称
先检查patch文件:git apply –stat newpatch.patch 检查能否应用成功:git apply –check newpatch.patch
应用:git apply newpatch.patch
git rev-parse HEAD 获取当前最后一个的 commit hash
git rev-parse –short HEAD
git clone –bare $url
git rebase -i 命令可以压缩合并多次提交 格式:git rebase -i [startpoint [endpoint]
其中-i的意思是–interactive,即弹出交互式的界面让用户编辑完成合并操作,[startpoint] [endpoint]则指定了一个编辑区间,如果不指定[endpoint],则该区间的终点默认是当前分支HEAD所指向的commit(注:该区间指定的是一个前开后闭的区间)。
执行这个命令后会跳到一个vi编辑器 里面的提示有: pick:保留该commit(缩写:p) reword:保留该commit,但我需要修改该commit的注释(缩写:r) edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e) squash:将该commit和前一个commit合并(缩写:s) fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f) exec:执行shell命令(缩写:x) drop:我要丢弃该commit(缩写:d)
例子: 在终端输入: git rebase -i HEAD~2 这里的 HEAD~2 表示合并最近两次的提交,进入编辑模式后,修改合入记录的pick,从上到下依次为旧commit->新commit,将最后一个commit改为squash,保存退出,然后会自动执行rebase操作并弹出commit合并界面,在将红框内的commit message修改掉,然后wq保持退出即可。再次push
1、git rebase -i HEAD~2 2表示多少个commit,从上到下以从新到老排序
2、将下面第2个pick修改为s,然后保存退出 pick 31bf5d1b IR2020060115552 update chronograf from v1.0.2 to v1.0.3 pick d6064738 BUG2020070903442 add database limit 修改为: pick 31bf5d1b IR2020060115552 update chronograf from v1.0.2 to v1.0.3 s d6064738 BUG2020070903442 add database limit
3、git push -f 推送到远端
A仓库B分支: git diff [commit1] [commit2] > x.patch B仓库B分支: git apply x.patch
git是用什么语言开发的?C语言
git 可以安装在哪些操作系统上? Linux, macOS, Solaris, Windows, Raspberry Pi
git init 初始化本地仓库
git add
git commit -m
git status 查看仓库当前状态
git diff查看修改内容
git diff HEAD --
git log查看提交历史
git reflog 查看历史命令
git reset–hard HEAD^回退版本
`HEAD`表示当前版本
上一个版本就是`HEAD^`
上上一个版本就是`HEAD^^`
git reset –hard commit_id在版本的历史之间穿梭
git checkout – file让这个文件回到最近一次git commit或git add时的状态。
本质:用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
git rm file从版本库中删除该文件,再执行git commit
git push命令把本地库的内容推送到远程
git clone命令克隆一个仓库
git branch 查看分支
git branch -v
git rev-parse –abbrev-ref HEAD获取当前分支名
git branch
git checkout <name>或者git switch <name>切换分支
git checkout -b <name>或者git switch -c <name>创建+切换分支
git merge
git branch -d
git log --graph命令可以看到分支合并图。
git log –stat
git stash 缓存工作现场
git stash pop回到工作现场
git cherry-pick <commit>命令,把bug提交的修改“复制”到当前分支,避免重复劳动。
git branch -D
git remote 查看远程库的信息
git remote –v 显示更详细的信息
修改:git remote set-url origin https://**
添加:git remote add upstream git@&&&&&&&&&
删除:git remote rm upstream
git checkout -b branch-name origin/branch-name在本地创建和远程分支对应的分支
git branch –set-upstream branch-name origin/branch-name建立本地分支和远程分支的关联
\1. 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,git checkout –file
\2. 当你改乱了工作区某个文件的内容,还添加到了暂存区,想丢弃修改,先执行git reset HEAD file,回到场景一,然后执行git checkout – < file >
\3. 提交了不合适的修改到版本库,撤销提交,用版本回退的方法
直接退回到某个patch:
\1. reset
\2. patch cherry pick 一下重新提交
https://blog.csdn.net/csdnlyu/article/details/79352811
如果配置了ssh, 但是无法git clone,执行:
git config –global http.sslVerify false
git config -l 检查参数配置是否正确
git remote set-url origin http://***
git remote –v
git pull –rebase 的时候可能会出现
fatal:Unable to fine remote helper for ‘http’的问题
https://blog.csdn.net/benben_2015/article/details/78803753
export LD_LIBRARY_PATH=/lib64:$LD_LIBRARY_PATH加个这个就没问题了
git config –global http.sslVerify false
可以在控制面板的用户账户中进行修改。
1.问题:git下载代码时,报“git出现RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errfno 10054”的问题
2.解决步骤:
2.1 首先输入如下命令: git config http.sslVerify “false”
2.2 如果输入上面命令提示报“ fatal: not in a git directory ”,则输入如下命令:git init
2.3 重新下载代码: git clone https://git.com……
2.4 如果还是git代码还是下载失败,则需要修改git缓存的大小为100MB,输入如下命令: git config –global http.postBuffer 100M
执行下面命令
git config --global core.autocrlf false
git config --global http.sslVerify false
现象 1.修改一行代码之后,git diff 发现整个文件都被修改;
2.git diff -b 正确显示修改的部分;
3.git diff -R 被修改的每行后面都增加了一个“^M”
4.采用网上常说的:
git config --global core.whitespace cr-at-eol //该命令可以让git diff的时候忽略换行符的差异
不能解决问题
解决方法 git diff –ignore-space-at-eol > ~test.diff git checkout . git apply –ignore-whitespace ~test.diff
Git进行代码管理的过程中尽量采用rebase 而不是merge
git fetch upstream
git checkout master
git merge upstream/master
git push
git checkout [AB共同的master commit id]
git switch -c x
git checkout master
git fetch B y:x
git checkout -b x B/y
git fetch *** 获取主干tag后,
git push -f origin --tags
git describe 与git log是否一致
git tag -d 23.3.0.1 本地删除tag
git push origin :refs/tags/23.3.0.1 远程删除tag
git tag -a 23.3.0.1 -m "view" 新建tag
git push -f origin 23.3.0.1 --tags 同步到远程仓
git tag -a tagName -m "commit"
git push origin --tag # 自己的仓库
https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
https://blog.csdn.net/ligang2585116/article/details/71094887
https://education.github.com/git-cheat-sheet-education.pdf
4/6 points (graded)
版本控制工具一节已经结束,快来做几道题看看自己掌握得如何吧~
SVN 和 Git 的相同点是?
diff 工具产生的差异结果包含哪些内容?
以下哪些是集中式版本控制工具?
以下说明正确的有?
SVN 相对于 Git 存在一些差异有?
不知道选啥
Git 相对于 SVN 有哪些优点?
sudo aptitude install git
sudo aptitude install git-doc git-svn git-email gitk
yum install git
yum install git-svn git-email gitk
Git基本配置
系统配置
git config –system core.autocrlf
用户配置
git config –global user.name
仓库配置
git config –local remote.origin.url
换行符:CRLF, LF
Linux下面安装 Git 的方式有哪些?
关于 Git 安装的操作,正确的有?
Git 和 TortoiseGit 的关系是?
关于 Git 配置的说明,正确的有?
版本库(Repository)
工作区(Working Directory)
暂存区(stage)
Git版本控制下的文件状态只有三种
已提交(committed)
已修改(modified)
已暂存(staged)
本节小测
4/4 points (graded)
将工作区中所有的新增文件添加到Git暂存区,以便提交,可以用什么命令?
在本地Git工程中,如果在分支A上进行了一系列git add/rm/mv/commit/pull操作,会直接影响Git远端服务器上分支A的节点内容。
在Windows开发环境和默认Git配置下,如果在本地Git工程已存在名为Demo的分支,同时新建分支,并命名为demo。那么在demo分支推送远端服务器过程中,会出现分支名不识别。
正确
错误
在本地Git工程中,执行git pull的更新操作相对于执行git fetch的更新操作来得安全些,可以让用户在确认更新内容符合预期后再自行决定节点合并。
课后小测
11/11 points (graded)
单选题:
\1. Git 是分布式版本控制系统,下列说法错误的是?
\2. 以下哪些是项目内部开源的好处?
①促进软件架构和代码的质量提升。 ②减少重复开发。 ③提高产出效率。 ④促进公司软件开发人员的整体能力提升。
\3. 在Git内文件的状态有以下哪些?
①已修改(modified)②已提交(committed)③已暂存(staged)
\4. 可以查看当前工作区是否干净或修改的文件处于什么状态的语句是?
\5. 查看本地和远端所有分支的命令是?
\6. 基于本地分支master,新建分支DTS并将分支转到DTS的命令行是?
\7. 如果把项目中文件 hello.c 的内容破坏了,如何使其还原至原始版本?
\8. 下列表述关于组织/仓库创建的说法错误的是?
\9. 以下哪个是修改完本地代码后提交并推送到远程仓库的正确操作顺序?
①$ git status ②$ git add [需提交的fileName] ③$ git commit ④$ git push
\10. 以下哪些操作可以本地获得基线上最新的代码?()
①$ git push ②$ git pull ③$ git pull –rebase ④$ git fetch origin + git merge origin/master
\11. 关于代码平台的 Merge Request,下列说法错误的是()
在缓冲区和控制信息间插入一个canary word
检查该值是否被修改,判断是否发生了溢出攻击
缓冲区溢出后通过执行shellcode达到攻击的目的。
设置堆栈不可执行,一旦堆栈中的数据被执行,立刻报告错误。即使溢出成功,也不能执行shellcode.
节省物理内存、提高内存利用率,阻止mmap将代码段映射并使用mprotect将其改为可写。
防止全局偏移表被恶意重写
以下哪个选项可以阻止通过重写GOT表中函数地址实现的攻击?
-WI, -z, relro, -z,now
ASLR是基础,只有操作系统开启ASLR功能,-fPIE –pie选项添加的随机化特征才会在程序加载和运行时展现。
在ASLR基础上,编译时开启-fPIE/-pie 选项会新增哪个段地址随机化?
.test或.code
##### 7.FORTIFY_SOURCE
使用栈保护选项-fstack-protector后的程序,如果遇到栈上发生溢出,给出的错误提示是“stack smashing detected”
ROP(Return-oriented Programming) 一种新型的基于代码复用技术的攻击,以下选项可以降低该攻击的成功率,提高攻击难度。
A.-WI,-z,noexecstack
B.-WI,-z,relro, -z,now
C.-fstack-protector-all
D.-fPIE -pie
在程序中一般都会用到命令行选项, 我们可以使用getopt 和getopt_long函数来解析命令行参数
getopt主要用来处理短命令行选项, 例如./test -v中-v就是一个短选项. 使用该函数需要引入头文件<unistd.h>, 下面是该函数的定义
int getopt(int argc, char * const argv[], const char * optstring);
其中 argc 和 argv 是main函数中的传递的参数个数和内容, optstring用来指定可以处理哪些选项, 下面是optstring的一个示例:
"a:bc"
该示例表明程序可以接受3个选项: -a -b -c, 其中 a 后面的 :表示该选项后面要跟一个参数, 即如 -a text的形式, 选项后面跟的参数会被保存到 optarg 变量中. 下面是一个使用示例:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv) {
int ch;
while((ch = getopt(argc, argv, "a:b")) != -1) {
switch(ch) {
case 'a':
printf("option a: %s\n", optarg);
break;
case 'b':
printf("option b \n");
break;
case '?': // 输入未定义的选项, 都会将该选项的值变为 ?
printf("unknown option \n");
break;
default:
printf("default \n");
}
}
}
执行 ./test -a aa -b -c 输出结果如下:
option a: aa
option b
unknown option
getopt_long支持长选项的命令行解析, 所为长选项就是诸如--help的形式, 使用该函数, 需要引入<getopt.h>下面是函数原型:
#include <getopt.h>
int getopt_long(int argc,
char * const argv[],
const char *optstring,
const struct option *longopts,
int *longindex);
int getopt_long_only(int argc,
char * const argv[],
const char *optstring,
const struct option *longopts,
int *longindex);
其中 argc , argv , optstring 和getopt中的含义一样, 下面解释一下longopts 和longindex
longopts
longopts 指向一个struct option 的数组, 下面是option的定义:
struct option {
const char *name;
int has_arg;
int *flag;
int val;
};
下面是各字段的含义
help下面是longopts的一个示例
struct option opts[] = {
{"version", 0, NULL, 'v'},
{"name", 1, NULL, 'n'},
{"help", 0, NULL, 'h'}
};
我们来看{"version", 0, NULL, 'v'}, version 即为长选项的名称, 即按如下形式--version, 0 表示该选项后面不带参数, NULL 表示直接将v返回(字符v在ascii码中对应的数值), 即在使用getopt_long遍历到该条选项时, getopt_long 返回值为字符v对应的ascii码值.
longindex
longindex表示长选项在longopts中的位置, 例如在上面的示例中, version 对应的 longindex 为0, name 对应的 longindex 为1, help对应的 longindex 为2, 该项主要用于调试, 一般设为 NULL 即可.
下面是一个使用示例:
void use_getpot_long(int argc, char *argv[]) {
const char *optstring = "vn:h";
int c;
struct option opts[] = {
{"version", 0, NULL, 'v'},
{"name", 1, NULL, 'n'},
{"help", 0, NULL, 'h'},
{NULL,0,NULL,0}
};
while((c = getopt_long(argc, argv, optstring, opts, NULL)) != -1) {
switch(c) {
case 'n':
printf("username is %s\n", optarg);
break;
case 'v':
printf("version is 0.0.1\n");
break;
case 'h':
printf("this is help\n");
break;
case '?':
printf("unknown option\n");
break;
case 0 :
printf("the return val is 0\n");
break;
default:
printf("------\n");
}
}
}
然后我们运行程序 ./test --name lzy --version --help --haha, 下面是运行结果:
username is lzy
version is 0.0.1
this is help
unknown option
当然我们也可以使用短选项 ./test -n lzy -v -h
下面我们对程序做一下修改, 这一次将 struct option 中的 flag 和 longindex 设为具体的值
void use_getpot_long2(int argc, char *argv[]) {
const char *optstring = "vn:h";
int c;
int f_v = -1, f_n = -1, f_h = -1, opt_index = -1;
struct option opts[] = {
{"version", 0, &f_v, 'v'},
{"name", 1, &f_n, 'n'},
{"help", 0, &f_h, 'h'},
{NULL,0,NULL,0}
};
while((c = getopt_long(argc, argv, optstring, opts, &opt_index)) != -1) {
switch(c) {
case 'n':
printf("username is %s\n", optarg);
break;
case 'v':
printf("version is 0.0.1\n");
break;
case 'h':
printf("this is help\n");
break;
case '?':
printf("unknown option\n");
break;
case 0 :
printf("f_v is %d \n", f_v);
printf("f_n is %d \n", f_n);
printf("f_h is %d \n", f_h);
break;
default:
printf("------\n");
}
printf("opt_index is %d\n\n", opt_index);
}
}
运行程序: ./test --name lzy --version --help , 下面是运行结果:
f_v is -1
f_n is 110
f_h is -1
opt_index is 1
f_v is 118
f_n is 110
f_h is -1
opt_index is 0
f_v is 118
f_n is 110
f_h is 104
opt_index is 2
我们可以看到当给 flag 指定具体的指针之后, getopt_long 会返回0, 因此会去执行case 0, 并且 val 的值赋给了 flag 指向的变量. 下面我们用短选项执行一下程序 ./test -n lzy -v -h, 下面是运行结果
username is lzy
opt_index is -1
version is 0.0.1
opt_index is -1
this is help
opt_index is -1
我们看到使用短选项的时候 getopt_long 就相当于 getopt , flag 和 longindex都不起作用了.
下面解释一下 getopt_long 和 getopt_long_only的区别, 首先用下列选项运行一下 use_getopt_long ./test -name lzy -version -help , 下面是输出结果:
username is ame
opt_index is -1
version is 0.0.1
opt_index is -1
./test2: invalid option -- 'e'
unknown option
opt_index is -1
./test2: invalid option -- 'r'
unknown option
opt_index is -1
./test2: invalid option -- 's'
unknown option
opt_index is -1
./test2: invalid option -- 'i'
unknown option
opt_index is -1
./test2: invalid option -- 'o'
unknown option
opt_index is -1
username is -help
opt_index is -1
我们看到使用短选项标识符 - 指向长选项时, 程序还是会按短选项来处理, 即一个字符一个字符的解析. 下面我们将 use_getopt_long 做一下更改, 即将 getopt_long 改为 getopt_long_only , 如下所示:
void use_getpot_long3(int argc, char *argv[]) {
const char *optstring = "vn:h";
int c;
struct option opts[] = {
{"version", 0, NULL, 'v'},
{"name", 1, NULL, 'n'},
{"help", 0, NULL, 'h'},
{NULL, 0, NULL, 0}
};
while((c = getopt_long_only(argc, argv, optstring, opts, NULL)) != -1) {
switch(c) {
case 'n':
printf("username is %s\n", optarg);
break;
case 'v':
printf("version is 0.0.1\n");
break;
case 'h':
printf("this is help\n");
break;
case '?':
printf("unknown option\n");
break;
case 0 :
printf("the return val is 0\n");
break;
default:
printf("------\n");
}
}
}
下面再运行程序 ./test -name lzy -version -help , 下面是运行结果:
username is lzy
version is 0.0.1
this is help
即使用 getopt_long_only 时, - 和 --都可以作用于长选项, 而使用 getopt_only 时, 只有 --可以作用于长选项.
http://blog.zhangjikai.com/2016/03/05/%E3%80%90C%E3%80%91%E8%A7%A3%E6%9E%90%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%8F%82%E6%95%B0–getopt%E5%92%8Cgetopt_long/
pwndbg是一个gdb的插件,在ctf中pwn题目中使用非常方便,尤其是对堆的查看,有很多独有的指令,相比起其他插件来说还是很方便的。
pwndbg的安装:
git clone https://github.com/pwndbg/pwndbg
cd pwndbg
./setup.sh
安装好之后要把gdb的插件切换为pwndbg:
vim ~/.gdbinit
source ~/peda/peda.py
pwndb不可和其他插件一起使用,如果使用的gdb版本不太匹配也会出现各种各样的问题,总之用的时候如果出现了一些奇怪的问题,脑子灵活点,可能是调试器的问题。
s //单步步入,遇到调用跟进函数中,相当于step into,
源码层面的一步
n //单步补过,遇到电泳不跟进,相当于step over,
源码层面的一步
c //continue,常用,继续执行到断点,没断点就一直执行下去
r //run,常用,重新开始执行
b *(0x123456) //
常用
,给0x123456地址处的指令下断点
b fun_name //
常用
,给函数fun_name下断点,
目标文件要保留符号才行
b file_name:15 //给file_name的15行下断点,
要有源码才行
b +0x10 //在程序当前停住的位置下0x10的位置下断点,同样可以-0x10,就是前0x10
break fun if $rdi==5 //条件断点,rdi值为5的时候才断
使用info break(简写: i b)来查看断点编号
delete 5 //常用,删除5号断点,直接delete不接数字删除所有
disable 5 //
常用
,禁用5号断点
clear //清除下面的所有断点
除syscall外还可以使用的有:
1)throw: 抛出异常
2)catch: 捕获异常
3)exec: exec被调用
4)fork: fork被调用
5)vfork: vfork被调用
6)load: 加载动态库
7)load libname: 加载名为libname的动态库
8)unload: 卸载动态库
9)unload libname: 卸载名为libname的动态库
10)syscall [args]: 调用系统调用,args可以指定系统调用号,或者系统名称
x /nuf 0x123456 //
常用
,x指令的格式是:x空格/nfu,nfu代表三个参数
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
s 按字符串显示。
b 按字符显示。
i 显示汇编指令。
p fun_name //打印fun_name的地址,需要保留符号
p 0x10-0x08 //计算0x10-0x08的结果
p &a //查看变量a的地址
p *(0x123456) //查看0x123456地址的值,注意和x指令的区别,x指令查看地址的值不用星号
p $rdi //显示rdi寄存器的值,
注意和x的区别,这只是显示rdi的值,而不是rdi指向的值
list //查看当前附近10行代码,
要有源码,list指令pwn题中几乎不用
,但为了完整性还是简单举几个例子
arena //显示arena的详细信息
bins //
常用
,查看所有种类的堆块的链表情况
heap //
数据结构的形式显示所有堆块
,会显示一大堆
tracemalloc //好用,会跟提示所有操作堆的地方
常见的资源,例如磁盘、网络、CPU 等等,都会存在竞争的问题,在构建分布式架构时,可以将原本连接在一起的组件、模块、资源拆分开来,以便达到最大的利用效率或性能。
资源隔离之后,当某一部分组件出现故障时,可以隔离故障,方便定位的同时,阻止传播,避免出现滚雪球以及雪崩效应。
资源隔离方法: cgroup 命令
绑核方法: taskset命令
https://cloud.tencent.com/developer/article/1908299
https://blog.csdn.net/qq_38232598/article/details/114263105
https://www.cnblogs.com/tencent-cloud-native/p/15192674.html
https://www.cnblogs.com/anay/p/11121708.html