目录 1
1. 前言 5
2. 脚本类工具 5
2.1. 双引号和单引号 5
2.2. 环境变量和变量 5
2.3. sed命令-字符串文本操作 5
2.4. sed和awk使用外部变量 6
2.5. awk给外部变量赋值 6
2.6. 设置shell模式 7
2.7. 设置shell提示 7
2.8. 浮点计算 7
2.9. 变量指定默认值 8
2.10. 确认是否继续 8
2.11. 取当前脚本文件路径 8
2.12. 字符串操作 8
2.12.1. 删除前尾空格 8
2.12.2. 大小写转换 9
2.12.3. 不区分大小写比较 9
2.12.4. 取字符串长度 9
2.12.5. 遍历字符串的每一个字符 9
2.12.6. 判断字符串是否为数字 10
2.12.7. 计算空格数 10
2.12.8. 换行符转成空格 10
2.12.9. 删除首尾空格 10
2.13. eval应用 10
2.14. grep应用 11
2.14.1. 或关系 11
2.14.2. 与关系 12
2.15. ps应用 12
2.15.1. 查看指定进程名的进程ID 12
2.15.2. 查看指定进程名的进程ID和完整命令行 12
2.15.3. 查看指定进程ID的CPU,以下几种都可以(“-o”后跟结果输出格式format) 12
2.15.4. 查看指定进程ID的内存 12
2.15.5. 同时查看指定进程ID的内存百分比和CPU百分比 12
2.15.6. 查看指定进程ID的CPU百分比和虚拟内存(vsz单位为kb) 13
2.15.7. 查看指定进程ID的虚拟内存和物理内存(rss单位为kb) 13
2.16. awk应用 13
2.16.1. 一或多个空格分隔 13
2.16.2. 取得IP和端口号 13
2.16.3. 取指定网卡上的IP地址 13
2.17. 日志滚动工具logrotate 14
3. 设备类工具 14
3.1. 查看网卡型号 15
3.2. dmidecode查看所有硬件信息工具 15
3.3. lscpu查看cpu工具 15
3.4. lspci查看主板工具 15
3.5. lsscsi查看SCSI卡工具 15
4. 系统类工具 15
4.1. umask命令 15
4.2. 修改命令行提示符 16
4.3. 修改登录欢迎或提示语 16
4.4. 查看产品ID 16
4.5. 命令systemctl 16
4.6. 命令journalctl 17
4.7. 重启服务 17
4.8. sar系统综合工具 18
4.9. vmstat系统级内存监测工具 18
4.10. iostat系统级磁盘IO监测工具 18
4.11. iotop进程级磁盘IO监测工具 19
4.12. top和htop 19
4.13. 定时查看CPU 19
4.14. 查看系统中断 19
4.15. 查看网卡中断 19
4.16. 查看中断亲和性 20
4.17. lsof 20
4.18. fuser 20
4.19. free查看内存工具 21
4.20. screen、byobu和tmux分屏工具 21
4.21. dtach 21
4.22. slabtop查看内核slab缓存工具 21
4.23. dmesg检测和控制内核环缓冲工具 21
4.24. dstat可取代vmstat/iostat/netstat/ifstat的工具 21
4.25. MultiTail类似tail的同时监控多个文档工具 22
4.26. Monitorix系统和网络监控工具 22
4.27. collectl全能性能监控工具 22
4.28. percona工具包 23
4.29. 修改用户密码 23
5. 磁盘类工具 23
5.1. fio-磁盘IOPS测试工具 24
5.2. sysbench 25
5.3. sfdisk分区工具 25
5.4. fdisk分区工具 26
5.5. cfdisk分区工具 26
5.6. parted分区工具 26
5.7. gparted分区工具 26
5.8. SCSI工具 26
5.9. RAID工具 26
5.10. hdparm磁盘性能测试工具 26
5.11. mount挂载磁盘工具 26
5.12. mkfs创建文件系统工具 26
5.13. df查看磁盘容量工具 27
5.14. du统计目录和文件大小工具 27
6. 进程类工具 27
6.1. top命令 27
6.2. 获取进程的线程数 27
6.3. pwdx命令-查看工作目录 27
6.4. pidof命令-查看进程ID 27
6.5. nice和ionice优先级调整工具 27
6.6. pstack查看调用栈工具 27
6.7. 查看可执行程序和共享库工具 27
6.8. ps命令 28
6.9. 按CPU使用率排序 28
6.10. 按内存使用率排序 29
6.11. pmap和查看进程内存映射 29
7. 性能类工具 30
7.1. valgrind和qcachegrind内存分析工具 32
7.2. perf性能分析工具 32
7.3. 压力测试工具:ab、tsung、siege 32
8. 网络类工具 33
8.1. netstat和ss命令 33
8.2. ifconfig和ip命令 33
8.3. ifdown和ifup 33
8.4. tcpdump网络抓包工具 33
8.5. ifstat网络流量实时查看工具 36
8.6. iptraf实时IP局域网监控 36
8.7. iftop网络带宽监控 36
8.8. nethogs网络带宽监控 36
8.9. slurm查看网络流量工具 36
8.10. Arpwatch以太网活动监控器 36
8.11. Suricata网络安全监控 36
8.12. Nagios网络/服务器监控 36
8.13. socat多功能的网络工具 36
8.14. mtr网络连通性判断工具 36
8.15. 查看网卡统计 37
8.16. 查看网卡RingBuffer大小 37
8.17. sar查看网络流量 37
8.18. tcpcopy引流 37
9. 开发类工具 37
9.1. 查找符号所在库 38
9.2. 添加预先加载共享库 38
10. /proc文件系统 38
10.1. /proc/meminfo 38
10.2. /proc/cpuinfo 38
10.3. /proc/PID和/proc/PID/maps 38
10.4. /proc/irq/ 38
10.5. /proc/net 39
10.6. /proc/sys/fs 39
10.7. /proc/sys/net 39
10.8. /proc/sys/vm 39
11. 其它 39
11.1. 切换用户执行 40
11.2. hwclock命令 40
11.3. history命令 40
11.4. shell中函数继承问题 40
11.5. 查看Linux各发行版本方法 41
11.6. 取IP地址命令 41
11.7. 清除系统缓存 41
11.8. 查看TCP数据 41
11.9. 查看UDP数据 41
11.10. 查看socket缓冲区默认大小 42
11.11. 查看socket缓冲区最大大小 42
11.12. 找出CPU占用最高的线程 42
11.13. Linux上查找造成IO高负载的进程 42
11.14. iptables简单应用 42
11.15. 配置DNS客户端方法 45
11.16. crontab使用环境变量 45
12. 几种修改Linux主机名的方法 46
12.1. 临时修改主机名 47
12.2. 永久修改主机名 47
12.3. 区别 48
13. process_monitor.sh进程监控重启工具 48
14. 远程批量操作工具 48
14.1. 批量执行命令工具:mooon_ssh 49
14.2. 批量上传文件工具:mooon_upload 50
14.3. 使用示例 50
15. iptables入门 52
本文是个大杂烩,内容为日常点滴的日积月累,持续更新当中,可关注博客(https://blog.csdn.net/Aquester或http://aquester.blog.chinaunix.net),查看最新版本。文中的内容,可帮忙开发提升分析和定位各类问题,比如找出导致IO负载高的进程等,以及一些简单的运维工作等。
单引号内的内容不会被展开,双引号内的内容会被展开。实践如下:
~> A=123 ~> B1="$A" ~> B2='$A' ~> echo $A 123 ~> echo $B1 123 ~> echo $B2 $A |
但如果单引号外有双引号,则规则同双引号,如:
~> B3="'$A'" ~> echo $B3 '123' |
在终端分别执行:
“MOOON_LOG_LEVEL=debug”和“export MOOON_LOG_LEVEL=debug” |
上述两者有何不同了?区别在于前者只对当前进程有效,而后者(环境变量)可以被子进程继承,也就是对子进程也有作用。
另外,环境变量总是键值对,所以值不能是一个shell数组。数组bash等中的概念,而环境变量是Linux等系统中的概念。
如需直接修改文件方式替换,只需sed后带参数“-i”。
sed 's/原字符串/替换字符串/' |
如果想删除换行符,则要这样做,因为sed默认会加换行符:
sed ":a;N;s/\n//g;ta" filename |
sed "s/原字符串包含'/替换字符串包含'/" |
sed 's?原字符串?替换字符串?' |
不同替换间使用分号分开。
x=MM sed 's/AB/'$x'/g' filename 或 sed 's/AB/'"$x"'/g' filename
sed 's/'"$val"'//' filename
awk '{ print "'$x'" }' filename
a=2;b=3;awk -v A=$a -v B=$b 'BEGIN{printf("%d,%d\n",A,B);}' |
假设将值存在文件t中,文件t内容如下,只有一行:
a b c |
需要将a、b和c分别赋给外部变量x、y和z,则脚本可写成如下:
eval $(awk '{ printf("x=%s\ny=%s\nz=%s",$1,$2,$3); }' ./t) echo $x echo $y echo $z |
请注意printf函数中的换行符\n是必须的,起关键作用的是eval命令,它在很多场景有特别的用处。
稍复杂点的示例,对一个表求记录数和某字段汇总,将结果分别赋值给Shell变量a和b:
eval $(mysql -srN -h127.0.0.1 -P3306 -uroot -p'12345678' test -e"SELECT COUNT(1),SUM(f_money) FROM t_test where f_time>='2019-07-18 00:00:00' and f_time<='2019-07-18 23:59:59'" | awk '{printf("a=%s\nb=%s\n",$1,$2);}') echo $a echo $b |
默认的shell是“emacs”模式,如果是一长串的命令,需要修改其中小部分,在命令模式下效率会很低,这个时候可以切换到vi模式:
$ set -o vi |
不带参数执行“set -o”可列出所有支持的模式:
$ set -o |
切换回“emacs”模式:
$ set -o emacs |
Linux的shell提示由环境变量PS1控制:
$ echo $PS1 [\u@\h \w]\$ |
常用参数:
\H |
完整的主机名 |
\h |
主机的第一个名字 |
\w |
完整的工作目录 |
\W |
仅父目录 |
\u |
当前用户名 |
\$ |
提示符,一般约定root的为“#”,普通用户的为“$” |
除此之外,还可设置字体和背景色,颜色格式为“\[\e[F;Bm\]”。其中“F”为Font之意,用于指定字体颜色;“B”为Background之意,用于指定背景颜色。
$ a=2;b=3;echo "scale=2; $a / $b" | bc .66
$ a=2;b=3;echo "scale=2; $a / $b" | bc -l .66 |
$ a=2;b=3;awk 'BEGIN{printf("%.2f\n","'$a'"/"'$b'");}' 0.67 |
REDIS_CLI=${REDIS_CLI:-redis-cli} |
echo -en "Confirm to continue? [yes/no]" read -r -p " " input if test "$input" != "yes"; then exit 1 fi |
“yes”和“no”带上醒目的黄颜色:
echo -en "Confirm to continue? [\033[1;33myes\033[m/\033[1;33mno\033[m]" read -r -p " " input if test "$input" != "yes"; then exit 1 fi |
FILEPATH="$(readlink -f $0)" # 脚本文件完整路径,包括目录和文件名 BASEDIR="$(dirname $FILEPATH)" # 本脚本文件所在目录 SHELLDIR="$(cd $BASEDIR/..&&pwd&&cd ->/dev/null)" # 上一级目录 |
line是一个前尾有空格的字符串:
line=" 123 " echo "A${line}B" line=`echo "$line" | xargs` echo "A${line}B" |
参考来源(BASH官方):
https://www.gnu.org/software/bash/manual/bash.html |
A="aBc" echo $A A="${A,,}" echo $A |
A="aBc" echo $A A="${A^^}" echo $A |
BASH可如下操作:
A1="ab" A2="Ab" shopt -s nocasematch [[ "$A1" = "$A2" ]];echo $? shopt -u nocasematch |
注意,这里不能使用“test "$A1" = "$A2";”,而只能使用语法“[[ "$A1" = "$A2" ]];”。从BASH-4.0开始,也可采用如下语法:
A1="ab" A2="Ab" test "${A1,,}" = "${A2,,}";echo $? |
下面这样也可以:
A1="ab" A2="Ab" [[ "${A1,,}" = "${A2,,}" ]];echo $? |
~> str="abcdef" ~> strlen=${#str} ~> echo $strlen 6 |
顺序遍历字符串的每一个字符(“${str:$i:1}”中的数字1表示取几个字符):
~> str="abcdef" ~> strlen=${#str} ~> echo $strlen 6 ~> for ((i=0; i<$strlen; ++i)) do echo ${str:$i:1}; done a b c d e f |
使用expr,判断expr的返回值,返回值为0表示是数字:
str1="123abc" str2="123000" $(expr $str1 + 0 > /dev/null 2>&1) echo $? $(expr $str2 + 0 > /dev/null 2>&1) echo $? |
echo "$str" | tr -cd ' ' | wc -c |
echo $str | tr '\n' ' ' |
echo "$str" | xargs |
如果变量名是动态的,这个时候就得用上eval命令:
$ C0="012" $ C1="345" $ C2="678" $ i=0 $ j=1 $ k=2
$ echo "\$C$i-\$C$j-\$C$k" # 没加eval时 $C0-$C1-$C2
$ eval "echo "\$C$i-\$C$j-\$C$k"" # 加上eval时,这句也可写成:eval "echo \"\$C$i-\$C$j-\$C$k\"" 012-345-678 |
命令“eval”的作用是再解析,还可以嵌套多层“eval”。
匹配结果包含“abc”或“xyz”的行:
ps aux|grep -E 'abc|xyz' |
使用双引号也可以(一般建议尽量用单引号,因为双引号存在被Shell解释的问题,一些字符需转义):
ps aux|grep -E "abc|xyz" |
如果使用“-e”则这样书写:
ps aux|grep -e "abc" -e "xyz" |
对于“-e”,单引号也可以:
ps aux|grep -e 'abc' -e 'xyz' |
下列这样也可以:
ps aux|grep "abc\|xyz" |
使用egrep也可以:
ps aux|egrep "abc|xyz" |
使用fgrep也可以:
ps aux|fgrep -e"abc" -e"xyz" ps aux|fgrep -e "abc" -e "xyz" ps aux|fgrep -e 'abc' -e 'xyz' |
或关系总结(其中“egrep”等同“grep -E”,而“fgrep”等同“grep -F”):
grep "PATTERN1\|PATTERN2" FILE grep -E "PATTERN1|PATTERN2" FILE grep -e PATTERN1 -e PATTERN2 FILE fgrep -e PATTERN1 -e PATTERN2 FILE egrep "PATTERN1|PATTERN2" FILE |
匹配结果包含“abc”并且包含“xyz”的行:
ps aux|grep "abc.*xyz" |
ps -C redis-server -o pid |
ps -C redis-server -o pid -o comm |
ps --pid=$PID -o %cpu ps -p $PID -o %cpu ps -p $PID -o pcpu ps -q $PID -o %CPU |
如果不想结果中包含输出头(Header),则可加上“h”修饰,如:
ps h -p 18374 -o pcpu |
ps h -p 18374 -o %mem ps h -p 18374 -o pmem |
ps h -p 18374 -o pcpu,pmem ps h -p 18374 -o pcpu -o pmem |
ps h -p 18374 -o pcpu -o vsz ps h -p 18374 -o pcpu -o vsize |
ps h -p 18374 -o vsz,rss ps h -p 18374 -o vsz -o rssize |
多个需要加上星号“*”或加号“+”修饰。
echo "1-2--3---4"|awk -F'-*' '{ printf("A:%s,B:%s,C:%s,D:%s\n", $1,$2,$3,$4); }' echo "1-2--3---4"|awk -F[-]* '{ printf("A:%s,B:%s,C:%s,D:%s\n", $1,$2,$3,$4); }' echo "1-2--3---4"|awk -F'[-]*' '{ printf("A:%s,B:%s,C:%s,D:%s\n", $1,$2,$3,$4); }'
echo "1-2--3---4"|awk -F'-+' '{ printf("A:%s,B:%s,C:%s,D:%s\n", $1,$2,$3,$4); }' echo "1-2--3---4"|awk -F[-]+ '{ printf("A:%s,B:%s,C:%s,D:%s\n", $1,$2,$3,$4); }' echo "1-2--3---4"|awk -F'[-]+' '{ printf("A:%s,B:%s,C:%s,D:%s\n", $1,$2,$3,$4); }' |
注意不能是:
echo "1-2--3---4"|awk -F'[-].*' '{ print $1,$2,$3,$4 }' |
还可如下方式书写(1表示一个):
echo "1-2--3---4"|awk -F'-{1,}' '{ printf("A:%s,B:%s,C:%s,D:%s\n", $1,$2,$3,$4); }' echo "1-2--3---4"|awk -F'[-]{1,}' '{ printf("A:%s,B:%s,C:%s,D:%s\n", $1,$2,$3,$4); }' |
node="127.0.0.1:2019" eval $(echo "$node" | awk -F[\ \:,\;\t]+ '{ printf("ip=%s\nport=%s\n",$1,$2); }') echo $ip echo $port |
ethX=eth1 echo $ethX ip=`netstat -ie|awk -F'[ :]+' 'BEGIN{ok=0;} {if (match($0, "'$ethX'")) ok=1; if ((1==ok) && match($0,"inet")) { ok=0; if (7==NF) printf("%s\n",$3); else printf("%s\n",$4); } }'` echo $ip |
Linux系统自带的日志滚动工具logrotate由两部分组成:一是命令行工具logrotate,二是后台服务rsyslogd。
使用rsyslogd,只需简单的配置即可实现日志滚动。rsyslogd的配置文件为/etc/logrotate.conf,但一般不建议直接修改logrotate.conf,而是在目录/etc/logrotate.d下新增文件的方式。
logrotate.conf会include所有logrotate.d目录下的文件,语法是一致的,区别是logrotate.conf定义了默认的配置,而logrotate.d目录下为专有配置。
下列为redis的配置示例:
# cat /etc/logrotate.d/redis /usr/local/redis/log/redis-6379.log /usr/local/redis/log/redis-6380.log /usr/local/redis/log/redis-6381.log { rotate 2 minsize 100M nocompress missingok create 0664 redis redis notifempty } |
常用配置项说明:
rotate |
指定日志文件备份数,如果值为0表示不备份 |
minsize |
表示日志文件达到多大才滚动 |
nocompress |
表示是否压缩备份的日志文件 |
missingok |
如果日志丢失,不报错继续滚动下一个日志 |
notifempty |
日志文件为空时,不进行轮转,默认值为ifempty |
create |
指定创建新日志文件的属性,logrotate是以root运行的,如果目标日志文件非root运行,则这个一定要指定好 |
lspci | grep -i ethernet |
使用示例:
lspci -vvv lspci -vvv -t |
用来设置文件和目录的默认权限,即使用touch等创建文件,或者使用mkdir 创建目录时的默认权限。
默认值一般是“0002”,如:
$ umask 0022 |
“0022”中的第一个“0”表示为八进制值,“022”对应的二进制值为“000 010 010”,数字“1”为屏蔽意思,即屏蔽对应的权限,权限顺序为“RWX”,即读、写和执行。取反后为“111 101 101”,即八进制值755,因此“umask 0022”等同于“chmod 0755”。
根据掩码值求文件默认权限:跟“6”减即可,比如“0022”对应的为“0644”,“6”对应的二进制值为“110”,即可读写无可执行。
根据掩码值求目录默认权限:跟“7”减即可,比如“0022”对应的为“0755”,“7”对应的二进制值为“111”,即可读写且可执行。
为文件和“6”相减,而目录和“7”相减?因为一般文件默认不需要可执行权限。
如果指定参数“-S”,则表示使用可读的字母表示权限,如:“umask u=rwx”,其中u表示用户自己,g表示用户组,o表示其它。
对于文件,可执行权限掩码总是无效的,即值总是为0,即使指定为1。
环境变量PS1控制命令行提示符,常见内置符号:
\u |
当前用户名 |
\h |
主机名,即hostname |
\w |
当前工作目录 |
在文件/etc/motd中编辑欢迎或提示语即可,motd为“message of today”的缩写。如果是在Linux主机上直接登录,则对应文件/etc/issue。
象Kubernetes要求每个节点的产品ID(product_uuid,亦即Linux的UUID)唯一:
cat /sys/class/dmi/id/product_uuid |
下面只列出了systemctl的部分用法。
systemctl poweroff # 关机 systemctl reboot # 重启 systemctl rescue # 进入单用户模式 systemd-analyze # 查看系统启动时间 loginctl list-users # 列出当前登录用户 loginctl user-status root # 查看用户root的状态 |
systemctl status |
如启动MySQL(这要求在目录/lib/systemd/system下存在文件mysql.service):
systemctl status mysql.service |
比如查看crond的依赖:
systemctl list-dependencies crond.service |
又比如查看sshd的依赖:
systemctl list-dependencies sshd.service |
在systemd出现之前,Linux系统及各应用的日志都是分别管理的,systemd开始统一管理了所有Unit的启动日志,这样可以只用一个journalctl命令,查看所有内核和应用的日志,下面只列出了journalctl命令的小部分用法。
journalctl # 查看所有日志(包括内核和应用日志) journalctl -k # 仅查看内核日志 journalctl -k -o json # 以JSON格式输出日志 journalctl -k -o json --no-pager # 不按页输出(一次性全输出,默认按页输出) journalctl -b # 查看系统本次启动日志,等效于“journalctl -b 0” journalctl -b -1 # 查看系统上一次启动日志 journalctl --disk-usage # 查看日志占用的磁盘大小 journalctl |
journalctl --since "10 min ago" journalctl --since="2019-11-22 19:50:22" journalctl --since yesterday journalctl --since "2019-11-20" --until "2019-11-21 10:00" |
journalctl _PID=`pidof crond` |
journalctl _UID=`id -r -u root` --since today |
不同发行版的Linux,重启服务可能有些区别,这里以CentOS为例重启crontab服务:
service crond restart |
systemctl restart crond |
其中service为老的重启服务方式,而systemctl是新的重启服务方式。service是一个脚本,而systemctl是一个可执行程序。
全称“System Activity Reporter”,即系统活动情况报告,最为全面的系统性能分析工具之一,也可用来查看网络流量。
$ vmstat procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 1397364 3553340 775800 22420964 0 0 0 41 0 0 6 10 84 0 0 |
$ iostat Linux 3.10.1-1-XXX-0041 (UN) 2018年12月12日 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle 6.13 0.01 10.00 0.02 0.00 83.84
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn sdb 0.11 0.11 3.66 3818251 131342429 sda 6.06 1.54 158.24 55370852 5672335360 dm-0 0.00 0.03 0.02 1126394 833860 dm-5 0.00 0.00 0.00 45657 5116 dm-6 0.00 0.00 0.00 45657 5116 dm-1 0.00 0.00 0.00 45658 5110 dm-2 0.00 0.00 0.00 45658 5116 dm-3 0.00 0.00 0.00 46478 5216 dm-4 0.00 0.00 0.00 43486 3369 dm-7 0.00 0.00 0.00 43269 3361 |
参数“-m”指定刷新频率,单位为秒。
iostat输出指标说明:
指标 |
说明 |
%util |
每秒用于I/O操作的时间百分比,100%表示饱和,80%表示有20%的磁盘空间时间,标示了磁盘繁忙程度。 |
tps |
每秒I/O次数 |
await |
平均每次设备I/O操作的等待时间(单位:毫秒) |
svctm |
平均每次设备I/O操作的服务时间(单位:毫秒),值大小和磁盘性能有关。如果值和await接近,表示几乎无I/O等待。如果await远大于svctm,表示I/O队列等待过长。 |
avgrq-sz |
平均每次设备I/O操作的数据大小(扇区) |
avgqu-sz |
平均I/O队列长度,值越小越好 |
wMB/s |
每秒写入的M字节数 |
rMB/s |
每秒读取的M字节数 |
r/s |
每秒完成的读I/O设备次数 |
w/s |
每秒完成的写I/O设备次数 |
rsec/s |
每秒读扇区数 |
wsec/s |
每秒写扇区数 |
rrqm/s |
每秒合并的读I/O,VFS将请求发给FS时,FS会对读取相同块(Block)的请求进行合并。 |
wrqm/s |
每秒合并的写I/O |
htop为top的加强版本。
mpstat -P ALL 1 mpstat -I SUM 1 |
示例(每秒显示一次):
mpstat -P ALL 1 |
cat /proc/interrupts |
grep eth1 /proc/interrupts |awk '{print $NF}' |
cat /proc/irq/74/smp_affinity # 以中断74为例 |
全称“List Open Files”,可用来查看进程打开了哪些文件,也可用来查看一个文件被哪些进程打开了,或者一个端口是哪个进程打开的等。
lsof -i:port,如:lsof -i:80 |
lsof abc.txt |
lsof -c abc |
lsof +d /usr/local/ |
lsof -d 4 |
lsof -u username |
lsof -p 12 |
lsof -i:10888 -r 2 |
ls +r 死循环执行,直到没有结果,如已没有程序占用端口号10888。
和lsof有些类似的功能,可查看文件、文件系统或套接字被哪些进程打开了。使用示例:
fuser -v -n tcp 2019 |
fuser -m -k /tmp/test fuser -m -k -i /tmp/test |
fuser -um /tmp/test |
用来模拟screen的detach的功能的小工具:http://dtach.sourceforge.net/。
$ dstat You did not select any stats, using -cdngy by default. ----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system-- usr sys idl wai hiq siq| read writ| recv send| in out | int csw 4 6 89 0 0 0| 746B 118k| 0 0 | 0 18B| 850 5461 8 9 82 0 0 0| 0 92k| 111k 71k| 0 0 |6888 15k 17 39 44 0 0 0| 0 96k| 107k 62k| 0 0 |7392 19k 2 3 94 0 0 0| 0 484k| 124k 171k| 0 0 |6855 13k |
# dstat -l -m -r -c --top-io --top-mem --top-cpu ---load-avg--- ------memory-usage----- --io/total- ----total-cpu-usage---- ----most-expensive---- --most-expensive- -most-expensive- 1m 5m 15m | used buff cach free| read writ|usr sys idl wai hiq siq| i/o process | memory process | cpu process 0.14 0.14 0.14|2710M 407M 6067M 117G|0.01 3.34 | 0 0 100 0 0 0|process_mon 960k 639B|redis-server 412M|report_proxy 0.0 0.13 0.14 0.14|2710M 407M 6067M 117G| 0 0 | 0 0 100 0 0 0|redis-serve 13k 9360B|redis-server 412M|report_proxy 0.1 0.13 0.14 0.14|2710M 407M 6067M 117G| 0 0 | 0 0 99 0 0 0|process_mon2027k 1986B|redis-server 412M|report_proxy 0.0 0.13 0.14 0.14|2710M 407M 6067M 117G| 0 0 | 0 0 100 0 0 0|sap1002 30k 624B|redis-server 412M|report_proxy 0.1 0.13 0.14 0.14|2710M 407M 6067M 117G| 0 9.00 | 0 0 99 0 0 0|process_mon2024k 1986B|redis-server 412M|report_proxy 0.1 0.13 0.14 0.14|2715M 407M 6067M 117G| 0 28.0 | 0 1 99 0 0 0|redis-serve 38k 4339k|redis-server 412M|report_proxy 0.1 0.68 0.25 0.18|2723M 407M 6067M 117G| 0 5.00 | 1 1 98 0 0 0|crond 13M 180k|redis-server 412M|report_proxy 0.1 |
可以交互式地运行或作为一个守护进程或同时二者兼备地运行,可替代ps、top、iotop和vmstat等,可以作为一个服务来监控远程机或者整个服务器集群。可使用yum或apt-get安装,官网:http://collectl.sourceforge.net/。
collectl
#<--------CPU--------><-----------Disks-----------><-----------Network----------> #cpu sys inter ctxsw KBRead Reads KBWrit Writes netKBi pkt-in netKBo pkt-out 37 37 382 188 0 0 27144 254 45 68 3 21 25 25 366 180 20 4 31280 296 0 1 0 0 25 25 368 183 0 0 31720 275 2 20 0 1 |
collectl -sjmf -oT
# <-------Int--------><-----------Memory-----------><------NFS Totals------> #Time Cpu0 Cpu1 Cpu2 Cpu3 Free Buff Cach Inac Slab Map Reads Writes Meta Comm 08:36:52 1001 66 0 0 2G 201M 609M 363M 219M 106M 0 0 5 0 08:36:53 999 1657 0 0 2G 201M 1G 918M 252M 106M 0 12622 0 2 08:36:54 1001 7488 0 0 1G 201M 1G 1G 286M 106M 0 20147 0 2 |
collectl -sn --verbose -oT
# NETWORK SUMMARY (/sec) # KBIn PktIn SizeIn MultI CmpI ErrIn KBOut PktOut SizeO CmpO ErrOut 08:46:35 3255 41000 81 0 0 0 112015 78837 1454 0 0 08:46:36 0 9 70 0 0 0 29 25 1174 0 0 08:46:37 0 2 70 0 0 0 0 2 134 0 0 |
collectl -sJ -oTm
# Int Cpu0 Cpu1 Cpu2 Cpu3 Type Device(s) 08:52:32.002 225 0 4 0 0 IO-APIC-level ioc0 08:52:32.002 000 1000 0 0 0 IO-APIC-edge timer 08:52:32.002 014 0 0 18 0 IO-APIC-edge ide0 08:52:32.002 090 0 0 0 15461 IO-APIC-level eth1 |
简称PT(Percona Toolkit),可用来监控MySQL、MongoDB等。
pt-pmp -p pid |
pt-visual-explain |
pt-index-usage |
注意如果用户密码过期,则它的Crontab也将失效。
chage -l test |
chage -M -1 test |
echo "test:123456"|chpasswd |
磁盘IOPS测试工具。MAN手册:https://linux.die.net/man/1/fio,源代码:http://freshmeat.sourceforge.net/projects/fio/。
fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=randwrite -ioengine=libaio -bs=4k -size=2G -numjobs=1 -runtime=100 -group_reporting -name=test |
fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=randread -ioengine=libaio -bs=4k -size=2G -numjobs=1 -runtime=100 -group_reporting -name=test |
fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=write -ioengine=libaio -bs=4k -size=2G -numjobs=1 -runtime=100 -group_reporting -name=test |
fio -filename=/dev/sdb -direct=1 -iodepth 16 -thread -rw=read -ioengine=libaio -bs=4k -size=2G -numjobs=1 -runtime=100 -group_reporting -name=test |
主要参数说明:
参数名 |
参数说明 |
filename |
测试文件名称(通常选择需要测试盘的data目录) |
direct |
直接操作磁盘,绕过系统Buffer |
rw |
取值:
|
bs |
单次I/O操作的块大小(假如bs值为4k,rw值为write,表示每次4k顺序写文件) |
rwmixwrite |
在混合读写的模式下写占的百分比,如“--rwmixwrite=20”表示写占20% |
size |
测试的文件大小 |
numjobs |
测试线程数 |
ioengine |
使用的I/O引擎,支持以下几种:
|
group_reporting |
指标显示结果,汇总每个进程的信息 |
runtime |
测试时长(单位:秒) |
nrfiles |
进程生成的文件数 |
zero_buffers |
用0初始化系统Buffer |
lockmem |
限定多少内存用于测试,如:--lockmem=1g |
下载地址:https://github.com/akopytov/sysbench/releases。
一个开源的、模块化的、跨平台的多线程性能测试工具,可以用来进行CPU、内存、磁盘I/O、线程、数据库的性能测试。目前支持的数据库有MySQL、Oracle和PostgreSQL。
示例:测试fsync是否为实时fsync:
sysbench --test=fileio --file-fsync-freq=1 --file-num=1 --file-total-size=16384 --file-test-mode=rndwr prepare sysbench --test=fileio --file-fsync-freq=1 --file-num=1 --file-total-size=16384 --file-test-mode=rndwr run |
运行时,如果遇到警告“Did you forget to run the prepare step”,则表示需要先执行“prepare”。
Python脚本测试:
#!/usr/bin/python # time python fsync.py import os, sys, mmap
# Open a file fd = os.open( "testfile", os.O_RDWR|os.O_CREAT|os.O_DIRECT ) m = mmap.mmap(-1, 512) for i in range (1,1000): os.lseek(fd,os.SEEK_SET,0) m[1] = "1" os.write(fd, m) os.fsync(fd) # Close opened file os.close( fd ) |
示例:列出所有分区
# sfdisk -l |
示例:列出所有分区
# fdisk -l |
具有互动式操作界面的磁盘分区工具,参数-P表示显示分区表的内容,附加参数“s”会依照磁区的顺序显示相关信息。
一个由GNU开发的功能强大的磁盘分区和分区大小调整工具。
parted的图形化版本。
测试磁盘缓存读性能使用示例:hdparm -t /dev/sda(或)hdparm -Tt /dev/sda。
文件/etc/fstab的内容和mount输出是一致的。
挂载一块磁盘之前,需要先创建好文件系统。
以进程ID值为2021为例,两种方法:
根据进程ID,查看指定进程的当前工作目录(注意不是程序文件所在目录),格式:pwdx pid,如pwdx 1。
根据进程名,查看进程的ID,格式:pidof 进程名,如:pidof init。
nice是进程的CPU优先级查看和调整工具,ionice是进程的IO优先级查看和调整工具。
根据进程ID,查看指定进程调用栈的工具,格式:pstack pid。
“ps”为“Process Snapshot”的缩写,使用频繁的用来查看当前进程的快照工具,数据来源于虚拟文件“/proc”,如果输出结果的用户名太长,则会用数字型的用户ID替代。
ps支持三种风格的命令行参数:
三种风格可以混合使用,但可能有冲突,三种风格有些名称相同但含义不同。以查看系统中所有进程为例:
查看进程树:
查看线程:
查看root运行的所有进程:ps -U root -u root u。以指定格式查看:
只显示进程ID为42的进程名:ps -q 42 -o comm=。只syslogd的进程ID:ps -C syslogd -o pid=。
“ps -ef”和“ps -Af”相同,原因是“-e”和“-A”作用相同。如果不想显示标题头,指定“--no-heading”即可。
ps -Ao pcpu,comm,pid,user,uid,tty --sort=-pcpu | head -n 6
说明:
ps -Ao pcpu,comm,pid,user,uid,tty --sort=pcpu | head -n 6
注意,这里是“-pcpu”,不是“pcpu”,前者按高到低排,后者从低到高排,顺序刚好相反。“pcpu”可用“%cpu”替代,效果完全相同。
如果按物理内存排序,用“rss”替代“pcpu”,按虚拟内存排,用“vsz”替代“pcpu”即可。
ps -Ao rss,pcpu,comm,pid,user,uid,tty --sort=-rss| head -n 6
ps -Ao rss,pcpu,comm,pid,user,uid,tty --sort=rss| head -n 6
借助pmap,即可查看指定进程的查看进程的内存映像信息。示例:
[root@centos ~]# pmap -xp 2044 2334: /usr/local/redis/bin/redis-server 0.0.0.0:6380 Address Kbytes RSS Dirty Mode Mapping 0000000000400000 1556 696 0 r-x-- /usr/local/redis-5.0.3/bin/redis-server 0000000000785000 8 8 4 r---- /usr/local/redis-5.0.3/bin/redis-server 0000000000787000 24 24 24 rw--- /usr/local/redis-5.0.3/bin/redis-server 000000000078d000 2200 132 132 rw--- [ anon ] 000000000159b000 132 56 56 rw--- [ anon ] 00007f9ed36d4000 4 0 0 ----- [ anon ] 00007f9ed36d5000 8192 12 12 rw--- [ anon ] 00007f9ed3ed5000 4 0 0 ----- [ anon ] 00007f9ed3ed6000 8192 12 12 rw--- [ anon ] 00007f9ed46d6000 4 0 0 ----- [ anon ] 00007f9ed46d7000 8192 12 12 rw--- [ anon ] 00007f9ed4ed7000 103588 0 0 r---- /usr/lib/locale/locale-archive 00007f9edb400000 8192 868 868 rw--- [ anon ] 00007f9edbcd3000 1756 520 0 r-x-- /usr/lib64/libc-2.17.so 00007f9edbe8a000 2044 0 0 ----- /usr/lib64/libc-2.17.so 00007f9edc089000 16 16 16 r---- /usr/lib64/libc-2.17.so 00007f9edc08d000 8 8 8 rw--- /usr/lib64/libc-2.17.so 00007f9edc08f000 20 12 12 rw--- [ anon ] 00007f9edc094000 92 68 0 r-x-- /usr/lib64/libpthread-2.17.so 00007f9edc0ab000 2044 0 0 ----- /usr/lib64/libpthread-2.17.so 00007f9edc2aa000 4 4 4 r---- /usr/lib64/libpthread-2.17.so 00007f9edc2ab000 4 4 4 rw--- /usr/lib64/libpthread-2.17.so 00007f9edc2ac000 16 4 4 rw--- [ anon ] 00007f9edc2b0000 28 4 0 r-x-- /usr/lib64/librt-2.17.so 00007f9edc2b7000 2044 0 0 ----- /usr/lib64/librt-2.17.so 00007f9edc4b6000 4 4 4 r---- /usr/lib64/librt-2.17.so 00007f9edc4b7000 4 4 4 rw--- /usr/lib64/librt-2.17.so 00007f9edc4b8000 8 4 0 r-x-- /usr/lib64/libdl-2.17.so 00007f9edc4ba000 2048 0 0 ----- /usr/lib64/libdl-2.17.so 00007f9edc6ba000 4 4 4 r---- /usr/lib64/libdl-2.17.so 00007f9edc6bb000 4 4 4 rw--- /usr/lib64/libdl-2.17.so 00007f9edc6bc000 1024 8 0 r-x-- /usr/lib64/libm-2.17.so 00007f9edc7bc000 2048 0 0 ----- /usr/lib64/libm-2.17.so 00007f9edc9bc000 4 4 4 r---- /usr/lib64/libm-2.17.so 00007f9edc9bd000 4 4 4 rw--- /usr/lib64/libm-2.17.so 00007f9edc9be000 128 36 0 r-x-- /usr/lib64/ld-2.17.so 00007f9edcbcf000 20 20 20 rw--- [ anon ] 00007f9edcbdc000 4 4 4 rw--- [ anon ] 00007f9edcbdd000 4 4 4 r---- /usr/lib64/ld-2.17.so 00007f9edcbde000 4 4 4 rw--- /usr/lib64/ld-2.17.so 00007f9edcbdf000 4 4 4 rw--- [ anon ] 00007fffc7af3000 132 16 16 rw--- [ stack ] 00007fffc7b1f000 8 4 0 r-x-- [ anon ] ffffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------- ------- ------- total kB 153824 2588 1244 |
除了使用pmap,还可如下方式:
[root@centos ~]# cat /proc/2334/maps 00400000-00585000 r-xp 00000000 fd:01 287120 /usr/local/redis-5.0.3/bin/redis-server 00785000-00787000 r--p 00185000 fd:01 287120 /usr/local/redis-5.0.3/bin/redis-server 00787000-0078d000 rw-p 00187000 fd:01 287120 /usr/local/redis-5.0.3/bin/redis-server 0078d000-009b3000 rw-p 00000000 00:00 0 0159b000-015bc000 rw-p 00000000 00:00 0 [heap] 7f9ed36d4000-7f9ed36d5000 ---p 00000000 00:00 0 7f9ed36d5000-7f9ed3ed5000 rw-p 00000000 00:00 0 [stack:2343] 7f9ed3ed5000-7f9ed3ed6000 ---p 00000000 00:00 0 7f9ed3ed6000-7f9ed46d6000 rw-p 00000000 00:00 0 [stack:2342] 7f9ed46d6000-7f9ed46d7000 ---p 00000000 00:00 0 7f9ed46d7000-7f9ed4ed7000 rw-p 00000000 00:00 0 [stack:2341] 7f9ed4ed7000-7f9edb400000 r--p 00000000 fd:01 125493 /usr/lib/locale/locale-archive 7f9edb400000-7f9edbc00000 rw-p 00000000 00:00 0 7f9edbcd3000-7f9edbe8a000 r-xp 00000000 fd:01 98905 /usr/lib64/libc-2.17.so 7f9edbe8a000-7f9edc089000 ---p 001b7000 fd:01 98905 /usr/lib64/libc-2.17.so 7f9edc089000-7f9edc08d000 r--p 001b6000 fd:01 98905 /usr/lib64/libc-2.17.so 7f9edc08d000-7f9edc08f000 rw-p 001ba000 fd:01 98905 /usr/lib64/libc-2.17.so 7f9edc08f000-7f9edc094000 rw-p 00000000 00:00 0 7f9edc094000-7f9edc0ab000 r-xp 00000000 fd:01 98931 /usr/lib64/libpthread-2.17.so 7f9edc0ab000-7f9edc2aa000 ---p 00017000 fd:01 98931 /usr/lib64/libpthread-2.17.so 7f9edc2aa000-7f9edc2ab000 r--p 00016000 fd:01 98931 /usr/lib64/libpthread-2.17.so 7f9edc2ab000-7f9edc2ac000 rw-p 00017000 fd:01 98931 /usr/lib64/libpthread-2.17.so 7f9edc2ac000-7f9edc2b0000 rw-p 00000000 00:00 0 7f9edc2b0000-7f9edc2b7000 r-xp 00000000 fd:01 98935 /usr/lib64/librt-2.17.so 7f9edc2b7000-7f9edc4b6000 ---p 00007000 fd:01 98935 /usr/lib64/librt-2.17.so 7f9edc4b6000-7f9edc4b7000 r--p 00006000 fd:01 98935 /usr/lib64/librt-2.17.so 7f9edc4b7000-7f9edc4b8000 rw-p 00007000 fd:01 98935 /usr/lib64/librt-2.17.so 7f9edc4b8000-7f9edc4ba000 r-xp 00000000 fd:01 98911 /usr/lib64/libdl-2.17.so 7f9edc4ba000-7f9edc6ba000 ---p 00002000 fd:01 98911 /usr/lib64/libdl-2.17.so 7f9edc6ba000-7f9edc6bb000 r--p 00002000 fd:01 98911 /usr/lib64/libdl-2.17.so 7f9edc6bb000-7f9edc6bc000 rw-p 00003000 fd:01 98911 /usr/lib64/libdl-2.17.so 7f9edc6bc000-7f9edc7bc000 r-xp 00000000 fd:01 98913 /usr/lib64/libm-2.17.so 7f9edc7bc000-7f9edc9bc000 ---p 00100000 fd:01 98913 /usr/lib64/libm-2.17.so 7f9edc9bc000-7f9edc9bd000 r--p 00100000 fd:01 98913 /usr/lib64/libm-2.17.so 7f9edc9bd000-7f9edc9be000 rw-p 00101000 fd:01 98913 /usr/lib64/libm-2.17.so 7f9edc9be000-7f9edc9de000 r-xp 00000000 fd:01 98898 /usr/lib64/ld-2.17.so 7f9edcbcf000-7f9edcbd4000 rw-p 00000000 00:00 0 7f9edcbdc000-7f9edcbdd000 rw-p 00000000 00:00 0 7f9edcbdd000-7f9edcbde000 r--p 0001f000 fd:01 98898 /usr/lib64/ld-2.17.so 7f9edcbde000-7f9edcbdf000 rw-p 00020000 fd:01 98898 /usr/lib64/ld-2.17.so 7f9edcbdf000-7f9edcbe0000 rw-p 00000000 00:00 0 7fffc7af3000-7fffc7b14000 rw-p 00000000 00:00 0 [stack] 7fffc7b1f000-7fffc7b21000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] |
开源的内存分析和性能分析工具。qcachegrind是一个valgrind辅助工具,可视化方式查看valgrind性能分析结果。
Linux自带的功能强大的性能分析工具,可结合火焰图。使用方式,如:perf top -p pid。自带了生成SVG格式的图形化工具timechart,也可结合FlameGraph生成火焰图。。
记录进程一段时间性能统计信息:
perf record -p pid -g -e event -o logfile perf report -i logfile |
ss是一个可以替代netstat的网络连接查看工具(socket statistics)。
示例1:查看TCP监听
netstat -lpnt |
示例1:查看TCP连接
netstat -lpna |
ip是一个可以替代ifconfig和route等的网络管理工具,为iproute2套件中的一员,而ifconfig是net-tools中已被废弃使用的一个命令,许多年前就已经没有维护了。
ip addr add 192.168.31.13/24 dev eth1 |
ip addr show eth1 |
ip addr del 192.168.31.13/24 dev eth1 |
ip route show |
ifdown和ifup实际是基于ifconfig的Shell脚本,可用ifdown禁用指定网卡,如“ifdown eth1”,而ifup则相反,用于启用指定网卡。
参数“-s”指定显示多少字节的包内容,-x表示仅以十六进制输出,-X表示同时以十六进制和文本方式输出,-e表示输出链接级别的头,-w指定结果写入文件。
tcpdump -i eth1 -n -vv -x -e -s 600 # 仅二进制 tcpdump -i eth1 -n -vv -X -e -s 600 # 二进制和文本 |
tcpdump -i eth1 -n -vv -X -e -s 600 -w x.cap |
tcpdump -i eth1 host 192.168.31.1 and port 80 |
tcpdump -i eth1 dst host 192.168.31.1 and dst port 80 |
tcpdump -i eth1 |
tcpdump udp port 10888 |
tcpdump tcp port 80 |
tcpdump host A and \(B or C \) # tcpdump host 127.0.0.1 and \(127.0.0.1 or 110.240.110.18 \) |
tcpdump ip A and not B |
tcpdump -i eth1 src host A |
tcpdump -i eth1 dst host B |
tcpdump tcp port 80 and host A |
tcpdump -D |
tcpdump -i any |
tcpdump -v |
更详细可以使用“tcpdump -vv”和“tcpdump -vvv”。
tcpdump -v -X |
tcpdump -v -XX |
tcpdump -c 100 |
tcpdump -w filename.log |
tcpdump -n |
tcpdump -s 500 |
如果要捕获所有字节则为:tcpdump -s 0。
tcpdump -n "broadcast or multicast" |
tcpdump -v "icmp or arp" |
tcpdump -v arp |
tcpdump -n "dst host 192.168.0.1 and (dst port 80 or dst port 443)" |
tcpdump -n udp dst portrange 1-1023 |
tcpdump dst port 23 |
tcpdump -n dst net 192.168.1.0/24 |
tcpdump -n src net 192.168.1.0/24 |
$ ifstat #kernel Interface RX Pkts/Rate TX Pkts/Rate RX Data/Rate TX Data/Rate RX Errs/Drop TX Errs/Drop RX Over/Rate TX Coll/Rate lo 8546 0 8546 0 11845K 0 11845K 0 0 0 0 0 0 0 0 0 eth1 93020 0 41717 0 8867K 0 5969K 0 0 0 0 0 0 0 0 0 |
按对端IP查看网络流量。
按进程查看网络流量:https://github.com/raboof/nethogs/releases。
全称“Socket CAT”,为netcat的加强版。
集成了traceroute和ping。
ethtool -S eth1 |
ethtool -g eth1 |
sar -n DEV 1 # 流量信息 sar -n EDEV 1 # 错误信息 sar -u 2 5 # 每2秒报告CPU使用率,共显示5行(次) sar -I 14 -o int14.file 2 10 每2秒报告14号中断,共显示10行(次),结果写入文件int14.file sar -f /var/log/sa/sa16 显示内存和网络统计,结果写入文件/var/log/sa/sa16 sar -A 显示所有统计 |
可使用tcpcopy工具将线上环境的流量引入到测试环境中,以将机器10.24.110.21的5000端口流量引流到机器10.23.25.11的5000端口为例:
tcpcopy -x 4077-10.23.25.11:5000 -s 10.23.25.12 -c 192.168.100.x -n 1 |
route add -net 192.168.100.0 netmask 255.255.255.0 gw 10.23.25.12 |
intercept -i eth1 -F tcp and src port 5000 |
因为TCP连接是有回包的,所以需要辅助机器帮助接收回包,一般是直接丢弃掉。
以查找符号“__libc_csu_init”所在库为例:
files=`ls /lib64/*.a`;for file in $files; do echo $file; nm $file | grep "__libc_csu_init"; done |
只需将需要预先加载的库添加到文件/etc/ld.so.preload即可,一行一个文件,如:
# cat /etc/ld.so.preload /lib64/libonion.so |
有关/proc的内容很庞大,系统监控需要从这里读取大量数据,这里逐步记录一些常用到的。
内存大小和使用信息。
CPU个数和频率等CPU信息。
进程的各种信息,其中PID为进程ID,假设进程ID为2019,则路径为“/proc/2019”。一个进程所创建和打开的文件描述符,全在/proc/PID/fd下,以Linux的init进程为例:
# ls /proc/1/fd 0 1 10 11 12 13 14 15 16 17 2 20 21 22 24 25 26 27 28 29 3 30 31 32 33 34 37 38 39 4 5 6 7 8 9 |
包括进程的命令行参数等均可以这个目录下得到,“cat /proc/PID/maps”可查看进程的内存映射。
该目录下存放的是以IRQ号命名的目录,如/proc/irq/40/表示中断号为40的相关信息。
该文件存放的是CPU位掩码(十六进制),修改该文件中的值可以改变CPU和某中断的亲和性。
该文件存放的是CPU列表(十进制),注意CPU核心个数用表示编号从0开始,如cpu0和cpu1等。
网络相关的:
可用来统计网卡流量。
文件系统相关:
网络相关:
内存相关:
使用场景:使用root创建好用户,然后切换到该用户执行,比如安装crontab监控。有两种方式:
su - zhangsan -c whoami su - zhangsan -c ps |
# runuser -u zhangsan whoami # runuser -u zhangsan ps |
如果发现启动时系统日志文件/var/log/messages中的初始启动时间不对,可能是因为/etc/adjtime设置问题,比如:
# cat /etc/adjtime 0.000000 1574671762 0.000000 1574671762 LOCAL |
可将LOCAL改成UTC解决时间问题:
# cat /etc/adjtime 0.000000 1574671762 0.000000 1574671762 UTC |
可通过执行命令“hwclock --systohc --utc”设置,如需改回LOCAL,执行“hwclock --systohc --localtime”即可。
一般/etc/profile文件中定义了history最多可显示的历史记录数,控制变量名为HISTSIZE。如果只是想history过滤某些命令,可通过设置变量HISTIGNORE来实现,比如:
export HISTIGNORE="*mooon_ssh*:*mooon_upload*:*mooon_download*" |
如果全局设置,可写入文件/etc/profile,不过一般不建议修改/etc/profile,而改为在目录/etc/profile.d下新建一个文件方式。
我们知道变量是会被子进程继承的,可以直接使用。有些情况下可能需要继承函数,以方便透明使用,方法非常简单,使用“export -f”,注意参数“-f”,它表示函数的意思,不带参数的export只针对变量。
function ifprop() { echo ":$1=$2" } export -f ifprop |
也可以使用“typeset -fx”替代“export -f”。
基本上各发行版本均在/etc目录下有个后缀为“-release”的文件,该文件即存储了发行版本的版本号信息,如:
cat /etc/SuSE-release |
cat /etc/slackware-version |
cat /etc/redhat-release |
netstat -ie|awk /broadcast/'{print $2}' netstat -ie|awk -F '[ :]+' /cast/'{print $4}' netstat -ie|awk -F '[ :]+' /cast/'{print $3}' |
echo 3 > /proc/sys/vm/drop_caches |
测试请参见:http://blog.chinaunix.net/uid-20682147-id-4209165.html。
cat /proc/net/tcp |
cat /proc/net/udp |
cat /proc/sys/net/core/rmem_default |
cat /proc/sys/net/core/rmem_max |
ps -mp 20693 -o THREAD,tid,time | sort -rn |
这是一个python脚本工具,使用方法如:iotop -o |
使用dmesg之前,需要先开启内核的IO监控:
echo 1 >/proc/sys/vm/block_dump或sysctl vm.block_dump=1 |
然后可以使用如下命令查看IO最重的前10个进程:
dmesg |awk -F: '{print $1}'|sort|uniq -c|sort -rn|head -n 10 |
# iostat -x 1 3 avg-cpu: %user %nice %system %iowait %steal %idle 1.06 0.00 0.99 1.09 0.00 97.85
Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util sda 0.49 17.29 1.74 6.75 23.47 200.18 11.73 100.09 26.33 0.10 12.25 5.73 4.87 |
找“await”值最大的设备(Device),如上的结果即为sda。然后使用mount找到sda挂载点,再使用fuser命令查看哪些进程在访问,如:
# fuser -vm /data |
iptables命令操作只对当前登录有效,如果需重启后也有效,可将操作放到/etc/rc.d/boot.local中,如:
/sbin/iptables -F /sbin/iptables -A INPUT -i eth0 -p tcp --sport 80 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp -j DROP /sbin/iptables -A INPUT -i eth0 -p udp -j DROP |
iptables是一个链的方式从前往后判断,如果前面的规则成立就不会往后继续,所以要注意顺序,每行对应一条规则。
参数“-A”是Append意思,也就是追加;参数“-I”是Insert意思,也就是插入;参数“-F”是Flush意思,表示清除(即删除)掉已有规则,也就是清空。
查看已有的规则,执行命令:
iptables -L -n |
带行号显示结果(DEL操作需要指定行号):
# iptables -L -n --line-number Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:443 2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:443 3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:443 4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:443 6 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8000 7 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:443 8 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 9 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 10 DROP udp -- 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT) num target prot opt source destination
Chain OUTPUT (policy ACCEPT) num target prot opt source destination |
从上可以看到,iptables有三种规则链(Chain):
参数“-I”和参数“-A”需要指定链(Chain)名,其中“-I”的链名后还需要指定第几条(行)规则。
可通过“-D”参数删除规则,有两种删除方式,一是匹配模式,二是指定第几条(行)。也可以通过“-R”参数修改已有规则,另外“-L”参数后也可以跟链(Chain)名,表示只列出指定链的所有规则。“-j”参数后跟的是动作,即满足规则时执行的操作,可以为ACCEPT、DROP、REJECT和REDIRECT等。
在iptables的INPUT链的第一行插入一条规则(可访问其它机器的80端口):
iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT |
在iptables的INPUT链尾追加一条规则(可访问其它机器的80端口):
iptables -A INPUT -p tcp --sport 80 -j ACCEPT |
如果要让其它机器可以访问本机的80端口,则为:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT |
插入前:
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0 |
插入:
# iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT |
插入后:
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0 |
追加前:
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0 |
追加:
# iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT |
追加后(ACCEPT将不能生效):
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 |
删除INPUT的第3条(即第3行,执行“iptables -L INPUT --line-numbers”显示行号)规则:
iptables -D INPUT 3 |
配置DNS客户端的方法非常简单,需要修改两个文件:
在这个文件里增加DNS服务器的IP地址,格式为:nameserver DNS服务器IP地址
如:
nameserver 192.168.1.46 |
可以有多行nameserver,如:
nameserver 192.168.1.46 nameserver 219.133.38.2 nameserver 219.133.38.3 |
在这个文件中增加如下内容即可:
hosts: files dns networks: files dns |
现在即可ping域名了,如:ping www.hadoopor.com。当然在ping之前要保证该机器是可以正常连接到DNS服务器的,DNS服务器的默认端口号为53,可以通过telnet命令来测试是否能够连接到DNS服务器,如:telnet 192.168.1.46 53。
有两种方式在crontab中定义变量:
A=123 * * * * * echo $A > /tmp/a.txt |
注意在定义变量时不能使用$引用其它变量,如下面的做法错误:
A=123 B=$A |
此文件定义变量的格式为:
NAME=VALUE |
同crontab,也不能使用$引用其它变量。操作系统在登录时使用的第一个文件是/etc/environment文件,/etc/environment文件包含指定所有进程的基本环境的变量。
千万注意,不要有“PATH=$PATH:/usr/local/jdk/bin”这样的用法,这将导致系统无法启动。
小技巧:想保持多台机器的crontab一致,但变量值不完全相同,这个时候可以考虑将变量配置在/etc/environment中,这样crontab就可以相同了。
如机器1:
A=123 |
机器2:
A=456 |
两者的crontab配置:
* * * * * echo "$A" > /x.txt |
一般不建议直接修改/etc/environment,而可采取在目录/etc/profile.d下新增一个.sh文件方式替代。但如果想crontab中生效,则只能修改/etc/environment,经测试/etc/profile.d方式不起作用。
另外注意在/etc/environment设置的变量,在shell中并不生效,但对crontab有效。
在安装一些系统时,需要修改hostname,比如安装Hadoop时需要修改主机名,而且主机名不能包含下划线。
实际上,主机名分三种(命令hostnamectl或hostnamectl status可查看三种主机名):
当三种主机名相同时,“hostnamectl status”只会显示“static”主机名,三种主机名的设置方法:
hostnamectl --pretty set-hostname NAME hostnamectl --static set-hostname NAME hostnamectl --transient set-hostname NAME |
|
hostnamectl修改的主机名,在系统重启之前会一直有效,而hostname只对当次有效。如果不指定参数,则一次设置三种主机名:
hostnamectl set-hostname NAME |
命令hostname不但可以查看主机名,还可以用它来修改主机名,格式为:hostname 新主机名。
在修改之前9.4.149.11对应的主机名为hadoop_10202,而9.4.149.6对应的主机名为hadoop_10203。两者的主机名均带有下划线,因此需要修改。为求简单,仅将原下划线去掉:
hostname hadoop10202
hostname hadoop10203
经过上述修改后,类似于修改环境变量,只临时有效,还需要修改相应的系统配置文件,以永久有效。
不同的Linux发行版本,对应的系统配置文件可能不同,SuSE 10.1是/etc/HOSTNAME:
# cat /etc/HOSTNAME hadoop_10202 |
将文件中的“hadoop_10202”,改成“hadoop10202”。有些Linux发行版本对应的可能是/etc/hostname文件,有些如CentOS和RedHat同时有/etc/hostname和/etc/sysconfig/network两个文件,修改/etc/hostname即可。
需注意:/etc/sysconfig/network的格式和/etc/hostname、/etc/HOSTNAME不同,为:
HOSTNAME=主机名 |
修改之后,需要重启网卡,以使修改生效,执行命令:/etc/rc.d/boot.localnet start(不同系统命令会有差异,这是SuSE上的方法,其它一些可能为:/etc/init.d/network restart或service network restart等),再次使用hostname查看,会发现主机名变了。
上述方法如果不能永久有效,则可使用hostnamectl修改来修改永久有效。如果还是不行,则可重启系统以使永久有效。
可以通过以下多种方法查看主机名:
批量修改/etc/hostname工具(其它可参照):
https://github.com/eyjian/libmooon/blob/master/shell/set_hostname.sh |
方法 |
效果 |
hostname |
当次登录临时有效,新登录或重新登录后无效 |
hostnamectl |
系统重启之前一直有效,重启后无效 |
/etc/hostname |
只有在系统重启后才有效 |
使用process_monitor.sh监控进程,当进程挂掉后,能够在两三秒内将进程重拉起,并且支持同一程序以不同参数启动多个实例,和不同用户以相同参数启动多个实例。
下载:https://github.com/eyjian/libmooon/blob/master/shell/process_monitor.sh。
一般建议将process_monitor.sh放在/usr/local/bin目录下,并设置好可执行权限,放在crontab中运行。
* * * * * /usr/local/bin/process_monitor.sh "/data/redis/bin/redis-server 6379" "/data/redis/bin/redis-server /data/redis/conf/redis-6379.conf" * * * * * /usr/local/bin/process_monitor.sh "/data/redis/bin/redis-server 6380" "/data/redis/bin/redis-server /data/redis/conf/redis-6380.conf" |
* * * * * /usr/local/bin/process_monitor.sh "/usr/local/jdk/bin/java -Dzookeeper" "/data/zookeeper/bin/zkServer.sh start" |
process_monitor.sh启动后,会在/tmp目录下创建以“/process_monitor-”打头的日志文件,假设root用户运行process_monitor.sh,则日志全路径为:/tmp/process_monitor-root.log。
远程批量工具包含:
可执行二进制包下载地址:
https://github.com/eyjian/libmooon/releases
源代码包下载地址:
https://github.com/eyjian/libmooon/archive/master.zip
批量工具除由三个工具组成外,还分两个版本:
当前C++版本比较成熟,GO版本相当简略,但C++版本依赖C++运行时库,不同环境需要特定编译,而GO版本可不依赖C和C++运行时库,所以不需编译即可应用到广泛的Linux环境。
使用简单,直接执行命令,即会提示用法,如C++版本:
$ mooon_ssh parameter[-c]'s value not set
usage: -h[]: Connect to the remote machines on the given hosts separated by comma, can be replaced by environment variable 'H', example: -h='192.168.1.10,192.168.1.11' -P[36000/10,65535]: Specifies the port to connect to on the remote machines, can be replaced by environment variable 'PORT' -u[]: Specifies the user to log in as on the remote machines, can be replaced by environment variable 'U' -p[]: The password to use when connecting to the remote machines, can be replaced by environment variable 'P' -t[60/1,65535]: The number of seconds before connection timeout -c[]: The command is executed on the remote machines, example: -c='grep ERROR /tmp/*.log' -v[1/0,2]: Verbosity, how much troubleshooting info to print |
参数名 |
默认值 |
说明 |
-u |
无 |
用户名参数,可用环境变量U替代 |
-p |
无 |
密码参数,可用环境变量P替代 |
-h |
无 |
IP列表参数,可用环境变量H替代 |
-P |
22,可修改源码,编译为常用端口号 |
SSH端口参数,可用环境变量PORT替代 |
-c |
无 |
在远程机器上执行的命令,建议单引号方式指定值,除非要执行的命令本身已经包含了单引号有冲突。使用双引号时,要注意转义,否则会被本地shell解释 |
-v |
1 |
工具输出的详细度 |
-thr |
1 |
线程数,当线程数大于2时,并发执行;如果值为0,表示线程数和IP数相同 |
参数名 |
默认值 |
说明 |
-u |
无 |
用户名参数,可用环境变量U替代 |
-p |
无 |
密码参数,可用环境变量P替代 |
-h |
无 |
IP列表参数,可用环境变量H替代 |
-P |
22,可修改源码,编译为常用端口号 |
SSH端口参数,可用环境变量PORT替代 |
-s |
无 |
以逗号分隔的,需要上传的本地文件列表,可以带相对或绝对目录 |
-d |
无 |
文件上传到远程机器的目录,只能为单个目录 |
-thr |
1 |
线程数,当线程数大于2时,并发执行;如果值为0,表示线程数和IP数相同 |
mooon_upload -s=/etc/hosts -d=/etc |
mooon_ssh -c='md5sum /etc/hosts' |
mooon_ssh -c='crontab -l' |
mooon_ssh -c='rm -f /tmp/crontab.empty;touch /tmp/crontab.empty' mooon_ssh -c='crontab /tmp/crontab.emtpy' |
mooon_ssh -c='crontab /tmp/crontab.online' |
因为awk用单引号,所以参数“-c”的值不能使用单引号,所以内容需要转义,相对其它来说要复杂点:
mooon_ssh -c="netstat -ie | awk -F[\\ :]+ 'BEGIN{ok=0;}{if (match(\$0, \"eth1\")) ok=1; if ((1==ok) && match(\$0,\"inet\")) { ok=0; if (7==NF) printf(\"%s\\n\",\$3); else printf(\"%s\\n\",\$4);} }'" |
不同的环境,IP在“netstat -ie”输出中的位置稍有不同,所以awk中加了“7==NF”判断,但仍不一定适用于所有的环境。需要转义的字符包含:双引号、美元符和斜杠。
$ export H=192.168.31.9,192.168.31.10,192.168.31.11,192.168.31.12,192.168.31.13 $ export U=kafka $ export P='123456'
$ mooon_ssh -c='/usr/local/jdk/bin/jps -m' [192.168.31.15] 50928 Kafka /data/kafka/config/server.properties 125735 Jps -m [192.168.31.15] SUCCESS
[192.168.31.16] 147842 Jps -m 174902 Kafka /data/kafka/config/server.properties [192.168.31.16] SUCCESS
[192.168.31.17] 51409 Kafka /data/kafka/config/server.properties 178771 Jps -m [192.168.31.17] SUCCESS
[192.168.31.18] 73568 Jps -m 62314 Kafka /data/kafka/config/server.properties [192.168.31.18] SUCCESS
[192.168.31.19] 123908 Jps -m 182845 Kafka /data/kafka/config/server.properties [192.168.31.19] SUCCESS
================================ [192.168.31.15 SUCCESS] 0 seconds [192.168.31.16 SUCCESS] 0 seconds [192.168.31.17 SUCCESS] 0 seconds [192.168.31.18 SUCCESS] 0 seconds [192.168.31.19 SUCCESS] 0 seconds SUCCESS: 5, FAILURE: 0 |
$ mooon_ssh -c='/data/kafka/bin/kafka-server-stop.sh' -u=kafka -p='123456' -h=192.168.31.15,192.168.31.16,192.168.31.17,192.168.31.18,192.168.31.19 [192.168.31.15] No kafka server to stop command return 1
[192.168.31.16] No kafka server to stop command return 1
[192.168.31.17] No kafka server to stop command return 1
[192.168.31.18] No kafka server to stop command return 1
[192.168.31.19] No kafka server to stop command return 1
================================ [192.168.31.15 FAILURE] 0 seconds [192.168.31.16 FAILURE] 0 seconds [192.168.31.17 FAILURE] 0 seconds [192.168.31.18 FAILURE] 0 seconds [192.168.31.19 FAILURE] 0 seconds SUCCESS: 0, FAILURE: 5 |
可修改/etc/rc.d/boot.local让iptables操作在系统重启后也生效,如:
/sbin/iptables -F /sbin/iptables -A INPUT -i eth0 -p tcp --sport 80 -j ACCEPT /sbin/iptables -A INPUT -i eth0 -p tcp -j DROP /sbin/iptables -A INPUT -i eth0 -p udp -j DROP |
iptables是一个链的方式从前往后判断,如果前面的规则成立就不会往后继续,所以要注意顺序,一般每行对应一条规则。
-A是Append意思,也就是追加 -I是Insert意思,也就是插入 -F表示清除(即删除)掉已有规则,也就是清空 |
查看已有的规则,执行命令:
iptables -L -n # 或 iptables -L -n --line-numbers |
如(参数-L为list意思,-n表示以数字方式显示IP和端口,不指定-n则显示为名称,如:http即80端口):
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:443 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT) target prot opt source destination
Chain OUTPUT (policy ACCEPT) target prot opt source destination |
从可以看到:iptables有三种规则链(Chain),即INPUT、OUTPUT和FORWARD。
-I和-A需要指定链(Chain)名,其中-I的链名后还需要指定第几条(行)规则。
可通过-D参数删除规则,有两种删除方式,一是匹配模式,二是指定第几条(行)。
也可以通过-R参数修改已有规则,另外-L参数后也可以跟链(Chain)名,表示只列出指定链的所有规则。
-j参数后跟的是动作,即满足规则时执行的操作,可以为ACCEPT、DROP、REJECT和REDIRECT等。
在iptables的INPUT链的第一行插入一条规则(可访问其它机器的80端口):
iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT |
在iptables的INPUT链尾追加一条规则(可访问其它机器的80端口):
iptables -A INPUT -p tcp --sport 80 -j ACCEPT |
在iptables的INPUT链的最前插入一条规则:
# iptables -I INPUT -s 10.125.32.45 -j DROP # 等同 iptables -I INPUT 1 -s 10.125.32.45 -j DROP # iptables -L INPUT --line-numbers Chain INPUT (policy ACCEPT) num target prot opt source destination 1 DROP all -- 10.125.32.45 anywhere 2 DROP all -- 10.125.32.44 anywhere |
如果要让其它机器可以访问本机的80端口,则为:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT |
插入前:
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0 |
插入:
# iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT |
插入后:
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0 |
追加前:
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0 |
追加:
# iptables -I INPUT 1 -p tcp --sport 80 -j ACCEPT |
追加后(ACCEPT将不能生效):
# iptables -L -n Chain INPUT (policy ACCEPT) target prot opt source destination DROP tcp -- 0.0.0.0/0 0.0.0.0/0 DROP udp -- 0.0.0.0/0 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp spt:80 |
删除INPUT的第3条(即第3行,执行“iptables -L INPUT --line-numbers”显示行号,注意行号从1开始而不是从0开始)规则:
iptables -D INPUT 3 |