Linux命令总结
一、BASH内置命令
1.eval
二、打包压缩
1、.tar包
tar -cvf test.tar [文件|目录] 只归档,不压缩
选项
- -c:建立tar包
- -t:查看tar包中的文件列表,例如:tar -tvf xxx.tar.gz
- -v:显示过程信息
- -f:必须是最后一个选项,后面紧跟打包文件名
- -C:
压缩时改变路径,例如:tar -zcvf test.tar.gz -C /tmp/ test/ 压缩/tmp/test下的所有文件,并把tar.gz包里的文件路径改为test/
解压时指定目录,例如:tar -zxvf test.tar.gz -C /usr/local
- -P:如果待压缩目录是绝对路径,则会报 tar: Removing leading `/' from member names错误,此时需要加-P选项,例如:
tar -zcPvf SA_top_r39247_20230616_043127.tar.gz /opt/bld/top/latest
选项
- -x:解包 tar -xvf test.tar
2、.tar[.gz|.bz2|.xz]包
压缩格式及选项
- -z:gz格式
- -j:bz2格式
- -J:xz格式
压缩
tar -zcvf test.tar.gz [文件|目录]
tar -jcvf test.tar.bz2 [文件|目录]
tar -Jcvf test.tar.xz [文件|目录]
解压
tar -zxvf test.tar.gz
tar -jxvf test.tar.bz2
tar -Jxvf test.tar.xz
3、.zip包
压缩:zip [选项] test.zip 目录|文件
选项
- -r 递归压缩目录
- -d 删除zip包中的文件 zip -d test.zip 文件
- -u 向zip包中添加文件 zip -u test.zip 文件
解压:unzip [选项] test.zip
选项
- -d 解压到指导目录 unzip -d /home test.zip
- -l 列出包含哪些文件 unzip -l testzip
4、.gz包
用于单个文件的压缩解压,压缩后原文件被删除。.tar.gz就是用这种压缩格式,tar用于把多个文件归档
压缩:gzip test.txt test.txt被删除,会多出一个test.txt.gz文件
解压:gzip -d test.txt.gz test.txt.gz被删除,恢复为test.txt
三、文件操作
1.cp/scp
cp命令用于本地文件或目录的复制
cp [选项] source dest
选项:
- -d:复制时保留符号链接
- -f:覆盖已经存在的目标文件时不给出提示。
- -i:覆盖已经存在的目标文件时会提示用户确认
- -p:同时复制修改时间和访问权限到新文件
- -l:不复制文件,只是生成硬链接
- -r:递归复制目录
- -v:显示正在复制的文件
scp命令用于远程文件或目录的复制
本地—>远程:scp [选项] 本地文件|目录 {用户名}@{ip}:路径
scp /tmp/aaa.txt root@192.168.5.101:/tmp
远程—>本地:scp [选项] {用户名}@{ip}:文件|目录 本地路径
scp root@192.168.5.101:/tmp/aaa.txt /tmp
- -r用于递归复制目录
2.find
基于文件名查找 -name或-iname(忽略大小写)
find {dir} -name {pattern}
# 查找当前目录及子目录下以.sh为后缀的文件
find ./ -name '*.sh'
# 查找C/C++源文件和头文件
find . -name '*.cc' -o -name '*.cpp' -o -name '*.h'
查找指定目录或排除某个目录 -path
# 查找当前目录下包含路径components/rootfs/的sh脚本
[jianjunyang@~/top]$ find . -path './components/rootfs/*.sh'
./components/rootfs/etc/tar_gather_log.sh
./components/rootfs/etc/fsmHealthMon.sh
./components/rootfs/etc/pmon.sh
./components/rootfs/etc/monNXPOam.sh
./components/rootfs/etc/hctosys.sh
./components/rootfs/etc/monFho.sh
余略
# 指定多个目录用-o连接
# 查找当前目录下包含路径components/rootfs/和common/的sh脚本
[jianjunyang@~/top]$ find . -path './components/rootfs/*.sh' -o -path './common/*.sh'
./components/rootfs/oam/selfMgmt/checkHardWare.sh
./components/rootfs/pyacs/pyacsStart.sh
./components/rootfs/pyacs/pyacsStop.sh
./common/3rdparty/netkit-rsh-0.17/comp.sh
./common/3rdparty/python/lib/python2.5/site-packages/pyOpenSSL-0.6/doc/tools/update-docs.sh
./common/3rdparty/python/lib/python2.5/site-packages/pyOpenSSL-0.6/doc/tools/push-docs.sh
# 查找当前目录下不包含路径components和common的sh脚本
[jianjunyang@~/top]$ find . -path './components' -prune -o -path './common' -prune -o -name '*.sh'
./components
./common
./nmk/pkg/vppRepack.sh
./nmk/pkg/CMCC_repack.sh
./nmk/pkg/JIESAI_repack.sh
./nmk/pkg/JIESAI_prebuild.sh
./nmk/pkg/CMCC_prebuild.sh
./nmk/pkg/prebuild.sh
./nmk/pkg/repack.sh
./nmk/pkg/cu_repack.sh
./nmk/pkg/du_repack.sh
./tools/export_package.sh
./tools/packUt.sh
./tools/cpfsem.sh
./tag.sh
./svntmp.sh
基于目录深度查找 -maxdepth
find命令默认会查找所有的子目录,-maxdepth为1时只查找当前目录
[jianjunyang@~/newest/R2.2.3/components/rootfs/etc]$ find . -maxdepth 1 -name '*.sh'
./monFgbuPhy.sh
./restartStack.sh
./monFho.sh
./tar_gather_log.sh
./hctosys.sh
./pmon.sh
./run-dpdk-bind.sh
./monPhyCPU.sh
./webOdiCommand.sh
./upload_gather_log.sh
./download.sh
./monNXPOam.sh
[jianjunyang@~/newest/R2.2.3/components/rootfs/etc]$
使用 ! 排除指定的模式
# 查找当前目录下不是以.sh为后缀的文件
[jianjunyang@~/newest/R2.2.3/components/rootfs/etc]$ find . -maxdepth 1 ! -name '*.sh'
.
./cfg_for_reference
./confdb_v2.xsd
./confdb_key.xsd
./interface.txt
./non-inheritance
[jianjunyang@~/newest/R2.2.3/components/rootfs/etc]$
基于文件类型查找 -type
| 标识 | 类型 |
| f | 普通文件 |
| d | 目录 |
| l | 符号链接 |
| c | 字符设备 |
| b | 块设备 |
| s | 套接字 |
| p | FIFO |
# 查找当前目录的子目录
[jianjunyang@~/newest/R2.2.3/components/rootfs]$ ll
total 7380
-rw-r--r-- 1 jianjunyang RnD 10 Aug 4 15:04 base_version
-rw-rw-r-- 1 jianjunyang RnD 6 Jul 11 16:06 branch_info
drwxrwxr-x 6 jianjunyang RnD 55 Aug 1 19:35 bts
drwxrwxrwx 3 jianjunyang RnD 105 Aug 11 17:07 dpdk
drwxrwxr-x 3 jianjunyang RnD 4096 Aug 2 10:08 etc
drwxrwxr-x 10 jianjunyang RnD 117 Jul 11 16:06 oam
-rw-rw-r-- 1 jianjunyang RnD 3776346 Aug 2 10:08 packWeb_nxp.pkg
-rw-rw-r-- 1 jianjunyang RnD 3758182 Aug 2 10:08 packWeb_x86.pkg
drwxrwxr-x 2 jianjunyang RnD 283 Aug 11 17:11 phy
drwxrwxr-x 4 jianjunyang RnD 150 Aug 11 17:08 pyacs
drwxrwxr-x 3 jianjunyang RnD 67 Jul 11 16:06 usr
-rw-rw-r-- 1 jianjunyang RnD 20 Aug 11 17:11 version
-rw-rw-r-- 1 jianjunyang RnD 48 Aug 11 17:11 version.addition
[jianjunyang@~/newest/R2.2.3/components/rootfs]$ find . -maxdepth 1 -type d
.
./bts
./etc
./oam
./phy
./usr
./dpdk
./pyacs
[jianjunyang@~/newest/R2.2.3/components/rootfs]$
基于文件大小查找 -size,+表示大于,-表示小于
| c | 字节 |
| k | 千字节 |
| M | 百万字节 |
| G | 百亿字节 |
# 查找大于20K的文件
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ ll -h
total 100K
-rw-rw-r-- 1 jianjunyang RnD 7.9K Jul 25 18:48 mmcheck.c
-rw-rw-r-- 1 jianjunyang RnD 2.6K Jul 22 18:26 mmchunk.c
-rw-rw-r-- 1 jianjunyang RnD 4.6K Jul 24 18:03 OamMmDbger.cc
-rw-rw-r-- 1 jianjunyang RnD 3.4K Jul 26 13:38 OamMmHook.c
-rw-r--r-- 1 jianjunyang RnD 28K Aug 11 16:26 OamShell.c
-rw-r--r-- 1 jianjunyang RnD 27K Aug 11 16:42 OamShTask.cc
-rw-rw-r-- 1 jianjunyang RnD 7.3K Jul 26 16:13 OamSignal.cc
-rw-rw-r-- 1 jianjunyang RnD 12K Jul 25 18:47 rbtree.c
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ find . -size +20k
./OamShTask.cc
./OamShell.c
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$
基于文件时间查找,单位是天,+表示大于,-表示小于
| -atime | 访问时间 |
| -mtime | 内容修改时间 |
| -ctime | 属性改变时间 |
注:小数部分被忽略,比如想匹配-atime +1的文件至少要2天未访问过
# 查找大于7天未修改的文件
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ ll
total 100
-rw-rw-r-- 1 jianjunyang RnD 8011 Jul 25 18:48 mmcheck.c
-rw-rw-r-- 1 jianjunyang RnD 2604 Jul 22 18:26 mmchunk.c
-rw-rw-r-- 1 jianjunyang RnD 4613 Jul 24 18:03 OamMmDbger.cc
-rw-rw-r-- 1 jianjunyang RnD 3427 Jul 26 13:38 OamMmHook.c
-rw-r--r-- 1 jianjunyang RnD 28155 Aug 11 16:26 OamShell.c
-rw-r--r-- 1 jianjunyang RnD 26802 Aug 11 16:42 OamShTask.cc
-rw-rw-r-- 1 jianjunyang RnD 7379 Jul 26 16:13 OamSignal.cc
-rw-rw-r-- 1 jianjunyang RnD 11339 Jul 25 18:47 rbtree.c
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ find . -mtime +7
./mmchunk.c
./OamMmHook.c
./OamMmDbger.cc
./rbtree.c
./mmcheck.c
./OamSignal.cc
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$
对find的结果执行相应的操作 -exec,只要是shell命令即可,{}表示文件集,+表示有多个文件
# 列出大于20K的文件信息
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ ll -h
total 100K
-rw-rw-r-- 1 jianjunyang RnD 7.9K Jul 25 18:48 mmcheck.c
-rw-rw-r-- 1 jianjunyang RnD 2.6K Jul 22 18:26 mmchunk.c
-rw-rw-r-- 1 jianjunyang RnD 4.6K Jul 24 18:03 OamMmDbger.cc
-rw-rw-r-- 1 jianjunyang RnD 3.4K Jul 26 13:38 OamMmHook.c
-rw-r--r-- 1 jianjunyang RnD 28K Aug 11 16:26 OamShell.c
-rw-r--r-- 1 jianjunyang RnD 27K Aug 11 16:42 OamShTask.cc
-rw-rw-r-- 1 jianjunyang RnD 7.3K Jul 26 16:13 OamSignal.cc
-rw-rw-r-- 1 jianjunyang RnD 12K Jul 25 18:47 rbtree.c
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ find . -size +20k -exec ls -lh {} +
-rw-r--r-- 1 jianjunyang RnD 28K Aug 11 16:26 ./OamShell.c
-rw-r--r-- 1 jianjunyang RnD 27K Aug 11 16:42 ./OamShTask.cc
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$
# 删除大于7天未修改的文件
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ ll -h
total 100K
-rw-rw-r-- 1 jianjunyang RnD 7.9K Jul 25 18:48 mmcheck.c
-rw-rw-r-- 1 jianjunyang RnD 2.6K Jul 22 18:26 mmchunk.c
-rw-rw-r-- 1 jianjunyang RnD 4.6K Jul 24 18:03 OamMmDbger.cc
-rw-rw-r-- 1 jianjunyang RnD 3.4K Jul 26 13:38 OamMmHook.c
-rw-r--r-- 1 jianjunyang RnD 28K Aug 11 16:26 OamShell.c
-rw-r--r-- 1 jianjunyang RnD 27K Aug 11 16:42 OamShTask.cc
-rw-rw-r-- 1 jianjunyang RnD 7.3K Jul 26 16:13 OamSignal.cc
-rw-rw-r-- 1 jianjunyang RnD 12K Jul 25 18:47 rbtree.c
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ find . -mtime +7 -exec rm {} +
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$ ll -h
total 56K
-rw-r--r-- 1 jianjunyang RnD 28K Aug 11 16:26 OamShell.c
-rw-r--r-- 1 jianjunyang RnD 27K Aug 11 16:42 OamShTask.cc
[jianjunyang@~/newest/R2.2.3/nanoOam/osAgent/src]$
# 给.sh后缀的文件添加可执行权限
[jianjunyang@~/newest/R2.2.3/components/rootfs/etc]$ find . -name '*.sh' -exec chmod a+x {} +
3.ls
ls -i 查看文件inode号
ls -[r]t 按时间排序,-r表示逆序输出
ls -[r]S 按文件大小排序
ls -X 按扩展名排序
ls -R 递归列出所有子目录
ls -d */ 列出当前目录下的子目录
# 列出当前目录下nanoOam下的子目录
[jianjunyang@~/R2.2.3.X]$ ls -d $PWD/nanoOam/*/ -1
/home/jianjunyang/R2.2.3.X/nanoOam/callTrace/
/home/jianjunyang/R2.2.3.X/nanoOam/cm/
/home/jianjunyang/R2.2.3.X/nanoOam/common/
/home/jianjunyang/R2.2.3.X/nanoOam/devMgmt/
/home/jianjunyang/R2.2.3.X/nanoOam/emulators_oam/
...
ls -l | grep ^- 列出当前目录下的普通文件
ls -1 每行列出一个文件或目录
ls -F 在文件或目录最后添加附加信息
*代表可执行文件;/代表目录;=代表socket文件;|代表FIFO文件;@代表连接文件;>代表设备文件
4.cat
cat [-AbEnTv] file
| -A | 相当于-vET,可显示特殊字符,比如tab、回车 |
| -b | 显示行号,空白行不显示 |
| -E | 将行尾的$显示出来 |
| -n | 连同空白行一起显示行号 |
| -T | 将Tab键以^I显示出来 |
| -v | 列出一些不可见的特殊字符 |
root@localhost:/opt/loads # cat >> aaa.txt
-----------------------
输入或粘贴文本(可以是多行)
-----------------------Ctrl-D
root@localhost:/opt/loads #
cat <<EOF 用于在shell脚本中创建多行文件,遇到EOF结束,cat <<-EOF会忽略EOF前的空格和tab
cat > a.txt <<EOF
Hello Shell
Hello Python
Hello Lua
EOF
5.lsof
6.od/xxd
四、目录操作
1. cd
cd [相对路径|绝对路径]
cd -
2. pushd popd dirs
pushd和popd是对一个目录栈进行操作,dirs是显示目录栈的内容。目录栈就是一个保存目录条目的栈结构,该栈结构的顶端永远都存放着当前目录
| -p | 每行显示一条记录 |
| -v | 每行显示一条记录,并显示该记录在栈中的索引 |
| -c | 除当前目录外清空目录栈 |
pushd [路径] 将指定路径添加到目录栈栈顶,也即将当前目录切换到指定路径
pushd +n 将当前目录切换到目录栈中索引为n的目录
pushd 不带参数切换栈顶的两个目录互相切换
popd +n 将目录栈中索引为n的目录移除出栈
pushd -n [路径] 添加目录到目录栈,不改变当前目录,仅对栈进行操作
popd -n +N 将索引为N的目录移除出目录栈,不改变当前目录,仅对栈进行操作
3. tree
以树状结构列出目录内容
五、目录树与挂载
我们知道Linux的目录是以树型结构管理的,目录树的最顶层是根目录,如下图所示

但是文件数据实际上是放在磁盘(的某个分区)中的,那么目录树与磁盘分区是怎么关联的呢?这就涉及到挂载的问题啦^_^
所谓挂载就是把某个目录作为挂载点,让其与磁盘的某个分区关联起来,进入该目录就可以存取该分区下的数据。根目录必须挂载到某个分区,其他目录可以根据需求选择挂载。

查询块设备TYPE、LABEL、UUID等信息
blkid
lsblk -f
挂载命令
- mount [-t 文件系统] UUID=' ' [挂载点]
- mount [-t 文件系统] 设备文件 [挂载点]
- mount [-t 文件系统] LABEL=' ' [挂载点]
挂载磁盘分区
[root@localhost:~] blkid /dev/vda4
/dev/vda4: UUID="c6c31bae-8a8a-43e7-a012-f6ce97debd18" TYPE="xfs"
[root@localhost:~] mount UUID='c6c31bae-8a8a-43e7-a012-f6ce97debd18' /mnt/xfs
挂载光盘
[root@localhost:~] blkid
/dev/sr0: UUID="2015-04-01-00-21-36-00" LABEL="CentOS 7 x86_64" TYPE="iso9660" PTTYPE="dos"
[root@localhost:~] mount /dev/sr0 /mnt/cdrom
[root@localhost:~] df -h /home/data/cdrom
[root@localhost:~] # 可以看到使用率是100%,因为光盘是只读设备
挂载U盘
[root@localhost:~] blkid
/dev/sdb1: UUID="B8B3-F207" TYPE="vfat"
[root@localhost:~] mount -t vfat -o codepage=437,iocharset=utf8 /dev/sdb1 /mnt/usb/
挂载ISO文件
[root@localhost:~] mount -o loop /tmp/CentOS-7.0-1406-x86_64-DVD.iso /mnt/iso
重新挂载(因为之前的挂载传入参数有误等原因)
[root@localhost:~] mount -o remount,rw,auto /
[root@localhost:~] #重新挂载根目录
将某个目录挂载到另一个目录(也可以通过软链接实现相同的效果)
[root@localhost:~] mount --bind /home/data /mnt/data
挂载远程NFS服务
怎么部署NFS(网络文件系统)服务请参考以下博客
https://blog.csdn.net/lihuifen2011/article/details/117257915
常用在文件服务器和主机、宿主机和开发板之间
[root@localhost:~] mount -t nfs [-o nolock] {IP}:{目录} /mnt/nfs
挂载Windows共享文件夹
首先在Windows创建共享文件夹,不会创建的话请参考网上的教程
在Linux执行以下命令挂载
[root@localhost:~] mount -t cifs -o username=***,password=*** //{IP}/共享文件夹 /mnt/share
==========可能出现的错误和解决方法 ==========
错误描述
mount error(112): Host is down
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
解决办法
控制面板->程序和功能->启动或关闭windows功能
勾选SMB的全部项,重启电脑

错误描述
mount error(13): Permission denied
Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
解决办法
mount命令中的username和password是指windows本地账户,不是Microsoft账户
在win10和win11中很多人是直接用Microsoft账户登录的,如果mount命令的username和password输入的是Microsoft账户和PIN码就会遇到这个错误
切换为本地账户登录就能解决,以win11为例

解除挂载
umount [-fn] 设备文件|挂载点
-f 强制卸载
-n 不更新/etc/mtab
六、磁盘管理
df [选项] [目录] 查看文件系统名、磁盘大小、使用率、挂载点等信息
- -h 以KB/MB/GB形式显示磁盘大小
- -T 显示文件系统类型
- -t 只显示某种文件系统,例如:df -t ext4 只查看ext4文件系统
- -i 显示inode信息
du [选项] [目录] 统计目录或文件所占磁盘的大小
- -h 以KB/MB/GB显示大小
- -s 仅显示总计,即目录的大小,默认显示当前目录,例如:du -sh /tmp
- -d 递归深度,不能跟-s一起使用
root@localhost:~/workspace # du -h -d 1
276M ./yjj
15M ./libxml2
151M ./packages
0 ./SVN-Repo
5.1G ./debug
292K ./beautify
5.6G .
fdisk
七、内存管理
free -h 查看内存使用情况
cat /proc/meminfo 查看内存总体信息
八、CPU管理
物理CPU数:主板上实际插入的CPU数,不重复的physical id有几个就有几个物理CPU。大部分主板都只有一个插槽,即只有一个物理CPU,貌似也有多CPU主板
CPU核心数:核心(Die)又称为内核,是CPU最重要的组成部分。CPU中心那块隆起的芯片就是核心,这里指单个CPU的核心数,比如双核、四核等
超(多)线程:将每个CPU内核拆分为两个虚拟内核(称为线程),这两个虚拟内核能够同时处理指令(如果程序允许的话),这意味着多线程有效地使CPU的内核数量增加了一倍
逻辑CPU数:物理CPU数 × 核心数
物理CPU数 × 核心数 × 2 (支持超线程)
/proc/cpuinfo文件重要字段解释:
| processor | 逻辑CPU编号 |
| vendor_id | 制造商 |
| cpu MHz | 主频 |
| cache size | CPU二级缓存大小 |
| physical id | 物理CPU编号 |
| cpu cores | 单个物理CPU的核心数 |
| siblings | 单个物理CPU的逻辑核数,超线程=2*cpu cores,否则=cpu cores |
| flags | 当前CPU支持的功能 |
| bogomips | 内核启动时粗略测算的CPU速度(单位: 百万指令每秒) |
| address sizes | 可访问的地址空间位数 |
lscpu 显示CPU架构信息,大部分字段都能跟/proc/cpuinfo中的对应起来
top 显示Linux系统中的进程,相当于windows的任务管理器
root@localhost:~ # top
top - 16:25:16 up 9:22, 2 users, load average: 0.01, 0.02, 0.05
Tasks: 168 total, 1 running, 167 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 3.1 sy, 0.0 ni, 96.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1867048 total, 924020 free, 449132 used, 493896 buff/cache
KiB Swap: 1679356 total, 1679356 free, 0 used. 1188584 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 191116 4152 2548 S 0.0 0.2 0:10.31 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.30 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
7 root rt 0 0 0 0 S 0.0 0.0 0:00.55 migration/0
输出结果解释
统计信息:
第一行:系统当前时间, 系统运行时间, 登录用户数, 最近1m/5m/15m系统的平均负载(单核平均负载=该值/CPU核数)
第二行:进程总数, 运行中的进程数, 睡眠中的进程数, 停止的进程数, 僵尸进程数
第三行:CPU信息, 用户空间占用CPU百分比, 内核空间占用CPU百分比, 修改过nice值的进程占用CPU百分比, 空闲态CPU百分比
如果是多核CPU, 按1可以切换每个CPU信息和CPU总体信息
[root@localhost ~]# top
top - 17:04:01 up 13 days, 23:03, 9 users, load average: 2.01, 2.09, 2.12
Tasks: 576 total, 1 running, 575 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.3 us, 1.0 sy, 0.0 ni, 98.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
第四行:内存信息
第五行:Swap交换分区信息
进程信息:
PR:进程优先级, 对于普通进程=NI+20, 对于实时进程该值是负数, 最高优先级的实时进程显示为rt
NI:进程nice值, 范围[-20,19]
VIRT:进程占用的虚拟内存
RES:进程占用的物理内存
SHR:进程占用的共享内存
TIME+:进程累计使用的CPU时间, 从左到右分别表示分钟、秒、百分之一秒, 如0:10.31表示0分10.31秒
top常用选项
| -p | 只显示某个进程 |
| -H | 显示线程信息 |
| -o | 指定排序字段,PID、RES、%CPU(默认)、%MEM、TIME+,比如top -o RES |
| -n | 指定刷新次数,top -n 3 刷新3次后退出 |
| -b | 非交互模式,通常配合-n将输出结果重定向到文件,top -b -n 1 > top.txt |
| -u | 查看特定用户启动的进程 |
top交互命令
| h键 | 显示帮助 |
| c键 | 显示进程完整命令,再按c键变回默认显示 |
| f键 | 选择需要显示的条目,上下键移动,空格键选择或取消 |
| M键 | 按驻留内存大小排序(RES) |
| P键 | 按CPU使用率排序 |
| T键 | 按TIME+排序 |
mpstat
vmstat
pidstat
九、进程管理
概念:
- 进程是程序的一次执行过程,是动态的,有生命周期的,可以被创建、撤销、暂停
- 进程是操作系统进行资源分配和调度的一个独立单位
资源:可以申请多少内存、一次调度能占用多少cpu时间、可以打开多少文件描述符、...
调度:CPU数远远小于系统中运行的进程数,所以操作系统要按某种策略让每个进程都能得到公平的执行
进程调度相关的概念:优先级、cpu亲和性(绑核)、时间片、调度算法、进程状态 ...
命令:
ps -eo user,sid,pgid,pid,ppid,psr,%cpu,%mem,vsz,rss,stat,lstart,stime,etime,time,comm cmd [-p PID] [--sort=-pcpu|-pmem]
按cpu使用率或内存使用率降序排序
| user | sid | pgid | pid | ppid | psr | %cpu | %mem | vsz | rss | stat | lstart | stime | etime | time | comm | cmd |
| 用户名 | 会话ID | 进程组ID | 进程ID | 父进程ID | 进程运行在哪个cpu核上 | CPU使用率 | 内存使用率 | 虚拟内存 | 物理内存 | 进程状态 | 启动时间(全格式,包括星期、年月日、时分秒) | 启动时间(精简格式) | 运行时间 | 占用CPU时间 | 进程名 | 进程命令行 |
#查看oamProcess所在进程组的进程
[root@localhost log]# ps -eo pid,ppid,pgid,sid,tty,comm|grep oamProcess
41001 1 39598 39530 pts/3 oamProcess
[root@localhost log]# ps -eo pid,ppid,pgid,sid,tty,comm|grep 39598
40902 1 39598 39530 pts/3 odsNameServer
41001 1 39598 39530 pts/3 oamProcess
41003 41001 39598 39530 pts/3 oamShell
41081 1 39598 39530 pts/3 pmon.sh
41141 1 39598 39530 pts/3 monPhyCPU.sh
41406 41001 39598 39530 pts/3 subProcess.sh
41407 41001 39598 39530 pts/3 subProcess.sh
41408 41001 39598 39530 pts/3 subProcess.sh
41409 41001 39598 39530 pts/3 subProcess.sh
41410 41001 39598 39530 pts/3 subProcess.sh
41602 1 39598 39530 pts/3 processPingFho.
41704 41406 39598 39530 pts/3 upapp
41842 41407 39598 39530 pts/3 cpcellapp
41904 41408 39598 39530 pts/3 cpgnbapp
41947 41409 39598 39530 pts/3 cpupproxy
42047 41410 39598 39530 pts/3 duapp
42191 1 39598 39530 pts/3 tclsh
42192 1 39598 39530 pts/3 bash
44173 41081 39598 39530 pts/3 sleep
44177 41602 39598 39530 pts/3 sleep
44195 41141 39598 39530 pts/3 sleep
44196 41001 39598 39530 pts/3 sh
44197 44196 39598 39530 pts/3 ipmitool
ps -e[fjl]
-e:列出全部进程
-f:以全格式显示进程信息[UID PID PPID C STIME TTY TIME CMD]
-j:以job格式显示进程信息[PID PGID SID TTY TIME CMD]
-l:以长格式显示进程信息[F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD]
[root@localhost log]# ps -ef|head -n 5
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Aug25 ? 00:00:58 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0 0 Aug25 ? 00:00:00 [kthreadd]
root 3 2 0 Aug25 ? 00:06:56 [ksoftirqd/0]
root 4 2 0 Aug25 ? 00:34:10 [ktimersoftd/0]
各列的含义
C:cpu使用率
STIME:启动时间
TTY:终端设备,?表示进程没有关联的终端,即守护进程
TIME:占用cpu的时间
ps aux
列出所有进程的信息,BSD风格的语法
[root@localhost log]# ps aux|head -n 5
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 199564 4248 ? Ss Aug25 0:58 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root 2 0.0 0.0 0 0 ? S Aug25 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? S Aug25 6:56 [ksoftirqd/0]
root 4 0.2 0.0 0 0 ? S Aug25 34:11 [ktimersoftd/0]
PROCESS STATE CODES
Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the state of a process:
D uninterruptible sleep (usually IO)
R running or runnable (on run queue)
S interruptible sleep (waiting for an event to complete)
T stopped by job control signal
t stopped by debugger during the tracing
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
For BSD formats and when the stat keyword is used, additional characters may be displayed:
< high-priority (not nice to other users)
N low-priority (nice to other users)
L has pages locked into memory (for real-time and custom IO)
s is a session leader
l is multi-threaded (using CLONE_THREAD, like NPTL pthreads do)
+ is in the foreground process group
# 按cpu降序输出
[root@localhost log]# ps aux --sort=-pcpu|head -n 5
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 885 2.3 0.0 0 0 ? SN Aug25 377:08 [kipmi0]
root 13559 1.9 0.0 369612 7792 ? Sl Sep01 118:44 /home/zby/netconf_test_server_4ru/eu01/bts/bin/netconf_test_server
root 37218 0.8 0.2 257556 70680 pts/3 Sl 19:14 0:07 oamProcess
root 4 0.2 0.0 0 0 ? S Aug25 34:12 [ktimersoftd/0]
# 按内存降序输出
[root@localhost log]# ps aux --sort=-pmem|head -n 5
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 836 0.0 0.3 210760 121300 ? Ss Aug25 0:27 /usr/lib/systemd/systemd-journald
root 37218 0.8 0.2 257556 70680 pts/3 Sl 19:14 0:07 oamProcess
root 1656 0.0 0.2 370976 65296 ? Ssl Aug25 0:22 /usr/sbin/rsyslogd -n
root 1652 0.0 0.0 574288 17532 ? Ssl Aug25 0:43 /usr/bin/python2 -Es /usr/sbin/tuned -l -P
ps -ejH
查看进程组ID、会话ID
ps -ejH|head -n 5
PID PGID SID TTY TIME CMD
2 0 0 ? 00:00:00 kthreadd
3 0 0 ? 00:06:56 ksoftirqd/0
4 0 0 ? 00:34:14 ktimersoftd/0
6 0 0 ? 00:00:00 kworker/0:0H
ps -T -p [PID]
查看进程的每个线程信息
root@localhost:/usr/local/SBNTS/var/log # ps -T -p 121270
PID SPID TTY TIME CMD
121270 121270 ? 00:00:01 cxsim
121270 121271 ? 00:00:00 cxsim
pstree [-p [PID]]
以树状图形式显示进程关系
[root@gnb ~]# pstree -p 70451
oamProcess(70451)─┬─ntpd(71514)
├─oamShell(70453)
├─subProcess.sh(70965)───upapp(71539)─┬─{upapp}(71563)
│ ├─{upapp}(71564)
│ ├─{upapp}(71565)
│ ├─{upapp}(71566)
│ ├─{upapp}(71567)
│ ├─{upapp}(71570)
│ ├─{upapp}(71572)
│ └─{upapp}(71573)
├─subProcess.sh(70966)───cpcellapp(71611)
├─subProcess.sh(70970)───cpgnbapp(71982)
├─subProcess.sh(70971)───cpupproxy(72030)
└─subProcess.sh(70972)───duapp(72251)─┬─{duapp}(72419)
├─{duapp}(72420)
├─{duapp}(72421)
├─{duapp}(73084)
├─{duapp}(73085)
├─{duapp}(73086)
└─{duapp}(73087)
# 带有{}的表示是一个线程
会话 终端 进程组 进程的关系
一个会话包含多个进程组,一个进程组包含多个进程,会话可能有控制终端,也可能没有,终端为会话中所有进程共享
在拥有控制终端的会话中,会话首领也称为控制进程,也就是登入系统的shell进程,Linux中通常就是bash
当用户登录系统时就会建立一个会话和进程组,该会话和进程组ID就是登入系统的shell进程的ID,并绑定一个控制终端(tty或pts)
ps -s SID -[fjl] 查看指定会话ID下的进程
ps -[fjl] 查看当前会话下的进程
# 查看当前会话下的进程
root@localhost:~ # ps -j
PID PGID SID TTY TIME CMD
18069 18069 18069 pts/1 00:00:00 bash
91837 91837 18069 pts/1 00:00:00 ps
# 查看会话1955下的进程
[root@localhost log]# ps -s 1955 -j
PID PGID SID TTY TIME CMD
1955 1955 1955 pts/2 00:00:00 bash
3452 1983 1955 pts/2 00:00:00 odsNameServer
3712 1983 1955 pts/2 00:00:07 oamProcess
3772 1983 1955 pts/2 00:00:00 monPhyCPU.sh
4075 1983 1955 pts/2 00:00:00 subProcess.sh
4076 1983 1955 pts/2 00:00:00 subProcess.sh
4077 1983 1955 pts/2 00:00:00 subProcess.sh
4078 1983 1955 pts/2 00:00:00 subProcess.sh
4079 1983 1955 pts/2 00:00:00 subProcess.sh
4355 1983 1955 pts/2 00:00:00 processPingFho.
4471 1983 1955 pts/2 00:00:00 dp_lanucher
4472 1983 1955 pts/2 00:00:02 upapp
4653 1983 1955 pts/2 00:00:00 cpcellapp
4698 1983 1955 pts/2 00:00:00 cpgnbapp
4751 1983 1955 pts/2 00:00:00 cpupproxy
4881 1983 1955 pts/2 00:00:02 duapp
前台进程组 后台进程组
- 一个会话只能有一个前台进程组,可以有多个后台进程组
- 子进程默认与父进程属于同一进程组,调用setpgid()可以将一个进程移动到其他进程组
- 进程组ID为该组中第一个进程的ID(组长进程)
- 组长进程退出不影响进程组中其他进程,进程组ID不变。只有最后一个进程退出,该进程组才会解散
前台进程:独占控制终端,无法执行其他命令。可以接收终端输入
后台进程:不继承标准输入,但会继承标准输出和标准错误输出。即无法接收输入,但仍然会打印输出
ctrl + z 暂停前台进程
jobs -l 查看进程工作号
bg %num 将进程放到后台运行
fg %num 将后台进程转到前台运行
在shell脚本中启动一个后台进程,shell脚本退出,后台进程被1号进程接管,进程组id不变
root@localhost:~/workspace # cat test.sh
#!/usr/bin/bash
echo "exec test.sh"
sleep 2m &
root@localhost:~/workspace # ./test.sh
exec test.sh
root@localhost:~/workspace # ps -eo user,sid,pgid,pid,ppid,stat,cmd|grep sleep
root 793 793 28562 808 S sleep 60
root 25569 28587 28588 1 S sleep 2m # test.sh退出, 父进程变为1号进程
root 25569 28605 28606 25569 S+ grep --color=auto sleep
root@localhost:~/workspace #
守护进程
守护进程是运行在后台,不受终端控制的一类特殊进程。标准输入输出都指向/dev/null
后台进程与守护进程区别
一个“后台进程”是否就是“守护进程”呢,用户关闭session(退出登录)后,“后台任务”是否还会继续执行呢? 答案是不一定
SIGHUP信号
SIGHUP 信号在用户终端(正常或非正常)结束时发出,用于控制同一session内的各个job,系统对SIGHUP信号的默认处理是终止进程
在 Linux 系统中,用户准备退出session时session会将SIGHUP信号发送给所有子进程,子进程收到信号后就会自动退出
后台进程不一定会收到SIGHUP信号
我们知道“前台进程”在session退出时会收到SIGHUP信号而退出,这和我们平时的工作经验是相符的
但是“后台任务”是否会收到SIGHUP信号取决于shell的huponexit参数:
# shopt命令用于显示和设置Shell中的行为选项,通过修改这些选项来改变Shell的行为
root@localhost:~ # shopt | grep huponexit
huponexit off
root@localhost:~ #
在大多数 Linux 系统中这个参数被设置成off,即session退出的时候不会把SIGHUP信号发送给“后台任务”,所以“后台任务”不会随着session退出而退出
有些Linux系统上的huponexit参数可能是on,所以一般不通过“后台任务”的方式启动“守护进程”
通过disown启动守护进程
disown命令可以将指定任务从“后台任务”列表(jobs命令的返回结果)中移除,因此session退出时就不会向它发出SIGHUP信号
需要注意的是,假如我们使用disown命令将指定任务移除出“后台任务”列表,那么在退出 session后如果后台进程与标准IO有交互,那么它就会挂掉。这是因为“后台任务”的标准IO继承自当前session,disown并没有改变这一点。一旦“后台任务”在退出session后继续读写标准IO,就会发现它已经不存在了从而报错终止运行
可以通过重定向标准IO解决这个问题:
root@localhost:~ # ./miniacsd > stdout.log 2> stderr.log < /dev/null &
通过nohup启动守护进程
root@localhost:~ # nohup ./miniacsd &
它可以实现如下功能:
- 阻止SIGHUP信号发送给这个进程
- 关闭标准输入使得该进程不再能接收任何输入,即使运行在后台
- 重定向stdout和stderr到nohup.out
- 需要注意的是nohup命令并不会将进程变成后台进程,因此一般需要加上&符号
十、账号管理
1./etc/passwd
2./etc/group
3./etc/shadow
4.id
5.groups
6.newgrp
7.useradd
8.passwd
9.usermod
10.userdel
11.su/sudo
12.w/who/last/lastlog
w/who 查看哪些用户在线
last 查看哪些用户在什么时候登录过
last reboot 查看系统重启信息
lastlog 查看每个账号的最近登录时间
十一、网络抓包
1.常用选项
- -D:列出所有可用接口
root@localhost:~# tcpdump -D
1.eth0 [Up, Running]
2.eth1 [Up, Running]
3.eth1.2 [Up, Running]
4.eth2 [Up, Running]
5.any (Pseudo-device that captures on all interfaces) [Up, Running]
6.lo [Up, Running, Loopback]
7.nflog (Linux netfilter log (NFLOG) interface)
8.nfqueue (Linux netfilter queue (NFQUEUE) interface)
9.usbmon1 (USB bus number 1)
10.usbmon2 (USB bus number 2)
11.usbmon3 (USB bus number 3)
12.usbmon4 (USB bus number 4)
- -i:指定网络接口
tcpdump -i any 抓取所有接口的数据包
tcpdump -i lo 抓取环回接口的数据包(127.0.0.1)
tcpdump -i eth0 抓取eth0接口的数据包
- -w:将数据包输出到文件,默认打印到屏幕
tcpdump -i ens37 -w /tmp/test.pcap
- -r:解析文件中的数据包
tcpdump -r /tmp/aaa.pcap 默认以紧凑格式打印报文
tcpdump -A -r /tmp/aaa.pcap 以ASCII格式打印报文
tcpdump -X -r /tmp/aaa.pcap 以十六进制格式打印报文
- -c:设置抓取的数据包数量,达到该数量自动终止抓包,默认不终止
tcpdump -i eth0 -c 200 -w /tmp/test.pcap 从eth0接口抓取200个数据包后终止
- -s:指定截取每个数据包多少字节,默认262144字节
tcpdump -i eth0 -s 2000-w /tmp/test.pcap 每个数据包截取2000字节
- -e:显示链路层头信息,比如源、目的MAC地址,IP协议版本
- -n:不解析域名,直接显示IP地址。域名解析会降低抓包速度,很多时候也不关注域名
- -nn:除了不解析域名,也不解析服务名,直接显示端口。比如21端口用于ftp,80端口用于http
- -X,-XX:以16进制和ascii形式输出数据包,一个X从IP层开始输出,两个XX从链路层开始输出
- -v,-vv,-vvv 打印详细的输出信息,v越多输出信息越多
- -t,-tt,-ttt,-tttt,-ttttt
-t:不显示时间戳,默认以hh:mm:ss.xxxxxx格式显示时间
-tt:显示时间戳
-ttt:显示当前数据包和前一包的时间差
-tttt:显示日期和时间
-ttttt:显示当前数据包和第一包的时间差
2.过滤条件
- host:IP地址过滤
tcpdump -i any host 172.16.0.11 抓取ip为172.16.0.11的数据包
tcpdump -i any src host 172.16.0.11 指定源ip地址
tcpdump -i any dst host 172.16.0.11 指定目的ip地址
- net:网段过滤
tcpdump -i any net 192.168.3.0/24 过滤192.168.3.0/24网段的数据包
- port:端口过滤
tcpdump -i eth0 port 80 过滤端口为80的数据包
tcpdump -i eth0 src port 80 指定源端口
tcpdump -i eth0 dst port 80 指定目的端口
- 协议过滤:ether,ip,ip6,arp,rarp,tcp,udp,icmp,sctp,vlan
tcpdump -i eth0 tcp 抓取tcp包
- 逻辑运算符
与:and 或 &&
或:or 或 ||
非:not 或 !
tcpdump -i eth0 tcp and host 192.168.1.254
- 根据偏移量过滤
proto[x:y] = z
protot表示协议(ether、arp、sctp、tcp、udp等),x表示位置,y表示大小(必须是1、2、4),z表示值
y等于1时:y可以省略且z为十进制数,否则z为十六进制数,以0x开头

示例1:抓源mac后两字节是0x1380的包
tcpdump -i any -nne ether[10:2]=0x1380
示例2:查看抓包文件icmp.pcap里192.168.209.33的arp广播和响应消息
tcpdump -nnevv -r icmp.pcap arp[24:4]=0xc0a8d121 or arp[14:4]=0xc0a8d121
示例3:过滤18.250.0网段的sctp消息,不含sctp[12]=04心跳和sctp[12]=05心跳响应消息
tcpdump net 18.250.0.0/24 and not "sctp[12]=04 or sctp[12]=05" # sctp第12字节是消息类型
示例4:过滤rtp流
tcpdump -i any -nne udp[8:1]=0x80
十二、网络工具
/proc/net 各种网络相关的数据文件
/proc/net/dev /proc/net/if_inet6 网络设备文件
/proc/net/route /proc/net/ipv6_route 路由信息文件
/etc/iproute2/ 路由表
/etc/sysconfig/network-scripts/ 网卡配置
1、ifconfig
显示或设置网络设备[ifconfig命令详解]
【显示】ifconfig [-as] [interface]
-a -- 显示所有网卡,包括已关闭的
-s -- 以短列表格式显示网卡信息
interface -- 网卡名,若不指定则显示所有激活的网卡
root@localhost:~ # ifconfig ens33
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.3.52 netmask 255.255.255.0 broadcast 192.168.3.255
inet6 fe80::20c:29ff:fe6d:5c9d prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:6d:5c:9d txqueuelen 1000 (Ethernet)
RX packets 122230 bytes 9246988 (8.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1131 bytes 154859 (151.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
root@localhost:~ # ifconfig -s
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
ens33 1500 122263 0 0 0 1138 0 0 0 BMRU
ens37 1500 0 0 0 0 0 0 0 0 BMU
lo 65536 4 0 0 0 4 0 0 0 LRU
virbr0 1500 0 0 0 0 0 0 0 0 BMU
root@localhost:~ #
显示内容解析
flags -- UP:网卡已启用
BROADCAST:网卡支持广播
RUNNING:网卡在运行中
MULTICAST:网卡支持多播
ether -- 以太网 00:0c:29:6d:5c:9d -- MAC地址 txqueuelen 1000 -- 网卡传送队列长度
【重启网卡】ifconfig -s <Iface> down -- 关闭网卡
ifconfig -s <Iface> up -- 启动网卡
【配置IPv4】ifconfig <Iface> <IP> [netmask 255.255.255.0 broadcast 192.168.1.255 up]
可以同时添加子网掩码、广播地址、并启动
【配置IPv6】ifconfig <Iface> add 33ffe:3240:800:1005::2/64
ifconfig <Iface> del 33ffe:3240:800:1005::2/64
2、route
显示/操作IP路由表
【显示】route [-n -ee] [-4|-6]
-n -- 显示ip地址而不是主机名
-ee -- 显示路由表的所有参数
-4 -- 显示IPv6路由表
-6 -- 显示IPv6路由表
root@localhost:~ # route -nee
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface MSS Window irtt
0.0.0.0 192.168.3.254 0.0.0.0 UG 0 0 0 ens33 0 0 0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 ens33 0 0 0
192.168.3.0 0.0.0.0 255.255.255.0 U 0 0 0 ens33 0 0 0
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0 0 0 0
root@localhost:~ # route -nee -6
Kernel IPv6 routing table
Destination Next Hop Flag Met Ref Use If
3ffe:ffff::/32 :: !n 1024 0 0 lo
fe80::/64 :: U 256 0 0 ens33
fe80::20c:29ff:fe6d:5c9d/128 :: Un 0 1 0 lo
ff00::/8 :: U 256 1 5 ens33
root@localhost:~ #
| Destination | 目的网段 |
| Gateway | 网关地址,0.0.0.0表示直连网段,不需要网关转发,直接走二层协议 |
| Genmask | 子网掩码 |
| Flags(Flag) | U、H、G、R、D、M、!,含义参见下表 |
| Metric(Met) | The 'distance' to the target,中转数 |
| Ref | 路由项引用次数 |
| Use | 此路由项被路由软件查找的次数 |
| Iface(If) | 网卡接口 |
| MSS | Default maximum segment size for TCP connections over this route. |
| Window | Default window size for TCP connections over this route. |
| irtt | 此路由的初始往返时间 |
| Next Hop | 下一跳地址,相当于Gateway |
| U | route is up |
| H | target is a host |
| G | use gateway |
| R | 恢复动态路由产生的表项 |
| D | 由路由的后台程序动态地安装 |
| M | 由路由的后台程序修改 |
| ! | 拒绝路由 |
路由匹配原则
- 最长子网掩码优先
- 最小管理距离AD优先(路由协议优先级)
- 最小Metric优先
【添加】
添加到主机的路由:route add -host 192.168.168.128 [gw 192.168.168.1] dev ens33
添加到网络的路由:route add -net 192.168.168.0 netmask 255.255.255.0 gw 192.168.168.1 dev ens33
route add -net 192.168.168.0/24 gw 192.168.168.1 dev ens33
添加默认网关:route add default gw IP
【删除】
route del -net|-host target [gw Gw netmask Nm] dev If
3、ip
ip命令的格式:
ip [options] object {command | help}
options:-s 表示统计信息,其他的用到时查看man手册
object:针对哪类网络参数执行命令,常用的有以下几类
addr 协议相关
link 网卡相关
route 路由相关
command:要执行的命令
show,set,add,del
4、arp/arping
5、tracepath/tracert
6、netstat
7、ss
获取socket统计信息,比netstat更详细
8、iptables
ls /proc/net
9、ping
十三、文本处理grep
基础用法
grep [-cinovw] pattern {file or dir -R} [-ABC n]
| -c | 计算搜索到的次数 |
| -i | 忽略大小写 |
| -n | 显示行号 |
| -m [NUM] | 只取前NUM个匹配项 |
| -o | 只显示匹配的字符而不是整行 |
| -v | 反向匹配,即不包括pattern的行 |
| -w | 全词匹配 |
| --include=FILE_PATTERN | 只搜索指定的文件类型 |
| --exclude=FILE_PATTERN | 跳过指定的文件类型 |
| -R | 递归查找目录 |
| -A | 输出匹配行及后面的n行 |
| -B | 输出匹配行及前面的n行 |
| -C | 输出匹配行及前后各n行 |
# 只搜索.config的文件
grep 'key word' . -R --include=*.config
# 只搜索.config 或.c的文件
grep 'key word' . -R --include=*{.config,.c}
# 跳过.config和.c的文件
grep 'key word' . -R --exclude=*{.config,.c}
使用正则表达式
| * | 重复前面字符0次或多次 |
| . | 一个任意字符 |
| .* | 0个或多个任意字符 |
| [] | 在括号中的一个任意字符 |
| [^] | 除了括号中的任意字符 |
| ^ | 匹配行首 |
| $ | 匹配行尾 |
| {n,m} | 限定匹配次数,n和m可以有一个为空 |
# 查找包含test或taste的行
grep -n 't[ae]st' example.txt
# 查找包含oo但前面不能是g的行
grep -n '[^g]oo' example.txt
# 查找包含数字的行
grep -n '[0-9]' example.txt
# 查找以the开头的行
grep -n '^the' example.txt
# 显示以.结束的行
grep '\.$' example.txt # .在shell中有特殊含义,需要转义
cat -An example.txt|head -n 10 #查看行尾是否有特殊字符
# 查找包含g,gg,ggg,gggg,...的行
grep 'g*g' example.txt
# 查找包含g...g的行
grep 'g.*g' example.txt
# 查找包含oo的行
grep 'o\{2\}' example.txt # {}在shell中有特殊含义,需要转义
# 查找包含go*g(2到5个o)的行
grep 'go\{2,5\}g' example.txt
# 查找包含go*g(2个以上o)的行
grep 'go\{2,\}' example.txt
十四、文本处理sed
以行为单位对文本进行替换、删除、新增、截取
sed [-nefi] [动作]
-n 安静模式,默认来自STDIN的数据都会输出到屏幕上。加上-n选项后只有经sed处理的那行才会输出
-e 执行sed动作,可以省略
-f filename 执行filename内的sed动作
-i 直接修改文件内容,而不是由屏幕输出
动作说明:[n1[,n2]] action
n1,n2不一定会存在,其表示动作作用的行数。比如在10~20行执行动作,则 10,20 action
| a | 插入下一行 |
| c | 取代,c后的字符串取代n1~n2之间的行 |
| d | 删除,d后面没有内容(因为删除嘛) |
| i | 插入上一行 |
| p | 输出,通常与-n一起使用 |
| s | 取代,可以配合正则使用,如1,20s/old/new/g |
root@localhost:~ # nl passwd|head -n 5
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# 删除第2-4行
root@localhost:~ # nl passwd|head -n 5|sed '2,4d'
1 root:x:0:0:root:/root:/bin/bash
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# 删除第2行
root@localhost:~ # nl passwd|head -n 5|sed '2d'
1 root:x:0:0:root:/root:/bin/bash
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# 删除最后4行
root@localhost:~ # nl passwd|head -n 5|sed '2,$d'
1 root:x:0:0:root:/root:/bin/bash
# 在第2行后面加一行drink tea
root@localhost:~ # nl passwd|head -n 5|sed '2a drink tea'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
drink tea
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# 替换第2-4行
root@localhost:~ # nl passwd|head -n 5|sed '2,4c No 2-4 line'
1 root:x:0:0:root:/root:/bin/bash
No 2-4 line
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# 只列出第5-7行
root@localhost:~ # nl passwd|sed -n '5,7p'
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
# 将行内的root替换为bird
root@localhost:~ # nl passwd|head -n 5|sed 's/root/bird/g'
1 bird:x:0:0:bird:/bird:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# 直接修改文件内容,将行尾的.改为!,.和!在shell中都有特殊用途,需要转义
root@localhost:~ # sed -i 's/\.$/\!/g' example.txt
十五、文本处理awk
将一行文本分成若干个字段进行处理,默认以空格分隔,每个字段对应的变量为$1 $2 $3 ...,$0表示整行
awk '[BEGIN {...}] 条件类型1 {动作1} 条件类型2 {动作2} ... [END {...}]' file
awk的处理流程:
a.读取第一行,将对应的字段赋值给$1,$2,...等变量,整行赋给$0
b.根据‘条件类型’判断是否需要执行后面的动作
c.执行完全部的条件类型与动作
d.对后续所有行重复上面的步骤
| NF | 每行的字段数,$NF表示最后一个Field |
| NR | 当前处理的是第几行 |
| FS | 分隔符,默认是空格 |
BEGIN :只在开始处理文本之前执行一次
END :只在所有文本处理完执行一次
[jianjunyang@~/newest/R2.2.3]$ last|head -n 5|awk '{print $1 "\t lines: " NR "\t columns: " NF}'
haoxian. lines: 1 columns: 10
linbin lines: 2 columns: 10
zhengby lines: 3 columns: 10
neville lines: 4 columns: 10
neville lines: 5 columns: 10
[jianjunyang@~/newest/R2.2.3]$ cat num.txt
1
2
3
4
5
# 逐行求和
[jianjunyang@~/newest/R2.2.3]$ cat num.txt|awk 'BEGIN {sum=0} {sum+=$1} END {print sum}' num.txt
15
# 同行的各字段求和
[jianjunyang@~/newest/R2.2.3]$ cat num.txt
1 2 3 4 5
[jianjunyang@~/newest/R2.2.3]$ cat num.txt|awk '
BEGIN {sum=0}
{for (i=1; i<=NF; i++) sum+=$$i}
END {print sum}'
15
[jianjunyang@~/newest/R2.2.3]$
| > | 大于 |
| < | 小于 |
| >= | 大于等于 |
| <= | 小于等于 |
| == | 等于 |
| != | 不等于 |
# 列出UID小于10的用户
[jianjunyang@~/newest/R2.2.3]$ cat /etc/passwd|awk 'BEGIN {FS=":"} $3<10 {print $1 "\t" $3}'
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
[jianjunyang@~/newest/R2.2.3]$
# 按行汇总每个人的支出
[jianjunyang@~/newest/R2.2.3]$ cat pay.txt
Name 1st 2nd 3th
VBird 23000 24000 25000
DMTsai 21000 20000 23000
Bird2 43000 42000 41000
[jianjunyang@~/newest/R2.2.3]$ cat pay.txt|awk '
NR==1 {printf "%10s%10s%10s%10s%10s\n",$1,$2,$3,$4,"Total"}
NR>=2 {total=$2+$3+$4;printf("%10s%10d%10d%10d%10.2fs\n",$1,$2,$3,$4,total)}'
Name 1st 2nd 3th Total
VBird 23000 24000 25000 72000.00s
DMTsai 21000 20000 23000 64000.00s
Bird2 43000 42000 41000 126000.00s
[jianjunyang@~/newest/R2.2.3]$
十六、其他文本命令
1.tr
用于删除或替换文本中的字符串
tr [-ds] SET1 ...
-d 删除SET1这个字符串
-s 删除重复的字符
# 把last命令的输出全部替换成大写字母
root@localhost:~ # last|tail -n 3|tr '[a-z]' '[A-Z]'
DESIGNER PTS/0 :0 WED MAY 31 23:26 - 23:26 (00:00)
DESIGNER :0 :0 WED MAY 31 23:26 - CRASH (4+15:54)
REBOOT SYSTEM BOOT 3.10.0-693.EL7.X WED MAY 31 23:24 - 15:23 (4+15:59)
# 删除文件中的\r字符
root@localhost:~ # cat file.txt|tr -d '\r'
# 删除重复出现的空格
root@localhost:~ # cat f1.txt
123 456 789 101
root@localhost:~ # cat f1.txt|tr -s ' '
123 456 789 101
# 删除多个重复字符
[jianjunyang@~]$ echo "I,,,am tr;;;;"|tr -s ',;'
I,am tr;
[jianjunyang@~]$
2. cut
以行为单位截取文本的某一片段,主要有如下2种用法
cut -d '分隔符' -f fields (用-d指定的分隔符分成几段,-f表示取出第几段)
root@localhost:~ # echo $PATH
/opt/bbu/bts/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
# 取出第3段
root@localhost:~ # echo $PATH|cut -d ':' -f 3
/usr/local/bin
# 取出第3段之后的所有段
root@localhost:~ # echo $PATH|cut -d ':' -f 3-
/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
# 取出第3至第5段
root@localhost:~ # echo $PATH|cut -d ':' -f 3-5
/usr/local/bin:/usr/sbin:/usr/bin
# 取出前5段
root@localhost:~ # echo $PATH|cut -d ':' -f -5
/opt/bbu/bts/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
root@localhost:~ #
cut -c 字符区间
root@localhost:~ # export|head -5
declare -x DISPLAY="localhost:10.0"
declare -x HISTCONTROL="ignoreboth"
declare -x HISTSIZE="1000"
declare -x HOME="/root"
declare -x HOSTNAME="localhost.localdomain"
# 提取第12个字符之后的部分
root@localhost:~ # export|head -5|cut -c 12-
DISPLAY="localhost:10.0"
HISTCONTROL="ignoreboth"
HISTSIZE="1000"
HOME="/root"
HOSTNAME="localhost.localdomain"
# 提取第12至16个字符之间的部分
root@localhost:~ # export|head -5|cut -c 12-16
DISPL
HISTC
HISTS
HOME=
HOSTN
root@localhost:~ #
3.paste
用于将单个文件的所有行合并为一行,或者横向拼接多个文件
root@localhost:~ # cat f1.txt
123
456
789
101
root@localhost:~ # cat f2.txt
abc
def
ghi
# 横向拼接多个文件,默认以tab分割
root@localhost:~ # paste f1.txt f2.txt
123 abc
456 def
789 ghi
101
# 指定分隔符
root@localhost:~ # paste -d '=' f1.txt f2.txt
123=abc
456=def
789=ghi
101=
# 将文件的所有行合并为一行,用-d指定分隔符
root@localhost:~ # paste -s f1.txt
123 456 789 101
# 列出shell的所有环境变量
root@localhost:~ # env|cut -d '=' -f 1|paste -s -d ' '
XDG_SESSION_ID HOSTNAME TERM SHELL HISTSIZE SSH_CLIENT SSH_TTY USER LD_LIBRARY_PATH LS_COLORS MAIL PATH PWD LANG HISTCONTROL SHLVL HOME LOGNAME XDG_DATA_DIRS SSH_CONNECTION LESSOPEN XDG_RUNTIME_DIR DISPLAY _ OLDPWD
root@localhost:~ #
4.xargs
给某个命令产生参数,后面没有跟任何命令时默认使用echo命令输出,默认读取标准输入
# 提取/etc/passwd的前3个用户名给id解析
root@localhost:~ # cut -d ':' -f 1 /etc/passwd|head -n 3|xargs -n 1 id
uid=0(root) gid=0(root) groups=0(root)
uid=1(bin) gid=1(bin) groups=1(bin)
uid=2(daemon) gid=2(daemon) groups=2(daemon)
root@localhost:~ #
5.sort
不加任何选项默认以字符顺序排序,第一个字符相同,按第二个排,以此类推
sort [-fbMnrutk] file or stdin
| -f | 忽略大小写 |
| -b | 忽略最前面的空格 |
| -M | 以月份名字排序,如JAN,FEB... |
| -n | 按数字排序,默认是字符 |
| -r | 反向排序 |
| -u | 如果出现相同的行,仅列出一行,相当于uniq |
| -t | 指定分隔符,默认以tab分割,和-k配合使用 |
| -k | 以指定区间来排序 |
# 用:分隔/etc/passwd并按第5列排序
root@localhost:~ # cat /etc/passwd|head -n 5|sort -t ':' -k 5
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
root@localhost:~ #
6.wc
统计行数、字数、字符数
wc [-lwm]
-l 仅列出行数
-w 仅列出字数(单词)
-m 仅列出字符数
7.uniq
重复的行只显示一次
uniq [-ic]
-i 忽略大小写
-c 进行计数,相同的行重复了多少次
# 查看某个用户登录了多少次
root@localhost:~ # last|cut -d ' ' -f 1|sort|uniq -c
1
38 designer
87 reboot
1029 root
1 wtmp
root@localhost:~ #
8.head&tail
head [-n [-]K]
输出前K行,默认输出前10行,如果为-K则输出第1行至倒数第K行(不包括倒数第K行)
tail [-n [+]K]
输出最后K行,默认输出最后10行,如果为+K则输出第K行至最后一行
tail -f file
滚动输出追加到文件尾的行,一般用于刷日志
tail -[数字]f file 指定刷多少行后停止,若不指定一直刷
暂停刷新 Ctrl+S 恢复刷新 Ctrl+Q 退出刷新 Ctrl+C
root@localhost:~ # cat f1.txt
123 => 第1行
456 => 第2行
789 => 第3行
101 => 第4行
102 => 第5行
103 => 第6行
104 => 第7行
# 输出前3行
root@localhost:~ # head -n 3 f1.txt
123
456
789
# 输出第1行至倒数第3行(不包括倒数第3行)
root@localhost:~ # head -n -3 f1.txt
123
456
789
101
# 输出最后3行
root@localhost:~ # tail -n 3 f1.txt
102
103
104
# 输出第3行至最后一行
root@localhost:~ # tail -n +3 f1.txt
789
101
102
103
104
9.printf
printf '输出格式' 文本内容,参考c语言的printf
| \f | 清除屏幕 |
| \t | tab键 |
| \xNN | 用16进制表示的ascii字符 |
| \" | 双引号 |
| \\ | 反斜杠 |
| %% | 百分号 |
| %ns | 输出字符串,占n个字符宽,默认右对齐,使用-表示左对齐 |
| %nd | 输出整数,占n位宽 |
| %N.nf | 输出浮点数,保留n位小数,总共10位宽 |
root@localhost:~ # printf "%-10s %-8s %-4s\n" 姓名 性别 "体重(kg)"
姓名 性别 体重(kg)
root@localhost:~ # printf "%-10s %-8s %-4.2f\n" 杨过 男 68.6543
杨过 男 68.65
10.less
less用于查看文本内容,支持搜索、翻页等操作
# 查看confdb_v2.xml每行的最后修改记录
svn blame -c 51014 components/rootfs/etc/confdb_v2.xml|less -N
常用选项和操作如下:
| -N | 显式行号,默认不显示 |
| 空格 | 向下翻页 |
| b | 向上翻页 |
| j | 向下滚动一行 |
| k | 向上滚动一行 |
| g | 跳转到文件开头 |
| G | 跳转到文件结尾 |
| q | 退出 |
| / | 搜索 |
| {行号}G | 跳到指定行 |
11.diff
该命令用于按行比较两个文件,有2种模式
normal模式 - 两个文件的不同分开显示,默认是这种模式
unified模式 - 两个文件的不同合在一起显示,类似于svn diff,使用-u选项启用这种模式
[jianjunyang@~/top/tmp]$ diff -u rootfs/etc/confdb_v2.xml ../components/rootfs/etc/confdb_v2.xml|head -n 50
--- rootfs/etc/confdb_v2.xml 2024-04-02 17:07:02.900805981 +0800
+++ ../components/rootfs/etc/confdb_v2.xml 2024-04-02 17:31:33.715112317 +0800
@@ -1,19 +1,19 @@
-<?xml version='1.0' encoding='utf-8'?>
-<Device xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://skynetworks.com.cn/nr/fapservice confdb_v2.xsd">
+<?xml version="1.0" encoding="utf-8"?>
+ <Device xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://skynetworks.com.cn/nr/fapservice confdb_v2.xsd">
<DeviceInfo>
- <DnPrefix />
+ <DnPrefix></DnPrefix>
<MU id="1">
- <ManufacturerOUI>0011B5</ManufacturerOUI>
- <Manufacturer>GR</Manufacturer>
- <ModelName>GR BU1002</ModelName>
+ <ManufacturerOUI>8CE468</ManufacturerOUI>
+ <Manufacturer>NR-gNB</Manufacturer>
+ <ModelName>SNB0000</ModelName>
<SerialNumber>SNB000000000</SerialNumber>
- <HardwareVersion>V1.1</HardwareVersion>
- <SoftwareVersion>GR_N-001-0394_V2.1.01.R01_211024-Release01</SoftwareVersion>
+ <HardwareVersion>1.0.0.0</HardwareVersion>
+ <SoftwareVersion />
<HardwarePlatform>x86</HardwarePlatform>
- <AdditionalHardwareVersion>V3.0023.07.202302</AdditionalHardwareVersion>
+ <AdditionalHardwareVersion />
<AdditionalSoftwareVersion />
- <ProvisioningCode />
- <ProductClass>ExtendedPicoCell</ProductClass>
+ <ProvisioningCode>NR-gNB</ProvisioningCode>
+ <ProductClass>SNB</ProductClass>
<UpTime>1000</UpTime>
<FirstUseDate>2019-09-17T00:00:00Z</FirstUseDate>
<Status>1</Status>
@@ -23,16 +23,16 @@
<DataModel>TR-181-X1</DataModel>
<PackPosition>1-1-1</PackPosition>
<SlotsOccupied>1</SlotsOccupied>
- <ManufacturerOUI>0011B5</ManufacturerOUI>
- <Manufacturer>GR</Manufacturer>
- <ModelName>GR BU1002</ModelName>
+ <ManufacturerOUI>8CE468</ManufacturerOUI>
+ <Manufacturer>NR-gNB</Manufacturer>
+ <ModelName>SNB0000</ModelName>
余略
输出结果解释:
--- rootfs/etc/confdb_v2.xml 2024-04-02 17:07:02.900805981 +0800
+++ ../components/rootfs/etc/confdb_v2.xml 2024-04-02 17:31:33.715112317 +0800显示两个文件的信息
@@ -1,19 +1,19 @@
第一个文件的1~19行和第二个文件的1~19行比较
再下面就是比较结果
- 表示从第一个文件删除
+ 表示添加到第一个文件
有用的选项
| -w | 忽略所有不可见字符 |
| -B | 忽略空白行 |
| -i | 忽略大小写 |
| -x PAT | 比较目录时排除PAT模式的文件 |
| -r | 比较目录时递归比较比较子目录 |
| -q | 比较目录时只输出不同文件,不进行文件内容比较 |
| -e | 将比较结果保存为ed脚本,通过ed程序执行该脚本修改文件1使其与文件2的内容相同 |
#1 保存ed脚本
[jianjunyang@~/top/tmp]$ diff -e rootfs/etc/confdb_v2.xml ../components/rootfs/etc/confdb_v2.xml > ed.txt
diff: rootfs/etc/confdb_v2.xml: No newline at end of file
#2 在ed脚本末尾添加write指令
[jianjunyang@~/top/tmp]$ echo "w" >> ed.txt
#3 将ed脚本应用于文件1
[jianjunyang@~/top/tmp]$ ed - rootfs/etc/confdb_v2.xml < ed.txt
Newline appended
12.patch
十七、ELF工具
objdump
nm
readelf
[jianjunyang@~]$ addr2line -e ./a.out -fCsp 0x401aef
OamUtils::StrSplit(std::string, std::string) at OamUtils.cc:31
[jianjunyang@~]$
# 0x401aef函数相对地址,可以通过printf("%p")或std::cout << std::hex << reinterpret_cast<void*>(fp)获得
addr2line 根据函数地址获取函数位置,编译时需加上-g选项
objcopy
十八、gdb调试
GDB启动(调试)方式
- gdb调试core文件
gdb program core_file
gdb -s sym_table -e program_release -c core_file #通过导入符号表调试core文件
先启动gdb program,[这里可以设置需要的gdb环境],然后使用core-file filename导入core文件
gcore [file] 在调试过程中手动导出core文件,若不指定file则默认为core.pid
Linux提供了两个脚本工具分别用来导出正在运行的进程的堆栈和core文件,都是封装了gdb命令
- /usr/bin/gstack 导出正在运行的进程的堆栈
- /usr/bin/gcore 导出正在运行的进程的core文件
gdb program pid
gdb -p pid
先启动gdb [program],然后attatch pid
当gdb附着到一个进程时,该进程的状态变为t+(参见进程管理章节),此时我们可以设置断点,接着continue让进程继续运行,此后可能会有两种结果:
(1) 进程因死循环或睡眠态等原因没有中断点,此时按Ctrl+C让进程重新变为t+,通过bt查看堆栈卡在哪里
(2) 顺利中断点就是我们预期的结果,此时就可以进行调试,比如查看堆栈、变量、内存等
调试完以后,先执行detach取消附着,再按q退出gdb,被调试进程继续运行
- gdb调试尚未执行的程序[深入理解debuginfo]
gdb --args program cmd-arguments #也可以在gdb启动后通过set args设置命令行参数
gdb -se program_debug #调试Debug版程序
gdb -s sym_table -e program_release #通过导入符号表调试Release版程序
| **提取符号表到单独的文件 strip/objcopy --only-keep-debug a.out a.out.debug #符号表文件后缀通常为.debug strip/objcopy --only-keep-debug libadd.so libadd.so.debug **使可执行文件或库和符号表关联起来,让gdb可以获取到调试信息 objcopy --add-gnu-debuglink=a.out.debug a.out objcopy --add-gnu-debuglink=libadd.so.debug libadd.so 然后.debug文件放在/usr/lib/debug/.build-id或跟a.out/.so相同目录 **软件发布时会删除符号表以减小软件包的大小 strip/objcopy --strip-debug a.out strip/objcopy --strip-debug libadd.so 从.debug中查看源码信息 readelf -w a.out.debug DW_AT_name #源文件名 DW_AT_comp_dir #源文件路径 如果想在gdb调试过程中查看源码,复制源文件到本地相应的路径(如无则新建)即可 |
调试程序依赖的动态库
动态库搜索路径
set sysroot path 设置调试程序的根目录,默认为空. 调试过程中所有的绝对路径都会加上path前缀,例如: /bin 会转为 /path/bin
set solib-absolute-prefix 作用同上,set sysroot的别名
set solib-search-path path 设置动态库路径,如果想设置多个路径则用冒号分隔,默认是当前路径. 作用是当使用'sysroot'没找到目标时就在该路径下查找
手动加载动态库
当执行start或调试core文件时gdb会自动加载动态库,当程序依赖的库太多时会占用很多内存,有时我们希望只加载需要的库即可
set auto-solib-add on|off 执行start之前设为off即不会自动加载动态库符号,默认为on
share [regex] 执行start后,用该命令加载需要的动态库,如果不加regex则加载所有的库
info share [regex] 查看当前加载的匹配regex的动态库,不加regex则列出所有已加载的库
nosharedlibrary 卸载从共享库加载的所有符号
查看源文件代码
| list | 列出当前所在行的周围10行 |
| list n | 列出第n行的周围10行 |
| list func-name | 列出该函数的前10行 |
| list n1,n2 | 列出第n1至n2行 |
| list file-name:func-name | 列出指定文件的某个函数的前10行 |
| list file-name:n1,n2 | 列出指定文件的第n1至n2行 |
| list file:class::func | 列出某个文件的某个类的某个函数的周围10行 |
基础命令
| start |
运行程序到
main
函数的起始处
|
| r/run |
运行要
debug
的程序
|
| n/next | 执行一条语句,不会跳入函数调用 |
| s/step | 执行一条指令,会跳入函数调用 |
| c/continue |
继续执行要
debug
的程序
|
| finish | 执行当前函数的所有语句并从栈帧返回,并打印返回值 |
| u/until line | 运行到某一行暂停 |
| bt |
打印函数调用堆栈
|
| f/frame [n] | 打印指定/当前栈帧的信息 |
| info f [n] | 打印指定/当前栈帧的详细信息,包括变量和寄存器地址 |
| info args | 打印调用当前函数的参数 |
| info locals | 打印当前函数的局部变量和值 |
| info registers | 查看寄存器 |
| info signals | 查看信号 |
| up | 打印调用当前函数的栈帧 |
| down | 打印被当前函数调用的栈帧 |
| p/print | 打印表达式的值 |
| whatis | 查看表达式的类型 |
| ptype | 查看数据类型的定义 |
| x /fmt addr | 打印内存 |
| call func arg1 arg2 ... | 调用程序中的一个函数 |
断点命令
b/break locspec [thread thread-id] 设置断点,参数可以是函数名,[文件名:]行号,指令地址
b locspec [thread thread-id] if cond 设置条件断点
对于多线程程序,断点可以设在指定线程上,如不指定则设在所有线程上
b 50
b file.cpp:50
b func #在函数开始处暂停
b file.cpp:func #指定文件名和函数名
b class:func #指定类名和函数名
b 50 if i==100 #当i等于100时在第50行暂停,常用于循环中
i/info b/break 查看断点信息
d/delete num 删除指定的断点
d 3 #删除断点3
d 1-3 #删除断点1-3
d 1-3 5-8 #删除断点1-3和断点5-8
d 1 3 5 6 #删除断点1 3 5 6
disable [b/breakpoints] [list...] 禁用断点
enable [b/breakpoints] [list...] 激活断点
enable [b/breakpoints] once list... 只激活激活一次
watch variable
watch a*b + c/d
watch *(type *)address #通过内存地址设置断点
watch variable thread 1 #只有1号线程操作变量时才暂停
查看内存
x/[n]f[u] [ADDR-expr]
ADDR-expr: 地址或地址表达式,不写则打印当前地址
n: 要显示几个地址单元,根据u确定每个单元多少字节,默认为1
f: 显示格式,有以下几种
o - octal x - hex d - decimal u - unsigned decimal
t - binary f - float a - address i - instruction
c - char s - string
u: 以多少字节作为一个内存单元,默认为4字节
b - byte,1字节 h - halfword,2字节 w - word,4字节 g - giant, 8 bytes
x/4i
(gdb) x/4i 0x401d1e <_ZZL18__gthread_active_pvE20__gthread_active_ptr+6>: add %al,(%rax) 0x401d20 <_ZNSs4_Rep11_S_terminalE>: add %al,(%rax) 0x401d22: add %al,(%rax) 0x401d24: add %ebx,(%rbx)x/s
(gdb) x/s 0x401cc0 0x401cc0: "Hello C++"
查看源码的内存
info line [文件名:]行号
info line [文件名:]函数
info line *addr #覆盖该地址的源代码范围
查看汇编代码
disas/disassemble [modifier] [start,end] #显示某个地址范围的汇编
disas/disassemble [modifier] [start,+length]
disas/disassemble [modifier] ['文件名'::函数名] #单引号不能省略
modifier可以是/m /s /r /b,低版本gdb可能没有/s /b标志
/m 显示汇编代码和源代码
/r 显示原始指令和符号表
(gdb) disas /m 'test.cpp'::main
Dump of assembler code for function main():
5 {
0x0000000000401328 <+0>: push %rbp
0x0000000000401329 <+1>: mov %rsp,%rbp
0x000000000040132c <+4>: push %rbx
0x000000000040132d <+5>: sub $0x18,%rsp
6 std::string str = "Hello C++";
=> 0x0000000000401331 <+9>: lea -0x11(%rbp),%rax
0x0000000000401335 <+13>: mov %rax,%rdi
0x0000000000401338 <+16>: callq 0x401140 <_ZNSaIcEC1Ev@plt>
0x000000000040133d <+21>: lea -0x11(%rbp),%rdx
0x0000000000401341 <+25>: lea -0x20(%rbp),%rax
......
(gdb) disas /r $pc,+20 #pc是程序计数器
Dump of assembler code from 0x401331 to 0x401345:
=> 0x0000000000401331 <main()+9>: 48 8d 45 ef lea -0x11(%rbp),%rax
0x0000000000401335 <main()+13>: 48 89 c7 mov %rax,%rdi
0x0000000000401338 <main()+16>: e8 03 fe ff ff callq 0x401140 <_ZNSaIcEC1Ev@plt>
0x000000000040133d <main()+21>: 48 8d 55 ef lea -0x11(%rbp),%rdx
0x0000000000401341 <main()+25>: 48 8d 45 e0 lea -0x20(%rbp),%rax
End of assembler dump.
(gdb) p &main
$3 = (int (*)(void)) 0x401328 <main()>
(gdb) disas /r 0x401328,+10
Dump of assembler code from 0x401328 to 0x401332:
0x0000000000401328 <main()+0>: 55 push %rbp
0x0000000000401329 <main()+1>: 48 89 e5 mov %rsp,%rbp
0x000000000040132c <main()+4>: 53 push %rbx
0x000000000040132d <main()+5>: 48 83 ec 18 sub $0x18,%rsp
=> 0x0000000000401331 <main()+9>: 48 8d 45 ef lea -0x11(%rbp),%rax
调试多进程
set follow-fork-mode parent|child 设置GDB在fork时继续调试父进程还是子进程
info inferiors 查看进程列表
inferior n 切换到编号为n的进程调试
调试多线程
info threads 查看线程
t/thread thread-id 切换线程
set scheduler-locking on|off 只运行当前线程/运行所有线程
thread apply [thread-id-list | all] command 对指定线程执行命令
其它命令
set、info、show、display、macro、dir
| **安装glibc调试信息调试printf/malloc/fork等系统调用 1.查询glibc版本 rpm -qa|grep glibc 2.debuginfo-install glibc-2.17-222.el7.x86_64 #debuginfo-install是一个python脚本 **安装libstdc++.so调试信息调试std::string/std::vector等C++标准库 1.rpm -qa|grep libstdc++ 2.debuginfo-install libstdc++-4.8.5-28.el7_5.1.x86_64 在使用libstdc++进行调试时,编译时要开启以下预定义宏: -D_GLIBCXX_DEBUG:开启libstdc++的调试模式 -D_GLIBCXX_DEBUG_PEDANTIC:开启libstdc++的严格调试模式 -D_GLIBCXX_DEBUG_VERBOSE:开启libstdc++的详细调试模式 -D_GLIBCXX_DEBUG_ASSERTIONS:开启libstdc++的断言检测 比如:g++ -g -D_GLIBCXX_DEBUG test.cpp **安装gcc调试信息,安装C++调试信息时这个也会被安装,一般不用单独安装 1.rpm -qa|grep libgcc 2.debuginfo-install libgcc-4.8.5-28.el7_5.1.x86_64 |
输出调试日志
有些命令输出的内容太多,比如bt、info functions、p [vector/map]等,如果显示在终端不好查看,gdb可以把这些内容输出到日志文件中
set logging on|off 开启/关闭日志模式
set logging file [name] 设置日志文件名,默认为gdb.txt
set logging overwrite on|off 以覆盖/追加方式输出
set logging redirect on|off 只输出到日志/既输出到日志又在终端显示
set logging 查看日志设置
数组打印长度
set print elements num
对于大数组,包括c++ string、vector、map等,默认只打印200个元素,通过该命令可以打印更多的元素
#打印堆上分配的数组
p *array@len #array为首地址,len为要打印的元素个数
- 其他调试工具
binutils
strace -p pid 打印进程的系统调用信息
pstack pid 查看进程调用堆栈,该命令是gstack的软链接
ldd 查看bin/.so的依赖库,它是一个shell脚本
cpp -dM /dev/null 查看gcc定义的所有预编译宏
十九、软件安装
Linux下软件包的下载与安装主要有两种机制:Debian下的dpkg,如Ubuntu;Red Hat系列下的RPM,如Fedora,CentOS
RPM安装升级
RPM安装包以rpm作为后缀,里面包含了在相应的硬件平台和操作系统下编译好的二进制文件,并且在头部会插入所依赖的软件信息,比如想要安装A,必须先安装B。所以在用rpm包安装软件时,首先会进行环境检查,如果硬件和系统与打包时的不一致,或者所依赖的软件未安装,那么就会安装失败。
rpm安装/升级/卸载:
- -i:install
- -v:显示安装信息
- -h:显示安装进度
rpm -ivh pkgname.rpm
rpm -ivh http://website.name/path/pkgname.rpm #以网络上的rpm包安装
- --test:测试该软件包是否可以被安装
rpm -ivh pkgname.rpm --test
- -e:uninstall,卸载
rpm -e pkgname
- -U:不管该软件有没有安装过,都会升级
- -F:如果该软件没有被安装过,则不会升级
rpm -Uvh pkgname.rpm
rpm -Fvh pkgname.rpm
rpm查询:
- -q:query,查询
- -qa:列出所有已安装的软件
rpm -qa
- -qi:列出该软件的详细信息,如版本、大小、开发者等
- -ql:列出该软件相关的文件和目录
- -qc:列出该软件的配置文件(/etc)
- -qd:列出该软件的帮助文档
- -qR:列出该软件所依赖的软件
rpm -q[ilcdR] pkgname
- -qf:查找该文件属于哪个已安装的软件
rpm -qf /usr/bin/sh
YUM在线安装升级
前面讲过,当rpm检查到所依赖的软件未安装时会退出安装。yum就很好地解决了这个问题,它会自动安装所依赖的软件,软件包是放在yum服务器上的,所以linux要能联网才行。当然,如果linux不能联网也可以把光盘或iso镜像挂载到某个目录作为软件源。
yum配置文件
/etc/yum.repos.d/目录下的文件就是yum软件源站点,我们也可以手动修改
root@192:~ # ll /etc/yum.repos.d/
total 36
-rw-r--r--. 1 root root 1664 Aug 30 2017 CentOS-Base.repo #CentOS官方软件源
-rw-r--r--. 1 root root 1309 Aug 30 2017 CentOS-CR.repo
-rw-r--r--. 1 root root 649 Aug 30 2017 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 314 Aug 30 2017 CentOS-fasttrack.repo
-rw-r--r--. 1 root root 630 Aug 30 2017 CentOS-Media.repo #挂载光盘或ISO作为软件源
-rw-r--r--. 1 root root 1331 Aug 30 2017 CentOS-Sources.repo
-rw-r--r--. 1 root root 3830 Aug 30 2017 CentOS-Vault.repo
-rw-r--r--. 1 root root 951 Oct 3 2017 epel.repo
-rw-r--r--. 1 root root 1050 Oct 3 2017 epel-testing.repo
root@192:~ #
yum repolist all 列出yum server的软件库有哪些,是否激活
yum查询
- list:列出软件源所有的软件名称以及版本
yum list
yum list pkgname 查看某个软件是否已安装
yum list installed 列出已安装的软件
yum list updates 列出需要更新的软件
- info:列出某个软件的详细信息,类似rpm -qi
yum info pkgname
yum安装/升级/卸载
- -y:当yum要等待用户输入时,该选项会自动输入yes
- --installroot=/some/path:将软件安装在/some/path,而不使用默认路径
- install:安装
- update:升级
yum install pkgname [-y --installroot=/some/path]
yum update pkgname
- remove:卸载
yum remove pkgname
二十、Linux日志
Linux系统重要的日志文件有下面这些:
- /var/log/boot.log
Linux系统启动时会检测与启动硬件,还会启动各种守护进程(服务),这些流程会被记录在该文件中
- /var/log/cron
定时任务日志,了解crontab与at命令
- /var/log/dmesg
Linux开机信息记录在该文件中。这些信息也会被记录在环状缓存中,通过dmesg命令查看
- /var/log/lastlog
记录所有账号最近一次登录系统的相关信息,不是文本文件,要用lastlog命令查看
- /var/log/messages
系统几乎所有的重要信息都会记录在这个文件中,很重要
- /var/log/secure
需要输入账号密码的信息都会记录在这里,如sshd
- /var/log/wtmp /var/log/btmp
/var/log/wtmp 登录成功的用户信息
/var/log/btmp 登录失败的用户信息
需要用last命令查看,比如last -f /var/log/btmp,直接运行last命令读取的就是/var/log/wtmp
更多推荐

所有评论(0)