shell 脚本学习-网络野路子
shell脚本攻略
Linux命令大全(手册)_Linux常用命令行实例详解_Linux命令学习手册
Unix 基础知识
shell知识点_亦乐-可乐的博客-CSDN博客
1.自定义Shell变量时,变量名有什么规则?
可以包括数字、字母、下划线,不能以数字开头
变量名区分大小写
赋值时等号两边不要有空格
尽量不要使用关键字和特殊字符
给同一个变量多次赋值时,最后一次的赋值生效
2.简述预定义变量KaTeX parse error: Can't use function '$' in math mode at position 2: 、$̲?、$0、$#、$*、$!的作… 保存当前运行进程的(PID)号
$? 保存命令执行结果的(返回状态)
$0 保存当前运行的(进程名)或(脚本名)
$# 保存位置变量的(个数)
$* 保存所有位置变量的(值)
$! 保存后台(最后一个进程)的PID号
$@传递给函数所有的参数
3.简述三种定界符在变量赋值操作中的特点。
双引号 " ":允许扩展,以 $ 引用其他变量
单引号 ’ ':禁用扩展,即便 $ 也视为普通字符
反撇号 :将命令的执行输出作为变量值
4.列出常见的整数值比较操作,并说明各自作用。
-eq 等于(Equal)
-ne 不等于(Not Equal)
-ge 大于或等于(Greater or Equal)
-le 小于或等于(Lesser or Equal)
-gt 大于(Greater Than)
-lt 小于(Lesser Than)
if 语句中的空格要注意
for语句
shell脚本——for循环语句(包含应用案例) - 百度文库
for-不带循环列表
shell for循环之不带列表(三)_lklong123的博客-CSDN博客
Shell 中的小括号用法
数组的使用
5.简述Shell环境常见的中断及退出控制指令。
break:跳出当前所在的循环体,执行循环体后的语句。
continue:跳过循环体内余下的语句,重新判断条件以便执行下一次循环。
exit:退出脚本,默认返回值是 0。
return:用在函数里 指定返回值。
shift:用于迁移位置变量,将 $1~$9 依次向左顺序移动。
*6.正则表达式中的+、?、分别表示什么含义?
+:最少匹配一次,比如a+可匹配a、aa、aaa等
?:最多匹配一次,比如a?可匹配零个或一个a
:匹配任意多次,比如a可匹配零个或任意多个连续的a
7.编写脚本的步骤?
1、明确脚本要实现的功能
2、需要使用哪些命令
3、需要使用哪些流程控制
4、数据是变化的,就要用变量来表示
8.说一下-n -z -d -f -e -r -w -x -l !-z在shell中分别代表什么意思?
-n 非空为真
-z 字符串为空为真
-d 是目录且存在为真
-f 是普通文件且存在为真
-e 存在为真
-r 可读为真
-w 可写为真
-x 可执行为真
-l 是链接为真
!-z不为空
**************************练习*************************************
B000000338640rt:shell$ if [[ -n $cc ]]; then echo "cc is not null"; else echo "cc is null"; fi
cc is null
B000000338640rt:shell$ if [[ -n $a ]]; then echo "cc is not null"; else echo "cc is null"; fi
cc is not null
B000000338640rt:shell$ echo $a $cc
3
B000000338640rt:shell$ echo $a
3
********************************************************************
9.shell变量的作用
为灵活管理Linux系统提供的特定参数,有两层意思
变量名:使用固定的名称,由系统预设或用户定义
变量值: 能够根据用户设置,系统环境的变化而变化
10变量的类型
自定义变量:由用户自己定义,修改和使用
环境变量: 由系统维护,用于设置工作环境
位置变量: 通过命令行给脚本程序传递参数
预定义变量:BASH中内置的一类变量,不能直接修改
11.定义一个新的变量
格式: 变量名=变量值
变量名以字母或下划线开头,区分大小写,建议全大写
**12.查看变量的值: echo 变 量 名 ∗ ∗ 赋 值 时 使 用 引 号 : 双 引 号 : 允 许 使 用 变量名** 赋值时使用引号: 双引号:允许使用 变量名∗∗赋值时使用引号:双引号:允许使用符引用其他变量值
单引号: 禁止引用其他变量值,$视为普通字符
反撇号:命令替换,提取命令执行后的输出结果
将键盘输入内容为变量赋值
格式: read [-p “提示信息”] 变量名
13.设置变量的作用范围(export将变量输出至子shell)
export 变量名
export 变量名=变量值
两种格式可以混合使用
14.整数变量的运算:
expr 变量1 运算符 变量2 [运算符 变量3]
常见的运算符
加法运算符 +
减法运算符: -
乘法运算符:*
除法运算符: /
取余运算:%
整数变量的运算(2)
((变量=变量运算符变量));
等号后面的变量可以是具体数值
例子:
((a=a+3));
15 . file 显示文件的信息
B000000338640rt:shell$ file learn_dpu.sh
learn_dpu.sh: Bourne-Again shell script text executable, ASCII text
B000000338640rt:shell$ which python
/usr/bin/python
B000000338640rt:shell$ file $(which python)
/usr/bin/python: Mach-O 64-bit executable x86_64
16 . Ismod命令
Linux系统设置:insmod命令详解 - 百度文库
insmod命令⽤于将给定的模块加载到内核中。Linux有许多功能是通过模块的⽅式,在需要时才载⼊kernel。如此可使kernel较为精简,
进⽽提⾼效率,以及保有较⼤的弹性。这类可载⼊的模块,通常是设备驱动程序。
insmod(选项)(参数)
选项
-f:不检查⽬前kernel版本与模块编译时的kernel版本是否⼀致,强制将模块载⼊;
-k:将模块设置为⾃动卸除;
-m:输出模块的载⼊信息;
-o<模块名称>:指定模块的名称,可使⽤模块⽂件的⽂件名;
-p:测试模块是否能正确地载⼊kernel;
-s:将所有信息记录在系统记录⽂件中;
-v:执⾏时显⽰详细的信息;
-x:不要汇出模块的外部符号;
-X:汇出模块所有的外部符号,此为预设置
参数
内核模块:指定要加载的内核模块⽂件。
实例
加载RAID1阵列级别模块,如下所⽰:
[root@localhost boot]# insmod /lib/modules/2.6.
18-8.el5/kernel/drivers/md/raid1.ko
[root@localhost boot]# lsmod | grep raid1
raid1 25153 0
在Linux中,modprobe和insmod都可以⽤来加载module,不过现在⼀般都推荐使⽤modprobe⽽不是insmod了。 modprobe和
insmod的区别是什么呢?
1) modprobe可以解决load module时的依赖关系,⽐如load moudleA就必须先load mouduleB之类的,它是通
过/lib/modules//modules.dep⽂件来查找依赖关系的。⽽insmod不能解决依赖问题。
2) modprobe默认会去/lib/modules/⽬录下⾯查找module,⽽insmod只在给它的参数中去找module(默认在当前⽬录找)。 这样,
有时insmod也有它的有⽤之处,举个例⼦吧。
有/root/my-mod.ko这个module,cd /root/,然后⽤insmod my-mod.ko(insmod /root/my-mod.ko)就可以insert这个module了,
但是⽤modprobe my-mod.ko(modprobe /root/my-mod.ko)却提⽰"FATAL: Module my-mod.ko not found",这就是因为
modprobe是到/lib/modules/`uname -r`/下去找module的,如果没找到就是这样了。
17 . runlevel
linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel,同样,当linux操作系统关闭时也要经历另外几个不同的runlevel.
在大多数的linux发行版本中,通常有8个runlevel
Runlevel System State
0 Halt the system
1 Single user mode
2 Basic multi user mode
3 Multi user mode
5 Multi user mode with GUI
6 Reboot the system
S, s Single user mode
18 . tee命令
用于显示程序的输出并将其复制到一个文件中。
语法-----tee [ -a ] [ -i ] [ File ... ]
描述-----tee 命令读取标准输入,然后将程序的输出写到标准输出,并同时将其复制到指定的一个或多个文件。
标志
-a 将输出添加到 File 的末尾而不是覆盖写入。
-i 忽略中断。
示例
1)要同时查看和保存一个命令的输出:lint program.c | tee program.lint
它在工作站上显示命令 lint program.c 的标准输出,同时在文件 program.lint 中保存输出的一个副本。如果 program.lint 文件早已存在,它将被删除并替换。
2)要同时查看一个命令的输出并保存到一个现有文件:lint program.c | tee -a program.lint
它将在工作站上显示 lint program.c 命令的标准输出,同时在 program.lint 文件尾部添加输出的一个副本。如果 program.lint 文件不存在,它将被创建。
19 . set -e
shell中脚本运行中可能出现命令执行失败的情况,如果执行失败对后续有影响那么就应该退出脚本,不继续往下执行。set -e 命令就可以避免操作失败还继续往下执行的问题。
set命令的-e参数:
linux系统自带的说明是:“Exit immediately if a simple command exits with a non-zero status.”,也就是说,在"set -e"之后出现的代码,一旦出现了返回值非零,整个脚本就会立即退出
20 . 查看系统版本
1)uname —help
-a, --all print all information, in the following order,
except omit -p and -i if unknown:
-s, --kernel-name print the kernel name
-n, --nodename print the network node hostname
-r, --kernel-release print the kernel release
-v, --kernel-version print the kernel version
-m, --machine print the machine hardware name
-p, --processor print the processor type or "unknown"
-i, --hardware-platform print the hardware platform or "unknown"
-o, --operating-system print the operating system
--help display this help and exit
--version output version information and exit
2)cat /proc/version
21 . tree
安装:yun install -y tree
22 . rpm
RPM 有五种基本的操作⽅式(不包括创建软件包): 安装, 卸载, 升级, 查询,和验证。
⼀、安装RPM包
RPM 软件包通常具有类似foo-1.0-1.i386.rpm 的⽂件名。其中包括软件包的名称(foo),版本号(1.0),发⾏号(1),和硬件平台(i386)。安
装⼀个软件包只需简单的键⼊以下命令:
$ rpm -ivh foo-1.0-1.i386.rpm
RPM安装完毕后会打印出软件包的名字(并不⼀定与⽂件名相同),⽽后打印⼀连串的#号以表⽰安装
进度。虽然软件包的安装被设计的尽量简单易⾏,但还是可能会发⽣如下的错误:
1、软件包已被安装
如果您的软件包已被安装, 将会出现以下信息:
$ rpm -ivh foo-1.0-1.i386.rpm
foo package foo-1.0-1 is already installed
error: foo-1.0-1.i386.rpm cannot be installed
如果您仍旧要安装该软件包,可以在命令⾏上使⽤--replacepkgs 选项,RPM将忽略该错误信息强⾏安装。
2、⽂件冲突
如果您要安装的软件包中有⼀个⽂件已在安装其它软件包时安装,会出现以下错误信息:
# rpm -ivh foo-1.0-1.i386.rpm
foo /usr/bin/foo conflicts with file from bar-1.0-1
error: foo-1.0-1.i386.rpm cannot be installed
要想让RPM 忽略该错误信息,请使⽤--replacefiles 命令⾏选项。
3、未解决依赖关系
RPM软件包可能依赖于其它软件包,也就是说要求在安装了特定的软件包之后才能安装该软件包。
如果在您安装某个软件包时存在这种未解决的依赖关系。会产⽣以下信息:
$ rpm -ivh bar-1.0-1.i386.rpm
failed dependencies: foo is needed by bar-1.0-1
您必须安装完所依赖的软件包,才能解决这个问题。如果您想强制安装(这是个坏主意,因为安装后的软
件包未必能正常运⾏),请使⽤--nodeps 命令⾏选项。
⼆、卸载RPM包
卸载软件包就象安装软件包时⼀样简单:
$ rpm -e foo
注意这⾥使⽤软件包的名字name ``foo,⽽不是软件包⽂件的名字file ``foo-1.0-1.i386.rpm。
如果其它软件包依赖于您要卸载的软件包,卸载时则会产⽣错误信息。如:
$ rpm -e foo
removing these packages would break dependencies:foo is needed by bar-1.0-1
若让RPM忽略这个错误继续卸载(这可不是⼀个好主意,因为依赖于该软件包的程序可能⽆法运⾏),请使⽤--nodeps 命令⾏选项。
三、升级RPM包
升级软件包和安装软件包⼗分类似:
$ rpm -Uvh foo-2.0-1.i386.rpm
foo ####################################
RPM将⾃动卸载已安装的⽼板本的foo 软件包,您不会看到有关信息。事实上您可能总是使⽤ -U 来安装软件包,因为即便以往未安装过该
软件包,也能正常运⾏。因为RPM 执⾏智能化的软件包升级,⾃动处理配置⽂件,您将会看到如下信息:
saving /etc/foo.conf as /etc/foo.conf.rpmsave
这表⽰您对配置⽂件的修改不⼀定能向上兼容。因此,RPM 会先备份⽼⽂件再安装新⽂件。您应当尽快解决这两个配置⽂件的不同之处,
以使系统能持续正常运⾏。
因为升级实际包括软件包的卸载与安装两个过程,所以您可能会碰到由这两个操作引起的错误。另⼀个你可能碰到的问题是:当您使⽤旧版
本的软件包来升级新版本的软件时,RPM会产⽣以下错误信息:
$ rpm -Uvh foo-1.0-1.i386.rpm
foo package foo-2.0-1 (which is newer) is already installed
error: foo-1.0-1.i386.rpm cannot be installed
如果你确有需要将该软件包”降级,加⼊ --oldpackage 命令选项就可以了。
四、查询已安装的软件包
使⽤命令rpm -q来查询已安装软件包的数据库。简单的使⽤命令 rpm -q foo 会打印出foo软件包的包名,版本号和发⾏号:
$ rpm -q foo
五、验证软件包
验证软件包是通过⽐较已安装的⽂件和软件包中的原始⽂件信息来进⾏的。验证主要是⽐较⽂件的尺⼨, MD5 校验码, ⽂件权限, 类型, 属主
和⽤户组等。rpm-V命令⽤来验证⼀个软件包。您可以使⽤任何包选择选项来查询您要验证的软件包。命令rpm -V foo将⽤来验证foo软件
包。
⼜如:
· 验证包含特定⽂件的软件包:
rpm -Vf /bin/vi
· 验证所有已安装的软件包:
rpm -Va
· 根据⼀个RPM包来验证:
rpm -Vp foo-1.0-1.i386.rpm
23 . 查看内核版本
1)uname -r : 显示操作系统的发行版号
2)uname -a :显示系统名、节点名称、操作系统的发行版号、内核版本等等。
3 ) lsb_release -a: 发布内核版本(yi)
24 . systemctl
CentOS 7.0 中⼀个最主要的改变,就是切换到了systemd。它⽤于替代红帽企业版Linux前任版本中的SysV和Upstart,对系统和服务进⾏管
理。systemd兼容SysV和Linux标准组的启动脚本。
Systemd是⼀个Linux操作系统下的系统和服务管理器。它被设计成向后兼容SysV启动脚本,并提供了⼤量的特性,如开机时平⾏启动系统
服务,按需启动守护进程,⽀持系统状态快照,或者基于依赖的服务控制逻辑。先前的使⽤SysV初始化或Upstart的红帽企业版Linux版本
中,使⽤位于/etc/rc.d/init.d/⽬录中的bash初始化脚本进⾏管理。⽽在RHEL 7/CentOS 7中,这些启动脚本被服务单元取代了。
服务单元以.service⽂件扩展结束,提供了与初始化脚本同样的⽤途。要查看、启动、停⽌、重启、启⽤或者禁⽤系统服务,你要使⽤
systemctl 来代替旧的service命令。注:为了向后兼容,旧的service命令在CentOS 7中仍然可⽤,它会重定向所有命令到新的 systemctl ⼯
具。
systemctl 命令有两⼤类功能:
1. 控制 systemd 系统
2. 管理系统上运⾏的服务
管理单个Unit
systemctl 提供了⼀组⼦命令来管理单个的 unit,其命令格式为:
systemctl [command] [unit]
command 主要有:
start:⽴刻启动后⾯接的 unit。
stop:⽴刻关闭后⾯接的 unit。
restart:⽴刻关闭后启动后⾯接的 unit,亦即执⾏ stop 再 start 的意思。
reload:不关闭 unit 的情况下,重新载⼊配置⽂件,让设置⽣效。
enable:设置下次开机时,后⾯接的 unit 会被启动。
disable:设置下次开机时,后⾯接的 unit 不会被启动。
status:⽬前后⾯接的这个 unit 的状态,会列出有没有正在执⾏、开机时是否启动等信息。
is-active:⽬前有没有正在运⾏中。
is-enable:开机时有没有默认要启⽤这个 unit。
kill :不要被 kill 这个名字吓着了,它其实是向运⾏ unit 的进程发送信号。
show:列出 unit 的配置。
mask:注销 unit,注销后你就⽆法启法启动这个 unit 了。
unmask:取消对 unit 的注销。
查看 unit 的配置
使⽤ show ⼦命令可以查看 unit 的详细配置情况:
查看系统上的 unit
systemctl 提供了⼦命令可以查看系统上的 unit,命令格式为:
systemctl [command] [--type=TYPE] [--all]
command 有:
list-units:列出当前已经启动的 unit,如果添加 -all 选项会同时列出没有启动的 unit。
list-unit-files:根据 /lib/systemd/system/ ⽬录内的⽂件列出所有的 unit。
--type=TYPE:可以过滤某个类型的 unit。
不带任何参数执⾏ systemctl 命令会列出所有已启动的 unit:
systemctl list-units
系统默认启动的服务是⾮常多的,上图只截取了前⾯⼏⾏。下⾯是对输出的介绍:
UNIT:项⽬的名称,包括各个 unit 的类别(看扩展名)。
LOAD:开机时 unit 的配置是否被加载。
ACTIVE:⽬前的状态,须与后续的 SUB 搭配!就是我们⽤ systemctl status 观察时,active的内容。
DESCRIPTION:描述信息。
注意,systemctl 不加参数,其实等同于 systemctl list-units!
查看是否有unit加载失败
systemctl --failed
检查 unit 之间的依赖性
很多服务之间是有依赖关系的,systemd 的⼀⼤亮点就是可以管理 unit 之间的依赖关系。我们可以通过下⾯的命令来查看 unit 间的依赖关系
systemctl list-dependencies XXX
25 . service命令
systemctl命令详解 - 百度文库
# 查看所有服务
[root@hdp-01 ~]# service --status-all
# 或分页查看
[root@hdp-01 ~]# service --status-all | more
[root@hdp-01 ~]# service --status-all | less
# 查看正在运⾏服务
[root@hdp-01 ~]# service --status-all | grep running
#或
[root@hdp-01 ~]# initctl list
#或
[root@hdp-01 ~]# systemctl
# 查看某个服务
[root@hdp-01 ~]# service --status-all | grep crond
crond (pid 1216) is running...
#或
[root@hdp-01 ~]# service crond status
crond (pid 1216) is running...
*********************************************************
Linux中的service命令的详细解释 - 百度文库
linxu下的service命令是⽤来控制系统服务的实⽤⼯具。下⾯由店铺为⼤家整理了linux的servie命令
的详细解释的相关知识,希望对⼤家有帮助!
⼀、Linux中的service命令的详细解释
service命令是Redhat Linux兼容的发⾏版中⽤来控制系统服务的实⽤⼯具,它以启动、停⽌、重新
启动和关闭系统服务,还可以显⽰所有系统服务的当前状态。
语法
service(选项)(参数)
选项
-h:显⽰帮助信息;
--status-all:显⽰所服务的状态。
参数
服务名:⾃动要控制的服务名,即/etc/init.d⽬录下的脚本⽂件名
常⽤⽅式
格式:service
打印指定服务
格式:service
启动指定的系统服务
格式:service
停⽌指定的系统服务
格式:service
重新启动指定的系统服务
格式:chkconfig --list
查看系统服务列表,以及每个服务的运⾏级别。
格式:chkconfig
设置指定服务
格式:chkconfig
设置指定服务
格式:ntsysv
以全屏幕⽂本界⾯设置服务开机时是否⾃动启动。
26 . grubby
https://www.csdn.net/tags/MtTaMgysNzQwMzg4LWJsb2cO0O0O.html
1 ) Linux I/O调度器
Linux I/O 调度器是Linux内核中的一个组成部分,用户可以通过调整这个调度器来优化系统性能。Linux I/O调度器(Linux I/O Scheduler)是LinuxI/O体系的一个组件,它介于通用块层和块设备驱动程序之间。
Linux IO调度层分析-1_iceshirley的博客-CSDN博客
Linux IO调度程序是块设备I/O子系统的主要组件,它介于通用块层和块设备驱动程序之间,所图2-1所示。当Linux内核组件要读写一些数据时,并不是请求一发出,内核便立即执行该请求,而是将其推迟执行。延迟的设定是块设备性能的关键机制!当传输一个新数据块时,内核检查能否通过扩展前一个一直处于等待状态的请求而满足新请求。
Linux整体I/O体系可以分为七层,它们分别是:
1. VFS虚拟文件系统:内核要跟多种文件系统打交道,内核抽象了这VFS,专门用来适配各种文件系统,并对外提供统一操作接口。
2. 磁盘缓存:磁盘缓存是一种将磁盘上的一些数据保留着RAM中的软件机制,这使得对这部分数据的访问可以得到更快的响应。磁盘缓存在Linux中有三种类型:Dentry cache ,Page cache , Buffer cache。
3. 映射层:内核从块设备上读取数据,这样内核就必须确定数据在物理设备上的位置,这由映射层(Mapping Layer)来完成。
4. 通用块层:由于绝大多数情况的I/O操作是跟块设备打交道,所以Linux在此提供了一个类似vfs层的块设备操作抽象层。下层对接各种不同属性的块设备,对上提供统一的Block IO请求标准。
5. I/O调度层:大多数的块设备都是磁盘设备,所以有必要根据这类设备的特点以及应用特点来设置一些不同的调度器。
6. 块设备驱动:块设备驱动对外提供高级的设备操作接口。
7. 物理硬盘:这层就是具体的物理设备。
27 . grubby
grubby在线修改内核参数_Yeliang Wu的博客-CSDN博客_grubby命令
grubby是一个命令行工具,用于更新和显示有关grub,lilo,elilo (ia64),yaboot(powerpc)和zipl(s390)引导加载程序的配置文件的信息。它主要设计用于安装新内核的脚本,并需要查找有关当前引导环境的信息。
修改新增一行/etc/default/grub
GRUB_ENABLE_BLSCFG=true
重新加载配置
grub2-mkconfig -o /boot/grub2/grub.cfg
重启服务
reboot
针对内核5.0.1-300新增一个参数
# grubby --update-kernel /boot/vmlinuz-5.0.1-300.fc30.x86_64 --args="amdgpu.dc=0"
或者
# grubby --update-kernel=/boot/vmlinuz-`uname -r` --args="amdgpu.dc=0"
针对内核5.0.1-300删除一个参数
# grubby --update-kernel /boot/vmlinuz-5.0.1-300.fc30.x86_64 --remove-args="amdgpu.dc=0"
# grubby --update-kernel=/boot/vmlinuz-`uname -r` --remove-args="amdgpu.dc=0"
针对所有内核修改参数
# grubby --update-kernel=ALL --args="nordrand"
# grubby --update-kernel=ALL --remove-args="nordrand"
28 . linux hugepage
Linux 巨型页(HugePages) - 知乎
页面是Linux管理内存的基本单位,一般为4KB。如果程序运行时,需要大量的内存,就会产生非常多的TLB未命中和缺页异常,4KB的尺寸显然称为程序的瓶颈。如果直接修改系统默认页面大小,那么系统中其他程序运行时,很可能又会造成内存浪费。所以,Linux引入了巨型页,这种巨型页允许管理远大于4k的大页面,默认是2M,相当于512个普通页面。简而言之,通过启用大页面,系统可以处理更少的页面表,因此访问/维护它们的开销也更少!
巨型页的应用集中在对内存需求大的领域,比如数据库、虚拟机等系统中。
为了加快速度,采用了分段机制映射,如下图,而在2级转换目录之后,可以直接指向2MB的巨型页。在1级转换目录之后更是可以指向1GB的超大巨型页。
查看巨型页信息
grep Huge /proc/meminfo
其中,
HugePages_Total表示大页面池的大小
HugePages_Free表示池中尚未分配的大页面数
HugePages_Rsvd表示保留的大页面数,这些页面尚未分配
HugePages_Surp是“盈余”页面,如果默认配置100,现在修改为80,则会显示20
Linux 大页内存 的使用_Mrpre的博客-CSDN博客_大页内存优缺点
Linux大页内存的使用
系统启用大页内存
下述操作,需要重启机器。
不建议 通过 设置 echo 1G > /proc/sys/vm/nr_hugepages的方式设置,因为系统不一定成功
设置大页内存的PAGESIZE
1、grubby --update-kernel=ALL --args="hugepagesz=1G”
Centos 下(其他发行版本自行Google)
设置大页内存的PAGE个数
2、grubby --update-kernel=ALL --args="hugepages=10”
上述1、2的顺序不能乱,乱了系统就没办法在启动阶段申请PAGE了。
或者直接在一个命令中完成:
grubby --update-kernel=ALL --args="hugepagesz=1G hugepages=10”
上面的目的都是在系统启动阶段划出大页供应用进程使用。
cat /proc/cpuinfo| grep 'processor'| wc -l
29 . NUMA
NUMA架构详解_bob62856的博客-CSDN博客_numa
NUMA架构详解
一 . 基本概念
非统一内存访问(NUMA)是一种用于多处理器的电脑内存体设计,内存访问时间取决于处理器的内存位置。 在NUMA下,处理器访问它自己的本地存储器的速度比非本地存储器(存储器的地方到另一个处理器之间共享的处理器或存储器)快一些。
1 ) SMP VS. AMP
那么两者之间的主要区别是什么呢? 总结下来有这么几点,
2 ) NUMA VS. UMA
NUMA(Non-Uniform Memory Access)非均匀内存访问架构是指多处理器系统中,内存的访问时间是依赖于处理器和内存之间的相对位置的。 这种设计里存在和处理器相对近的内存,通常被称作本地内存;还有和处理器相对远的内存, 通常被称为非本地内存。
UMA(Uniform Memory Access)均匀内存访问架构则是与NUMA相反,所以处理器对共享内存的访问距离和时间是相同的。
由此可知,不论是NUMA还是UMA都是SMP架构的一种设计和实现上的选择。
阅读文档时,也常常能看到ccNUMA(Cache Coherent NUMA),即缓存一致性NUMA架构。 这种架构主要是在NUMA架构之上保证了多处理器之间的缓存一致性。降低了系统程序的编写难度。
x86多处理器发展历史上,早期的多核和多处理器系统都是UMA架构的。这种架构下, 多个CPU通过同一个北桥(North Bridge)芯片与内存链接。北桥芯片里集成了内存控制器(Memory Controller)。
下图是一个典型的早期 x86 UMA 系统,四路处理器通过 FSB (前端系统总线, Front Side Bus) 和主板上的内存控制器芯片 (MCH, Memory Controller Hub) 相连,DRAM 是以 UMA 方式组织的,延迟并无访问差异。
在 UMA 架构下,CPU 和内存控制器之间的前端总线 (FSB) 在系统 CPU 数量不断增加的前提下, 成为了系统性能的瓶颈。因此,AMD 在引入 64 位 x86 架构时,实现了 NUMA 架构。之后, Intel 也推出了 x64 的 Nehalem 架构,x86 终于全面进入到 NUMA 时代。x86 NUMA 目前的实现属于 ccNUMA。
从 Nehalem 架构开始,x86 开始转向 NUMA 架构,内存控制器芯片被集成到处理器内部,多个处理器通过 QPI 链路相连,从此 DRAM 有了远近之分。 而 Sandybridge 架构则更近一步,将片外的 IOH 芯片也集成到了处理器内部,至此,内存控制器和 PCIe Root Complex 全部在处理器内部了。 下图就是一个典型的 x86 的 NUMA 架构:
二、NUMA Hierarchy
1、NUMA Node 内部
一个NUMA Node内部是由一个物理CPU和它所有的本地内存(Local Memory) 组成的。广义得讲, 一个NUMA Node内部还包含本地IO资源,对大多数Intel x86 NUMA平台来说,主要是PCIe总线资源。 ACPI规范就是这么抽象一个NUMA Node的。
1) 物理 CPU
一个CPU Socket里可以由多个CPU Core和一个Uncore部分组成。每个CPU Core内部又可以由两个CPU Thread组成。 每个CPU thread都是一个操作系统可见的逻辑CPU。对大多数操作系统来说,一个八核HT打开的CPU会被识别为16个CPU。 下面就说一说这里面相关的概念
2)本地内存
在Intel x86平台上,所谓本地内存,就是CPU可以经过Uncore部件里的iMC访问到的内存。而那些非本地的, 远程内存(Remote Memory),则需要经过QPI的链路到该内存所在的本地CPU的iMC来访问。 曾经在Intel IvyBridge的NUMA平台上做的内存访问性能测试显示,远程内存访问的延时时本地内存的一倍。
可以假设,操作系统应该尽量利用本地内存的低访问延迟特性来优化应用和系统的性能。
3)本地 IO 资源
如前所述,Intel自从SandyBridge处理器开始,已经把PCIe Root Complex集成到CPU里了。 正因为如此,从CPU直接引出PCIe Root Port的PCIe 3.0的链路可以直接与PCIe Switch或者PCIe Endpoint相连。 一个PCIe Endpoint就是一个PCIe外设。这就意味着,对某个PCIe外设来说,如果它直接于哪个CPU相连, 它就属于哪个CPU所在的NUMA Node。
与本地内存一样,所谓本地IO资源,就是CPU可以经过Uncore部件里的PCIe Root Complex直接访问到的IO资源。 如果是非本地IO资源,则需要经过QPI链路到该IO资源所属的CPU,再通过该CPU PCIe Root Complex访问。 如果同一个NUMA Node内的CPU和内存和另外一个NUMA Node的IO资源发生互操作,因为要跨越QPI链路, 会存在额外的访问延迟问题。
其它体系结构里,为降低外设访问延迟,也有将IB(Infiniband)总线集成到CPU里的。 这样IB设备也属于NUMA Node的一部分了。
可以假设,操作系统如果是NUMA Aware的话,应该会尽量针对本地IO资源低延迟的优点进行优化。
图:PCLe Root Complex Location
2、NUMA Node 互联
在Intel x86上,NUMA Node之间的互联是通过 QPI(QuickPath Interconnect) Link的。 CPU的Uncore部分有QPI的控制器来控制CPU到QPI的数据访问。
下图就是一个利用 QPI Switch 互联的 8 NUMA Node 的 x86 系统
三、NUMA Affinity
NUMA Affinity(亲和性)是和NUMA Hierarchy(层级结构)直接相关的。对系统软件来说, 以下两个概念至关重要,
1、CPU NUMA Affinity
CPU NUMA的亲和性是指从CPU角度看,哪些内存访问更快,有更低的延迟。如前所述, 和该CPU直接相连的本地内存是更快的。操作系统如果可以根据任务所在CPU去分配本地内存, 就是基于CPU NUMA亲和性的考虑。因此,CPU NUMA亲和性就是要尽量让任务运行在本地的NUMA Node里。
2、Device NUMA Affinity
设备NUMA亲和性是指从PCIe外设的角度看,如果和CPU和内存相关的IO活动都发生在外设所属的NUMA Node, 将会有更低延迟。这里有两种设备NUMA亲和性的问题,
1)DMA Buffer NUMA Affinity
大部分PCIe设备支持DMA功能的。也就是说,设备可以直接把数据写入到位于内存中的DMA缓冲区。 显然,如果DMA缓冲区在PCIe外设所属的NUMA Node里分配,那么将会有最低的延迟。 否则,外设的DMA操作要跨越QPI链接去读写另外一个NUMA Node里的DMA缓冲区。 因此,操作系统如果可以根据PCIe设备所属的NUMA node分配DMA缓冲区, 将会有最好的DMA操作的性能。
2)Interrupt NUMA Affinity
设备DMA操作完成后,需要在CPU上触发中断来通知驱动程序的中断处理例程(ISR)来读写DMA缓冲区。 很多时候,ISR触发下半部机制(SoftIRQ)来进入到协议栈相关(Network,Storage)的代码路径来传送数据。 对大部分操作系统来说,硬件中断(HardIRQ)和下半部机制的代码在同一个CPU上发生。 因此,DMA缓冲区的读写操作发生的位置和设备硬件中断(HardIRQ)密切相关。假设操作系统可以把设备的硬件中断绑定到自己所属的NUMA node, 那之后中断处理函数和协议栈代码对DMA缓冲区的读写将会有更低的延迟。
四、Firmware 接口
由于NUMA的亲和性对应用的性能非常重要,那么硬件平台就需要给操作系统提供接口机制来感知硬件的NUMA层级结构。 在x86平台,ACPI规范提供了以下接口来让操作系统来检测系统的NUMA层级结构。
ACPI 5.0a规范的第17章是有关NUMA的章节。ACPI规范里,NUMA Node被第9章定义的Module Device所描述。 ACPI规范里用Proximity Domain对NUMA Node做了抽象,两者的概念大多时候等同。
1、SRAT(System Resource Affinity Table)
主要描述了系统boot时的CPU和内存都属于哪个Proximity Domain(NUMA Node)。 这个表格里的信息时静态的,如果是启动后热插拔,需要用OSPM的_PXM方法去获得相关信息。
2、SLIT(System Locality Information Table)
提供CPU和内存之间的位置远近信息。在SRAT表格里,只能告诉给定的CPU和内存是否在一个NUMA Node。 对某个CPU来说,不在本NUMA Node里的内存,即远程内存们是否都是一样的访问延迟取决于NUMA的拓扑有多复杂(QPI的跳数)。 总之,对于不能简单用远近来描述的NUMA系统(QPI存在0,1,2等不同跳数), 需要SLIT表格给出进一步的说明。同样的,这个表格也是静态表格,热插拔需要使用OSPM的_SLI方法。
3、DSDT(Differentiated System Description Table)
从Device NUMA角度看,这个表格给出了系统boot时的外设都属于哪个Proximity Domain(NUMA Node)。
ACPI规范OSPM(Operating System-directed configuration and Power Management) 和OSPM各种方法就是操作系统里的ACPI驱动和ACPI firmware之间的一个互动的接口。 x86启动OS后,没有ACPI之前,firmware(BIOS)的代码是无法被执行了,除非通过SMI中断处理程序。 但有了ACPI,BIOS提前把ACPI的一些静态表格和AML的bytecode代码装载到内存, 然后ACPI驱动就会加载AML的解释器,这样OS就可以通过ACPI驱动调用预先装载的AML代码。 AML(ACPI Machine Language)是和Java类似的一种虚拟机解释型语言,所以不同操作系统的ACPI驱动, 只要有相同的虚拟机解释器,就可以直接从操作系统调用ACPI写好的AML的代码了。 所以,前文所述的所有热插拔的OSPM方法,其实就是对应ACPI firmware的AML的一段函数代码而已。
30 . isolcpus
https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux_openstack_platform/7/html/instances_and_images_guide/ch-cpu_pinning
配置带有 NUMA 的 CPU 固定(CPU Pinning)
本章介绍了与 NUMA 拓扑相关的信息,以及如何在支持 NUMA 的系统上配置 OpenStack 环境。在这类设置中,虚拟机实例被固定到专用的 CPU 内核,从而可以通过更加智能的调度来提高客户机的性能。
在引导选项中,使用 isolcpus 并加上 CPU 列表。这可以把主机进程限制为只能访问列出的 CPU 内核。对于以上的示例,您可以运行:
grubby --update-kernel=ALL --args="isolcpus=2,3,6,7"
***************************DPU 代码-dpu_release install.sh安装************************
BVS_CPU=`cat /etc/bcc/init.d/reserve_cpu | awk -F: '/pmd:/{print $2}'`
BBLK_CPU=`cat /etc/bcc/init.d/reserve_cpu | awk -F: '/spdk:/{print $2}'`
if [[ -n $BVS_CPU ]] && [[ -n $BBLK_CPU ]]; then
CPULIST="$BVS_CPU,$BBLK_CPU"
grubby --args="isolcpus=$CPULIST nohz_full=$CPULIST rcu_nocbs=$CPULIST" --update-kernel=ALL
fi
*****************************************************************************************
check_reserve_cpu
https://ku.baidu-int.com/knowledge/HFVrC7hq1Q/pKzJfZczuc/yphoo2jVgf/yLOJ9rL0ky3iVQ
用于机器实际的CPU资源预留(即,nova-compute中汇报的预留CPU资源)和预期的CPU预留(CPU预留文件中的资源)不一致时的处理
示例,如下输出说明预留核和虚机使用的核不冲突
==========
[[email protected] ~]# cat /etc/bcc/init.d/reserve_cpu
nova_reserve_bcc:39,79,0,40,1,41,2,42,3,43
rootagent:39,79
iaasagent:0,40,1,41
cds-agent:2,42,3,43
[[email protected] ~]# for i in `virsh list --all | grep instance | awk '{print $2}'`;do virsh vcpupin $i;done
VCPU: CPU Affinity
/etc/bcc/init.d/reserve_cpu
这个文档中保存的是预留cpu信息
/etc/bcc/init.d/reserve_mem
大页预留文件:文件格式按照NUMA开关分别如下:
(1)开numa(预留非大页26GB + 大页6GB,共计24GB)
预留文件格式如下
total:728
node0:364
node1:364
nova_reserve:4,2
bvs_reserve:4,2
31 . 常用命令
# 查看内核发行版本
lsb_release -a
# 查看进程
ps -ef
# 包含cpu,mem占比
ps axu
# 查看磁盘使用情况
32 . linux下查看网卡信息
linux下怎么查看网卡信息-linux运维-PHP中文网
ifconfig: 最常用的配置和查看网络接口信息的命令,服务器上执行此命令会得到类下文的内容,一下内容可看到多个设备和设备状态、信息。
lspci |grep -i 'eth' 或 lspci | grep -i net命令:可列出每个pci总线上的设备,通过grep过滤后可得到网卡设备列表,下文可看到我pci总线上的网络设备有俩,是两个intel的网卡:(grep -i :忽略大小写)
iwconfig :用于查看无线网络,如果你设备上有无线网卡此时可用此命令来查看,我的设备上并没有无线网卡设备,因此会会得到如下信息。
ethtool 命令主要用于查询配置网卡参数;用法:ethtool ethN //其中 N 是对应网卡的编号,如eth0、eth1等等
**************************************执行结果****************************************************
******************************在host ip上执行*****************************************************
[root@host-100-88-97-221 ~]# ifconfig
eth0 Link encap:Ethernet HWaddr FA:F6:00:10:DC:C8
inet addr:192.168.32.8 Bcast:192.168.47.255 Mask:255.255.240.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:21435741 errors:0 dropped:0 overruns:0 frame:0
TX packets:17898870 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:13588136074 (12.6 GiB) TX bytes:4313671776 (4.0 GiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:5263032 errors:0 dropped:0 overruns:0 frame:0
TX packets:5263032 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1162514424 (1.0 GiB) TX bytes:1162514424 (1.0 GiB)
[root@host-100-88-97-221 ~]# ethtool eth0
Settings for eth0:
Supported ports: [ ]
Supported link modes: Not reported
Supported pause frame use: No
Supports auto-negotiation: No
Advertised link modes: Not reported
Advertised pause frame use: No
Advertised auto-negotiation: No
Speed: Unknown!
Duplex: Unknown! (255)
Port: Other
PHYAD: 0
Transceiver: internal
Auto-negotiation: off
Link detected: yes
*******************************在soc host上执行**************************************************
# ifconfig
bond0: flags=5187
inet 10.40.186.76 netmask 255.255.255.192 broadcast 10.40.186.127
inet6 fe80::b605:5dff:fec1:2354 prefixlen 64 scopeid 0x20
ether b4:05:5d:c1:23:54 txqueuelen 1000 (Ethernet)
RX packets 40546926 bytes 8103197008 (7.5 GiB)
RX errors 0 dropped 63136 overruns 0 frame 0
TX packets 79414719 bytes 70994951726 (66.1 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163
inet 169.254.100.3 netmask 255.255.255.0 broadcast 169.254.100.255
inet6 fe80::b605:5dff:fec1:2356 prefixlen 64 scopeid 0x20
ether b4:05:5d:c1:23:56 txqueuelen 1000 (Ethernet)
RX packets 200217 bytes 25482455 (24.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 200030 bytes 18142512 (17.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xfb200000-fb2fffff
lo: flags=73
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 1000 (Local Loopback)
RX packets 614434 bytes 30738330 (29.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 614434 bytes 30738330 (29.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
xgbe0: flags=6211
ether b4:05:5d:c1:23:54 txqueuelen 1000 (Ethernet)
RX packets 23929176 bytes 4893231431 (4.5 GiB)
RX errors 0 dropped 87 overruns 0 frame 0
TX packets 40503103 bytes 39851091609 (37.1 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
xgbe1: flags=6211
ether b4:05:5d:c1:23:54 txqueuelen 1000 (Ethernet)
RX packets 16617750 bytes 3209965577 (2.9 GiB)
RX errors 0 dropped 37 overruns 0 frame 0
TX packets 38911616 bytes 31143860117 (29.0 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# ethtool eth0
Settings for eth0:
Supported ports: [ FIBRE ]
Supported link modes: 1000baseKX/Full
Supported pause frame use: Symmetric
Supports auto-negotiation: Yes
Supported FEC modes: Not reported
Advertised link modes: 1000baseKX/Full
Advertised pause frame use: Symmetric
Advertised auto-negotiation: Yes
Advertised FEC modes: Not reported
Speed: 1000Mb/s
Duplex: Full
Port: FIBRE
PHYAD: 0
Transceiver: internal
Auto-negotiation: on
Supports Wake-on: pumbg
Wake-on: g
Current message level: 0x00000007 (7)
drv probe link
Link detected: yes
33 . vim
命令
gg:跳到文件头
shift+g: 跳到文件末尾
dG:清空
set nu:显示行
命令行:/ ?查找
:3,24d 删除多行
34 . shell中使用字典
shell脚本使用字典_cy413026的博客-CSDN博客_shell 字典
35 . jq命令
解析json的命令
ubuntu安装:sudo apt-get install jq
36 . ${@:2}命令
Linux shell 中的 $@、${@:2}、${@:3:1}
#!/bin/bash
#输出全部
echo $@ #输出结果:5 4 3 2 1
#从第2个开始,输出剩下的
echo ${@:2} #输出结果:4 3 2 1
#从第3个开始,输出1个
a=${@:3:1} #输出结果:3
echo $a
#bash test.sh 5 4 3 2 1
5 4 3 2 1
4 3 2 1
3
37 . tr命令
Shell tr 命令简介 - 简书
tr 命令用于转换字符、删除字符和压缩重复的字符。它从标准输入读取数据并将结果输出到标准输出。
tr 命令的语法如下:
tr [OPTION]... SET1 [SET2]
如果参数 SET1 和 SET2 同时制定,并没有指定 -d 选项,那么 tr 命令将把 SET1 中指定的每个字符替换为 SET2 中相同位置的字符
使用 -d 选项,tr 命令可以删除指定的字符
38 . 字典和数组的遍历
#!/bin/bash
echo "shell定义字典"
#必须先声明
declare -A dic
dic=([key1]="value1" [key2]="value2" [key3]="value3")
#打印指定key的value
echo ${dic["key1"]}
#打印所有key值
echo ${!dic[*]}
#打印所有value
echo ${dic[*]}
#遍历key值
for key in $(echo ${!dic[*]})
do
echo "$key : ${dic[$key]}"
done
echo "shell定义数组"
#数组
list=("value1" "value2" "value3")
#打印指定下标
echo ${list[1]}
#打印所有下标
echo ${!list[*]}
#打印数组下标
echo ${list[*]}
#数组增加一个元素
list=("${list[@]}" "value3")
39 . md5sum的用法
Linux的md5sum命令用法_一颗跳跳啵仔糖的博客-CSDN博客_md5sum
MD5算法可以用来验证网络文件传输的完整性。Linux的md5sum命令便用于生成和校验文件的md5值。需要注意的是,md5sum检验的是文件内容,而不是文件名。
(1)查看字符串的md5值
[root@k8s-m1 ~]# echo "apple" | md5sum
30c6677b833454ad2df762d3c98d2409 -
[root@k8s-m1 ~]#
[root@k8s-m1 ~]# echo "apple" | md5sum | awk '{ print $1 }'
30c6677b833454ad2df762d3c98d2409
(2)查看文件的md5值
[root@k8s-m1 ~]# echo "hello" > testmd5
[root@k8s-m1 ~]#
[root@k8s-m1 ~]# md5sum testmd5
b1946ac92492d2347c6235b4d2611184 testmd5
40 . rpmbuild
Linux下rpmbuild命令的使用_柒️的博客-CSDN博客_rpmbuild
RPM包的分类
RPM有五种基本的操作功能:安装、卸载、升级、查询和验证。
linux软件包分为两大类:
(1)二进制类包,包括rpm安装包(一般分为i386和x86等几种)
(2)源码类包,源码包和开发包应该归位此类(.src.rpm)。
有时候为了方便源码包的安装,和我们自己订制软件包的需求,我们会把一些源码包按照我们的需求来做成rpm包,当有了源码包就可以直接编译得到二进制安装包和其他任意包。spec file是制作rpm包最核心的部分,rpm包的制作就是根据spec file来实现的。在制作自定义rpm包的时候最好不要使用管理员进行,因为管理员权限过大,如果一个命令写错了,结果可能是灾难性的,而制件一个rpm 包普通用户完全可以实现。
rpm打包
1.安装 rpm-build 包
yum install rpm-build
可以先查看下rpmbuild版本,如果有就不需要再安装了
rpmbuild --version
2.安装 rpmdevtools
yum install rpmdevtools
3.创建⼯作空间
rpmdev-setuptree是rpmdevtools中带的初始化环境脚本,执⾏后会在⽤户主⽬录下创建rpmbuild⽬录和.rpmmacros⽂件,同时⽣成所需的
⼦⽬录和默认的控制参数,执⾏:
rpmdev-setuptree
⾃动⽣成的⽬录结构:
-- rpmbuild
|-- BUILD
|-- RPMS
|-- SOURCES
|-- SPECS
|-- SRPMS
4.创建 SPEC ⽂件
SPEC⽂件控制整个rpm的打包过程,包含了打包的全部信息和控制参数,可以使⽤ rpmdev-newspec 命令来创建⼀个初始的SPEC⽂
件,SPEC⽂件需放⼊rpmbuild/SPECS⽬录
rpmdev-newspec zookeeper.spec
spec文件
(1)信息定义阶段:定义软件包的名字、版本等信息和打包过程中⽤到的变量等
(2)制作准备阶段:解压源码包、补丁包并打补丁
(3)编译阶段:设置编译参数并编译源码
(4)安装阶段:定义安装过程所执⾏的命令,包括安装前、安装后、卸载前、卸载后执⾏的操作
(5)清理阶段:清理打包过程中⽤到的⽬录⽂件等
(6)⽂件设置阶段:要打包的⽂件和⽬录,并设置⽂件权限等
# 1.信息定义阶段
### 软件名字,要与spec的⽂件名⼀致
Name: apache-zookeeper
### 软件主版本号
Version: 3.6.1
### 发⾏编号,每打包⼀次值递增,主版本号发布新版后需重置该值
Release: 1
### ⼀⾏简短的软件简介,结尾不要加标点
Summary: Zookeeper is a highly reliable distributed coordination service
Group:
### 软件许可
License: Apache 2.0
### 软件项⽬主页
URL: https://zookeeper.apache.org/
### 放置在SOUIRCES⽬录的软件源码包名,可以指定多个:source1、source2等
#Source0: %{name}.%{version}.tar.gz
### 在 install 阶段的测试安装⽬录,⽅便写files
#buildroot: %_topdir/BUILDROOT
#BuildRequires: go
### 安装软件包时所需的依赖包列表,可以指定版本如 bash >= 1.1.1
#Requires: readline-devel,pcre-devel,openssl-devel
### 程序的详细多⾏描述,每⾏必须⼩于等于 80 个字符,空⾏表⽰开始新段
%description
Zookeeper 3.6.1
# 2.准备阶段
%prep
## 静默模式解压并进⼊解压后的⽬录,也常⽤:%autosetup -n %{name}
# 3. 编译阶段
%build
# 4.安装阶段
%install
### 删除之前的残留⽂件
## rpm安装前制⾏的脚本
%pre
### $1==1 代表的是第⼀次安装,2代表是升级,0代表是卸载
#if [ $1 == 1 ];then
# /usr/sbin/useradd -r %{nginx_user} 2> /dev/null
#fi
## rpm安装后制⾏的脚本
%post
###卸载前执⾏的脚本
%preun
###卸载后执⾏的脚本
%postun
rm -rf opt/zookeeper
# 5.清理阶段
%clean
### 删除buildroot⽬录
rm -rf %{buildroot}
# 6.⽂件设置阶段
%files
### 设定默认权限,如果下⾯没有指定权限,则继承默认
%defattr (-,root,root)
###要打包的⽂件和⽬录,在执⾏完rpmbuild -bi后,参考%{rootbuild}下⽣成的⽂件和⽬录
/opt/zookeeper
编写完 SEPC ⽂件后,可以通过 rpmlint 检查是否有配置错误
rpmlint motan-go.spec
5 . 执行打rpm包的命令
cd /root/rpmbuild/SPECS
rpmbuild -ba zookeeper.spec
6 . 测试安装
rpm -Uvh apache-zookeeper-3.6.1-1.x86_64.rpm
41 . makefile
Makefile有三个⾮常有⽤的变量。分别是$@,$^,$<代表的意义分别是:
$@--⽬标⽂件,$^--所有的依赖⽂件,$<--第⼀个依赖⽂件。
1 ) ifneq
日常使用 Makefile 编译文件时,可能会遇到需要分条件执行的情况,比如在一个工程文件中,可编译的源文件很多,但是它们的类型是不相同的,所以编译文件使用的编译器也是不同的。手动编译去操作文件显然是不可行的(每个文件编译时需要注意的事项很多),所以 make 为我们提供了条件判断来解决这样的问题。
需要解决的问题:要根据判断,分条件执行语句。
条件语句的作用:条件语句可以根据一个变量的值来控制 make 执行或者时忽略 Makefile 的特定部分,条件语句可以是两个不同的变量或者是常量和变量之间的比较。
关键字 |
功能 |
ifeq |
判断参数是否不相等,相等为 true,不相等为 false。 |
ifneq |
判断参数是否不相等,不相等为 true,相等为 false。 |
ifdef |
判断是否有值,有值为 true,没有值为 false。 |
ifndef |
判断是否有值,没有值为 true,有值为 false。 |
2 ) wildcard
在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果
需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTERN...) 。在Makefile中,
它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,
函数会忽略模式字符并返回空。需要注意的是:这种情况下规则中通配符的展开和上一小节匹配通配符的区别
一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用“$(
patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列
表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。因此在一个目录下
可以使用如下内容的Makefile来将工作目录下的所有的.c文件进行编译并最后连接成为一个可执行文件:
3 ) .PHONY
在Makefile中,.PHONY后面的target表示的也是一个伪造的target, 而不是真实存在的文件target,注意Makefile的target默认是文件。在Makefile中,.PHONY后面的target表示的也是一个伪造的target, 而不是真实存在的文件target,注意Makefile的target默认是文件。
4 ) override
通常在执行 make 时,如果通过命令行定义了一个变量,那么它将替代在 Makefile中出现的同名变量的定义。
就是说,对于一个在 Makefile 中使用常规方式(使用“=”、“:=”或者“define”)定义的变量,我们可以在执行 make 时通过命令行方式重新指定这个变量的值,命令行指定的值将替代出现在 Makefile 中此变量的值。
如果不希望命令行指定的变量值替代在 Makefile 中的变量定义,那么我们需要在 Makefile 中使用指示符“override”来对这个变量进行声明。
42 . grep命令
# 在当前目录下寻找包含字符串的所有文件
grep -r 'glib.h' .
# 查看进程,把grep进程排除
grep -v 'grep'
43 . 查看内存
cat /proc/meminfo
可以查看总内存,剩余内存、可使用内存等信息
44 . 校验端口占用情况
netstat -anp |grep
45 . CPU软中断
46 . shell中数组/列表操作,数组的使用
Shell 数组 | 菜鸟教程
#定义
list=('A' 'B' 'C' 'D')
# 获取数组中所有元素
${my_array[*]}
${my_array[@]}
# 获取第n个元素
${array_name[index]}
# 赋值
my_array[0]=A
my_array[1]=B
my_array[2]=C
my_array[3]=D
# 获取数组长度
${#my_array[*]}
${#my_array[@]}
# 遍历数组
for data in ${list[@]}
do
echo ${data}
done
47 . shell中字典的使用
shell下字典 - 百度文库
# 定义,使用-A定义字典
declare -A dict
dic=([key1]="value1" [key2]="value2" [key3]="value3")
#追加字典
dic+=([key4]="value4" [key5]="value5" [key6]="value5")
#打印指定key的value
echo ${dic["key1"]}
#打印所有key值
echo ${!dic[*]}
#打印所有value
echo ${dic[*]}
48 . 查看某端口的进程
lsof -i:8090
netstat -ap|grep 8090
49 . 系统时间
date
date=`date`
echo $date
50 . shell脚本中指定接收参数的方法
1 ) 使用示例
https://blog.csdn.net/sinat_36521655/article/details/79296181
while getopts ":a:b:c:" opt
do
case $opt in
a)
echo "参数a的值$OPTARG"
;;
b)
echo "参数b的值$OPTARG"
;;
c)
echo "参数c的值$OPTARG"
;;
?)
echo "未知参数"
exit 1;;
esac
done
2 ) getopts 使用详解
getopt 与 getopts用法详解_爱研究的陈先生的博客-CSDN博客_getopts
shell命令之——getopts-蒲公英云
command -a value -b value
51 . python调用shell脚本的几种方法
通过 Python 来调用 Shell 脚本的三种常用方式_独家雨天的博客-CSDN博客_python shell
通过 os.system 运行
import os
return_code = os.system('ls -al .')
print("return code:", return_code)
52 . 清理磁盘
190机器无法门神登录,后来发现是dev/sda2磁盘打满,baas_agent无法启动
/dev/sda2 占用空间100%的处理方法_小Leetcode~的博客-CSDN博客_dev/sda2
/dev/sda是指整个硬盘,实际使用中一般都会有分区,也就是/dev/sda1, /dev/sda2这样的。有一些分区已经挂载了,使用df命令,可以看到各个分区分区被挂载到哪个目录,然后ls查看想要查的目录。
df -h 命令查看磁盘使用情况
因为我把用户程序部署在/user下面,所以映射到/dev/sda2这块磁盘上,瞬间打满。
把/user下面我的部署包移动到空间比较大的/home/ssd1下 解决
53 . set -e/set -x/set -u
linux shell set -x,linux命令之set x详解_湖山祯崇的博客-CSDN博客
set -x与set +x指令
用于脚本调试。set是把它下面的命令打印到屏幕
set -x 是开启 set +x是关闭 set -o是查看 (xtrace)。
针对一部分script,可以选择 set -x 和 set +x配套使用。比如在一个脚本里:
set -x # activate debugging from here
set +x # stop debugging from here
set指令能设置所使用shell的执行方式,可依照不同的需求来做设置
-a 标示已修改的变量,以供输出至环境变量。
-b 使被中止的后台程序立刻回报执行状态。
-C 转向所产生的文件无法覆盖已存在的文件。
-d Shell预设会用杂凑表记忆使用过的指令,以加速指令的执行。使用-d参数可取消。
-e 若指令传回值不等于0,则立即退出shell。
-f 取消使用通配符。
-h 自动记录函数的所在位置。
-H Shell 可利用"!"加的方式来执行history中记录的指令。
-k 指令所给的参数都会被视为此指令的环境变量。
-l 记录for循环的变量名称。
-m 使用监视模式。
-n 只读取指令,而不实际执行。
-p 启动优先顺序模式。
-P 启动-P参数后,执行指令时,会以实际的文件或目录来取代符号连接。
-t 执行完随后的指令,即退出shell。
-u 当执行时使用到未定义过的变量,则显示错误信息。
-v 显示shell所读取的输入值。
-x 执行指令后,会先显示该指令及所下的参数。
+ 取消某个set曾启动的参数。
54 . echo
echo -n :表示不换行输出
echo `ifconfig`
echo "`ifconfig`"
55 . 查看cpu核数
cat /proc/cpuinfo| grep 'processor'| wc -l
56 . fdisk -l
通过fdisk -l 查看机器所挂硬盘个数及分区情况;
fdisk 能划分磁盘成为若干个区,同时也能为每个分区指定分区的文件系统,比如linux,fat32,linux swap,fat16以及其实类Unix类操作系统的文件系统等.当然用fdisk 对磁盘操作分区后,还要对分区进行格式化所需要的文件系统,这样一个分区才能使用.
主分区[Primary](包括扩展分区[Extended])的总数不能超过4个;也就是说主分区[Primary]+扩展分区[Extended]总数最多是4,扩展分区[Extended]分区只能有一个
因此如果要分成4快磁盘分区的话,那么最多是可以:
P+P+P+P 或者
P+P+P+E
其中3P+E只有3个可用的磁盘,扩展分区不能直接使用,还要分区成逻辑分区[Logical]才行.
在linux中,IDE硬盘最多有59个逻辑分区(/dev/hda5到/dev/hda63),SATA硬盘则最多有11个逻辑分区(/dev/sda5到/dev/sda15)
fdisk -l 查看硬盘及分区信息
Disk /dev/sda: 500.1 GB, 500107862016 bytes
255 heads, 63 sectors/track, 60801 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Device Boot Start End Blocks Id System
/dev/sda1 * 1 13 104391 83 Linux 主分区
/dev/sda2 14 6387 51199155 83 Linux 主分区
/dev/sda3 6388 7407 8193150 82 Linux swap / Solaris 主分区
/dev/sda4 7408 60801 428887305 5 Extended 扩展分区
/dev/sda5 7408 20155 102398278+ 83 Linux 逻辑分区
/dev/sda6 20156 26529 51199123+ 83 Linux 逻辑分区
通过上面的信息 我们知道此机器挂载了1个硬盘sda,大小500G
有255个磁面,63个扇区,60801个磁柱(意味着最后一个分区只能分到60800磁柱的时候整个硬盘的所有空间就分完了);
每个磁柱的容量是8225280 bytes 约为 8.225280M
57 . seq 生成数组
for i in `seq 0 $seq_end`;
do {
iperf3 -c $server_ip --bind $local_ip --cport $((6000+$i)) -p $((5200+$i)) -4 -d -A $i -t 60 --logfile ./iperf3.log.$i > rtt.log.$i; }&
done
58 . iperf
网络测试工具——iperf3详细使用说明_玩转智能机器人的博客-CSDN博客_iperf3
A(客户端)IP地址:192.168.3.95
B(服务端)IP地址:192.168.3.250
服务端:iperf -s -i 1
TCP测试:
# TCP上行测试-b 带宽;
客户端:iperf3 -c 192.168.3.250 -i 1 -t 10 -b 7M
TCP下行测试:在A(客户端)设备启动shell窗口,输入指令
客户端:iperf3 -c 192.168.3.250 -i 1 -t 10 -b 7M -R
UDP测试:
# 服务端
iperf -s -i 1
# 作为服务端运行,报告回显间隔时间1s,服务端不区分tcp或udp
# UDP上行测试
# 客户端
iperf3 -u -c 192.168.3.250 -b 70M -i 1 -t 10
#作为客户端运行,限制带宽70M,报告回显间隔1s,测试时间10s
# UDP下行测试
iperf3 -u -c 192.168.3.250 -b 70M -i 1 -t 10 -R
Usage: iperf [-s|-c host] [options]
iperf [-h|--help] [-v|--version]
Server or Client:
-p, --port # server port to listen on/connect to
-f, --format [kmgKMG] format to report: Kbits, Mbits, KBytes, MBytes
-i, --interval # seconds between periodic bandwidth reports
-F, --file name xmit/recv the specified file
-A, --affinity n/n,m set CPU affinity
-B, --bind
-V, --verbose more detailed output
-J, --json output in JSON format
--logfile f send output to a log file
-d, --debug emit debugging output
-v, --version show version information and quit
-h, --help show this message and quit
Server specific:
-s, --server run in server mode
-D, --daemon run the server as a daemon
-I, --pidfile file write PID file
-1, --one-off handle one client connection then exit
Client specific:
-c, --client
-u, --udp use UDP rather than TCP
-b, --bandwidth #[KMG][/#] target bandwidth in bits/sec (0 for unlimited)
(default 1 Mbit/sec for UDP, unlimited for TCP)
(optional slash and packet count for burst mode)
-t, --time # time in seconds to transmit for (default 10 secs)
-n, --bytes #[KMG] number of bytes to transmit (instead of -t)
-k, --blockcount #[KMG] number of blocks (packets) to transmit (instead of -t or -n)
-l, --len #[KMG] length of buffer to read or write
(default 128 KB for TCP, 8 KB for UDP)
--cport
-P, --parallel # number of parallel client streams to run
-R, --reverse run in reverse mode (server sends, client receives)
-w, --window #[KMG] set window size / socket buffer size
-C, --congestion
-M, --set-mss # set TCP/SCTP maximum segment size (MTU - 40 bytes)
-N, --no-delay set TCP/SCTP no delay, disabling Nagle's Algorithm
-4, --version4 only use IPv4
-6, --version6 only use IPv6
-S, --tos N set the IP 'type of service'
-L, --flowlabel N set the IPv6 flow label (only supported on Linux)
-Z, --zerocopy use a 'zero copy' method of sending data
-O, --omit N omit the first n seconds
-T, --title str prefix every output line with this string
--get-server-output get results from server
--udp-counters-64bit use 64-bit counters in UDP test packets
--no-fq-socket-pacing disable fair-queuing based socket pacing
(Linux only)
[KMG] indicates options that support a K/M/G suffix for kilo-, mega-, or giga-
iperf3 homepage at: http://software.es.net/iperf/
Report bugs to: GitHub - esnet/iperf: iperf3: A TCP, UDP, and SCTP network bandwidth measurement tool
59 . scp命令
scp -r -P port local_folder remote_username@remote_ip:remote_folder
60 . fio命令
FIO – IO压力测试工具_武晓兵的博客-CSDN博客
FIO是测试IOPS的⾮常好的⼯具,⽤来对硬件进⾏压⼒测试和验证,⽀持13种不同的I/O引擎, 包括:sync,mmap, libaio, posixaio, SG v3, splice, null, network, syslet, guasi, solarisaio 等等
fio最初是用来节省为特定负载写专门测试程序,或是进行性能测试,或是找到和重现bug的时间。写这么一个测试应用是非常浪费时间的。因此需要一个工具来模拟给定的io负载,而不用重复的写一个又一个的特定的测试程序。但是test负载很难定义。因为可能会产生很多进程或线程,他们每一个都用他们自己的方式产生io。fio需要足够灵活得来模拟这些case。
command:
fio -filename=/dev/sdb1 -direct=1 -iodepth 1 -thread -rw=randread -ioengine=psync -bs=16k -size=200G -numjobs=10 -runtime=1000 -group_reporting -name=mytest
# 顺序读:
fio -filename=/dev/sdb1 -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest
# 随机写
fio -filename=/dev/sdb1 -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=1000 -group_reporting -name=mytest
# 混合随机读写
fio -filename=/dev/sdb1 -direct=1 -iodepth 1 -thread -rw=randrw
-rwmixread=70 -ioengine=psync -bs=16k -size=200G -numjobs=30 -runtime=100 -group_reporting -name=mytest -ioscheduler=noop
说明:
filename=/dev/sdb1 测试文件名称,通常选择需要测试的盘的data目录。
direct=1 测试过程绕过机器自带的buffer。使测试结果更真实。
rw=randwrite 测试随机写的I/O
rw=randrw 测试随机写和读的I/O
bs=16k 单次io的块文件大小为16k
bsrange=512-2048 同上,提定数据块的大小范围
size=5g 本次的测试文件大小为5g,以每次4k的io进行测试。
numjobs=30 本次的测试线程为30.
runtime=1000 测试时间为1000秒,如果不写则一直将5g文件分4k每次写完为止。
ioengine=psync io引擎使用pync方式
rwmixwrite=30 在混合读写的模式下,写占30%
group_reporting 关于显示结果的,汇总每个进程的信息。
此外
lockmem=1g 只使用1g内存进行测试。
zero_buffers 用0初始化系统buffer。
nrfiles=8 每个进程生成文件的数量。
另一种运行方式:
典型的fio的工作过程
1)写一个job文件来描述要访真的io负载。一个job文件可以控制产生任意数目的线程和文件。典型的job文件有一个global段(定义共享参数),一个或多少job段(描述具体要产生的job)。
2)运行时,fio从文件读这些参数,做处理,并根据这些参数描述,启动这些访真线程/进程
运行fio
运行方式:
$fio job_file
它会根据job_file的内容来运行。你可以在命令行中指定多个job file,fio进串行化运行这些文件。相当于在同一个job file不同的section之间使用了stonewall参数。
job文件格式
job file格式采用经典的ini文件,[]中的值表示job name,可以采用任意的ASCII字符,‘global’除外,global有特殊的意义。Global section描述了job file中各个job的默认配置值。一个job section可以覆盖global section中的参数,一个job file可以包含几个global section.一个job只会受到它上面的global section的影响。‘;’和‘#’可以用作注释
例1 :两个进程,分别从一个从128MB文件中,随机读的job file.
;–start job file–
[global]
rw=randread
size=128m
[job1]
[job2]
;–end job file–
job1和job2 section是空的,因为所有的描述参数是共享的。没有给出filename=选项,fio会为每一个job创建一个文件名,如果用命令写,则是:
$fio –name=global –rw=randread –size=128m –name=job1 –name=job2
例2 : 多个进程随机写文件的实例
;–start job file –
[random-writers]
ioengine=libaio
iodepth=4
rw=randwrite
bs=32k
direct=0
size=64m
numjobs=4
;–end job file–
没有global section,只有一个job section.
上一个实例的说明:采用async,每一个文件的队列长度为4,采用随机写,采用32k的块,采用非direct io,共有4个进程,每个进程随机写64M的文件。也可以采用下面的命令
$fio –name=random-writers –ioengine=libaio –iodepth=4 –rw=randwrite –bs=32k –direct=0 –size=64m –numjobs=4
*************************************************************************************************************************
filename
待测试的文件或块设备。
若为文件,则代表测试文件系统的性能;例:-filename=/work/fstest/fio.img
若为块设备,则代表测试裸设备的性能; 例:-filename=/dev/sdb1
ioengine
采用的文件读写方式
sync:采用read,write,使用fseek定位读写位置。
psync:采用pread、pwrite进行文件读写操作
vsync:采用readv(2) orwritev(2)进行文件读写操作,
libaio:Linux异步读写IO(Linuxnative asynchronous I/O)
posixaio: glibc POSIX 异步IO读写,使用aio_read(3)and aio_write(3)实现IO读写。
mmap: File is memory mappedwith mmap(2) and data copied using memcpy(3).
splice: splice(2) isused to transfer the data and vmsplice(2) to transfer data from user-space tothe kernel.
syslet-rw: Use thesyslet system calls to make regular read/write asynchronous.
sg:SCSI genericsg v3 I/O.
net : Transferover the network. filename must be set appropriately to `host/port’ regardlessof data direction. If receiving,only the port argument is used.
netsplice: Like net,but uses splice(2) and vmsplice(2) to map data and send/receive.
Guasi : The GUASI I/Oengine is the Generic Userspace Asynchronous Syscall Interface approach toasycnronous I/O.
direct
当前测试是否采用直接IO方式进行读写,如果采用直接IO,则取值-direct=1,否则取值-direct=0。
采用直接IO写测试,会使得测试结果更加真实。
rw
读写模式。
read:顺序读测试,使用方式-rw=read
write:顺序写测试,使用方式-rw=write
randread:随机读测试,使用方式-rw=randread
randwrite:随机写测试,使用方式-rw=randwrite
randrw:随机读写,-rw=randrw;默认比率为5:5,通过参数-rwmixread设定读的比率,如-rw=randrw-rwmixread=70,说明读写比率为70:30。或rwmixwrite
bs
单次IO的大小;例:-bs=4k
bssplit
设备读写访问的IO大小,例:-bssplit=4k/30:8k/40:16k/30,随机读4k文件占30%、8k占40%、16k占30%
size
本次测试文件的大小;例-size=1G
iodepth
IO队列深入,即一次下发的IO的个数,例如:-iodepth=16
runtime
设置测试运行的时间,单位秒,例:-runtime=300
sync
设置同步模式,同步-sync=1,异步-sync=0
fsync
设置数据同步模式,同步-fsync=1,异步-fsync=0
numjobs
测试进程的并发数,默认为,例:-numjobs=16
61 . ioping