一、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套接字
pFIFO
# 查找当前目录的子目录
[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是显示目录栈的内容。目录栈就是一个保存目录条目的栈结构,该栈结构的顶端永远都存放着当前目录

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 sizeCPU二级缓存大小
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使用率或内存使用率降序排序

usersidpgidpidppidpsr%cpu%memvszrssstatlstartstimeetimetimecommcmd
用户名会话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/ 网卡配置

        Linux系统的网络命名空间那些事

        Linux网络命名空间命令实操

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)网卡接口
MSSDefault maximum segment size for TCP connections over this route.
WindowDefault window size for TCP connections over this route.
irtt此路由的初始往返时间
Next Hop下一跳地址,相当于Gateway
Flag含义说明
Uroute is up
Htarget is a host
Guse gateway
R恢复动态路由产生的表项
D由路由的后台程序动态地安装
M由路由的后台程序修改
!拒绝路由

路由匹配原则

  1. 最长子网掩码优先
  2. 最小管理距离AD优先(路由协议优先级)
  3. 最小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

sed动作
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.对后续所有行重复上面的步骤

awk内置变量
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清除屏幕
\ttab键
\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 --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... 只激活激活一次

enable [b/ breakpoints ] delete list... 激活一次后删除
特殊断点watchpoint
watch  expr  [ thread thread-id]  当变量被访问、读写或表达式值改变时暂停

watch variable

watch a*b + c/d

watch *(type *)address  #通过内存地址设置断点

watch variable thread 1 #只有1号线程操作变量时才暂停

注意事项:
        当监控局部变量时,一旦局部变量失效,断点也会失效
        如果监控指针变量,注意区分watch *p和watch p的含义
常见应用场景:比如定位结构体成员何时被改变

查看内存

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  对指定线程执行命令

[gdb调试线程死锁实战]

其它命令

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

Logo

更多推荐