Linux命令总结
一、压缩/解压1、tar -cvf test.tar [文件|目录]只打包,不压缩选项-c:建立tar包-v:显示过程信息-f:必须是最后一个选项,后面紧跟打包文件名2、tar -xvf test.tar解开tar包选项-x:解包3、压缩格式选项-z:gz格式-j:bz2格式-J:xz格式压缩tar -zcvf test.tar.gz [文件|目录]tar -jcvf test.tar.bz2 [
一、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
四、目录切换
基本目录切换命令:cd [相对路径|绝对路径]、cd -
进阶目录切换命令:pushd、popd和dirs
pushd和popd是对一个目录栈进行操作,dirs是显示目录栈的内容。目录栈就是一个保存目录条目的栈结构,该栈结构的顶端永远都存放着当前目录
-p | 每行显示一条记录 |
-v | 每行显示一条记录,并显示该记录在栈中的索引 |
-c | 除当前目录外清空目录栈 |
pushd [路径] 将指定路径添加到目录栈栈顶,也即将当前目录切换到指定路径
pushd +n 将当前目录切换到目录栈中索引为n的目录
pushd 不带参数切换栈顶的两个目录互相切换
popd +n 将目录栈中索引为n的目录移除出栈
pushd -n [路径] 添加目录到目录栈,不改变当前目录,仅对栈进行操作
popd -n +N 将索引为N的目录移除出目录栈,不改变当前目录,仅对栈进行操作
五、目录树与挂载
我们知道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
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 查看每个账号的最近登录时间
十一、网络抓包
- -w:将数据包输出到文件 tcpdump -i ens37 -w /tmp/test.pcap 默认打印到屏幕
- -n
- -nn
- -nnn 以数字形式显示域名和端口,否则会显示域名和服务名
- -X
- -XX
- -XXX 以16进制和ascii的形式显示数据包
- -v
- -vv
- -vvv 打印详细的输出信息
- -r:解析文件中的数据包
tcpdump -r /tmp/aaa.pcap 默认以紧凑格式打印报文
tcpdump -A -r /tmp/aaa.pcap 以ASCII格式打印报文
tcpdump -X -r /tmp/aaa.pcap 以十六进制格式打印报文
- -i:指定网络接口
tcpdump -i any 抓取所有接口的数据包
tcpdump -i lo 抓取环回接口的数据包(127.0.0.1)
tcpdump -i eth0 抓取eth0接口的数据包
- -c:设置抓取的数据包数量,达到该数量自动终止抓包,默认不终止
tcpdump -i eth0 -c 200 -w /tmp/test.pcap 从eth0接口抓取200个数据包后终止
- -s:截取每个数据包的报文大小,默认截取68字节
tcpdump -i eth0 -s 0 -w /tmp/test.pcap 每个数据包截取68字节
tcpdump -i eth0 -s 200 -w /tmp/test.pcap 每个数据包截取200字节
- 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 过滤192.168.3.0的数据包
- 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等
tcpdump -i eth0 tcp 抓取tcp包
- 逻辑运算符
与:and 或 &&
或:or 或 ||
非:not 或 !
tcpdump tcp and port 80 and (dst host (192.168.1.254 or 192.168.1.200))
十二、网络工具
/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
addr2line 根据函数地址获取函数位置,编译时需加上-g选项
十八、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
调试多线程
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)