标题:shell脚本养成计划
1、shell篇
1.1、变量
1.1.1、特殊变量
!:指定如下解释程序是一个可执行文件,需要指定的的shell去运行它;
- $?:每一个命令都有自己的返回值,为0表示成功异常,非0则表明执行异常;
- $0:当前执行脚本的名称,或者也可以看作执行命令的第一个参数(即脚本文件);
- $1-9:脚本执行时,依次传递的参数1-9;
- $#:脚本执行时,传递参数的个数;
- $*:输入参数的具体内容,(将多个参数并作一个单词处理);
- $@:输入参数的列表对象;
- $$:当前进程的PID;
- $!:上一个后台进程的PID
如下所示:测试脚本。执行:bash 1.sh hah heh hihi
#!/bin/bash
systemctl restart docker.service
echo "\$?: $?"
echo "\$0: $0"
echo "\$1: $1, \$2: $2, \$3: $3"
echo "\$#: $#"
echo "\$*: $*"
arr=$@
for "${str}" in ${arr}; do echo "${"${str}"}"; done
测试查看运行的对应结果。
1.1.2、普通变量
name=ike
,定义普通变量,只在当前shell中有效;
变量的引用方式(上下文同)
- $key,${key}:可以解决歧义,${#key}:输出变量值的定义长度;
- '$key',"$key":单引号输出为$key,双引号则为变量值;
[root@VM-218-88-centos ~/]# name=hehe
[root@VM-218-88-centos ~/]# echo "$name"
hehe
[root@VM-218-88-centos ~/]# echo '$name'
$name
1.1.3、环境变量
export name=ike
;定义系统的环境变量,在当前shell和其他子shell中都可以引用;env
,查看当前shell全体的环境变量;unset name
,清除指定的环境变量;source xxx.sh
,在当前shell中执行脚本,可以引用当前shell所有变量;
1.2、符号处理
1.2.1、排序与或
- ; :命令的排序执行,无论成功失败与否
- && :逻辑与,按照命令排序的顺序,成功后进入下一个命令的执行;
- || :逻辑或,按照命令排序的顺序,失败后进入下一个命令的执行;
如下所示:
[root@VM-218-88-centos /]# go tls_test_0.js ; echo "success"
go tls_test_0.js: unknown command
Run 'go help' for usage.
success
[root@VM-218-88-centos /]# go tls_test_0.js && echo "success"
go tls_test_0.js: unknown command
Run 'go help' for usage.
[root@VM-218-88-centos /]# go tls_test_0.js || echo "success"
go tls_test_0.js: unknown command
Run 'go help' for usage.
success
1.2.2、重定向
- 覆盖:> :标准输出的结果覆盖目标文件;
- 追加:>>:标准输出的结果追加到目标文件;
- 覆盖:2>:错误输出的结果覆盖目标文件;
- 追加:2>>:错误输出的结果追加到目标文件;
- 合并:&>:标准和错误信息都直接覆盖目标文件;
- 合并:&>>:标准和错误信息都直接追加目标文件;
- <:将目标文件的内容作为执行命令的输入参数
- <<END:从标准键盘(控制台)中读取数据,换行分隔,直到遇见分界符END才终止(分界符可以是任意自定义字符串)
- &>/dev/null:清空命令的输出,即不要它,/dev/null,磁盘特殊块,可以看作黑洞,永久为空
特殊使用:command < file > 1.log,将file作为命令的输入参数,然后将执行结果输出到1.log
如下所示:执行一个mongo批量操作数据的脚本,然后操作记录输出到1.log文件中;
docker exec -i mongo mongo < mongo_update.js > 1.log
1.2.3、管道
与重定向不同的是,管道可以将两个甚至多个不同的命令(程序或者进程)连接到一起,将上一个命令的输出作为下一个命令的输入,依次执行,连接方式为|
,称为管道符。即:它改变了数据输入输出的方向
下一个命令只能处理上一条命令正确的输出,
1、查找文件中xxxx内容:cat fileName |grep 'xxxx'
;
2、查找xxxx相关服务列表:systemctl list-units |grep xxxx
;
3、假如知道日志文件的结构,要筛选它指定分隔列表的带有web
内容字段:
[root@VM-218-88-centos /]# cat 20220808.access_12.csv |awk -F , '{print $2}' |grep "web"
"rio3_internal_web"
"rio3_internal_webapi"
"rio3_internal_web"
"rio3_internal_web"
"rio3_internal_webapi"
"rio3_internal_web"
"rio3_internal_webapi"
1.3、条件判断
1.3.1、if
基本语法:
if [command]; then
# 符合该条件的执行语句
fi
if [ command ];then
# 符合该条件执行的语句
elif [ command ];then
# 符合该条件执行的语句
else
# 符合该条件执行的语句
fi
command
可以是条件,也可以是执行命令(中括号两边必须要有空格,强制),如果command为命令执行后,返回的$? = 0,那么往下执行then,否则跳到下一个判断或者跳出if,- then和fi是分开的语句,如果要在一行展示,则它俩之间必须要有分号隔开;
- 条件判断对于变量之间的比对需要加双引号,方便处理;
- 单独使用><(大于小于)时,会被当成命令的重定向,需要使用>,<转译代替;
- 使用-z或者-n来检查长度的时候,没有定义的变量也为0,所以:空变量和没有初始化的变量可能会干扰shell,在不确定变量的内容的时候,可以使用-n或者-z提前判断一下;
- 条件可以是双圆括号(( )):表示数学表达式,允许在比较中进行简单的算术操作,双圆括号里面的'>','<'号不需要转意;
- 条件可以是双方括号[[ ]]:表示高级字符串处理函数,使用标准的字符串比较,还可以使用匹配模式,从而定义与字符串相匹配的正则表达式。
常用针对文件的条件判断
- [ -a file ]: 如果 file 存在则为真。
- [ -d file ]: 如果 file 存在且是一个目录则返回为真。
- [ -e file ]: 如果 指定的文件或目录存在时返回为真。
- [ -f file ]: 如果 file 存在且是一个普通文件则返回为真。
- [ -r file ]: 如果 file 存在且是可读的则返回为真。
- [ -w file ]: 如果 file 存在且是可写的则返回为真。(一个目录为了它的内容被访问必然是可执行的)
- [ -x file ]: 如果 file 存在且是可执行的则返回为真。
字符串判断
- [ -z "${str}" ] :如果str的长度为零则返回为真,即空是真;
- [ -n "${str}" ] :如果str的长度非零则返回为真,即非空是真;
- [ "${str}" ] :如果字符串不为空则返回为真,与-n类似;
- [ "${str1}" == "${str2}" ]: 如果两个字符串相同则返回为真;
- [ "${str1}" != "${str2}" ]: 如果字符串不相同则返回为真;
逻辑判断
- [ ! expr ] :逻辑非,如果 expr 是false则返回为真。
- [ expr1 -a expr2 ] :逻辑与,如果 expr1 and expr2 全真则返回为真。
- [ expr1 -o expr2 ] :逻辑或,如果 expr1 或者 expr2 为真则返回为真。
- [ ] || [ ] :两个条件取或,用OR来合并两个条件
- [ ] && [ ] :两个条件取与,用AND来合并两个条件
1、判断一个目录(文件夹)是否存在,不存在的话创建
#!/bin/bash
if [ ! -d "$1" ];then
mkdir -pv "$1"
fi
1.3.2、while
都是条件判断执行,while用于循环,基本语法:
while condition
do
statements
done
condition
:与上文的if类似,同理do和done是分开的语句,如果要在一行展示,则它俩之间必须要有分号隔开;
1、如下所示(1~100的累加):
shell中,默认都是字符串操作。(())声明内部为算术表达式,变量引用不需$;let可以指定语句为算术表达式,语句内变量无需$
#!/bin/bash
# (())用法,表明内部为算术表达式,变量引用不需$
i=0
num=0
while ((i <= 100))
do
((num+=i))
((i+=1))
done
echo "1+2+3+……+100=$num"
# []:变量引用必须加""
i=0
num=0
while [ "$i" -le 100 ]
do
let num+=i;
let i+=1
done
echo "1+2+3+……+100=$num"
# [[]]:使用标准的字符串比较,无需给变量引用添加""
i=0
num=0
while [[ $i -le 100 ]]
do
let num+=i;
let i+=1
done
echo "1+2+3+……+100=$num"
1.4、时区&时间
1.4.1、date
查看系统时间:date
,查看系统时区:date -R
;+0800表示东八区
[root@VM-165-128-centos /]# date
2022年 08月 13日 星期六 13:22:14 CST
[root@VM-165-128-centos /]# date -R
Sat, 13 Aug 2022 13:22:18 +0800
修改系统时间:date -s "20220809 11:32"
;
1.4.2、timedatectl
操作系统的时区命令,
查询系统时区信息;timedatectl
或者 timedatectl status
;
[root@VM-165-128-centos /]# timedatectl status
Local time: 六 2022-08-13 13:26:23 CST
Universal time: 六 2022-08-13 05:26:23 UTC
RTC time: 六 2022-08-13 05:26:24
Time zone: Asia/Shanghai (CST, +0800)
NTP enabled: yes
NTP synchronized: yes
RTC in local TZ: no
DST active: n/a
罗列出所有的时区列表;timedatectl list-timezones
;
# -i:不屈分大小写过滤
[root@VM-165-128-centos /]# timedatectl list-timezones |grep -i shanghai
Asia/Shanghai
设置系统时区:timedatectl set-timezone Asia/Shanghai
;(多为保证多台机器时区一致);
设置系统时间:timedatectl set-time "2022-08-13 13:27:33"
;
- UTC:整个地球分为24时区,每个时区有本地时间,在国际通信上使用统一时间称为通用协调时:UTC;
- GMT:格林威治时间,英国皇家天文台标准时区,本初子午线所在地;
- CST:中国标准时间(china standard time);
- DST:夏令时,夏天日出较早,将时钟拨快一小时;
UTC + 8 = GMT + 8 = CST;(故:有些日志信息判断故障时间时,需要+8)
1.4.3、time
测量指定命令&脚本的耗时长;
[root@VM-165-128-centos /]# time sleep 10s
real 0m10.001s
user 0m0.001s
sys 0m0.000s
- real:指定命令&脚本 实际运行耗时;
- user:用户态代码运行耗时;
- sys:系统态代码运行耗时;
1.4.4、sleep
将目前命令&脚本,在此暂停一段时间后再执行,即休眠;
[root@VM-165-128-centos /]# date;sleep 20s;date
2022年 08月 13日 星期六 13:46:50 CST
2022年 08月 13日 星期六 13:47:10 CST
- s 为秒,m 为 分钟,h 为小时,d 为日数
1.5、下载&安装&网络
1.5.1、scp
完整名称:secure copy。在本地服务器上,将指定文件复制到指定机器的指定目录中。(传输过程加密)
- -P:指定ssh端口;
- -p:保留源文件的时间,权限相关参数;
- -4:强制只使用ipv4寻址;-6:强制使用ipv6寻址;
- -r:递归复制整个目录;
- -q:隐藏进度条;
- -v:调试模式显示连接,传输的详细信息;
如下:指定ssh端口3000,显示调试模式信息,递归将ikejcwang/workspace/grpc_test/
目录复制到主机9.135.218.88的/root/ikejcwang/
目录中。执行过程中会提示输入密码:
^C[root@VM-153-56-centos ~]# scp -P 3000 -v -r ikejcwang/workspace/grpc_test/ root@9.135.218.88:/root/ikejcwang/
Executing: program /usr/bin/ssh host 9.135.218.88, user root, command scp -v -r -t /root/ikejcwang/
OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /root/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 52: Applying options for *
……………………………………
1.5.2、wget
文件下载的工具命令。通过给定的URL,将远程文件下载到本地的当前目录中,支持http,https,ftp。命令为:wget [options] url。
- -O:指定其他名称来保存下载的文件,eg:
wget -O haha.tar url
; - -o:将下载的日志信息存入指定文件,注意是下载信息,而不是下载的内容;eg:
wget -o 1.log url
; - -P:将文件下载到指定目录;eg:
wget -P /data/ url
; - --spider:测试链接是否有效;statusCode:200/404;
1.5.1、rpm
软件包管理工具,根据提供的.rpm源代码文件自动编译、安装;
- -i:--install,安装(指定源文件);
- -v:--verbose,显示详细信息,
- -h:--hash,显示进度;eg:安装时显示进度及详细信息,
rpm -ivh xxxx.rpm
- --nodeps:不检测依赖性;
- -U:upgrade,升级包;
- -e:erase,卸载指定包;
- -q:查询是否安装(以下皆须配合-q使用);
- -a:所有,eg:查询已经安装的所有rpm包:
rpm -qa
- -i:查询软件信息,eg:查询指定包信息:
rpm -qi python-javapackages-3.4.1-11.el7.noarch
- -l:列表,eg:查看包安装位置:
rpm -ql trousers-0.3.13-1.el7.x86_64
- -f:查询系统文件属于哪个rpm包:rpm -qf 系统文件名
- -R:检测包的依赖性,rpm -qR 包名
注意:涉及依赖性问题的话,需依次解决(安装,正向逐个安装,卸载,反向逐个卸载)
[root@localhost Packages]# rpm -e httpd
错误:依赖检测失败:
httpd = 2.4.6-67.el7.centos 被 (已安裝) httpd-devel-2.4.6-67.el7.centos.x86_64 需要
[root@localhost Packages]# rpm -e httpd-devel
[root@localhost Packages]# rpm -e httpd
1.5.2、yum
基于rpm包管理,能够从指定的服务器自动下载rpm包安装,并且自动处理好依赖关系,一次性的安装所有依赖的软件包,无需繁琐的逐个处理:yum [options] [command] [packages……]
[root@VM_0_15_centos ~]# cd /etc/yum.repos.d/
[root@VM_0_15_centos yum.repos.d]# ls
CentOS-Base.repo CentOS-Epel.repo docker-ce.repo mysql-community.repo mysql-community-source.repo yarn.repo
如果系统能够联网,使用默认的网络源文件CentOS-Base.repo,
- gpgcheck:1指RPM的数字证书生效,写成0就是不生效;
- gpgkey:数字证书的公钥文件保存位置。
- enable:此容器是否生效(1),默认生效;
- baseurl:yum源服务器的地址。
- name:说明
配置文件见/etc/yum.conf
,各项操作命令如下:
- yum list:列出所有可安装的列表;
- yum check-update:列出所有可更新的软件列表;
- yum update :更新所有软件;
- yum install -y :安装指定软件,-y:自动yes,下同;
- yum update -y :更新指定软件
- yum remove -y :卸载
- yum search 关键词:查找
- yum clean packages:清除缓存目录下的软件包
- yum clean headers:清除缓存目录下的 headers
- yum clean oldheaders: 清除缓存目录下旧的 headers
- yum clean:yum clean all,皆等于:yum clean packages && yum clean oldheaders
软件组:
- yum grouplist:列出所有可用的软件组列表
- yum groupinstall :安装指定软件组
- 卸载,更新……类似
1.5.3、dig
域名查询工具,从DNS服务器查询主机IP地址,该命令属于Bind的一部分,并没有在Linux即成,需要:yum install bind-utils
dig www.wangjc.vip
,默认依次使用/etc/resolv.conf文件配置的地址作为DNS服务器,若/etc/resolv.conf没有配置,则使用网卡配置的DNS服务器;(注:它不会去解析本地hosts文件);
dig @10.123.119.98 www.baidu.com
:指定dns服务器进行查询;
1.5.4、host
同在bind-utils下面,还有一个host命令,也是做域名解析,只不过用起来比较简单(注:也不会去解析本地hosts)
hosts www.baidu.com
- -v:显示查询的详情信息
1.6、系统相关
1.6.1、cpu信息
lscpu
查看cpu相关信息,厂商,型号,频率,核数……原理是从sysfs和/proc/cpuinfo收集cpu体系结构信息
cat /proc/cpuinfo
也可以使用这样查看,然后定向过滤字段即可;
1.6.2、磁盘空间
df
查看Linux文件系统磁盘的使用情况
# 或者使用df -Bg,
[root@VM-165-128-centos /]# df -h
文件系统 容量 已用 可用 已用% 挂载点
devtmpfs 7.7G 0 7.7G 0% /dev
tmpfs 7.7G 0 7.7G 0% /dev/shm
tmpfs 7.7G 2.2M 7.7G 1% /run
tmpfs 7.7G 0 7.7G 0% /sys/fs/cgroup
/dev/vda1 99G 23G 73G 24% /
tmpfs 1.6G 0 1.6G 0% /run/user/0
/dev/vdb1 197G 4.0G 183G 3% /data
overlay 99G 23G 73G 24% /var/lib/docker/overlay2/***/merged
overlay 99G 23G 73G 24% /var/lib/docker/overlay2/***/merged
overlay 99G 23G 73G 24% /var/lib/docker/overlay2/***/merged
overlay 99G 23G 73G 24% /var/lib/docker/overlay2/***/merged
- -h:单位换算成G,方便阅读模式;
- -B:指定单位,M,G……
- -a:显示全部文件系统;
- -i:显示本地文件系统;
du
查看文件/文件夹的磁盘空间占用情况(可以精细化到文件);
[root@VM-218-88-centos ~/ikejcwang]# du -sh soft/ workspace/
3.9G soft/
22G workspace/
[root@VM-218-88-centos ~/ikejcwang]# du -h -d1
8.0G ./rio_work
3.9G ./soft
498M ./redis_cluster
11M ./ssh_cert
14G ./rio_install
22G ./workspace
48G .
- -s:统计指定文件&文件夹的占用大小,统计总量;
- -h:自动单位换算,方便阅读性;
- -a:依次递归显示指定目录下,每个文件的占用大小;
- -c:除了依次递归显示指定目录下的文件&文件夹,还计算总量;
- -d:依次显示指定目录下,指定层级的占用大小,也可以改为2层,3层;eg:
du -hd1 /
;统计根目录下每个文件&文件夹大小;
1.7、文件操作
1.7.1、cat 和 tac
tac是cat的反过来,所以其功能与cat类似却是相反,eg:tac文件是倒过来的从下往上,用法不常见;
cat :连接文件,或者标准输入并打印好,主要有三大功能:
- 一次显示整个文件的内容:cat fileName;
- 创建一个新文件,并从键盘完成输入:cat > fileName;
- 将多个文件内容合并为一个文件,或者连接起来查看:cat file1 file2 > newfile
参数用法:
- -n:--number,对输出的所有行进行编号,从1开始;
- -s:--squeeze-blank,有连续两行以上的空台,就替换为一行;
- -b:--number-nonblank,对空行输出编号,从1开始;
- -E:--show-ends,在每行结束处显示$;
1、创建一个sh文件,并嵌入内容(注意,嵌入的$需要转译处理):
[root@VM-218-88-centos /]# cat > test.sh <<END
> #!/bin/bash
> p=\$1
> echo \${p}
> END
[root@VM-218-88-centos /]#
2、对文件内容加上行号然后
[root@VM-218-88-centos /]# cat -n test.sh > test_new.sh
[root@VM-218-88-centos /]# cat test_new.sh
1 #!/bin/bash
2 p=$1
3 echo ${p}
3、去掉行号复原($被识别到了,还是不要对.sh文件这么用,此处只是测试)
[root@VM-218-88-centos /]# cat test_new.sh | awk '{print $2}' > test_new2.sh
[root@VM-218-88-centos /]# cat test_new2.sh
#!/bin/bash
p=$1
echo
1.7.2、stat
详细的显示文件的状态信息,可以看出文件大小,权限,最近查看,变更时间……
[root@VM-218-88-centos /]# stat httpTest.js
文件:"httpTest.js"
大小:499 块:8 IO 块:4096 普通文件
设备:fc01h/64513d Inode:2359301 硬链接:1
权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root)
最近访问:2022-06-29 15:06:40.781116820 +0800
最近更改:2022-06-29 15:06:40.781116820 +0800
最近改动:2022-06-29 15:06:40.789116812 +0800
创建时间:-
1.7.3、cp
文件复制,复制目录时,必须添加-r,或者-R参数;
覆盖替换复制,除了使用mv之外,还可以cp -rf
1.7.4、file
查看文件/文件夹的类型;file fileName
1.7.5、basename
给basename一个指定的路径,basename会删掉所有的前缀,包括路径最后一个/,然后将后缀字符串显示出来,且可选择是否去掉文件后缀;
如下所示:
[root@VM-165-128-centos ~/]# basename /root/ikejcwang/dist.tar .tar
dist
[root@VM-165-128-centos ~/]# basename /root/ikejcwang/dist.tar
dist.tar
[root@VM-165-128-centos ~/]# basename /root/ikejcwang/
ikejcwang
1.8、文本处理利器
1.8.1、awk
优秀的智能文本处理工具:打印文件中的某一列,它会智能的去切分数据,不管是tab,还是空格……或者指定分隔符;
- -F:指定分隔符,eg:指定分隔符为,:-F ","
- -v:指定变量和默认值;
- $NF:代表最后一个字段;
- NR:代表第几行;
- FS:输入分隔符(即-F的意思);
- OFS:输出字段分隔符;
- RS:输入记录分隔符;
- $0:显示整行;
- 1…N:第一个字段到第N个字段;
eg:查找用户名列表:
[root@VM-218-88-centos /]# cat /etc/passwd |awk -F ":" '{print $1}'
root
bin
daemon
指定行号,采用变量自增,打印最后一列($NF)
[root@VM-218-88-centos /]# cat /etc/passwd |awk -F ":" -v "i=0" '{i++;print i,$NF}'
1 /bin/bash
2 /sbin/nologin
3 /sbin/nologin
4 /sbin/nologin
根据上文,打印第33行的最后一列(NR==33):
[root@VM-218-88-centos /]# cat /etc/passwd |awk -F ":" 'NR==33{print $NF}'
/sbin/nologin
输出字段的分隔符(OFS="--";),一般与-F(或者FS)配合使用,重新定义内容的分隔:
[root@VM-218-88-centos /]# cat /etc/passwd |awk -F ":" -v "i=0" '{OFS="--";i++;print i,$NF,$1}'
1--/bin/bash--root
2--/sbin/nologin--bin
3--/sbin/nologin--daemon
4--/sbin/nologin--adm
优先级判定
- BEGIN:最高优先级,最先执行,位于PROGRAM之前,不依赖数据源;
- PROGRAM:默认,对数据流操作的,必选(默认)代码块;
- END:处理数据流之后,如果需要END,就必须事先有PROGRAM的支持
注意:如果只用BEGIN或者END,然后跟上数据源是没有效果的,数据源只对PROGRAM生效
如下所示:
# BEGIN后面不需要加任何数据源,也可以打印内容
[root@VM-218-88-centos /]# awk -v "name=ike" 'BEGIN{print name}'
ike
[root@VM-218-88-centos /]# awk -v "name=ike" -v "age=27" 'BEGIN{OFS="--";print name,age}'
ike--27
其余的小技巧;
- 打印一个文件的行数:
awk 'END{print NR}' /etc/passwd
- 打印最后一行:
awk 'END{print $0}' /etc/passwd
- 打印按指定分隔符分隔的列数:
awk -F ":" 'END{print NF}' /etc/passwd
1.8.2、grep
全局搜索的一个正则表达式,并且输出到屏幕上,在文件中对指定的关键词进行查找,并且高亮显示所在行的位置;
参数列表:
- -i:忽略大小写;
- -v:取反匹配,即筛选出不满足的行;
- -n:输出时显示行号;
- -r:递归查找,一般针对整个文件夹下的内容进行检索时,对应还有个命令rgrep;
还可以配合正则表达式使用-E
[root@VM-218-88-centos /]# grep -E "(/?)wang" /etc/passwd
ikejcwang:x:1001:0::/home/ikejcwang:/bin/bash
wang:x:1002:1000::/home/wang:/bin/bash
[root@VM-218-88-centos /]# grep -E "^wang" /etc/passwd
wang:x:1002:1000::/home/wang:/bin/bash
1.8.3、sed
作为快速文本的处理利器,应用简单实用广泛;工作流程:读取->执行->显示;
命令格式为:set [options] '编辑命令' file1 file2…
- -e:使用指定的命令&脚本来处理输入的文本文件;
- -f:使用指定的脚本文件来处理输入的文本文件;
- -n:表示仅显示处理后的结果;
- -i:直接编辑文本文件;
- -r,-E:使用扩展正则表达式;
- -s:将多个文件视为独立文件,而不是单个的长文件流;
常见的操作动作如下:
- a:增加,在当前行下面增加一行指定内容;
- c:替换,将选定行替换为指定内容
- d:删除,删除选定的行;
- i:插入,在选定行上面插入一行指定内容;
- p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印出所有内容;如果有非打印字符,则以ASCII码输出。其通常与"-n"选项一起使用;
- s:替换,替换指定字符;
- y:字符转换。
# 创建一个文件,并输入内容
[root@VM-218-88-centos /]# cat <<end >text.txt
> haha,1
> hehe,2
> hihi,3
> huhu,4
> end
# -n(显示执行结果),p:全量打印文件内容
[root@VM-218-88-centos /]# sed -n 'p' text.txt
haha,1
hehe,2
hihi,3
huhu,4
# 只显示第二行
[root@VM-218-88-centos /]# sed -n '2p' text.txt
hehe,2
# 显示第二道第四行的内容
[root@VM-218-88-centos /]# sed -n '2,4p' text.txt
hehe,2
hihi,3
huhu,4
# 第二个n,表示显示下一行的内容,(输出偶数行)
[root@VM-218-88-centos /]# sed -n 'n;p' text.txt
hehe,2
huhu,4
# 输出1-4行之间的奇数行
[root@VM-218-88-centos /]# sed -n '1,4{p;n}' text.txt
haha,1
hihi,3
删除的用法,注意:只是删除输出文本,并未删除源文本内容
sed:-e 表达式 #1,字符 3:命令后含有多余的字符
[root@VM-218-88-centos ~/ikejcwang]# sed -n "1d;p" text.txt
hehe,2
hihi,3
huhu,4
[root@VM-218-88-centos ~/ikejcwang]# sed -n "1,3d;p" text.txt
huhu,4
替换,/g全量,/gi全量且忽略大小写,替换的特殊字符,需要转译(同样支持针对特定行内容替换)
[root@VM-218-88-centos ~/ikejcwang]# sed -n "s/h/ike/;p" text.txt
ikeaha,1
ikeehe,2
ikeihi,3
ikeuhu,4
[root@VM-218-88-centos ~/ikejcwang]# sed -n "s/h/ike/g;p" text.txt
ikeaikea,1
ikeeikee,2
ikeiikei,3
ikeuikeu,4
set -i,编辑文本文件,(无需p输出打印了);
sed -i 's/https:\/\/真实的域名/http:\/\/9.133.222.55/g' host-template
sed -i 's/真实的域名/9.135.218.88/g' host-template
sed -i 's/真实的签名/KpRklaXpaoTeVTm/g' host-template
1.8.4、vim
强大的文本编辑器(值得总结的太多太多),系统没有的话安装:yum -y install vim*
此处记录的多是常用且复杂的操作:
- 多行注释:在ESC模式下,按Ctrl+V,滑动选择多行,再按Shift+i进入插入模式,输入注释符号,完成后ESC,加鼠标点一下;
- 多行取消注释:在ESC模式下,按Ctrl+V,滑动选择多行,再按d即可完成去注释;
- 替换模式:正常模式,按r,然后输入替换字符。(替换一堆,先按v,进入可视模式选中,然后按r,输入替换字符);
- 清空文件:ggdG,(gg:到文件头部,G:到文件尾部);
- :set spell / nospell:开启/关闭拼写检查功能;
插入模式:
- gI:在当前行的头部插入;
- A:在当前行的尾部插入;
- a:在光标后插入;
- O:在上面新建一行插入;
- o:在下面新疆一行插入;
- :r filename:在当前位置插入指定文件内容;
- :[n]r filename:在指定行位置插入指定文件内容;
复制粘贴删除:
- y:复制可视模式下选中的文本;
- yy 或 Y:复制当前行;
- y$,y0:从光标当前位置复制到文件尾部,从光标当前位置复制到文件头部;
- d:删除(剪切)可视模式下选中的文本,没选中就是光标处文本;
- dd :删除(剪切)1行(当前行);
- d$ 或 D:删除(剪切)当前位置到行尾的内容;
- p:在光标之后粘贴;
- P:在光标之前粘贴;
替换:
- :s/old/new/,替换当前行的第一个,加/g替换当前行的全部
撤回与反撤回:
- u:撤回,一直到初始打开状态;
- ctrl+r:反向撤回,一直到最新编辑状态;
1.8.5、wc
word count的缩写,用于文本内容的统计。单词条目,行数,字符数,字节数……
wc test.txt
:执行后显示,第一个是行数,第二个单词数(空格分隔),第三个是字节数。
- -l:只统计行数;
- -w:只统计单词数;
- -c:只统计字节数;
- -m:只统计字符数;
1.8.6、base64
base64:加密,
base64 -d:解密
base64 file.txt
cat file.txt | base64
1.8.7、md5sum
计算指定文本,文件的md5值,可用来对比文件内容是否不一致;
# 判断压缩包的md5值,与真实版本是否一致
[root@VM-165-128-centos /]# time md5sum nstall-v1.2.2.zip
9966218540ef813f1673b5913f984c1c install-v1.2.2.zip
real 0m1.829s
user 0m1.672s
sys 0m0.156s
time计算命令执行的耗时。
1.8.8、jq
json文本格式处理的神器。curl url | jq
wget -O jq https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64
chmod +x ./jq
cp jq /usr/bin
1.9、进程&任务
1.9.1、w
查看当前系统正在登录的用户有哪些(开启的ssh连接数量),以及它们各自的休眠时长,行为动作
[root@VM-218-88-centos ~/ikejcwang]# w
17:53:20 up 6 days, 17:29, 4 users, load average: 0.06, 0.08, 0.08
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 10.91.79.167 10:15 41:55 0.11s 0.00s -bash
root pts/1 10.91.79.167 10:15 0.00s 0.02s 0.02s -bash
root pts/2 10.91.79.167 10:16 6.00s 0.01s 0.01s -bash
root pts/3 10.91.79.167 10:16 6:49m 0.00s 0.00s -bash
- 17:53:20:当前时间;
- up 6 days,17:29:系统的正常运行时间(距离上一次重启);
- 4 users:目前有4个user/from在线上;
- load average: 0.06, 0.08, 0.08:系统的平均负载值(统计3个时间段),1分钟为0.06,5分钟为0.08, 15分钟为0.08;
- USER:登录的用户名;
- TTY:终端名称;
- FROM:开启ssh访问的客户端IP地址;
- LOGIN@:当前会话登录的开始时间;
- IDLE:会话多久没用活跃(s秒,m分钟……);
- JCPU:当前会话所有进程使用的CPU时间,进程结束停止计时;开启新的进程重新计时;
- PCPU:当前会话的CPU执行当前程序花的时间;当前程序即为当前会话的WHAT值。
1.9.2、top
动态的显示系统当前资源的利用率和进程运行实况
top
,常用参数如下:
- -p:指定进程号来监控,eg:
top -p 6328
; - -i:过滤掉任何闲置或者僵尸进程,eg:
top -i
; - -c:显示进程完整的命令;eg:
top -c
; - -d:设置动态刷新的时间间隔,eg:每秒刷一次:
top -d 1
,(默认3秒) top -p 320 -p 330 -d 5 -c
:间隔5秒,完整命令显示进程号330和320的实时运行情况;
先说交互命令(简单介绍):
- 1:切换显示每个cpu的状态;
- E:切换内存显示的单位:K,M,G,T,P;
- M:根据内存占用的大小来进行排序降序;
- P:根据CPU使用的百分比大小进行排序;
然后各项参数配置:
- 第一行(系统参数):top:当前时间;up:机器运行时间(距上次重启);user:当前ssh会话数;系统负载平均值(1,5,15)分钟
- 第二行(当前task分类):total:当前有进程数;running:正在运行进程;sleeping:正在休眠进程;stopped:停止进程数;zombie:僵尸进程数;
第三行(CPU信息,按1展示所有cpu信息)
us:用户空间占用cpu的百分比(各种脚本,应用,webserver……都算作运行在用户空间的进程);
sy:内核空间占用cpu的百分比(所有进程使用系统资源时都有Linux内核处理,当大量IO操作,或者IO阻塞时,sy会增大);
ni:用户进程空间改变过优先级;
id:空闲cpu的百分比;
wa:等待输入输出占用cpu百分比,通过wa可以判断系统瓶颈是否在IO上面;
hi:硬中断占用百分比;si:软中断占用百分比;
st:超分(超卖)的判断指标。如果远大于0(1、需要额定更多CPU资源的虚拟机;2、物理机超卖,多个虚拟机之间在疯狂竞争资源)
第四行(物理内存信息,按E切换换算单位)
total:物理内存总量;
free:目前空闲内存量;
used:目前已使用的内存量;
buffer/cache:目前用作内核缓存的内存量;
第五行(交换区内存信息,按E切换换算单位)
total:交换区内存总量;
free:空闲交换区内存量;
used:目前使用的交换区内存量;
buffer/cache:缓冲的交换区内存量;
第4,5行分别是物理内存与swap交互区的信息,所有程序都运行在内存中,但是当内存的free变少时不用大惊小怪,有使用就会有释放,并不一定代表物理内存不够用了,而swap才是衡量的重要条件,swap是由硬盘提供支撑的,当物理内存不够使用时,操作系统才会把数据临时放到swap中,当swap的used上升严重,则说明物理内存资源枯竭。
第六行(进程信息,按i过滤调所有闲置 或者僵尸进程)
PID:进程ID;
USED:启动该进程的操作用户;
PR:优先级;
NI:nice值,值越小,优先级越高;
VIRT:进程使用的虚拟内存总量,(按E切换换算单位,同下)VIRT=SWAP+RES;
RES:进程使用的未被换出的物理内存。RES=CODE+DATA;
SHR:共享内存大小;
S:进程状态。D=不可中断的睡眠状态,R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程;
%CPU:实时更新,上个更新到现在的CPU时间占用百分比;
%MEM:进程使用的物理内存百分比;
TIME+:进程使用的CPU时间总计,单位1/100秒;
COMMAND:命令名/命令行
1.9.3、kill
终止进程的运行,kill [参数] PID
- -l:不加参数会列出信号全部名称,加参数会显示信号编号,eg:
kill -l kill
,输出9;
杀死指定进程:kill -9 PID
;
高级命令:killall node
,杀死所有的同名进程;
1.9.4、nohub
运行指定进程不受终端关闭&挂断的影响,可以配合&关键词使用(&:表示将该任务放到后台执行)
nohub node httpServer.js &
1.9.5、ps
静态的列出系统当前运行的进程列表;
- -aux:显示所有用户的进程(unix形式);
- -ef:显示所有用户的进程(Linux形式);
- -u:列出当前用户的进程;
- -aux --sort -pcpu:按cpu使用率降序显示;
- -aux --sort -pmem:按内存使用率降序显示;
1.9.6、systemd
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 8月05 ? 00:01:57 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
系统基础服务组件的集合,PID为1,负责启动其他程序(服务),可在/etc/systemd/system/
查看并新建&编辑服务,然后systemctl daemon-reload
,然后启动&重启指定服务;
命令格式:systemctl [command] [serviceName]
- reload:重新加载服务配置文件;
- enable:设置服务开机自启;
- disable:设置服务开机不自启;
- Is-enabled:查看服务是否开机自启;
- systemctl list-units:列出正在运行的units,eg:
systemctl list-units |grep wukong
(筛选所有wukong服务) - systemctl -a:列出所有服务,eg:
systemctl -a | grep wukong |grep dead
(查看死掉的wukong服务)
1.9.7、lsof
多用来查看端口情况,也可以查看当前端口连接数,进程连接;
lsof -i:port
,lsof -i tcp:port
,losf -p pid
[root@VM-165-128-centos ~]# lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 20642 root 22u IPv4 2880945779 0t0 TCP *:http (LISTEN)
node 20661 root 20u IPv4 2949532751 0t0 TCP VM-165-128-centos:http->10.99.17.135:24667 (ESTABLISHED)
1.9.8、netstat
一个监控 TCP / IP 网络的非常有用的工具,它可以显示实际的网络连接以及每一个网络接口设备的状态信息;
查看机器的tcp连接数;
[root@VM-218-88-centos /]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
ESTABLISHED 299
FIN_WAIT2 1
TIME_WAIT 113
查看tcp端口是否被监听:
[root@VM-218-88-centos /]# netstat -tunlp|grep 808
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 12463/node
tcp 0 0 0.0.0.0:8081 0.0.0.0:* LISTEN 10742/node
tcp 0 0 0.0.0.0:8082 0.0.0.0:* LISTEN 10742/node
tcp 0 0 127.0.0.1:8088 0.0.0.0:* LISTEN 16368/webapi
查看端口,协议,PID相关信息:
netstat -a # 显示所有端口
netstat -at # 显示所有tcp端口
netstat -au # 显示所有udp端口
netstat -s # 显示协议(所有端口)的统计信息
netstat -st # 显示tcp协议(所有端口)的统计信息
netstat -su # 显示udp协议(所有端口)的统计信息
- -a:列出所有连线的socket;
- -c:持续动态列出当前网络状态;
- -e:显示网络其他相关信息;
- -l:列出所有listen的socket;
- -p:显示正在运行的程序名称和识别信息;
- -n:直接使用的是IP地址;
- -o:显示计时器;
- -r:显示路由列表;
- -t:显示tcp协议的连线列表;
- -u:显示udp协议的连线列表;
1.10、归档与压缩
1.10.1、tar
压缩打包工具,正常流程是:先使用tar 将多个文件归档为一个总文件(archive),然后再用gzip将archive压缩成更小的文件,但是日常很多操作都是一步到位;
- -xvf:(x解开,x细节展示,f文件)解压缩,-C:解压缩到指定目录;
- -tf:显示归档文件的内容,不解开;
- -cvf:(c创建,x细节展示,f文件)打包,
- -z:归档+压缩;解压gz格式的压缩文件(省略了gzip,gunzip,一步到位)
tar -cvf file.tar file/
:将file文件夹打包归档成file.tar,并展示归档细节
tar -xvf file.tar -C file_new
:将file.tar解压缩至file_new目录中;
如果压缩包本身就为gz格式
tar -zcvf file.tar.gz file/
:将file文件夹打包归档成file.tar.gz,并展示归档细节
tar -zxvf file.tar.gz -C file_new
:将file.tar.gz解压缩至file_new目录中;
(日常多为-z使用,但并没有标注压缩文件后缀.gz,可以使用file命令查看)
少见的.tar.xz格式:
tar -Jcvf name.tar.xz ./
:压缩,tar -Jxvf name.tar.xz
:解压
1.10.2、zip/unzip
- -r:压缩目录(必选),采用递归方式;
- -q:不显示执行过程;
- -d:解压到指定目录;
- -o:覆盖解压
zip -r mydata.zip mydata/
,unzip -q -o mydata.zip -d mydata_new
2、工具篇
2.1、压测工具
2.1.1、wrk
需要先下载源码包编译,然后使用。(可以选择cp到/usr/bin下面)
git clone https://github.com/wg/wrk
cd wrk
make # 需要事先安装gcc依赖
压测说明:
./wrk -t100 -c10 -d20s url
- -c:跟服务器建立并保持的tcp连接数量;
- -d:压测时间;
- -t:使用多少个线程进行压测,即并发值;
- -s:指定lua脚本路径;
- -H:为每一个HTTP请求添加头;
- -v:显示当前wrk详细信息
结果说明:
- Non -2xx or -3xx response:表示报错请求数量;
- 压测的qps计算:(完成请求数 - 报错请求数) / -d