Linux学习笔记

  • 查看cpu命令

    小技巧

    1. cp小技巧

    cp /etc/test{,.bak}  #此命令执行效果同等于  cp /etc/test  /etc/test.bak   此方法写的格式也用用作mv,echo等.
    echo 1111{,.bak}
    1111 1111.bak
    

    2. 恢复传统网卡名

    因为centos7后就修改了网卡名,所以我们将网卡名都改成eth0,这样也好认,统一一下

    vim /etc/default/grub
    #第六行修改成以下配置
    GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.    lvm.lv=centos/swap rhgb quiet net.ifnames=0
    #然后运行下面的命令
    grub2-mkconfig -o /boot/grub2/grub.cfg  && reboot
    

    注意:改了之后将之前的配置文件删除哦。而且将配置文件名字,配置里的名字也都改成eth0.不然网络会有问题

    3. 让grep 结果有颜色

    alias grep= 'grep --color=auto'
    

    4. 查看关键字是否时程序中的保留字

    范例:

    type then
    then 是 shell 关键字
    

    5. 主机名不支持 _ 符号

    6. 设置命令别名

    alias cdnet='cd /etcsysconfig/network-scripts/'
    

    7. tcpdump

    tcpdump -S tcp  -nn -i em1 -c 20
    

    8. 查看所使用的端口

    netstat -nltp
    
    

    9. 取随机数

    内建的随机数生成器变量:

    echo $RANDOM    #取值范围:0-32767
    

    10. set查看所有变量

    set 能看所有变量包括环境变量,普通变量 与 env 不同,env 只列环境变量。set 看到的变量看不到你没用过的变量,没有用过的变量它不生成你也就看不到。

    set 
    

    11. Centos安装编译安装环境

    sudo yum groupinstall "Development Tools"
    

    12. 磁盘Inode

    #查看硬盘 Inode占用值
    [root@TEST ~ 06:08:01]#df -i                                
    文件系统                   Inode 已用(I)  可用(I) 已用(I)% 挂载点
    devtmpfs                  470465     384   470081       1% /dev
    tmpfs                     473444       1   473443       1% /dev/shm
    tmpfs                     473444    1642   471802       1% /run
    tmpfs                     473444      16   473428       1% /sys/fs/cgroup
    /dev/mapper/centos-root 47708160  347708 47360452       1% /
    /dev/sda1                 524288     340   523948       1% /boot
    #Inode一个文件占用一个值,如果想快速占满分区Inode值可采用以下办法
    #我们找一个少一点的,比如 /boot 它空闲的是523948那我们就创建523948个文件,这样就可以快速占满了
    [root@TEST ~ 06:08:01]#cd /boot
    [root@TEST ~ 06:08:01]#touch test{1..523948}
    

    13. 修改Linux终端命令提示符颜色

    终端命令提示符的变量其实就是 PS1变量,如果要改提示符颜色的话就需要更改PS1的变量

    范例:

    #临时将终端修改成黄字黑底,显示当前用户的账号名称、主机的第一个名字、完整的当前工作目录名称、24小时格式时间,这样设置只是临时生效,退出终端重新进就会失效
    PS1=”[\e[32;40m][\u@\h \w \T]$[\e[0m]”
    #永久修改,就是将上面的命令 写入/etc/profile或/etc/bashrc或/etc/profile.d下的sh文件 对全部用户生效;写入~/.bash_profile或~/.bashrc 只对当前用户生效。然后 source 一下就可以生效。
    

    14. 查看yum软件依赖哪个包

    范例:

    [root@TEST ~/ddd/study 04:17:52]#yum provides compress
    已加载插件:fastestmirror
    Loading mirror speeds from cached hostfile
     * base: ftp.sjtu.edu.cn
     * extras: mirror.bit.edu.cn
     * updates: ftp.sjtu.edu.cn
    base/7/x86_64/filelists_db                               | 7.2 MB     00:01     
    extras/7/x86_64/filelists_db                             | 224 kB     00:00     
    updates/7/x86_64/filelists_db                            | 2.7 MB     00:00     
    ncompress-4.2.4.4-3.1.el7_8.x86_64 : Fast compression and decompression
                                       : utilities
    源    :base
    匹配来源:
    文件名    :/usr/bin/compress
    

    15. 自动挂载光驱

    实现这一步需要光驱已跟主机相连。才可以实现这神奇的挂载效应。

    #先安装autofs软件包
    yum -y install autofs
    #设置开机启动并现在启动这个服务
    systemctl enable --now autofs
    #然后我们进入神奇的路径,这个路径就是默认自动挂载的光盘路径
    cd /misc/cd
    #默认是五分钟不访问这个路径自动卸载
    

    16. 查看光盘安装包的类型个数,并排序

    #方式一
    [root@TEST /misc/cd/Packages 02:34:13]#ls *.rpm | rev | cut -d"." -f2 | rev | sort | uniq -c
       1405 noarch
       2666 x86_64
    #方式二
    [root@TEST /misc/cd/Packages 02:34:25]#ls *.rpm | egrep -o "[^.]+\.rpm$" | sort | uniq -c
       1405 noarch.rpm
       2666 x86_64.rpm
    

    17. 去掉别名作用

    #比如你之前设置了mv的别名,将mv原来的命令改为别的了,但是我们还是需要mv命令的那我们需要在 前面加\,例子:
    [root@TEST /var/lib/rpm 03:35:54]#\mv --help
    

    18. 光盘救援模式安装软件

    当我们误删系统某个命令造成系统环境崩坏的时候我们可以通过光盘的救援模式来恢复。下面也有写,不过这里单独针对重新安装软件包做一个介绍。

    #比如我们一不小心将rpm工具卸载了
    rpm -e rpm --nodeps
    #然后我们进入救援模式执行下面命令
    rpm -ivh rpm-4.11.rpm. --root=/mbt/sysimage/
    #这里我们需要指定一下安装的根目录,因为在救援模式下你直接安装的话是安装在救援系统下的根目录,并不是我们系统中的根目录,所以需要切换一下。
    #这里提一下切换根目录的命令
    chroot --root=/mnt/sysimage/
    

    19.复制文件

    cp -r /test/.  ./. #复制test目录下的隐藏与非隐藏文件到当前目录下
    

    查看cpu命令

    #查看物理CPU个数
    cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
    # 查看每个物理CPU中core的个数(即核数)
    cat /proc/cpuinfo| grep "cpu cores"| uniq
    #查看逻辑CPU的个数
    cat /proc/cpuinfo| grep "processor"| wc -l
    #查看CPU信息(型号)
    cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c
    

    日常命令

    1. echo

    1.1 echo {}简化配置样例

    [root@centos8 ~]#echo {000..20..2} 
    000 002 004 006 008 010 012 014 016 018 020 
    [root@centos8 ~]#echo {a..z..2} 
    a c e g i k m o q s u w y 
    [root@centos8 ~]#echo {A..z} 
    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z
    
    echo "dhdjdjd" | rev    #倒序
    

    1.2 echo 换行

    [root@TEST ~/Script 07:19:30]#echo -e "+\n-\n*]\n/"
    +
    -
    *]
    /
    

    2. tr命令

    说明:tr命令多用于去重,替换等操作。

    选项:
    --d delete:删除所有属于第一字符集的字符
    -s --squeeze-repeats:把连续重复的字符以单独一个字符表示,即去重 -t --truncate-set1:将第一个字符集对应字符转化为第二字符集对应的字符
    -c -C --comp1ement: 取字符集的补集
    范例:

    #将/etc/issue中的小写字母转换成大写字母
    tr 'a-z'  'A-Z' < /etc/issue
    #删除fstab文件中的所有abc中任意字符
    tr -d abc < /etc/fstab
    #将df 输出结果中的空格去重
    df | tr -s ' '
    

    3. ss 查看端口连接状态

    ss -nt
    State       Recv-Q Send-Q     Local Address:Port                    Peer Address:Port              
    ESTAB       0      0          172.16.80.130:22                       172.16.80.1:62103 
    

    无命令运行路径排查

    ps aux
    root      15094  0.0  0.0 108088   612 pts/1    S+   21:44   0:00 tail -f test.log
    cd /proc/15094/
    ls -al
    lrwxrwxrwx.   1 root root 0 12月 13 21:45 exe -> /usr/bin/tail   #命令软连接在bin下
    

    强制同步磁盘

    sync
    

    Linux用户管理

    如果说生产中有新员工A要接替离职员工B的工作,我们按照原有的逻辑需要将原有的老用户B删除,然后创建一个新用户A并且新用户A的id与老用户B的一样。这样的操作比较麻烦,我们只需将老用户B的用户名改成新用户A的用户名即可。至于如何修改就是将原有用户的家目录名,mail目录名等目录名改为新的目录名即可。

    创建系统用户

    useradd -r -s /bin/false -u 336 mysql #创建mysql用户,并设为系统用户指定uid为336,指定为不可登陆shell
    

    指定用户信息

    chfn user
    

    修改用户默认信息

    usermod  [参数] [用户]
    选项:
      -c, --comment 注释            GECOS 字段的新值
      -d, --home HOME_DIR           用户的新主目录
      -e, --expiredate EXPIRE_DATE  设定帐户过期的日期为 EXPIRE_DATE
      -f, --inactive INACTIVE       过期 INACTIVE 天数后,设定密码为失效状态
      -g, --gid GROUP               强制使用 GROUP 为新主组
      -G, --groups GROUPS           新的附加组列表 GROUPS
      -a, --append GROUP            将用户追加至上边 -G 中提到的附加组中,
                                    并不从其它组中删除此用户
      -h, --help                    显示此帮助信息并推出
      -l, --login LOGIN             新的登录名称
      -L, --lock                    锁定用户帐号
      -m, --move-home               将家目录内容移至新位置 (仅于 -d 一起使用)
      -o, --non-unique              允许使用重复的(非唯一的) UID
      -p, --password PASSWORD       将加密过的密码 (PASSWORD) 设为新密码
      -R, --root CHROOT_DIR         chroot 到的目录
      -P, --prefix PREFIX_DIR       prefix directory where are located the /etc/* files
      -s, --shell SHELL             该用户帐号的新登录 shell
      -u, --uid UID                 用户帐号的新 UID
      -U, --unlock                  解锁用户帐号
      -v, --add-subuids FIRST-LAST  add range of subordinate uids
      -V, --del-subuids FIRST-LAST  remove range of subordinate uids
      -w, --add-subgids FIRST-LAST  add range of subordinate gids
      -W, --del-subgids FIRST-LAST  remove range of subordinate gids
      -Z, --selinux-user  SEUSER       用户账户的新 SELinux 用户映射
    

    查看用户信息

    finger [用户]
    chage -l [用户] #查看用户密码策略
    

    批量创建

    批量创建用户

    newusers passwd 格式文件
    

    批量修改用户密码

    chpasswd 接受标准输出,所以用做于批量修改用户密码命令。

    echo username:passwd | chpasswd
    

    查看用户所在组

    groups test
    

    查看组里所存在用户

    groupmems -l -g root
    

    新建用户默认配置

    新建用户默认配置是调用/etc/skel 目录下的文件,如果误删了用户下的默认配置后可通过复制 它目录下的配置文件
    新建默认配置文件三个文件
    新建用户的相关文件:
    /etc/default/useradd
    /etc/skel/*
    /etc/login.defs

    ls -al /etc/skel/
    cp -r /etc/skel/.  ./ #此命令是复制/etc/skel 目录小隐藏与非隐藏的所有文件到当前目录
    

    Shadow存放密码文件

    test:$6$6M4GcIQN$KeyHVaBtDV.ZuCt.hwKGKPj24t/ec4J9xXlgIJ5F3jgLE8FVY5zNV2zJ0K6aNB/TEIrWTVsolYiG88pYkHqRq1:18609:0:99999:7:::
    #配置文件格式:用户+加密密码+密码修改时间1970unix元年开始算+口令最短有效期+口令过期时间+过期提前通知时间+密码过期宽限期+账号有效期
    

    指定ID创建用户

    Linux系统看是否同个用户是看ID的,而不是看名字是否一样。所以两台主机需要用到同用户互联服务的时候我们需要创建同ID的用户,范例命令如下👇:

    useradd -r -u 333 -s /sbin/nologin -c "Seafile" seafile 
    

    su用法

    su - test -c "touch test.logs" #完全切换账户,家创建文件
    su test -c "touch test.logs"    #非完全切换账户,当前环境创建文件
    

    查看进程

    pstree树状查看进程

    Linux pstree命令将所有行程以树状图显示,树状图将会以 pid (如果有指定) 或是以 init 这个基本行程为根 (root),如果有指定使用者 id,则树状图会只显示该使用者所拥有的行程。
    使用权限:所有使用.

    pstree 
    
    pstree -p   #可查看进程号
    

    Linux文件查找压缩管理

    Linux文件查找

    1. locate命令

    locate 查询系统上预建的文件索引数据库 /var/lib/mlocate/mlocate.db
    索引的构建是在系统较为空闲时自动进行(周期性任务),执行updatedb可以更新数据库
    索引构建过程需要遍历整个根文件系统,很消耗资源
    工作特点:
    查找速度快
    模糊查找
    非实时查找
    搜索的是文件的全路径,不仅仅是文件名
    可能只搜索用户具备读取和执行权限的目录

    最小化安装的时候可能没有locate命令,需要自己安装.

    1.1 locate常用命令
    #安装locate命令
    yum -y install mlocate.x86_64
    #强制更新locate数据库
    updatedb
    
    1.2 locate命令格式
    locate [OPTION]... [PATTERN]...
    

    常用选项:

    -i 不区分大小写的搜索
    -n N 只列举前N个匹配项目
    -r 使用基本正则表达式
    
    1.3 locate范例
    #搜索名称或路径中包含“conf”的文件
    locate conf
    #使用Regex来搜索以“.conf”结尾的文件
    locate -r '\.conf$'
    
    #搜索实例
    [root@centos8 ~]#locate -n 10 -ir '\.CONF$'
    /boot/loader/entries/5b85fc7444b240a992c42ce2a9f65db5-0-rescue.conf
    /boot/loader/entries/5b85fc7444b240a992c42ce2a9f65db5-4.18.0-147.el8.x86_64.conf
    /etc/autofs.conf
    /etc/autofs_ldap_auth.conf
    /etc/dracut.conf
    /etc/fuse.conf
    /etc/host.conf
    /etc/idmapd.conf
    /etc/kdump.conf
    /etc/krb5.conf
    

    2. find命令

    find 是实时查找工具,通过遍历指定路径完成文件查找
    工作特点:
    查找速度略慢
    精确查找
    实时查找
    查找条件丰富
    可能只搜索用户具备读取和执行权限的目录
    格式:

    find [OPTION]... [查找路径] [查找条件] [处理动作]
    

    查找路径:指定具体目标路径;默认为当前目录
    查找条件:指定的查找标准,可以文件名、大小、类型、权限等标准进行;默认为找出指定路径下的所
    有文件
    处理动作:对符合条件的文件做操作,默认输出至屏幕

    2.1 指定搜索目录层级

    -maxdepth level 最大搜索目录深度,指定目录下的文件为第1级
    -mindepth level 最小搜索目录深度
    范例:

    find /etc -maxdepth 2 -mindepth 2
    
    2.2 对每个目录先处理目录内的文件,再处理目录本身
    -depth -d
    

    范例:

    [root@centos8 data]#tree /data/test
    /data/test
    ├── f1.txt
    ├── f2.txt
    └── test2
    └── test3
    ├── f3.txt
    └── f4.txt
    4 directories, 2 files
    [root@centos8 data]#find /data/test
    /data/test
    /data/test/f1.txt
    /data/test/f2.txt
    /data/test/test2
    /data/test/test2/test3
    /data/test/test2/test3/f3.txt
    /data/test/test2/test3/f4.txt
    [root@centos8 data]#find /data/test -depth
    /data/test/f1.txt
    /data/test/f2.txt
    /data/test/test2/test3/f3.txt
    /data/test/test2/test3/f4.txt
    /data/test/test2/test3
    /data/test/test2
    /data/test
    
    2.3 根据文件名和inode查找
    -name "文件名称":支持使用glob,如:*, ?, [], [^],通配符要加双引号引起来
    -iname "文件名称":不区分字母大小写
    -inum n 按inode号查找
    -samefile name 相同inode号的文件
    -links n 链接数为n的文件
    -regex “PATTERN”:以PATTERN匹配整个文件路径,而非文件名称
    

    范例:

    find -name snow.png
    find -iname snow.png
    find / -name ".txt"
    find /var –name "log*"
    [root@centos8 data]#find -regex ".*\.txt$"
    ./script40/b.txt
    ./f1.txt
    
    2.4 根据属主、属组查找
    -user USERNAME:查找属主为指定用户(UID)的文件
    -group GRPNAME: 查找属组为指定组(GID)的文件
    -uid UserID:查找属主为指定的UID号的文件
    -gid GroupID:查找属组为指定的GID号的文件
    -nouser:查找没有属主的文件
    -nogroup:查找没有属组的文件
    
    2.5 根据文件类型查找
    -type TYPE
    TYPE可以是以下形式:
    f: 普通文件
    d: 目录文件
    l: 符号链接文件
    s:套接字文件
    b: 块设备文件
    c: 字符设备文件
    p: 管道文件
    

    范例:

    #查看/home的目录
    find /home –type d -ls
    
    2.6 空文件或目录

    -empty
    范例:

    #它会显示空文件夹或者大小为0的文件
    find /app -type d -empty
    
    2.7 组合条件
    与:-a ,默认多个条件是与关系
    或:-o
    非:-not !
    

    范例:

    #默认两个条件一起就是与的关系不用加-a,比如下面的命令就是查找 /etc下空的文件夹
    [root@TEST ~ 01:30:59]#find /etc  -type d -empty
    #下面的查找因加了多个条件导致Linux系统处理时有个优先级的问题,就跟我们小学的加减乘除计算有个优先级处理一样,需要加小括号。例子如下可以看一下加与没加的区别。
    [root@centos8 ~]#find /etc/ -type d -o -type l |wc -l
    307
    [root@centos8 ~]#find /etc/ -type d -o -type l -ls |wc -l
    101
    [root@centos8 ~]#find /etc/ \( -type d -o -type l \) -ls |wc -l
    307
    

    德·摩根定律:

    • (非 A) 或 (非 B) = 非(A 且 B)
    • (非 A) 且 (非 B) = 非(A 或 B)
    • 示例
      !A -a !B = !(A -o B)
      !A -o !B = !(A -a B)

    范例:

    find -user joe -group joe
    find -user joe -not -group joe
    find -user joe -o -user jane
    find -not \( -user joe -o -user jane \)
    find / -user joe -o -uid 500
    [root@centos8 data]#find ! \( -type d -a -empty \)| wc -l
    56
    [root@centos8 data]#find ! -type d -o ! -empty |wc -l
    56
    [mage@centos8 data]$find ! -user wang ! -user mage
    .
    ./script40
    ./script40/backup
    ./script40/backup/args.sh
    ./script40/backup/chook_rabbit.sh
    ./script40/backup/disk_check.sh
    ./script40/backup/ping.sh
    ./script40/backup/systeminfo.sh
    ./script40/backup/test_read.sh
    ./script40/backup/test.sh
    ./script40/if_bmi.sh
    ./script40/case_yesorno.sh
    ./script40/case_yesorno2.sh
    ./script40/b.txt
    ./f1.txt
    ./test
    ./test/f1.txt.link
    ./f1.txtlink
    ./test2
    [root@centos8 home]#ll
    total 0
    drwx------. 2 mage mage 62 Jan 16 17:53 mage
    drwx------. 2 wang wang 62 Jan 16 10:43 wang
    drwx------ 2 xiaoming xiaoming 62 Apr 6 09:51 xiaoming
    [root@centos8 home]#find ! \( -user wang -o -user mage \)
    .
    ./xiaoming
    ./xiaoming/.bash_logout
    ./xiaoming/.bash_profile
    ./xiaoming/.bashrc
    [root@centos8 home]#find ! -user wang -a ! -user mage
    .
    ./xiaoming
    ./xiaoming/.bash_logout
    ./xiaoming/.bash_profile
    ./xiaoming/.bashrc
    #找出/tmp目录下,属主不是root,且文件名不以f开头的文件
    find /tmp ( -not -user root -a -not -name 'f*' ) -ls
    find /tmp -not ( -user root -o -name 'f*' ) –ls
    
    2.8 排除目录

    后面在消化先放一边

    范例:

    #查找/etc/下,除/etc/sane.d目录的其它所有.conf后缀的文件
    find /etc -path '/etc/sane.d' -a -prune -o -name "*.conf"
    #查找/etc/下,除/etc/sane.d和/etc/fonts两个目录的所有.conf后缀的文件
    find /etc \( -path "/etc/sane.d" -o -path "/etc/fonts" \) -a -prune -o -name
    "*.conf"
    #排除/proc和/sys目录
    find / \( -path "/sys" -o -path "/proc" \) -a -prune -o -type f -a -mmin -1
    
    2.9 根据文件大小来查找
    -size [+|-]#UNIT
    常用单位:k, M, G,c(byte),注意大小写敏感
    #UNIT: (#-1, #]
    如:6k 表示(5k,6k]
    -#UNIT:[0,#-1]
    如:-6k 表示[0,5k]
    +#UNIT:(#,∞)
    如:+6k 表示(6k,∞)
    

    范例:

    [root@TEST ~/ddd/study 02:56:24]#du -sh *
    4.0K    disk.sh
    36K LICENSE
    4.0K    README.en.md
    4.0K    README.md
    4.0K    sync_git.sh
    4.0K    systeminfo.sh
    [root@TEST ~/ddd/study 02:56:32]#find /root/ddd/study/  -size +33k
    /root/ddd/study/LICENSE
    [root@TEST ~/ddd/study 02:57:33]#find /root/ddd/study/  -size +34k
    /root/ddd/study/LICENSE
    [root@TEST ~/ddd/study 02:57:36]#find /root/ddd/study/  -size +35k
    [root@TEST ~/ddd/study 02:57:39]#find /root/ddd/study/  -size 37k
    [root@TEST ~/ddd/study 02:59:13]#find /root/ddd/study/  -size 35k
    /root/ddd/study/LICENSE
    [root@TEST ~/ddd/study 02:59:16]#find /root/ddd/study/  -size 34k
    [root@TEST ~/ddd/study 02:59:20]#find /root/ddd/study/  -size 36k
    [root@TEST ~/ddd/study 02:59:22]#find /root/ddd/study/  -size 35k
    /root/ddd/study/LICENSE
    #以上看一下区别对比一下。
    find / -size +10G
    #需要注意的是以下两个搜索结果是不一致的
    find / -size 1024k
    find /  -size  1M
    #一个是搜索大小1024k-1023k之间的文件
    #一个是搜索大小0m-1m之间的文件
    
    2.10 根据时间戳
    -atime 文件读取时间
    -mtime 文件修改时间
    -ctime 文件属性修改时间
    以“天”为单位
    -atime [+|-]#
    #: [#,#+1)
    +#: [#+1,∞]
    -#: [0,#)
    -mtime
    -ctime
    以“分钟”为单位
    -amin
    -mmin
    -cmin
    

    范例:

    #查看一分钟之内发生变化的文件
    find /etc/ -mmin -1 -ls
    #其他写法同理
    
    2.11 根据权限
    -perm [/|-]MODE
    MODE: 精确权限匹配
    /MODE:任何一类(u,g,o)对象的权限中只要能一位匹配即可,或关系,属于模糊查询,+ 从CentOS 7开始淘汰,使用 / 
    -MODE:每一类对象都必须同时拥有指定权限,与关系
    0 表示不关注
    

    说明:
    find -perm 755 会匹配权限模式恰好是755的文件
    只要当任意人有写权限时,find -perm /222就会匹配
    只有当每个人都有写权限时,find -perm -222才会匹配
    只有当其它人(other)有写权限时,find -perm -002才会匹配

    2.12 处理动作
    -print:默认的处理动作,显示至屏幕
    -ls:类似于对查找到的文件执行“ls -l”命令
    -fls file:查找到的所有文件的长格式信息保存至指定文件中,等同于  `find 目录 -ls > file`
    -delete:删除查找到的文件,慎用!
    -ok COMMAND {} \; 对查找到的每个文件执行由COMMAND指定的命令,对于每个文件执行命令之前,都会
    交互式要求用户确认
    -exec COMMAND {} \; 对查找到的每个文件执行由COMMAND指定的命令
    {}: 用于引用查找到的文件名称自身
    
    [root@TEST ~/ddd/study 02:59:25]#find /root/ddd/study/  -size 35k
    /root/ddd/study/LICENSE
    [root@TEST ~/ddd/study 03:00:56]#find /root/ddd/study/  -size 35k -ls
    141883862   36 -rw-rw-r--   1 root     root        35147 1月  9 16:16 /root/ddd/study/LICENSE
    [root@TEST ~/ddd/study 03:01:00]#find /root/ddd/study/  -size 35k -delete
    [root@TEST ~/ddd/study 03:01:14]#ll
    总用量 20
    -rwxrwxr-x. 1 root root  750 1月   9 16:16 disk.sh
    -rw-rw-r--. 1 root root  823 1月   9 16:16 README.en.md
    -rw-rw-r--. 1 root root  912 1月   9 16:16 README.md
    -rw-rw-r--. 1 root root  665 1月   9 16:16 sync_git.sh
    -rwxrwxr-x. 1 root root 1076 1月   9 16:16 systeminfo.sh
    
    

    范例:

    #备份配置文件,添加.orig这个扩展名
    find -name ".conf" -exec cp {} {}.orig \;
    #提示删除存在时间超过3天以上的joe的临时文件
    find /tmp -ctime +3 -user joe -ok rm {} \;
    #在主目录中寻找可被其它用户写入的文件
    find ~ -perm -002 -exec chmod o-w {} \;
    #查找/data下的权限为644,后缀为sh的普通文件,增加执行权限
    find /data –type f -perm 644 -name "*.sh" –exec chmod 755 {} \;
    
    2.13 xargs命令详解

    由于很多命令不支持管道|来传递参数,xargs用于产生某个命令的参数,xargs 可以读入 stdin 的数
    据,并且以空格符或回车符将 stdin 的数据分隔成为参数
    另外,许多命令不能接受过多参数,命令执行可能会失败,xargs 可以解决
    注意:文件名或者是其他意义的名词内含有空格符的情况
    find 和 xargs 的组合:
    find | xargs COMMAND

    参数:

    -a file 从文件中读入作为 stdin
    -e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
    -p 当每次执行一个argument的时候询问一次用户。
    -n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
    -t 表示先打印命令,然后再执行。
    -i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
    -r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
    -s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
    -L num 从标准输入一次读取 num 行送给 command 命令。
    -l 同 -L。
    -d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
    -x exit的意思,主要是配合-s使用。。
    -P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。
    

    demo范例参考

    范例:

    #显示10个数字
    [root@centos8 ~]#seq 10 | xargs
    1 2 3 4 5 6 7 8 9 10
    #删除当前目录下的大量文件
    ls | xargs rm
    #
    find -name "*.sh" | xargs ls -Sl
    [root@centos8 data]#echo {1..10} |xargs
    1 2 3 4 5 6 7 8 9 10
    [root@centos8 data]#echo {1..10} |xargs -n1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@centos8 data]#echo {1..10} |xargs -n2
    1 2
    3 4
    5 6
    7 8
    9 10
    #批量创建和删除用户
    echo user{1..10} |xargs -n1 useradd
    echo user{1..100} | xargs -n1 userdel -r
    #这个命令是错误的
    find /sbin/ -perm /700 | ls -l
    #查找有特殊权限的文件,并排序
    find /bin/ -perm /7000 | xargs ls -Sl
    #此命令和上面是又区别的,区别可参考文件特殊权限与find的权限查找目录
    find /bin/ -perm -7000 | xargs ls -Sl
    #以字符nul分隔
    find -type f -name "*.txt” -print0 | xargs -0 rm
    #并发执行多个进程
    seq 100 |xargs -i -P10 wget -P /data http://10.0.0.8/{}.html
    #并行下载视频范例,可以试试
    seq 199 | xargs -i -P3 you-get https://www.bilibili.com/video/BV1Et411E7dx?p={}
    

    权限管理

    chown用法

    用法:chown [选项]... [所有者][:[组]] 文件...
     或:chown [选项]... --reference=参考文件 文件...

    chmod用法

    chmod有多种用法可用数字也可用模式。参数说明如下:
    MODE:who opt permission
    who:u,g,o,a
    opt:+,-,=
    permission:r,w,x
    修改指定一类用户的所有权限
    u= g= o= ug= a= u=,g=
    修改指定一类用户某个或某个权限
    u+ u- g+ g- o+ o- a+ a- + -
    -R: 递归修改权限
    --reference: 复制文件权限
    4:读 2:写 1:执行
    注意:用户的最终权限,是从左向右进行顺序匹配,即,所有者,所属组,其他人,一旦匹配权限立即
    生效,不再向右查看其权限

    • 范例
    ----r-xr-x.  2 root root  39 12月 13 22:31 test9
    #这个文件虽然组权限可读写,但因使用者权限不足所无法读写
    
    chmod a+w  file #给file文件所有用户添加读权限
    chmod  -R g+x /testdir #给testdir目录下所有文件添加组执行权限
    chmod  600 file #添加读写权限
    

    Linux特殊权限

    SUID:4 SGID:2 STICKY:1
    对文件及目录还有二进制配置会产生不同的效果,记一个对自己平常会用到的。

    • 对目录配置

    如果对目录配置了s权限,那么这个目录下创建的文件会继承父目录的组权限。

    范例

    chmod 2755 test9
    ls al | grep test9
    drwsr-sr-x.  2 root  nginx   39 12月 13 22:31 test9
    cd test9 && touch 345
    ls -al 
    -rw-r--r--.  1 root  nginx    0 12月 14 13:42 345
    

    chattr用法

    设置文件的特殊属性,可以访问 root 用户误操作删除或修改文件
    不能删除,改名,更改
    chattr +i
    只能追加内容,不能删除,改名
    chattr +a
    显示特定属性
    lsattr
    范例:

    [root@centos8 data]#chattr +i dir
    [root@centos8 data]#lsattr dir
    ------------------ dir/fstab
    ------------------ dir/f1.txt
    [root@centos8 data]#lsattr *
    ------------------ dir/fstab
    ------------------ dir/f1.txt
    ------------------ f11.txt
    ------------------ f22.txt
    [root@centos8 data]#ll
    total 8
    drwxr-xr-x 2 root root 33 Dec 18 14:32 dir
    -rw-r--r-- 1 root root 719 Dec 18 14:30 f11.txt
    -rw-r--r-- 1 root root 6 Dec 18 14:30 f22.txt
    [root@centos8 data]#rm -rf dir
    rm: cannot remove 'dir/fstab': Operation not permitted
    rm: cannot remove 'dir/f1.txt': Operation not permitted
    [root@centos8 data]#lsattr
    ------------------ ./f11.txt
    ------------------ ./f22.txt
    ----i------------- ./dir
    [root@centos8 data]#chattr -i dir
    [root@centos8 data]#lsattr
    ------------------ ./f11.txt
    ------------------ ./f22.txt
    ------------------ ./dir
    

    ACL配置

    可以在不修改传统权限的情况下增加用户权限。

    ACL生效顺序:
    所有者,自定义用户,所属组|自定义组,其他人

    ACL相关命令
    • 设置命令 setfacl [参数] [用户|用户组|] 修改文件只能设置用户,组,不能设置other

    范例:

    #设置f1.txt,wang用户有读写权限
    setfacl -m u:wang:6 f1.txt
    #设置f1.txt,wang组有读写权限
    setfacl -m g:wang:6 f1.txt
    #移除此用户ACL权限
    setfacl -x u:wang f1.txt
    #清空所有ACL权限,还原成最初的权限
    setfacl -b f1.txt
    
    • 查看命令
      getfacl [文件]

    • mask参数

    #限制中间用户的权限,只许比它低不许比它高
    setfacl -m mask::rw f1.txt
    
    • 备份ACL
    #备份ACL
    getfacl -R /tmp/dir > acl.txt
    #消除ACL权限
    setfacl -R -b /tmp/dir
    #还原ACL权限
    setfacl -R --set-file=acl.txt /tmp/dir
    #还原ACL权限
    setfacl --restore acl.txt
    #查看ACL权限
    getfacl -R /tmp/dir
    

    umask用法

    umask 的值可以用来保留在创建文件权限
    实现方式:
    新建文件的默认权限: 666-umask,如果所得结果某位存在执行(奇数)权限,则将其权限+1,偶
    数不变
    新建目录的默认权限: 777-umask
    非特权用户umask默认是 002
    root的umask 默认是 022

    umask
    #模式方式显示
    umask –S
    #输出可被调用
    umask –p
    

    单个文件压缩与解压

    文件压缩工具压缩比排名: xz > bzip2 > gzip > compress
    压缩比越高压缩后的文件也就越小,但压缩的时候占用的系统资源也就越大

    1. compress和uncompress

    此工具来自于ncompress包
    格式

    compress Options [file ...]
    uncompress file.Z
    

    常用选项:

    -d 解压缩,相当于uncompress
    -c 结果输出至标准输出,不删除原文件
    -v 显示详情
    zcat file.Z 不显式解压缩的前提下查看文本文件内容
    zcat file.Z >file
    

    2. gzip和gunzip

    格式:

    gzip [OPTION]... FILE ...
    

    常用选项:

    -k keep, 保留原文件,CentOS 8 新特性
    -d 解压缩,相当于gunzip
    -c 结果输出至标准输出,保留原文件不改变
    -# 指定压缩比,#取值为1-9,值越大压缩比越大
    

    范例:

    #解压缩
    gunzip file.gz
    #不显式解压缩的前提下查看文本文件内容
    zcat file.gz
    gzip -c messages >messages.gz
    gzip -c -d messages.gz > messages
    zcat messages.gz > messages
    cat messages | gzip > m.gz
    

    3. bzip2和bunzip2

    来自于 bzip2 包

    格式:

    bzip2 [OPTION]... FILE ...
    

    常用选项:

    -k keep, 保留原文件
    -d 解压缩
    -c 结果输出至标准输出,保留原文件不改变
    -# 1-9,压缩比,默认为9
    

    范例:

    bunzip2 file.bz2 解压缩
    bzcat file.bz2 不显式解压缩的前提下查看文本文件内容
    

    4. xz和unxz

    来自于 xz

    格式:
    xz [OPTION]... FILE ...

    选项:

    -k keep, 保留原文件
    -d 解压缩
    -c 结果输出至标准输出,保留原文件不改变
    -# 压缩比,取值1-9,默认为6
    

    范例:

    unxz file.xz 解压缩
    xzcat file.xz 不显式解压缩的前提下查看文本文件内容
    

    目录压缩于解压

    1. zip和unzip

    zip 可以实现打包目录和多个文件成一个文件并压缩,但可能会丢失文件属性信息,如:所有者和组信
    息,不建议使用一般建议使用 tar 代替
    来自于zip 和 unzip 包
    范例:

    #打包并压缩
    zip –r /backup/sysconfig.zip /etc/sysconfig/
    #不包括目录本身,只打包目录内的文件和子目录
    cd /etc/sysconfig; zip -r /root/sysconfig.zip *
    #默认解压缩至当前目录
    unzip /backup/sysconfig.zip
    #解压缩至指定目录,如果指定目录不存在,会在其父目录(必须事先存在)下自动生成
    unzip /backup/sysconfig.zip -d /tmp/config
    cat /var/log/messages | zip messages -
    #-p 表示管道
    unzip -p message.zip > message
    

    2. tar归档压缩命令

    tar 即 Tape ARchive 磁带归档,可以对目录和多个文件打包一个文件,并且加上参数后可以压缩也可以解压,保留文件属性不丢失,常用于备份功能,推荐使用
    格式:
    tar [OPTION]...

    2.1 创建归档,保留权限

    此功能只是归档并没有压缩,p是保留权限的意思,通过测试可以不加默认就是保留权限的,但是不管加不加p参数都无法保留ACL权限,ACL权限是需要单独备份的,这里需要注意一下。

    tar -cpvf /PATH/FILE.tar FILE...
    
    2.2 追加文件至归档

    注:不支持对压缩文件追加

    tar -rf /PATH/FILE.tar FILE...
    
    2.3 查看归档文件中的文件列表
    tar -t -f /PATH/FILE.tar
    
    2.4 展开归档,解压

    注意:同样适用于解压,属于通用命令的,它会自我识别调用解压工具。

    #v参数可加可不加,v参数的作用是 详细列出已处理的文件,不需要的可不加
    tar xvf /PATH/FILE.tar
    tar xvf /PATH/FILE.tar -C /PATH/
    
    2.5 tar压缩功能

    注意: tar需要结合压缩工具才可以压缩,压缩本事是调用压缩工具的,所以你要压缩某种格式的时候必须要已经安装了这个压缩工具不然会报错。

    压缩参数:

    -z 相当于gzip压缩工具
    -j 相当于bzip2压缩工具
    -J 相当于xz压缩工具
    

    范例:

    [root@centos8 ~]#tar zcvf etc.tar.gz /etc/
    [root@centos8 ~]#tar jcvf etc.tar.bz2 /etc/
    [root@centos8 ~]#tar Jcvf etc.tar.xz /etc/
    [root@centos8 ~]#ll etc.tar.*
    -rw-r--r-- 1 root root 3645926 Dec 20 22:00 etc.tar.bz2
    -rw-r--r-- 1 root root 5105347 Dec 20 21:59 etc.tar.gz
    -rw-r--r-- 1 root root 3101616 Dec 20 22:00 etc.tar.xz
    #只打包目录内的文件,不所括目录本身
    [root@centos8 ~]#cd /etc
    [root@centos8 etc]#tar zcvf /root/etc.tar.gz *
    #利用 tar 进行文件复制
    [root@centos8 ~]#tar c /data/ | tar x -C /backup
    tar: Removing leading `/' from member names
    
    • 排除文件

    范例:

    #压缩的时候排除 /app/host1 与/app/hosts2文件
    tar zcvf /root/a.tgz --exclude=/app/host1 --exclude=/app/host2 /app
    

    -T 选项指定输入文件 -X 选项指定包含要排除的文件列表

    范例:

    tar zcvf mybackup.tgz -T /root/includefilelist -X /root/excludefilelist
    

    3. split文件切割命令

    split 命令可以分割一个文件为多个文件,一般在有单个文件大小限制的时候用。

    范例:

    #分割大的 tar 文件为多份小文件
    split -b Size –d tar-file-name prefix-name
    split -b 1M mybackup.tgz mybackup-parts
    #切换成的多个小分文件使用数字后缀,每个小文件大小1M
    split -b 1M –d mybackup.tgz mybackup-parts
    

    将多个切割的小文件合并成一个大文件

    cat mybackup-parts* > mybackup.tar.gz
    

    4. cpio老打包解包工具

    cpio 是历史悠久的打包和解包工具,不过目前也已较少使用
    cpio命令是通过重定向的方式将文件进行打包备份,还原恢复的工具,它可以解压以“.cpio”或者“.tar”结
    尾的文件
    格式:

    cpio [选项] > 文件名或者设备名
    cpio [选项] < 文件名或者设备名
    

    常用选项:

    -o output模式,打包,将标准输入传入的文件名打包后发送到标准输出
    -i input模式,解包,对标准输入传入的打包文件名解包到当前目录
    -t 预览,查看标准输入传入的打包文件中包含的文件列表
    -O filename 输出到指定的归档文件名
    -A 向已存在的归档文件中追加文件
    -I filename 对指定的归档文件名解压
    -F filename 使用指定的文件名替代标准输入或输出
    -d 解包生成目录,在cpio还原时,自动的建立目录
    -v 显示打包过程中的文件名称
    

    范例:

    #将etc目录备份,并不压缩
    find ./etc -print | cpio -ov > bak.cpio
    #将/data内容追加bak.cpio
    find /data | cpio -oA -F bak.cpio
    #内容预览
    cpio –tv < etc.cpio
    #解包文件
    cpio –idv < etc.cpio
    

    查看文件类型

    file  文件名
    #范例
    [root@TEST ~ 11:03:42]#file mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz 
    mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz: gzip compressed data, from Unix, last modified: Fri Sep 27 16:22:43 2019
    

    软件包管理

    内容概述

    • 软件运行环境
    • 软件包基础
    • rpm包管理
    • yum和dnf 管理
    • 定制yum仓库
    • 编译安装
    • Ubuntu软件管理
      ### 1. 软件运行与编译

    1.1 软件相关概念

    1.1.1 ABI

    ABI即 Application Binary Interface
    Windows与Linux不兼容
    ELF(Executable and Linkable Format)
    PE(Portable Executable)
    库级别的虚拟化:
    Linux: WINE
    Windows: Cygwin

    1.1.2 API

    API即Application Programming Interface,API可以在各种不同的操作系统上实现给应用程序提供完全
    相同的接口,而它们本身在这些系统上的实现却可能迥异,主流的操作系统有两种,一种是Windows系
    统,另一种是Linux系统。由于操作系统的不同,API又分为Windows API和Linux API。在Windows平
    台开发出来的软件在Linux上无法运行,在Linux上开发的软件在Windows上又无法运行,这就导致了软
    件移植困难,POSIX 标准的出现就是为了解决这个问题
    POSIX:Portable Operating System Interface 可移植操作系统接口,定义了操作系统应该为应用程序
    提供的接口标准,是IEEE为要在各种UNIX操作系统上运行的软件而定义的一系列API标准的总称。
    Linux和windows都要实现基本的posix标准,程序就在源代码级别可移植了

    1.2 C语言程序的实现过程

    C 程序源代码 --> 预处理 --> 编译 --> 汇编 --> 链接
    
    • 预处理
      1)将所有的#define删除,并且展开所有的宏定义
      2)处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等
      3)处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
      4)删除所有注释 “//”和”/* */”.
      5)添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
      6)保留所有的#pragma编译器指令,因为编译器需要使用它们

    • 编译

    • 汇编

    • 链接
      以上这些概念就不详细描述了,如有需要百度。

    范例:

    #分步骤编译运行
    
    gcc -E hello.c -o hello.i 
    #对hello.c文件进行预处理,生成了hello.i 文件
    
    gcc -S hello.i -o hello.s 
    #对预处理文件进行编译,生成了汇编文件
    
    gcc -c hello.s -o hello.o 
    #对汇编文件进行编译,生成了目标文件
    
    gcc hello.o -o hello
    #对目标文件进行链接,生成可执行文件
    #一步实现编译过程
    
    gcc hello.c -o hello 
    
    #直接编译链接成可执行目标文件
    

    1.3 软件模块的静态和动态链接

    链接主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确地衔接,分为静态
    和动态链接
    解释图:

    1.3.1 静态链接
    > 比较少用。
    
    • 把程序对应的依赖库复制一份到包
    • 生成模块文件libxxx.a
    • 嵌入程序包
    • 升级难,需重新编译
    • 占用较多空间,迁移容易
    1.3.2 动态链接
    • 只把依赖加做一个动态链接
    • 生成模块文件libxxx.so
    • 连接指向
    • 占用较少空间,升级方便
    1.3.3 模块(库)文件
    ⚠️注意

    库很重要要是删了就很影响很多以来库的文件或者命令,会严重影响系统环境。如果真的哪天误删了,可以通过重启用光盘启动,进入光盘的救援模式来恢复。Linux的光盘救援模式类似于Windows的PE功能。
    光盘的救援模式就是一个小的Linux系统,比如我们把动态库的一下文件或者命令删除了,我们进入救援模式复制一个回去我们的系统就好,建议同版本的,非同版本的暂未测试。

    1.3.3.1 查看查看二进制程序所依赖的库文件

    范例:

    [root@TEST ~/linux-5.10.6 05:38:04]#ldd /bin/cat
        linux-vdso.so.1 =>  (0x00007fffec2e1000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f41197b1000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4119b7f000)
    [root@TEST ~/linux-5.10.6 05:43:41]#ldd /bin/ls
        linux-vdso.so.1 =>  (0x00007ffdbe750000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fcf674d2000)
        libcap.so.2 => /lib64/libcap.so.2 (0x00007fcf672cd000)
        libacl.so.1 => /lib64/libacl.so.1 (0x00007fcf670c4000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fcf66cf6000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fcf66a94000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fcf66890000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fcf676f9000)
        libattr.so.1 => /lib64/libattr.so.1 (0x00007fcf6668b000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fcf6646f000)
    
    1.3.3.2 管理及查看本机装载的库文件
    #加载配置文件中指定的库文件
    ldconfig
    #显示本机已经缓存的所有可用库文件名及文件路径映射关系
    /sbin/ldconfig –p
    
    1.3.3.3 配置文件
    /etc/ld.so.conf,
    /etc/ld.so.conf.d/*.conf
    
    1.3.3.4 缓存文件
    /etc/ld.so.cache
    

    2. 软件包和包管理器

    2.1 软件包介绍

    开源软件最初只提供了.tar.gz的打包的源码文件,用户必须自已编译每个想在GNU/Linux上运行的软
    件。用户急需系统能提供一种更加便利的方法来管理这些软件,当Debian诞生时,这样一个管理工具
    dpkg也就应运而生,可用来管理deb后缀的"包"文件。从而著名的“package”概念第一次出现在
    GNU/Linux系统中,稍后Red Hat才开发自己的rpm包管理系统

    2.1.1 软件包中的文件分类
    • 二进制文件
    • 库文件
    • 配置文件
    • 帮助文件

    范例:利用 cpio工具查看包文件列表

    rpm2cpio 包文件|cpio –itv 预览包内文件
    rpm2cpio 包文件|cpio –id “*.conf” 释放包内文件
    #例如下面释放 bash的rpm包内容到当前目录下。
    rpm2cpio bash-4.2.46-34.el7.x86_64.rpm  | cpio -idv
    
    2.1.2 程序包管理器

    软件包管理器功能:
    将编译好的应用程序的各组成文件打包一个或几个程序包文件,利用包管理器可以方便快捷地实现程序
    包的安装、卸载、查询、升级和校验等管理操作
    主流的程序包管理器

    • redhat:rpm文件, rpm 包管理器,rpm:Redhat Package Manager,RPM Package Manager
    • debian:deb文件, dpkg 包管理器
    2.1.3 包命名

    源代码打包文件命名:

    name-VERSION.tar.gz|bz2|xz
    VERSION: major.minor.release
    

    rpm包命名方式:

    name-VERSION-release.arch.rpm
    VERSION: major.minor.release
    release:release.OS
    bash-4.2.46-34.el7.x86_64.rpm
    bash包-bash版本号-bash打包次数-bash适用于el7版本-适用于64位系统
    

    常见的arch:

    • x86: i386, i486, i586, i686
    • x86_64: x64, x86_64, amd64
    • powerpc: ppc
    • 跟平台无关:noarch
    2.1.4 分类和拆包

    软件包为了管理和使用的便利,会将一个大的软件分类,放在不同的子包中。
    包的分类

    • Application-VERSION-ARCH.rpm: 主包
    • Application-devel-VERSION-ARCH.rpm 开发子包
    • Application-utils-VERSION-ARHC.rpm 其它子包
    • Application-libs-VERSION-ARHC.rpm 其它子包
    2.1.5 包的依赖

    软件包之间可能存在依赖关系,甚至循环依赖,即:A包依赖B包,B包依赖C包,C包依赖A包。出现这种情况的话就一起装
    安装软件包时,会因为缺少依赖的包,而导致安装包失败。
    解决依赖包管理工具:

    • yum:rpm包管理器的前端工具
    • dnf:Fedora 18+ rpm包管理器前端管理工具,CentOS 8 版代替 yum
    • apt:deb包管理器前端工具
    • zypper:suse上的rpm前端管理工具
    2.1.6 程序包管理器相关文件

    1.包文件组成 (每个包独有)

    包内的文件
    元数据,如:包的名称,版本,依赖性,描述等
    可能会有包安装或卸载时运行的脚本

    2.数据库(公共):/var/lib/rpm

    • 程序包名称及版本
    • 依赖关系
    • 功能说明
    • 包安装后生成的各文件路径及校验码信息
    2.1.7 获取程序包的途径

    软件包需要事先将源码进行编译后打包形成,获取包的途径如下:

    1. 系统镜像
    2. 第三方组织提供,比如epel源
    3. 搜索引擎,等等

    http://pkgs.org

    http://rpmfind.net

    http://rpm.pbone.net

    https://sourceforge.net

    除了主流的阿里,163开源网站等这里分享一个网站:

    rpm
    epel

    2.1.8 自己制作

    将源码文件,利用工具,如:rpmbuild,fpm等工具制作成rpm包文件

    3. 包管理器rpm

    ⚠️ 主要是查询命令,其他了解

    CentOS系统上使用rpm命令管理程序包
    功能:
    安装、卸载、升级、查询、校验、数据库维护

    不过现在因为rpm安装方式会因为各种依赖的问题比较繁琐,所以现在很少使用rpm方式安装软件。一般用来查询。

    3.1 查询

    格式:
    rpm {-q|--query} [select-options] [query-options]

    常用选项:

    [select-options]
    
    -a:所有包
    
    -f:查看指定的文件由哪个程序包安装生成
    
    -p rpmfile:针对尚未安装的程序包文件做查询操作
    
    [query-options]
    
    --changelog:查询rpm包的changelog
    
    -c:查询程序的配置文件
    
    -d:查询程序的文档
    
    -i:information
    
    -l:查看指定的程序包安装后生成的所有文件
    
    --scripts:查询程序包自带的脚本
    
    #和CAPABILITY相关
    --whatprovides CAPABILITY:查询指定的CAPABILITY由哪个包所提供
    
    --whatrequires CAPABILITY:查询指定的CAPABILITY被哪个包所依赖
    
    --provides:列出指定程序包所提供的CAPABILITY
    
    -R:查询指定的程序包所依赖的CAPABILITY
    
    

    常用查询用法:

    -qa
    
    -q PACKAGE
    
    -qi PACKAGE
    
    -qc PACKAGE
    
    -ql PACKAGE
    
    -qd PACKAGE
    
    -q --scripts PACKAGE
    
    -qf FILE
    
    -qpi PACKAGE_FILE
    
    -qpl PACKAGE_FILE, ...
    
    

    范例:

    #查询包的依赖关系,不过这个方法用的不多了
    [root@TEST /misc/cd/Packages 05:59:09]#rpm -q --whatrequires  bash
    sendmail-8.14.7-6.el7.x86_64
    initscripts-9.49.53-1.el7_9.1.x86_64
    dracut-033-572.el7.x86_64
    lvm2-2.02.187-6.el7_9.3.x86_64
    rsyslog-8.24.0-57.el7_9.x86_64
    autofs-5.0.7-116.el7_9.x86_64
    
    #查询此软件包是否存在
    [root@TEST /var/lib/rpm 03:16:04]#rpm -q yum
    yum-3.4.3-168.el7.centos.noarch
    #这样后面我们写脚本的时候也可以通过这个命令来查询此包是否已经安装如果没有安装那就执行安装
    [root@TEST /var/lib/rpm 03:24:04]#rpm -q yum &> /dev/null | yum -y install yum
    #查询所有包,一般用来模糊查询,如下:
    [root@TEST /var/lib/rpm 03:30:42]#rpm -qa | grep yu
    yum-metadata-parser-1.1.4-10.el7.x86_64
    yum-3.4.3-168.el7.centos.noarch
    keyutils-libs-1.5.8-3.el7.x86_64
    python-pyudev-0.15-9.el7.noarch
    yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch
    #查询已安装包的信息
    [root@TEST /misc/cd/Packages 04:37:30]#rpm -qi  tree
    Name        : tree
    Version     : 1.6.0
    Release     : 10.el7
    Architecture: x86_64
    Install Date: 2021年01月12日 星期二 16时35分49秒
    Group       : Applications/File
    Size        : 89505
    License     : GPLv2+
    Signature   : RSA/SHA256, 2014年07月04日 星期五 13时36分46秒, Key ID 24c6a8a7f4a80eb5
    Source RPM  : tree-1.6.0-10.el7.src.rpm
    Build Date  : 2014年06月10日 星期二 03时28分53秒
    Build Host  : worker1.bsys.centos.org
    Relocations : (not relocatable)
    Packager    : CentOS BuildSystem <http://bugs.centos.org>
    Vendor      : CentOS
    URL         : http://mama.indstate.edu/users/ice/tree/
    Summary     : File system tree viewer
    Description :
    The tree utility recursively displays the contents of directories in a
    tree-like format.  Tree is basically a UNIX port of the DOS tree
    utility.
    #查询rpm包文件的信息,可用于未安装包前的查询
    [root@TEST /misc/cd/Packages 04:44:00]#rpm -qpi tree-1.6.0-10.el7.x86_64
    #查询安装包增加配置了哪些文件
    [root@TEST /misc/cd/Packages 04:46:12]#rpm -ql tree
    /usr/bin/tree
    /usr/share/doc/tree-1.6.0
    /usr/share/doc/tree-1.6.0/LICENSE
    /usr/share/doc/tree-1.6.0/README
    /usr/share/man/man1/tree.1.gz
    #未安装前查询这个包安装后会哪些配置文件
    [root@TEST /misc/cd/Packages 04:44:25]#rpm -qpl tree-1.6.0-10.el7.x86_64.rpm
    /usr/bin/tree
    /usr/share/doc/tree-1.6.0
    /usr/share/doc/tree-1.6.0/LICENSE
    /usr/share/doc/tree-1.6.0/README
    /usr/share/man/man1/tree.1.gz
    # 查询文件来自哪个包,当然并不是所有的文件都可以查询
    [root@TEST /misc/cd/Packages 04:47:44]#rpm -qf /usr/bin/tree
    tree-1.6.0-10.el7.x86_64
    #查询的数据信息都是来自于 /var/lib/rpm 下的数据库。
    
    3.2 安装

    很少用,原因上面有提到。

    格式:
    rpm {-i|--install} [install-options] PACKAGE_FILE…

    选项:

    -v: verbose
    -vv:
    -h: 以#显示程序包管理执行进度
    

    常用组合:
    rpm -ivh PACKAGE_FILE ...

    rpm包安装[install-options]:

    --test: 测试安装,但不真正执行安装,即dry run模式
    --nodeps:忽略依赖关系
    --replacepkgs | replacefiles
    --nosignature: 不检查来源合法性
    --nodigest:不检查包完整性
    --noscripts:不执行程序包脚本
    %pre: 安装前脚本 --nopre
    %post: 安装后脚本 --nopost
    %preun: 卸载前脚本 --nopreun
    %postun: 卸载后脚本 --nopostun
    

    范例:

    #安装的话只需要带一个i参数就行了 v是显示安装详细信息,h是显示安装进度
    [root@TEST /misc/cd/Packages 04:34:24]#rpm -ivh tree-1.6.0-10.el7.x86_64.rpm
    准备中...                          ################################# [100%]
    正在升级/安装...
       1:tree-1.6.0-10.el7                ################################# [100%]
    
    3.3 升级和降级

    rpm包升级

    rpm {-U|--upgrade} [install-options] PACKAGE_FILE...
    rpm {-F|--freshen} [install-options] PACKAGE_FILE...
    

    upgrade:安装有旧版程序包,则“升级”,如果不存在旧版程序包,则“安装”
    freshen:安装有旧版程序包,则“升级”, 如果不存在旧版程序包,则不执行升级操作
    --oldpackage:降级
    --force: 强制安装
    常用组合

    #安装有旧版程序包,则“升级”,如果不存在旧版程序包,则“安装”
    rpm -Uvh PACKAGE_FILE ...
    #安装有旧版程序包,则“升级”, 如果不存在旧版程序包,则不执行升级操作。简称只升级。
    rpm -Fvh PACKAGE_FILE ...
    

    升级注意项:
    (1) 不要对内核做升级操作;Linux支持多内核版本并存,因此直接安装新版本内核
    (2) 如果原程序包的配置文件安装后曾被修改,升级时,新版本提供的同一个配置文件不会直接覆盖老
    版本的配置文件,而把新版本文件重命名(FILENAME.rpmnew)后保留

    3.4 卸载

    与安装同理,也会因为各种依赖包的问题有可能卸载不了,所以也很少用。

    格式:
    rpm -e 包名
    rpm {-e|--erase} [--allmatches] [--nodeps] [--noscripts] [--notriggers] [--test]
    PACKAGE_NAME ...

    注意:当包卸载时,对应的配置文件不会删除, 以FILENAME.rpmsave形式保留
    范例:

    rpm -e tree-1.6.0-10.el7.x86_64
    #强行删除rpm包,并恢复
    #重启进入rescue模式
    #mkdir /mnt/cdrom
    #mount /dev/sr0 /mnt/cdrom
    #rpm -ivh /mnt/cdrom/Packages/rpm-4.11.3-40.el7.x86_64.rpm --root=/mnt/sysimage
    #reboot
    
    3.5 检验

    只安装包时,系统本身也会检查包的来源是否合法。
    也可用来自己检查包的完整性和签名

    rpm -K|--checksig rpmfile

    在检查包的来源和完整性前,必须导入所需要公钥
    范例:

    #没有导入的话可以自己手动导入一下密钥
    [root@TEST /misc/cd/Packages 10:00:40]#rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
    #查询导入的密钥
    [root@TEST /misc/cd/Packages 10:00:40]#rpm -qa "gpg-pubkey"
    gpg-pubkey-f4a80eb5-53a7ff4b
    #也可用 rpm -qi gpg-pubkey-f4a80eb5-53a7ff4b 查看内容
    

    软件在安装时,会将包里的每个文件的元数据,如:大小,权限,所有者,时间等记录至rpm相关的数
    据库中,可以用来检查包中的文件是否和当初安装时有所变化
    rpm {-V|--verify} [select-options] [verify-options]

    范例:比如我们将依赖centos-release包的 /etc/issue 文件修改了

    [root@TEST /misc/cd/Packages 10:06:15]#rpm -qf /etc/issue
    centos-release-7-9.2009.1.el7.centos.x86_64
    [root@centos8 ~]#rpm -V centos-release
    S.5....T. c /etc/issue
    #依照下面的属性对比可以看出此包中的 /etc/issue文件修改了文件大小,内容变了,时间变了,
    

    属性详细对比:

    S file Size differs
    M Mode differs (includes permissions and file type)
    5 digest (formerly MD5 sum) differs
    D Device major/minor number mismatch
    L readLink(2) path mismatch
    U User ownership differs
    G Group ownership differs
    T mTime differs
    P capabilities differ
    . (点) 表示当前位置代表的字符含义一致
    c 所在的位置表示文件类型
    c 配置文件
    d 文件数据文件
    g 该文件不属于某个文件(极少情况)
    l 许可证文件(license file)
    r 自述文件(READ ME)
    
    3.6 数据库

    rpm包安装时生成的信息,都放在rpm数据库中
    /var/lib/rpm

    如果删除了这个目录下的文件那就rpm数据信息就玩完了,虽然有几个恢复命令可以恢复,但只是恢复数据的格式,并不能恢复原有的数据,意义不大。

    #重建数据库命令
    rpm {--initdb|--rebuilddb}
    initdb: 初始化,如果事先不存在数据库,则新建之,否则,不执行任何操作
    rebuilddb:重建已安装的包头的数据库索引目录
    
    ⚠️误操作恢复技巧

    俗话说常在路边走哪有不湿鞋。接下来针对非正常卸载rpm软件的的一个恢复做一个笔记。

    #模拟误删除的环境,假设我误删除了 tree 的命令
    [root@TEST ~ 05:41:35]#rm -rf /usr/bin/tree
    #因为我们删除了tree所需要的文件,所以已经无法使用了,我们先查询一下这个删除的文件依赖于哪个包。这里说一下因为我们只是删除了配置文件,所以这里还是可以查询到文件所使用的包的,毕竟数据库里还有数据。
    [root@TEST ~ 05:41:35]#rpm -qf /usr/bin/tree
    tree-1.6.0-10.el7.x86_64
    #然后我们去网上下载这个rpm包,然后通过覆盖安装或者强制安装的方式来安装,不然会报错。这里采用的是覆盖安装的方式
    [root@TEST ~ 05:46:35]#rpm -ivh /misc/cd/Packages/tree-1.6.0-10.el7.x86_64.rpm --replacepkgs
    #也可通过将rpm包解包,然后找到你删除的文件并移动到原路径,但不推荐,有一定可能丢失属性。所以就不演示了。
    

    4. yum和dnf

    简介

    CentOS 使用 yum, dnf 解决rpm的包依赖关系
    YUM: Yellowdog Update Modifier,rpm的前端程序,可解决软件包相关依赖性,可在多个库之间定位
    软件包,up2date的替代工具,CentOS 8 用dnf 代替了yum ,不过保留了和yum的兼容性,配置也是通
    用的

    4.1 dnf/yum工作原理

    yum/dnf 是基于C/S 模式

    • yum 服务器存放rpm包和相关包的元数据库
    • yum 客户端访问yum服务器进行安装或查询等

    yum 实现过程
    先在yum服务器上创建 yum repository(仓库),在仓库中事先存储了众多rpm包,以及包的相关的
    元数据文件(放置于特定目录repodata下),当yum客户端利用yum/dnf工具进行安装时包时,会自动
    下载repodata中的元数据,查询远数据是否存在相关的包及依赖关系,自动从仓库中找到相关包下载并
    安装。
    yum服务器的仓库可以多种形式存在:

    • file:// 本地路径
    • http://
    • https://
    • ftp://

    注意:yum仓库指向的路径一定必须是repodata目录所在目录

    4.2 yum客户端配置
    4.2.1 yum配置文件说明
    /etc/yum.conf #为所有仓库提供公共配置
    /etc/yum.repos.d/*.repo: #为每个仓库的提供配置文件
    

    帮助参考: man 5 yum.conf
    相关变量

    yum的repo配置文件中可用的变量:
    $releasever: 当前OS的发行版的主版本号,如:8,7,6
    $arch: CPU架构,如:aarch64, i586, i686,x86_64等
    $basearch:系统基础平台;i386, x86_64
    $contentdir:表示目录,比如:centos-8,centos-7
    $YUM0-$YUM9:自定义变量
    

    范例:

    http://server/centos/$releasever/$basearch/
    http://server/centos/7/x86_64
    http://server/centos/6/i386
    

    Centos7的yum.conf的一些说明(Centos8配置可能有点区别不过大致相同):

    [root@TEST / 01:38:18]#cat /etc/yum.conf 
    #基本不用去动这个配置,保持默认即可。
    [main]
    cachedir=/var/cache/yum/$basearch/$releasever    #yum下载的RPM包的缓存目录
    keepcache=0         #缓存是否保存,1保存,0不保存。
    debuglevel=2        #调试级别(0-10),默认为2(具体调试级别的应用,我也不了解)。
    logfile=/var/log/yum.log        #yum的日志文件所在的位置
    exactarch=1                 #在更新的时候,是否允许更新不同版本的RPM包,比如是否在i386上更新i686的RPM包。
    obsoletes=1             #这是一个update的参数,具体请参阅yum(8),简单的说就是相当于upgrade,允许更新陈旧的RPM包。
    gpgcheck=1              #是否检查GPG(GNU Private Guard),一种密钥方式签名。默认是检查的,如果安装失败的话需要手动导入密钥,一般 repo都有配置密钥路径的,不再需要我们手动导入。
    plugins=1               #是否允许使用插件,默认是0不允许,但是我们一般会用yum-fastestmirror这个插件。
    installonly_limit=5         #允许保留多少个内核包。
    bugtracker_url=http://bugs.centos.org/set_project.php?project_id=23&ref=http://bugs.centos.org/bug_report_page.php?category=yum
    distroverpkg=centos-release
    

    repo仓库配置文件说明(repo文件路径在/etc/yum.repos.d):

    [repositoryID]
    #仓库ID需要确保它的唯一性,因为我们会配属多个仓库,不要添加特殊符号
    name=Some name for this repository
    #name就是一个描述
    baseurl=url://path/to/repository/
    #配置互联网仓库地址,当然也可配置本地
    enabled={1|0}
    gpgcheck={1|0}
    gpgkey=URL
    enablegroups={1|0}
    failovermethod={roundrobin|priority}
    roundrobin:意为随机挑选,默认值
    priority:按顺序访问
    cost= 默认为1000
    

    Centos默认repo配置范例:

    #仓库名
    [base]
    #描述
    name=CentOS-$releasever - Base
    #mirrorlist指向的是一个文件路径,这个文件里配置了很多的仓库路径,包含了互联网的多个镜像站点
    mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
    #指向yum仓库路径,因为我们访问这个地址太慢了,所以一般不使用这个,用的都是国内的比如阿里云,当然这个也可配置多个仓库地址,如果上面一个仓库地址访问失败那就访问下面那个,提高了容错率。效果与mirrorlist一同。例子如下
    #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
    #需要与前面的http对齐         http://mirror.centos.org/centos/$releasever/os/$basearch/
    #注意上面的地址是rpm元数据的repodata文件夹的路径地址,而不是包的地址
    #gpgcheck1是校验的,0是不校验不安全。
    gpgcheck=1
    #配置密钥路径,如果没有配置的话第一次安装的时候需要手动导入密钥。
    gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
    #启用这个仓库,不写的话默认就是启动的。
    enabled=1
    

    4.2.2 yum配置其他网络源

    因Centos yum源属于国外下载安装较慢,大家可通过相关配置国内源,国内的阿里,清华大学,华为云都还是不错的。

    #阿里云
    https://mirrors.aliyun.com/centos/$releasever/os/x86_64/
    #华为云
    https://mirrors.huaweicloud.com/
    #清华大学
    https://mirrors.tuna.tsinghua.edu.cn/centos/$releasever/os/x86_64/
    

    EPEL同理

    个人比较推荐阿里,阿里比较方便。阿里的开源镜像站地址:点击前往

    配置网络仓库例子:

    vim test.repo
    #这是一个最简单最偷懒的一个配置。
    [Test]
    name=This is test
    baseurl= https://mirrors.aliyun.com/centos/7/os/x86_64/
    #其他的不配默认这个仓库是启用的,然后默认也是检查这个密钥的,不过不安全不建议。
    gpgcheck=0
    
    4.2.3 yum配置本地源

    建议将原有的配置文件备份,然后重新创建一个配置文件哦。

    #挂载光盘至某目录,如/mnt/cdrom
    mount /dev/cdrom /mnt/cdrom
    #创建配置文件
    [root@centos7 ~]#vim /etc/yum.repos.d/centos7.repo
    [CentOS7]
    name=CentOS 7
    baseurl=file:///mnt/cdrom
    gpgcheck=0
    enabled=1
    
    4.3 yum命令

    格式:
    yum [options] [command] [package ...]

    常用选项:

    -y #自动回答为“yes”
    -q #静默模式
    --nogpgcheck #禁止进行gpg check
    --enablerepo=repoidglob #临时启用此处指定的repo,支持通配符,如:”*“
    --disablerepo=repoidglob #临时禁用此处指定的repo,和上面语句同时使用,放在后面的生效
    
    4.3.1 显示仓库列表

    yum repolist [all|enabled|disabled]

    范例:

    [root@centos8 ~]#yum repolist
    [root@centos8 ~]#yum repolist all
    Last metadata expiration check: 0:01:32 ago on Sun 29 Dec 2019 12:13:10 AM CST.
    repo id repo name status
    AppStream AppStream
    enabled: 4,681
    BaseOS BaseOS
    enabled: 1,655
    epel EPEL
    disabled
    extras extras
    disabled
    [root@centos8 ~]#yum --enablerepo=ep* --disablerepo=A* repolist
    Last metadata expiration check: 0:01:18 ago on Sun 29 Dec 2019 12:13:27 AM CST.
    repo id repo name
    status
    BaseOS BaseOS
    1,657
    epel EPEL
    3,733
    
    4.3.2 显示程序包

    格式:

    yum list
    yum list [all | glob_exp1] [glob_exp2] [...]
    yum list {available|installed|updates} [glob_exp1] [...]
    

    范例:

    [root@centos8 data]#dnf list mariadb-server
    Last metadata expiration check: 0:05:03 ago on Sun 08 Dec 2019 04:11:17 PM CST.
    Available Packages
    mariadb-server.x86_64 3:10.3.11-2.module_el8.0.0+35+6f2527ed
    AppStream
    #显示多个版本的包,--showduplicates 参数作用
    [root@centos8 data]#dnf list mariadb-server --showduplicates
    Last metadata expiration check: 0:05:11 ago on Sun 08 Dec 2019 04:11:17 PM CST.
    Available Packages
    mariadb-server.x86_64 3:10.3.11-2.module_el8.0.0+35+6f2527ed
    AppStream
    [root@centos8 data]#dnf list mariadb-server --disablerepo=AppStream
    Last metadata expiration check: 0:05:23 ago on Sun 08 Dec 2019 04:11:17 PM CST.
    Available Packages
    MariaDB-server.x86_64 10.4.10-1.el8
    mariadb2
    [root@centos8 data]#dnf list mariadb-server --showduplicates --
    disablerepo=AppStream
    Last metadata expiration check: 0:05:41 ago on Sun 08 Dec 2019 04:11:17 PM CST.
    Available Packages
    MariaDB-server.x86_64 10.3.17-1.el8
    mariadb
    MariaDB-server.x86_64 10.3.18-1.el8
    mariadb
    MariaDB-server.x86_64 10.3.20-1.el8
    mariadb
    MariaDB-server.x86_64 10.4.7-1.el8
    mariadb2
    MariaDB-server.x86_64 10.4.8-1.el8
    mariadb2
    MariaDB-server.x86_64 10.4.10-1.el8
    mariadb2
    #挑出特定仓库里可用的包,available属于可用的包。
    [root@centos8 ~]#yum --disablerepo="A*" --disablerepo="B*" --disablerepo="e*"
    list available
    
    4.3.3 yum-config-manager命令

    可以生成yum仓库的配置文件及启用或禁用仓库,需要安装yum-utils包
    格式:

    #增加仓库
    yum-config-manager --add-repo URL或file
    #禁用仓库
    yum-config-manager --disable “仓库名"
    #启用仓库
    yum-config-manager --enable “仓库名”
    

    范例:

    #禁用epel仓库
    yum-config-manager --disable epel
    #开启epel仓库
    yum-config-manager --enable epel
    
    4.3.4 yum安装包
    yum install package1 [package2] [...]
    yum reinstall package1 [package2] [...] #重新安装
    
    4.3.5 yum卸载包

    yum remove | erase package1 [package2] [...]

    4.3.6 yum升级和降级包
    yum update [package1] [package2] [...]
    yum downgrade package1 [package2] [...] (降级)
    

    检查可用升级:
    yum check-update

    4.3.6 查询

    查看程序包information:

    yum info [...]

    查看指定的特性(可以是某文件)是由哪个程序包所提供:
    yum provides | whatprovides feature1 [feature2] [...]
    注意:文件要写全路径,而不只是文件名,否则无法查询到
    范例:

    [root@centos8 ~]# ll /etc/vsftpd/vsftpd.conf
    ls: cannot access '/etc/vsftpd/vsftpd.conf': No such file or directory
    #注意要写文件全路径才能查询到
    [root@centos8 ~]#yum provides vsftpd.conf
    Last metadata expiration check: 0:56:45 ago on Fri 10 Apr 2020 11:24:00 AM CST.
    Error: No Matches found
    [root@centos8 ~]# yum provides /etc/vsftpd/vsftpd.conf
    Last metadata expiration check: 0:33:13 ago on Fri 27 Dec 2019 03:47:34 PM CST.
    vsftpd-3.0.3-28.el8.x86_64 : Very Secure Ftp Daemon
    Repo : AppStream
    Matched from:
    Filename : /etc/vsftpd/vsftpd.conf
    

    以指定的关键字搜索程序包名及summary信息
    yum search string1 [string2] [...]

    查看指定包所依赖的capabilities:
    yum deplist package1 [package2] [...]

    范例:

    [root@TEST ~ 04:01:44]#yum deplist rpm
    已加载插件:fastestmirror
    Loading mirror speeds from cached hostfile
     * base: mirrors.aliyun.com
     * extras: mirrors.163.com
     * updates: mirrors.163.com
    软件包:rpm.x86_64 4.11.3-45.el7
       依赖:/bin/bash
       provider: bash.x86_64 4.2.46-34.el7
       依赖:/bin/sh
       provider: bash.x86_64 4.2.46-34.el7
       依赖:/usr/bin/db_stat
       provider: libdb-utils.x86_64 5.3.21-25.el7
       依赖:coreutils
       provider: coreutils.x86_64 8.22-24.el7_9.2
       依赖:curl
       provider: curl.x86_64 7.29.0-59.el7_9.1
       依赖:libacl.so.1()(64bit)
       provider: libacl.x86_64 2.2.51-15.el7
       依赖:libaudit.so.1()(64bit)
       provider: audit-libs.x86_64 2.8.5-4.el7
       依赖:libbz2.so.1()(64bit)
       provider: bzip2-libs.x86_64 1.0.6-13.el7
       依赖:libc.so.6(GLIBC_2.3.4)(64bit)
       provider: glibc.x86_64 2.17-317.el7
       依赖:libcap.so.2()(64bit)
       provider: libcap.x86_64 2.22-11.el7
       依赖:libdb-5.3.so()(64bit)
       provider: libdb.x86_64 5.3.21-25.el7
       依赖:libdl.so.2()(64bit)
       provider: glibc.x86_64 2.17-317.el7
       依赖:libelf.so.1()(64bit)
       provider: elfutils-libelf.x86_64 0.176-5.el7
       依赖:liblua-5.1.so()(64bit)
       provider: lua.x86_64 5.1.4-15.el7
       依赖:liblzma.so.5()(64bit)
       provider: xz-libs.x86_64 5.2.2-1.el7
       依赖:libm.so.6()(64bit)
       provider: glibc.x86_64 2.17-317.el7
       依赖:libnss3.so()(64bit)
       provider: nss.x86_64 3.53.1-3.el7_9
       依赖:libpopt.so.0()(64bit)
       provider: popt.x86_64 1.13-16.el7
       依赖:libpopt.so.0(LIBPOPT_0)(64bit)
       provider: popt.x86_64 1.13-16.el7
       依赖:libpthread.so.0()(64bit)
       provider: glibc.x86_64 2.17-317.el7
       依赖:libpthread.so.0(GLIBC_2.2.5)(64bit)
       provider: glibc.x86_64 2.17-317.el7
       依赖:librpm.so.3()(64bit)
       provider: rpm-libs.x86_64 4.11.3-45.el7
       依赖:librpmio.so.3()(64bit)
       provider: rpm-libs.x86_64 4.11.3-45.el7
       依赖:libselinux.so.1()(64bit)
       provider: libselinux.x86_64 2.5-15.el7
       依赖:libz.so.1()(64bit)
       provider: zlib.x86_64 1.2.7-18.el7
       依赖:popt(x86-64) >= 1.10.2.1
       provider: popt.x86_64 1.13-16.el7
       依赖:rtld(GNU_HASH)
       provider: glibc.x86_64 2.17-317.el7
       provider: glibc.i686 2.17-317.el7
    
    4.3.7 仓库缓存

    清除目录/var/cache/yum/缓存
    yum clean [ packages | metadata | expire-cache | rpmdb | plugins | all ]

    构建缓存:
    yum makecache

    范例:管理yum缓存

    [root@centos7 ~]#du -sh /var/cache/yum
    93M /var/cache/yum
    [root@centos7 ~]#ls /var/cache/yum/x86_64/7/
    base epel extras timedhosts timedhosts.txt
    [root@magedu ~]#yum clean all
    Loaded plugins: fastestmirror
    Cleaning repos: base epel extras
    Cleaning up list of fastest mirrors
    [root@centos7 ~]#du -sh /var/cache/yum
    4.0K /var/cache/yum
    [root@centos7 ~]#yum makecache
    ......
    Metadata Cache Created
    [root@centos7 ~]#du -sh /var/cache/yum
    276M /var/cache/yum
    
    4.3.8 查看yum事务历史

    yum 执行安装卸载命令会记录到相关日志中
    日志 文件:

    #CentOS 7以前版本日志
    /var/log/yum.log
    #CentOS 8 版本日志
    /var/log/dnf.rpm.log
    /var/log/dnf.log
    

    日志命令
    yum history [info|list|packages-list|packages-info|summary|addoninfo|
    redo|undo|rollback|new|sync|stats]

    范例:

    [root@centos8 ~]#yum history
    ID | Command line | Date and time | Action(s) | Altered
    -------------------------------------------------------------------------------
    22 | install yum-utils | 2019-12-22 13:44 | Install | 1
    21 | remove vsftpd | 2019-12-22 13:39 | Removed | 1
    20 | install vsftpd | 2019-12-22 13:39 | Install | 1
    19 | install python3 | 2019-12-22 12:26 | Install | 3
    18 | install perl | 2019-12-22 12:25 | Install | 156
    17 | install httpd -y | 2019-12-21 20:21 | Install | 10
    ...省略...
    [root@centos8 ~]#yum history info 22
    Transaction ID : 22
    Begin time : Sun 22 Dec 2019 01:44:08 PM CST
    Begin rpmdb : 607:35cd823ff347e56ceb688a9f72715eabb3c53d41
    End time : Sun 22 Dec 2019 01:44:08 PM CST (0 seconds)
    End rpmdb : 608:24139ec38fc131c182b75fdaad0626692045da94
    User : root <root>
    Return-Code : Success
    Releasever : 8
    Command Line : install yum-utils
    Packages Altered:
    Install dnf-utils-4.0.2.2-3.el8.noarch @BaseOS
    [root@centos8 ~]#yum history undo 22 -y
    Removed:
    dnf-utils-4.0.2.2-3.el8.noarch
    Complete!
    [root@centos8 ~]#yum history redo 22 -y
    
    4.3.9 安装及升级本地程序包
    #现在可以直接 install,无需加前面localinstall参数来
    yum localinstall|install rpmfile1 [rpmfile2] [...]
    yum localupdate|update rpmfile1 [rpmfile2] [...]
    
    4.3.10 包组管理的相关命令
    yum grouplist [hidden] [groupwildcard] [...]
    yum groupinstall group1 [group2] [...]
    yum groupupdate group1 [group2] [...]
    yum groupremove group1 [group2] [...]
    yum groupinfo group1 [...]
    
    4.3.11 实现私用 yum仓库

    部署步骤:

    此步只是将光盘里的安装包内部http,这样就不需要每台机器都去挂载光盘,然后安装软件里。

    #部署httpd
    [root@localhost 7]# yum install httpd
    #创建目录
    [root@localhost 7]# mkdir -p /var/www/html/centos/7
    #将原来光盘文件里的文件导入到你创建的目录,也可直接挂载.工作中建议直接拷贝不要挂载。
    [root@localhost 7]# mount /dev/sr0 /var/www/html/centos/7
    [root@localhost 7]# pwd
    /var/www/html/centos/7
    [root@localhost 7]# ls
    CentOS_BuildTag  GPL       LiveOS    RPM-GPG-KEY-CentOS-7
    EFI              images    Packages  RPM-GPG-KEY-CentOS-Testing-7
    EULA             isolinux  repodata  TRANS.TBL
    #启动httpd服务并设置为开机启动
    [root@localhost 7]# systemctl enable --now httpd
    #然后浏览器访问服务器地址即可。
    

    客户端配置:客户端的配置意思与前面的网络配置差不多意思,无非就是更换一下地址。点击前往

    4.3.12 下载公网yum源到本地

    手动下载公网yum仓库的相关包和meta数据到本地范例:

    #CentOS 8 dnf 工具集成
    
    dnf reposync --help #查看帮助
    
    #默认只下载rpm包,不下载meta数据,需要指定--download-metadata 才能下载meta。
    
    dnf reposync --repoid=REPOID --download-metadata -p /path
    
    #CentOS 7 以前版本,reposync工具来自于yum-utils包
    
    reposync --repoid=REPOID --download-metadata -p /path
    
    #下载之前需要配置好各个仓库,然后再通过reposync下载指定repoid与meta数据到 /path 路径。
    

    reposync范例:

    #配置公网源
    [root@centos8 ~]#cat /etc/yum.repos.d/base.repo
    [epel]
    name=EPEL
    baseurl=https://mirrors.aliyun.com/epel/8/Everything/x86_64/
    gpgcheck=0
    #查看一下仓库是否配置成功
    [root@centos8 ~]#dnf repolist
    Last metadata expiration check: 0:07:40 ago on Sun 22 Dec 2019 03:14:16 PM CST.
    repo id repo name status
    AppStream AppStream 4,681
    BaseOS BaseOS 1,655
    epel EPEL 3,707
    #下载相关仓库包和元数据到本地/var/www/html
    [root@centos8 ~]#dnf reposync --repoid=epel --download-metadata -p
    /var/www/html
    #--download-metadata 加此选项可以下载元数据
    #下载相关的key文件
    [root@repo-server ~]#wget -P /var/www/html/epel/
    https://mirrors.aliyun.com/epel/RPM-GPG-KEY-EPEL-8
    #下面两个步骤只有没meta数据才需要执行
    #[root@centos8 ~]#dnf -y install createrepo httpd
    #[root@centos8 ~]#createrepo /var/www/html/epel/
    [root@centos8 ~]#ls /var/www/html/epel/
    Packages repodata
    

    rsync同步公网源:

    暂时国内镜像站我只知道中科大开源镜像站支持rsync同步,有一个好处就是不需要提前配置仓库地址,只需要通过rsync同步即可,执行一条命令即可。

    rsync同步范例:

    #首先机器需要提前安装rsync
    [root@repo-server ~ 02:07:59]#yum -y install rsync
    #然后同步,这里同步epel下x86_64架构的centos所有包到/data/yum_data/epel/x86_64/目录。只是为了节省硬盘空间与同步时间,你也可以完全同步修改一下地址即可。
    [root@repo-server ~ 02:07:59]#rsync -av  rsync://rsync.mirrors.ustc.edu.cn/repo/epel/7/x86_64/  /data/yum_data/epel/x86_64/
    

    科大源同步方法与注意事项

    4.3.13 DNF 介绍

    DNF,即DaNdiFied,是新一代的RPM软件包管理器。DNF 发行日期是2015年5月11日,DNF 包管理
    器采用Python 编写,发行许可为GPL v2,首先出现在Fedora 18 发行版中。在 RHEL 8.0 版本正式取代
    了 YUM,DNF包管理器克服了YUM包管理器的一些瓶颈,提升了包括用户体验,内存占用,依赖分
    析,运行速度等
    配置文件:
    /etc/dnf/dnf.conf
    仓库文件:
    /etc/yum.repos.d/ *.repo
    日志:
    /var/log/dnf.rpm.log
    /var/log/dnf.log
    dnf 用法与yum一致

    dnf [options] <command> [<arguments>...]
    dnf --version
    dnf repolist
    dnf reposync
    dnf install httpd
    dnf remove httpd
    dnf clean all
    dnf makecache
    dnf list installed
    dnf list available
    dnf search nano
    dnf history undo 1
    

    CentOS 7 使用 dnf ,下载并安装下面包:

    wget http://springdale.math.ias.edu/data/puias/unsupported/7/x86_64/dnf-conf-
    0.6.4-2.sdl7.noarch.rpm
    wget http://springdale.math.ias.edu/data/puias/unsupported/7/x86_64/dnf-0.6.4-
    2.sdl7.noarch.rpm
    wget http://springdale.math.ias.edu/data/puias/unsupported/7/x86_64/python-dnf-
    0.6.4-2.sdl7.noarch.rpm
    wget https://mirrors.aliyun.com/centos/7/extras/x86_64/Packages/python2-
    libcomps-0.1.8-12.el7.x86_64.rpm
    wget https://mirrors.aliyun.com/centos/7/extras/x86_64/Packages/libcomps-0.1.8-
    12.el7.x86_64.rpm
    
    4.3.14 yum错误的排错思路

    yum 和 dnf 失败最主要原因:

    • yum的配置文件格式或路径错误
      解决方法:检查/etc/yum.repos.d/*.repo文件格式
    • yum cache
      解决方法:yum clean all
    • 网络不通:
      解决方法:网卡配置
    一些小技巧
    #显示@anaconda的已安装系统的时候安装的包
    [root@TEST /etc/yum.repos.d 04:23:34]#yum list less
    已加载插件:fastestmirror
    Loading mirror speeds from cached hostfile
    已安装的软件包
    less.x86_64                                    458-9.el7                                    @anaconda
    #然后我们安装一个httpd,然后后面显示 @updates,表示是通过updates源安装的。这里涉及你repo仓库ID名。
    [root@TEST /etc/yum.repos.d 04:34:45]#yum list | grep httpd
    httpd-tools.x86_64                          2.4.6-97.el7.centos        @updates 
    httpd.x86_64                                2.4.6-97.el7.centos        updates  
    httpd-devel.x86_64                          2.4.6-97.el7.centos        updates  
    httpd-manual.noarch                         2.4.6-97.el7.centos        updates
    #centos8yum卸载掉时候会卸载依赖包,centos7卸载掉时候只会卸载单独的包。如果想要卸载掉时候可以看yum日志,然后一个一个卸载或者下面这个操作执行
    #首先查看yum历史记录
    [root@TEST /etc/yum.repos.d 04:44:00]#yum history
    已加载插件:fastestmirror
    ID     | 命令行                   | 日期和时间       | 操作           | 变更数 
    -------------------------------------------------------------------------------
        26 | history undo 18          | 2021-01-13 16:43 | Erase          |    4   
        25 | remove httpd             | 2021-01-13 16:23 | Erase          |    1   
        24 | install httpd            | 2021-01-13 16:23 | Install        |    1   
    history list
    #然后通过ID查看你刚刚安装了什么
    [root@TEST /etc/yum.repos.d 04:44:08]#yum history info 18
    已加载插件:fastestmirror
    事务 ID: 18
    起始时间    : Tue Jan 12 18:14:20 2021
    启动 RPM 数据库     : 374:256035a1b6eff4dc537e44e1f413c112632a5c3d
    结束时间       :            18:14:21 2021 (1 秒)
    结束 RPM 数据库      : 379:4e983244c968a7f2b0100438ba295c2d5b06868b
    用户           : root <root>
    返回码    : 成功
    命令行   : -y install httpd
    事务完成属主:
        已安装 rpm-4.11.3-45.el7.x86_64                        @base
        已安装 yum-3.4.3-168.el7.centos.noarch                 @base
        已安装 yum-plugin-fastestmirror-1.1.31-54.el7_8.noarch @base
    已变更的包:
        依赖安装 apr-1.4.8-7.el7.x86_64                 @base
        依赖安装 apr-util-1.5.2-6.el7.x86_64            @base
        安装 httpd-2.4.6-97.el7.centos.x86_64       @updates
        依赖安装 httpd-tools-2.4.6-97.el7.centos.x86_64 @updates
        依赖安装 mailcap-2.1.41-2.el7.noarch            @base
    history info
    #确认无误后,然后撤销刚刚的安装操作,那就会卸载刚刚安装的所有安装包。
    [root@TEST /etc/yum.repos.d 04:45:23]#yum history undo 18
    #如果卸载错误了,可以直接将刚刚执行的事件重做一遍
    [root@TEST /etc/yum.repos.d 04:50:19]#yum history redo 25
    

    5. 程序源码编译安装

    5.1 源码编译介绍

    程序包编译安装:
    源代码-->预处理-->编译-->汇编-->链接-->执行
    多文件:文件中的代码之间,很可能存在跨文件依赖关系
    虽然有很多开源软件将软件打成包,供人们使用,但并不是所有源代码都打成包,如果想使用开源软
    件,可能需要自已下载源码,进行编译安装。另外即使提供了包,但是生产中需要用于软件的某些特
    性,仍然需要自行编译安装。但是利用源代码编译安装是比较繁琐的,庆幸的是有相关的项目管理工具
    可以大大减少编译过程的复杂度。

    5.2 开源程序源代码的获取

    项目官方自建站点:
    apache.org (ASF:Apache Software Foundation)
    mariadb.org
    ...
    代码托管:
    Github.com
    gitee.com
    SourceForge.net
    code.google.com

    5.3 编译源码的项目工具
    • C、C++的源码编译:使用 make 项目管理器
      configure脚本 --> Makefile.in --> Makefile
      相关开发工具:
      autoconf: 生成configure脚本
      automake:生成Makefile.in
      上面脚本文件一般情况都是开发给生成好了的,无需我们操作。
    • java的源码编译: 使用 maven
    5.4 C语言源代码编译安装过程

    利用编译工具,通常只需要三个大的步骤

    • ./configure
      (1) 通过选项传递参数,指定安装路径、启用特性等;执行时会参考用户的指定以及Makefile.in文
      件生成Makefile
      如果包里已有Makefile文件,我们可以先查看一下默认的Makefile文件,如果已有那就可以可以跳过这一步。
      (2) 检查依赖到的外部环境,如依赖的软件包
    • make 根据Makefile文件,会检测依赖的环境,进行构建应用程序,
    • make install 复制文件到相应路径
      注意:安装前可以通过查看README,INSTALL获取帮助
    5.4.1 编译安装准备

    准备:安装相关的依赖包

    • 开发工具:make, gcc (c/c++编译器GNU C Complier)
    • 开发环境:开发库(glibc:标准库),头文件,可安装开发包组 Development Tools
    • 软件相关依赖包
      生产实践:基于最小化安装的系统建议安装下面相关包
    yum install gcc make autoconf gcc-c++ glibc glibc-devel pcre pcre-devel openssl
    openssl-devel systemd-devel zlib-devel vim lrzsz tree tmux lsof tcpdump wget
    net-tools iotop bc bzip2 zip unzip nfs-utils man-pages
    
    5.4.2 编译安装
    • 5.4.2.1 运行configure脚本生成Makefile文件

    其选项主要功能:

    • 可以指定安装位置
    • 指定启用的特性
      获取其支持使用的选项 ./configure --help 选项分类:
    • 安装路径设定:
      --prefix=/PATH:指定默认安装位置,默认为/usr/local/
      --sysconfdir=/PATH:配置文件安装位置
      System types:支持交叉编译
    • 软件特性和相关指定:
      Optional Features: 可选特性
      --disable-FEATURE
      --enable-FEATURE[=ARG]
      Optional Packages: 可选包
      --with-PACKAGE[=ARG] 依赖包
      --without-PACKAGE 禁用依赖关系

    注意: 通常被编译操作依赖的程序包,需要安装此程序包的“开发”组件,其包名一般类似于namedevel-
    VERSION

    • 5.4.2.2 make

    其实你运行make的时候已经在当前目录下已经将程序编译好了。不过我们还需要将编译好的东西复制到之前指定的路径。

    • 5.4.2.3 make install

    复制编译好的文件到之前指定的目录下。

    5.4.3 安装后的配置

    这一步主要是让我们可以像yum安装后那样命令的使用,而不是每次使用都需要进到目录下执行命令比较麻烦。

    1. 二进制程序目录导入至PATH环境变量中
      编辑文件/etc/profile.d/NAME.sh
      bash export PATH=/PATH/TO/BIN:$PATH
    2. 相关用户及文件
      有些开源软件编译完成后,还需要创建相关的用户及文件
    3. 导入帮助手册
      编辑/etc/man.config|man_db.conf文件,添加一个MANPATH

    范例1:Centos7编译安装tree1.8

    #1 安装相关的依赖包
    [root@centos7 ~]#yum install gcc make
    #2 下载源码并解压
    [root@centos7 ~]#tar xvf tree-1.8.0.tgz
    #3 进入解压缩的目录,README和INSTALL
    [root@centos7 ~]#cd tree-1.8.0/
    [root@centos7 tree-1.8.0]#cat README
    [root@centos7 tree-1.8.0]#cat INSTALL
    #4 修改源码的版本号
    [root@centos7 tree-1.8.0]#sed -i 's#v1\.8\.0#v.8.8.8#' tree.c
    #5 编译准备,这里因开发者已经给我们生成好了Makefile,我们可以直接通过修改这这个文件的配置达到我们安装到指定目录下的效果,比如我们需要将tree安装到/apps/tree下。
    [root@centos7 tree-1.8.0]#vim Makefile
    prefix = /apps/tree
    #6 编译
    [root@centos7 tree-1.8.0]#make
    #7 安装
    [root@centos7 tree-1.8.0]#make install
    #8 修改PATH变量,如果使用的是默认的路径/usr下的话那这一步可以忽略,原因可看看bash配置文件目录
    #默认无法直接运行tree
    [root@centos7 ~]#tree
    -bash: tree: command not found
    [root@centos7 ~]#echo 'PATH=/apps/tree/bin:$PATH' > /etc/profile.d/tree.sh
    . /etc/profile.d/tree.sh
    #或者利用软链接实现
    [root@centos7 ~]#ln -s /apps/tree/bin/tree /usr/local/bin
    #9 验证结果
    [root@centos7 ~]#tree --version
    tree v8.8.8 (c) 1996 - 2018 by Steve Baker, Thomas Moore, Francesc Rocher,
    Florian Sesser, Kyosuke Tokoro
    #10 添加man帮助
    #默认无法查看man
    [root@centos7 ~]#man tree
    No manual entry for tree
    [root@centos7 ~]#vim /etc/man_db.conf
    MANDATORY_MANPATH /apps/tree/man
    [root@centos7 ~]#man tree
    #11 运行tree查看生成的文件列表
    [root@centos7 ~]#tree /apps/tree
    /apps/tree
    ├── bin
    │ └── tree
    └── man
    └── man1
    └── tree.1
    3 directories, 2 files
    

    范例2:编译安装cmatrix

    这个工具包解压后提供了两种方式一种就是直接使用make编译安装,因为开发者已经生成了Makefile文件了。不过你也可以通过./confingure脚本来自定义。

    #先提前安装编译安装环境
    [root@repo-server ~ 05:39:11]#yum -y install autoconf ncurses-devel make gcc
    #下载解压包
    [root@repo-server ~ 05:39:11]#wget https://github.com/abishekvashok/cmatrix/releases/download/v2.0/cmatrix-v2.0-Butterscotch.tar
    [root@repo-server /usr/local/src 05:40:34]#tar xvf cmatrix-v2.0-Butterscotch.tar
    #进入目录
    [root@repo-server /usr/local/src 05:41:52]#cd cmatrix/
    #通过查看路径我们能看到这个源码包中已经有了Makefile文件了,而且也有configure。不像tree包直有一个Makefile文件。不过这个Makefile的文件有点多,有兴趣的可以看看,对我们日常有关的无非还是几个路径。建议还是自己生成一个Makefile比较好。
    #自定义配置路径
    [root@repo-server /usr/local/src 05:41:52]#./configure --prefix=/apps/cmatrix
    #编译安装
    [root@repo-server /usr/local/src 05:41:52]#make && make install
    #配置环境
    [root@repo-server /usr/local/src 05:41:52]#echo 'PATH=/apps/cmatrix/bin:$PATH' > /etc/profile.d/cmatrix.sh
    [root@repo-server /usr/local/src 05:41:52]#. /etc/profile.d/cmatrix.sh
    #或者用软链接实现
    [root@repo-server /usr/local/src 05:41:52]#ln -sv /apps/cmatrix/bin/cmatrix /usr/local/bin/
    #运行
    [root@repo-server /usr/local/src 05:41:52]#cmatrix -a -b -C yellow
    #配置帮助
    [root@repo-server /usr/local/src 05:41:52]#vim /etc/man_db.conf
    MANDATORY_MANPATH /apps/cmatrix/share/man
    

    范例3:编译安装openssl

    因为centos上自带的版本太老了,现在很多软件无法安装。现给它来个升级

    #官网下载最新包,解压
    [root@TEST ~ 07:40:41]#wget https://www.openssl.org/source/old/1.1.1/openssl-1.1.1h.tar.gz
    [root@TEST ~ 07:40:41]#tar xvf openssl-1.1.1h.tar.gz
    #进入目录,自定义配置
    [root@TEST ~ 07:40:41]#cd openssl-1.1.1h
    [root@TEST ~/openssl-1.1.1h 07:42:14]#./config --prefix=/app/openssl
    #编译安装
    [root@TEST ~/openssl-1.1.1h 07:42:14]#make && make install
    #配置环境
    [root@TEST ~/openssl-1.1.1h 07:44:27]#echo "export PATH=/app/openssl/bin:$PATH" > /etc/profile.d/openssl.sh
    #退出账号重新登就生效了
    #配置动态库不然会报错,可以先用ldd查看一下库是否缺失
    [root@TEST ~ 07:46:53]#ldd /app/openssl/bin/openssl
            linux-vdso.so.1 =>  (0x00007ffc4e964000)
            libssl.so.1.1 => /app/openssl/lib/libssl.so.1.1 (0x00007fade178e000)
            libcrypto.so.1.1 => /app/openssl/lib/libcrypto.so.1.1 (0x00007fade12a4000)
            libdl.so.2 => /lib64/libdl.so.2 (0x00007fade10a0000)
            libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fade0e84000)
            libc.so.6 => /lib64/libc.so.6 (0x00007fade0ab6000)
            /lib64/ld-linux-x86-64.so.2 (0x00007fade1a20000)
    #如果有缺失就将源码编译的openssl路径下的lib加入到默认搜索路径
    [root@TEST ~ 07:49:15]#echo "/app/openssl/lib/" >> /etc/ld.so.conf
    #使文件生效
    [root@TEST ~ 07:49:35]#ldconfig -v
    #测试成功
    [root@TEST ~ 07:50:24]#openssl version
    OpenSSL 1.1.1h  22 Sep 2020
    

    软连接设置

    ln -s 原路径   软连接名
    ln -s test ddd
    

    文本处理

    vim工具使用

    插入模式

    i #insert, 在光标所在处输入
    I #在当前光标所在行的行首输入
    a #append, 在光标所在处后面输入
    A #在当前光标所在行的行尾输入
    o #在当前光标所在行的下方打开一个新行
    O #在当前光标所在行的上方打开一个新行
    p #复制当前行
    

    冒号命令

    w #写(存)磁盘文件
    wq #写入并退出
    x #写入并退出
    X #加密
    q #退出
    q! #不存盘退出,即使更改都将丢失
    r filename #读文件内容到当前文件中
    w filename #将当前文件内容写入另一个文件
    !command #执行命令
    r!command #读入命令的输出
    

    地址定界

    格式:
    :start_pos,end_pos cmd

    #   #具体第#行,例如2表示第2行
    #,#     #从左侧#表示起始行,到右侧#表示结尾行
    #,+#    #从左侧#表示的起始行,加上右侧#表示的行数,范例:2,+3 表示2到5行
    .   #当前行
    $   #最后一行
    .,$-1   #当前行到倒数第二行
    %   #全文, 相当于1,$
    /pattern/   #从当前行向下查找,直到匹配pattern的第一行,即:正则表达式
    /pat1/,/pat2/   #从第一次被pat1模式匹配到的行开始,一直到第一次被pat2匹配到的行结束
    #,/pat/     #从指定行开始,一直找到第一个匹配patttern的行结束
    /pat/,$     #向下找到第一个匹配patttern的行到整个文件的结尾的所有行
    

    地址定界后可跟编辑命令

    d #删除
    y #复制
    w file #将范围内的行另存至指定文件中
    r file #在指定位置插入指定文件中的所有内容
    

    vim快速查找替换

    格式:
    s/要查找的内容/替换为的内容/修饰符
    说明:

    要查找的内容:可使用基末正则表达式模式
    替换为的内容:不能使用模式,但可以使用\1, \2, ...等后向引用符号;还可以使用“&”引用前面查找时查
    找到的整个内容

    修饰符:

    i #忽略大小写
    g #全局替换,默认情况下,每一行只替换第一次出现
    gc #全局替换,每次替换前询问
    

    转义符写法,如:#,@
    范例:
    就是将原来的 / 换成 #,@ 符号就行。

    s@/etc@/var@g
    $s#/home/root#/GGGGGG#g
    

    个性化定制vim

    配置文件路径:

    /etc/vimrc  #全局
    ~/.vimrc    #个人
    
    • 行号
      显示:set number,简写 set nu
      取消显示:set nonumber, 简写 set nonu
    • 忽略字符的大小写
      启用:set ignorecase,简写 set ic
      不忽略:set noic
    • 自动缩进
      启用:set autoindent,简写 set ai
      禁用:set noai
    • 复制保留格式
      启用:set paste
      禁用:set nopaste
    • 显示Tab和换行符 I 和$显示
      启用:set list
      禁用:set nolist
    • 高亮搜索
      启用:set hlsearch
      禁用:set nohlsearch
    • 语法高亮
      启用:syntax on
      禁用:syntax off
    • 文件格式
      i #忽略大小写
      g #全局替换,默认情况下,每一行只替换第一次出现
      gc #全局替换,每次替换前询问
      s@/etc@/var@g
      s#/boot#/#i
      /etc/vimrc #全局
      ~/.vimrc #个人
      启用windows格式:set fileformat=dos
      启用unix格式:set fileformat=unix
      简写 set ff=dos|unix
    • Tab 用空格代替
      启用:set expandtab 默认为8个空格代替Tab
      禁用:set noexpandtab
      简写:set et
    • Tab用指定空格的个数代替
      启用:set tabstop=# 指定#个空格代替Tab
      简写:set ts=4
    • 设置文本宽度
      set textwidth=65 (vim only)
      set wrapmargin=15
    • 设置光标所在行的标识线
      启用:set cursorline,简写 set cul
      禁用:set nocursorline
    • 加密
      启用: set key=password
      禁用: set key=
    • 了解更多
      set 帮助
      :help option-list
      :set or :set all

    命令模式快捷键

    快捷键太多不一一描述,只列举几个自己认为常用的命令。

    • 字符间跳转

    h: 左 L: 右 j: 下 k: 上
    COMMAND:跳转由#指定的个数的字符

    • 单词间跳转:
      w:下一个单词的词首
      e:当前或下一单词的词尾
      b:当前或前一个单词的词首
      COMMAND:由#指定一次跳转的单词数

    • 当前页跳转:
      H:页首 M:页中间行 L:页底

    • 行首行尾跳转:
      ^ 跳转至行首的第一个非空白字符
      0 跳转至行首
      $ 跳转至行尾

    • 行间移动:
      G 最后一行
      1G, gg 第一行

    • 复制命令(yank)
      y 复制,行为相似于d命令

    • 删除命令(delete)
      d 删除命令,可结合光标跳转字符,实现范围删除,组合用法贼多,常用组合
      100 dd 删除100行
      d$ 删除到行尾
      d^ 删除到非空行首
      d0 删除到行首

    • 粘贴命令(paste)
      p 缓冲区存的如果为整行,则粘贴当前光标所在行的下方;否则,则粘贴至当前光标所在处的后面
      P 缓冲区存的如果为整行,则粘贴当前光标所在行的上方;否则,则粘贴至当前光标所在处的前面

    • 改变命令(change)
      c: 删除后切换成插入模式
      cc:删除当前行并输入新内容,相当于S

    • 撤消更改
      u 撤销最近的更改,相当于windows中ctrl+z
      Ctrl - r 重做最后的“撤消”更改,相当于windows中crtl+y

    • 帮助
      :help
      :help topic
      Use :q to exit help
      vimtutor

    编辑二进制

    #以二进制方式打开文件
    vim -b binaryfile
    #扩展命令模式下,利用xxd命令转换为可读的十六进制
    :%!xxd
    #切换至插入模式下,编辑二进制文件
    #切换至扩展命令模式下,利用xxd命令转换回二进制
    :%!xxd -r
    #保存退出
    

    查看文本文件内容

    1. cat命令使用案例

    2. head命令使用案例

    格式:head [OPTION]... [FILE]...
    选项:
    -c # 指定获取前#字节
    -n # 指定获取前#行
    -# 同上
    范例:

    [root@centos8 ~]#head -n 3 /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    [root@centos8 ~]#head -3 /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    

    3. tail命令使用案例

    格式:tail [OPTION]... [FILE]...

    选项:
    -c # 指定获取后#字节
    -n # 指定获取后#行
    -# 同上
    -f 跟踪显示文件fd新追加的内容,常用日志监控,相当于 --follow=descriptor,当文件删除再新建同名
    文件,将无法继续跟踪文件
    -F 跟踪文件名,相当于--follow=name --retry,当文件删除再新建同名文件,将可以继续跟踪文件

    范例

    [root@centos8 ~]#cat /data/f1.txt
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [root@centos8 ~]#tail -n 3 /data/f1.txt
    8
    9
    10
    
    ----------------------------
    # 查询第三条开始的内容,常用做于筛选掉首条无用注释。
    [root@centos8 ~]#tail -n +3 /data/f1.txt
    3
    4
    5
    6
    7
    8
    9
    10
    
    [root@centos8 ~]#tail -3 /var/log/messages
    Dec 20 09:49:01 centos8 dbus-daemon[952]: [system] Successfully activated
    service 'net.reactivated.Fprint'
    Dec 20 09:49:01 centos8 systemd[1]: Started Fingerprint Authentication Daemon.
    Dec 20 09:49:13 centos8 su[6887]: (to mage) root on pts/0
    #查询末尾100条数据,并持续展示
    [root@centos8 ~]#tail -100f /var/log/messages
    Dec 20 08:36:40 centos8 systemd[1321]: Startup finished in 52ms.
    Dec 20 08:36:40 centos8 systemd[1]: Started User Manager for UID 0.
    Dec 20 08:47:01 centos8 systemd[1]: Starting dnf makecache...
    Dec 20 08:47:02 centos8 dnf[1465]: AppStream
    213 kB/s | 4.3 kB 00:00
    Dec 20 08:47:02 centos8 dnf[1465]: BaseOS
    163 kB/s | 3.9 kB 00:00
    Dec 20 08:47:04 centos8 dnf[1465]: EPEL
    2.6 kB/s | 5.3 kB 00:02
    Dec 20 08:47:09 centos8 dnf[1465]: EPEL
    884 kB/s | 4.3 MB 00:05
    Dec 20 08:47:12 centos8 dnf[1465]: extras
    727 B/s | 1.5 kB 00:02
    Dec 20 08:47:12 centos8 dnf[1465]: Metadata cache created.
    Dec 20 08:47:12 centos8 systemd[1]: Started dnf makecache.
    #只查看最新发生的日志
    [root@centos8 ~]#tail -fn0 /var/log/messages
    [root@centos8 ~]#tail -0f /var/log/messages
    
    # 管道符范例
    [root@centos8 data]#ifconfig | head -2 | tail -1
    │
    inet 10.0.0.8 netmask 255.255.255.0 broadcast 10.0.0.255
    

    4. cut命令使用案例

    说明:cut命令多用于内容提取。

    选项:

    -d DELIMITER: 指明分隔符,默认tab
    -f FILEDS:
    #: 第#个字段,例如:3
    #,#[,#]:离散的多个字段,例如:1,3,6
    #-#:连续的多个字段, 例如:1-6
    混合使用:1-3,7
    -c 按字符切割
    --output-delimiter=STRING指定输出分隔符
    

    范例:

    [root@TEST data]# ifconfig
    ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.16.80.130  netmask 255.255.255.0  broadcast 172.16.80.255
            inet6 fe80::3553:1f6c:91c1:c235  prefixlen 64  scopeid 0x20<link>
    #此命令结合head、tail、tr、cut一起来提取IP地址
    [root@TEST data]# ifconfig | head -2 | tail -1 | tr -s  ' ' | cut -d " " -f3
    172.16.80.130
    #此命令为提取messages的第二个字符
    cat -d " " -f2 messages
    
    

    查看非文本文件内容

    1. hexdump使用案例

    范例:

    hexdump -C -n 512 /dev/sda
    00000000 eb 63 90 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0 |.c..............|
    echo {a..z} | tr -d ' '|hexdump -C
    00000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 |abcdefghijklmnop|
    00000010 71 72 73 74 75 76 77 78 79 7a 0a |qrstuvwxyz.|
    0000001b
    

    2. od 使用案例

    [root@centos8 ~]#echo {a..z} | tr -d ' '|od -t x
    0000000 64636261 68676665 6c6b6a69 706f6e6d
    0000020 74737271 78777675 000a7a79
    0000033
    [root@centos8 ~]#echo {a..z} | tr -d ' '|od -t x1
    0000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70
    0000020 71 72 73 74 75 76 77 78 79 7a 0a
    0000033
    [root@centos8 ~]#echo {a..z} | tr -d ' '|od -t x1z
    0000000 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 >abcdefghijklmnop<
    0000020 71 72 73 74 75 76 77 78 79 7a 0a >qrstuvwxyz.<
    0000033
    

    分析处理文本文件内容

    1. paste命令使用案例

    paste 合并多个文件同行号的列到一行

    格式
    paste [OPTION]... [FILE]...

    选项
    -d :分隔符:指定分隔符,默认用TAB
    -s : 所有行合成一行显示
    范例:
    可以看出cat与paste区别

    ❯ cat 1 2
    1 2 3 4 5 6 7 8 9 10
    11 14 17 20
    ❯ paste 1 2
    1 2 3 4 5 6 7 8 9 10    11 14 17 20
    # 行显示看不太明显,咱们看一下列显示。
    ❯ cat 1 2
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    ❯ paste 1 2
    1   11
    2   12
    3   13
    4   14
    5   15
    6   16
    7   17
    8   18
    9   19
    10  20
    ❯ paste -d":" 1 2
    1:11
    2:12
    3:13
    4:14
    5:15
    6:16
    7:17
    8:18
    9:19
    10:20
    ❯ paste -s 1 2
    1   2   3   4   5   6   7   8   9   10
    11  12  13  14  15  16  17  18  19  20
    

    2. wc统计命令使用案例

    wc 命令可用于统计文件的行总数、单词总数、字节总数和字符总数
    可以对文件或STDIN中的数据统计

    常用选项:
    -l 只计数行数
    -w 只计数单词总数
    -c 只计数字节总数
    -m 只计数字符总数
    -L 显示文件中最长行的长度

    范例:

    > wc story.txt
    39 237 1901 story.txt
    行数 单词数 字节数
    
    df | tail -n $(echo `df | wc -l`-1|bc)
    

    3. sort 排序命令使用案例

    格式:
    sort [options] file(s)
    常用选项
    -r 执行反方向(由上至下)整理
    -R 随机排序
    -n 执行按数字大小整理
    -f 选项忽略(fold)字符串中的字符大小写
    -u 选项(独特,unique),合并重复项,即去重
    -t c 选项使用c做为字段界定符
    -k # 选项按照使用c字符分隔的 # 列来整理能够使用多次

    范例:

    #查看分区利用率最高值
    [root@centos8 ~]#df| tr -s ' ' '%'|cut -d% -f5|sort -nr|head -1
    100
    #将passwd文件已:作为分隔符,按第三列作为一个排序标准。
    sort -nt: -k3 /etc/passwd
    

    4. uniq显示重复命令使用案例

    常用选项:
    -c: 显示每行重复出现的次数
    -d: 仅显示重复过的行
    -u: 仅显示不曾重复的行
    uniq常与sort一起配合使用:

    范例:

    #组合使用筛选并将访问次数最多的IP筛选出来
    
    cut -d“ ” -f1 /var/log/nginx.access.log | sort | uniq -c | sort -nr | head -1
    

    5. diff比较文件使用案例

    范例:

    [root@centos8 ~]#cat f1.txt
    mage
    注明第5行有区别(改变)
    复制对文件改变patch
    diff 命令的输出被保存在一种叫做“补丁”的文件中
    使用 -u 选项来输出“统一的(unified)”diff格式文件,最适用于补丁文件
    2.6.4.2 patch
    patch 复制在其它文件中进行的改变(要谨慎使用)
    适用 -b 选项来自动备份改变了的文件
    范例:
    zhang
    wang
    xu
    [root@centos8 ~]#cat f2.txt
    magedu
    zhang sir
    wang
    xu
    shi
    [root@centos8 ~]#diff f1.txt f2.txt
    1,2c1,2
    < mage
    < zhang
    ---
    > magedu
    > zhang sir
    4a5
    > shi
    # 加上 -u 参数显示更加详细,样例看下面示范。
    [root@centos8 ~]#diff -u f1.txt f2.txt
    --- f1.txt 2019-12-13 21:31:30.892775671 +0800
    +++ f2.txt 2019-12-13 22:00:14.373677728 +0800
    @@ -1,4 +1,5 @@
    -mage
    -zhang
    +magedu
    +zhang sir
    wang
    xu
    +shi
    
    --------------next--------------
    # diff -u 配合patch可达到以下结果
    [root@centos8 ~]#diff -u f1.txt f2.txt > f.patch
    [root@centos8 ~]#rm -f f2.txt
    [root@centos8 ~]#patch -b f1.txt f.patch
    patching file f1.txt
    [root@centos8 ~]#cat f1.txt
    magedu
    zhang sir
    wang
    xu
    shi
    [root@centos8 ~]#cat f1.txt.orig
    mage
    zhang
    wang
    xu
    # orig是刚刚 patch 保留的源文件
    

    注意:注明第5行有区别(改变)
    复制对文件改变patch
    diff 命令的输出被保存在一种叫做“补丁”的文件中
    使用 -u 选项来输出“统一的(unified)”diff格式文件,最适用于补丁文件

    6. patch复制其他文件中进行的改变

    注意:默认选项会之前替换掉原来的文件,建议添加 -b的参数。

    范例在上一diff命令中有提到,可以参考一二。
    5. diff比较文件使用案例

    7. cmp命令比较二进制使用案例

    不常用忽略。

    文本处理三剑客

    文本处理三剑客之grep

    作用:文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行
    模式:由正则表达式字符及文本字符所编写的过滤条件。

    格式:

    grep [OPTIONS] PATTERN [FILE...]
    

    常用选项:

    --color=auto 对匹配到的文本着色显示
    -m # 匹配#次后停止
    -v 显示不被pattern匹配到的行
    -i 忽略字符大小写
    -n 显示匹配的行号
    -c 统计匹配的行数
    -o 仅显示匹配到的字符串
    -q 静默模式,不输出任何信息
    -A # after, 后#行
    -B # before, 前#行
    -C # context, 前后各#行
    -e 实现多个选项间的逻辑or关系,如:grep –e ‘cat ’ -e ‘dog’ file
    -w 匹配整个单词
    -E 使用ERE,相当于egrep
    -F 不支持正则表达式,相当于fgrep
    -f file 根据模式文件处理
    -r 递归目录,但不处理软链接
    -R 递归目录,但处理软链接
    

    范例:

    #下面都是最常用的写法,主要是将标准输入的结果过滤出能匹配的行。匹配正则玩法更多。
    [root@TEST ~]# cat /etc/passwd | grep 'root'
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    [root@TEST ~]# grep 'root' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    #-q 静默,不输出任何信息,可用作脚本来用
    [root@TEST ~]# grep -q 'FFFFFFF' /etc/passwd
    [root@TEST ~]# echo $?
    1
    [root@TEST ~]# grep -q root /etc/passwd
    [root@TEST ~]# echo $?
    0
    #输出非0表示表示这个筛选不存在为无结果,输出结果0的表示有这个结果。一般在编写脚本的时候使用。
    [root@TEST ~]# cat 123.log 
    root
    bash
    [root@TEST ~]# grep -f 123.log  /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    test:x:1000:1000::/home/test:/bin/bash
    test1:x:1001:1001:test,test,11111,33333:/home/test1:/bin/bash
    nginx:x:1003:1005::/home/nginx:/bin/bash
    varnish:x:1004:1006::/home/varnish:/bin/bash
    #-f 是将文件中的内容作为过滤条件。
    

    正则表达式

    简单来说功能上大于通配符,一个功能增强版的通配符功能,但于通配符不通,通配符处理文件名,正则表达式处理文本内容中的字符串的。

    1. 基本正则表达式

    1.1 字符匹配

    . 匹配任意单个字符,可以是一个汉字
    [] 匹配指定范围内的任意单个字符,示例:[wang] [0-9] [a-z] [a-zA-Z]
    [^] 匹配指定范围 ==外==  的任意单个字符,示例:[^wang]
    [:alnum:] 字母和数字
    [:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
    [:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
    [:upper:] 大写字母
    [:blank:] 空白字符(空格和制表符)
    [:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广)
    [:cntrl:] 不可打印的控制字符(退格、删除、警铃...)
    [:digit:] 十进制数字
    [:xdigit:]十六进制数字
    [:graph:] 可打印的非空白字符
    [:print:] 可打印字符
    [:punct:] 标点符号
    

    范例:

    [root@TEST ~]# grep r..t /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    gentoo:x:1002:1003:Gentoo Distrbution:/home/gentoo:/bin/csh
    
    

    1.2 匹配次数

    用在要指定次数的字符后面,用于指定前面的字符要出现的次数

    * 匹配前面的字符任意次,包括0次,贪婪模式:尽可能长的匹配
    .* 任意长度的任意字符
    \? 匹配其前面的字符0或1次,即:可有可无
    \+ 匹配其前面的字符至少1次,即:肯定有,>=1
    \{n\} 匹配前面的字符n次  =n
    \{m,n\} 匹配前面的字符至少m次,至多n次   m≤字符≤n,也就是能匹配的范围是在 m,n 之间。
    
    \{,n\} 匹配前面的字符至多n次,<=n
    \{n,\} 匹配前面的字符至少n次  >=n
    

    范例:

    echo google | grep 'go*gle'
    google
    echo ggle | grep 'go*gle'
    ggle
    #*只在乎星号前面值,也就是o。
    echo gafdsfedfasfgle | grep 'g.*le'
    gafdsfedfasfgle
    # .*功能类似于通配符中的 * 功能
    echo gogle | grep 'go\?gle'
    gogle
    echo google | grep 'go\?gle'
    # \? 只匹配其前面的字符0或1次。
    

    1.3 位置锚定

    ^ 行首锚定,用于模式的最左侧
    $ 行尾锚定,用于模式的最右侧
    ^PATTERN$ 用于模式匹配整行
    ^$ 空行
    ^[[:space:]]*$ 空白行
    \< 或 \b 词首锚定,用于单词模式的左侧
    \> 或 \b 词尾锚定,用于单词模式的右侧
    \<PATTERN\> 匹配整个单词
    

    范例:

    cat 1 
    1
    2
    3
    4
    
    5
    6
    
    7
    8
    11
    #
    #
    #
    #
    #
    #
    #
    #
    #
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    grep ^# 1                                      
    #
    #
    #
    #
    #
    #
    #
    #
    #
    grep -v ^# 1                                     
    1
    2
    3
    4
    
    5
    6
    
    7
    8
    11
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    grep -v ^$ 1                                    
    1
    2
    3
    4
    5
    6
    7
    8
    11
    #
    #
    #
    #
    #
    #
    #
    #
    #
    a b c d e f g h i j k l m n o p q r s t u v w x y z
    echo fdsfafroot | grep 'root\>'
    fdsfafroot
    
    -------------------next-------------
    #组合案例,筛选出硬盘使用率,grep -o 是只显示匹配到的,匹配不到的不显示。
    
    df | grep '^/dev/sd' | grep -o ' *[0-9]\{1,3\}%'
    

    1.4 分组

    分组:() 将多个字符捆绑在一起,当作一个整体处理,如:(root)+
    后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名
    方式为: \1, \2, \3, ...
    \1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符

    范例:

    #匹配1文件中的每行出现abc一次的
    
    cat 1
    abcabcabcabc
    abc
    abc abc
    grep '\(abc\)\{1\}' 1
    abcabcabcabc
    abc
    abc abc
    grep '\(abc\)\{2\}' 1
    abcabcabcabc
    abc abc
    grep '\(abc\)\{3\}' 1
    abcabcabcabc
    grep -E '(abc){2,3}' 1
    abcabcabc
    abcabc
    

    1.5 或者

    示例:

    a\|b #a或b
    C\|cat #C或cat
    \(C\|c\)at #Cat或cat
    

    范例

    基本正则表达式作业的一些范例

    grep "^[[:space:]].\+[^[:space:]]" /etc/grub2.cfg
    
    # 筛选IP
    ifconfig eth0 | egrep -o '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1
    172.16.80.130
    # 简略写法
    ifconfig eth0 | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1
    

    Shell脚本编程之基础部分

    1. 脚本自动创建注释内容

    在家目录下 .vimrc中添加一下配置

    autocmd BufNewFile *.sh exec ":call SetTitle()"
      9 func SetTitle()
     10         if expand("%:e") == 'sh'
     11         call setline(1,"#!/bin/bash")
     12         call setline(2,"#- - - - - - - - -- --Script comment information - - - - - - - - - -")
     13         call setline(3,"#Author:                               拉基")
     14         call setline(4,"#Email:                        helpdesk81@outlook.com")
     15         call setline(5,"#Creation time:                ".strftime("%Y-%m-%d"))
     16         call setline(6,"#FileName:                     ".expand("%:t"))
     17         call setline(7,"#Blog address:                 https://www.cnblogs.com/98record/")
     18         call setline(8,"#Copyright (C)                  ".strftime("%Y")."All rights reserved")
     19         call setline(9,"#- - - - - - - - - - - - - end - - - - - - - - - - - - - - - - - -")
     20         endif
     21 endfunc
     22 autocmd BufNewFile * normal G
     vim test.sh
      1 #!/bin/bash
      2 #- - - - - - - - -- --Script comment information - - - - - - - - - -
      3 #Author:                               拉基
      4 #Email:                        helpdesk81@outlook.com
      5 #Creation time:                2020-12-20
      6 #FileName:                     ddd.sh
      7 #Blog address:                 https://www.cnblogs.com/98record/
      8 #Copyright (C)                  2020All rights reserved
      9 #- - - - - - - - - - - - - end - - - - - - - - - - - - - - - - - -
    

    2. 远程执行脚本

    curl -s 远程脚本地址 | bash
    

    3. 脚本调试方式

    bash -n test.sh #检查语法错误
    bash -x test.sh #检查时观察,可排查代码中的命令错误,逻辑错误,-n 是无法检查出来的。
    

    4. 变量

    4.1 变量命名法则

    • 不能使程序中的保留字:如:if, for
    • 只能使用数字、字母及下划线,且不能以数字开头,注意:不支持短横线 “ - ”,和主机名相反
    • 见名知义,用英文单词命名,并体现出实际作用,不要用简写,如:ATM
    • 统一命名规则:驼峰命名法, studentname,大驼峰StudentName 小驼峰studentName
    • 变量名大写:STUDENT_NAME
    • 局部变量小写
    • 函数名小写

    4.2 变量定义和引用

    变量的生效范围等标准划分变量类型

    • 普通变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell
      进程均无效
    • 环境变量:生效范围为当前shell进程及其子进程
    • 本地变量:生效范围为当前shell进程中某代码片断,通常指函数
    4.2.1 变量赋值
    name = 'value'
    

    value 可以是以下多种形式

    直接字串:name='root'
    变量引用:name="$USER"
    命令引用:name=`COMMAND` 或者 name=$(COMMAND)
    

    注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存,脚本中的变量会随着脚
    本结束,也会自动删除。变量赋值不要带空格时连着写的。

    4.2.2 变量引用

    弱引用和强引用

    • "$name " 弱引用,其中的变量引用会被替换为变量值
    • '$name ' 强引用,其中的变量引用不会被替换为变量值,而保持原字符串

    范例:

    [root@TEST ~]# NAME=cto
    [root@TEST ~]# echo $NAME
    cto
    [root@TEST ~]# echo i am $NAME
    i am cto
    [root@TEST ~]# echo "i am $NAME"
    i am cto
    [root@TEST ~]# echo 'i am $NAME'
    i am $NAME
    
    [root@TEST ~]# DIR_FILE=`ls /`
    [root@TEST ~]# echo $DIR_FILE
    bin boot data dev etc home lib lib64 media mnt opt proc root run sbin srv sys testdir tmp usr var
    
    • 一个常犯的复制错误例子:
    [root@centos8 ~]#TITLE=cto
    [root@centos8 ~]#NAME=wang
    [root@centos8 ~]#TITLE=$NAME
    [root@centos8 ~]#echo $NAME
    wang
    [root@centos8 ~]#echo $TITLE
    wang
    [root@centos8 ~]#NAME=mage
    [root@centos8 ~]#echo $NAME
    mage
    [root@centos8 ~]#echo $TITLE
    wang
    
    4.2.2.1 细节
    • 变量赋值按源命令显示保留原格式,例子如下:

    仔细观察 两者的区别

    [root@TEST ~]# DIR_FILE=`ls ~`
    [root@TEST ~]# echo "$DIR_FILE"
    123.log
    ddd1
    ddd2
    ddd3
    ddd4
    ddd5
    issue.log
    mysql-5.6.46-linux-glibc2.12-x86_64
    mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
    test.log
    test.sh
    test.txt
    [root@TEST ~]# echo $DIR_FILE
    123.log ddd1 ddd2 ddd3 ddd4 ddd5 issue.log mysql-5.6.46-linux-glibc2.12-x86_64 mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz test.log test.sh test.txt
    
    • 定义多个变量的细节
    [root@TEST ~]# NAME="
    > 1
    > 2
    > 3
    > "
    [root@TEST ~]# echo $NAME
    1 2 3
    [root@TEST ~]# echo "$NAME"
    
    1
    2
    3
    
    [root@TEST ~]# NAME="1
    > 2
    > 3"
    [root@TEST ~]# echo "$NAME"
    1
    2
    3
    

    4.3 删除变量

    4.3.1 显示已定义的所有变量
    set         # 可通过查询自己的变量
    
    4.3.2 删除已经定义的变量

    建议不再使用此变量的时候手动删除此变量。

    unset <name>        
    #后面不需要加$符号,例子如下
    [root@TEST ~]# set | less | grep ^NAME
    NAME=$'1\n2\n3'
    [root@TEST ~]# unset NAME
    [root@TEST ~]# set | less | grep ^NAME
    

    4.4 环境变量

    因为普通变量中只能继承系统变量,父进程无法继承子进程的变量。然而子进程也不能继承父进程的变量,子进程的变量可与父进程变量名同。如果需要将父进程变量赋值给子进程需要配置系统的环境变量,成为系统变量,让子进程也可继承。

    注意:

    • 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量
    • 一旦子进程修改从父进程继承的变量,将会新的值传递给孙子进程
    • 一般只在系统配置文件中使用,在脚本中较少使用

    变相声明和赋值:

    #声明并赋值
    export name=VALUE
    declare -x name=VALUE
    #或者分两步实现
    name=VALUE
    export name
    

    4.5 只读变量

    只读变量:只能声明定义,但后续不能修改和删除,即常量

    很少用到,暂且忽略。后续用到再查。

    4.6 位置变量

    位置变量:在bash shell中内置的变量, 在脚本代码中调用通过命令行传递给脚本的参数

    $1, $2, ... 对应第1个、第2个等参数,shift [n]换位置
    $0 命令本身,包括路径
    $* 传递给脚本的所有参数,全部参数合为一个字符串
    $@ 传递给脚本的所有参数,每个参数为独立字符串
    $# 传递给脚本的参数的个数
    注意:$@ $* 只在被双引号包起来的时候才会有差异
    set -- #清空所有位置变量
    

    范例:

    [root@centos8 ~]#cat /data/scripts/arg.sh
    #!/bin/bash
    #
    #********************************************************************
    #Author: wangxiaochun
    #QQ: 29308620
    #Date: 2020-04-01
    #FileName: arg.sh
    #URL: http://www.magedu.com
    #Description: The test script
    #Copyright (C): 2020 All rights reserved
    #********************************************************************
    echo "1st arg is $1"
    echo "2st arg is $2"
    echo "3st arg is $3"
    echo "10st arg is ${10}"
    echo "11st arg is ${11}"
    echo "The number of arg is $#"
    echo "All args are $*"
    echo "All args are $@"
    echo "The scriptname is `basename $0`"
    [root@centos8 ~]#bash /data/scripts/arg.sh {a..z}
    1st arg is a
    2st arg is b
    3st arg is c
    10st arg is j
    11st arg is k
    The number of arg is 26
    All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
    All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
    The scriptname is arg.sh
    
    
    #--------------$*和$@的区别--------------
    [root@centos8 scripts]#cat f1.sh
    #!/bin/bash
    echo "f1.sh:all args are $@"
    echo "f1.sh:all args are $*"
    ./file.sh "$*"
    [root@centos8 scripts]#cat f2.sh
    #!/bin/bash
    echo "f2.sh:all args are $@"
    echo "f2.sh:all args are $*"
    ./file.sh "$@"
    [root@centos8 scripts]#cat file.sh
    #!/bin/bash
    echo "file.sh:1st arg is $1"
    [root@centos8 scripts]#./f1.sh a b c
    f1.sh:all args are a b c
    f1.sh:all args are a b c
    file.sh:1st arg is a b c
    [root@centos8 scripts]#./f2.sh a b c
    f2.sh:all args are a b c
    f2.sh:all args are a b c
    file.sh:1st arg is a
    

    4.7 退出状态码变量

    进程执行后,将使用变量 \(? 保存状态码的相关数字,不同的值反应成功或失败,\)?取值范例 0-255

    $?的值为0 #代表成功
    $?的值是1到255 #代表失败
    exit 数字   #可指定值,可以在输出  $? 的时候是你指定的值。
    

    范例

    [root@TEST ~ 10:01:19]#curl  www.baiddddddu.com &> /dev/null
    [root@TEST ~ 10:04:31]#echo $?
    6
    [root@TEST ~ 10:04:39]#curl  www.baidu.com &> /dev/null
    [root@TEST ~ 10:11:26]#echo $?
    0
    

    注意:

    • 脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
    • 如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

    4.8 命令的执行顺序

    由上往下依次顺序执行

    把命令行分成单个命令词
    展开别名
    展开大括号的声明{}
    展开波浪符声明 ~
    命令替换$() 和 ``
    再次把命令行分成命令词
    展开文件通配*、?、[abc]等等
    准备I/0重导向 <、>
    运行命令
    

    5. 防止扩展(转义)

    5.1 加反斜线

    反斜线(\)会使随后的字符按原意解释。也就是转义。

    范例:

    echo Your cost: \$5.00
    Your cost: $5.00
    

    5.2 加引号

    单引号(’’)防止所有扩展
    双引号(”“)也可防止扩展,但是以下情况例外:$(美元符号)
    

    5.3 变量扩展

    `` : 反引号,命令替换
    \:反斜线,禁止单个字符扩展
    !:叹号,历史命令替换
    

    6. 脚本安全和set用法

    6.1 set命令

    可以用来定制shell环境

    变量:
    h:hashall,打开选项后,Shell 会将命令所在的路径hash下来,避免每次都要查询。通过set +h将h选
    项关闭
    i:interactive-comments,包含这个选项说明当前的 shell 是一个交互式的 shell。所谓的交互式shell,
    在脚本中,i选项是关闭的
    m:monitor,打开监控模式,就可以通过Job control来控制进程的停止、继续,后台或者前台执行等
    B:braceexpand,大括号扩展
    H:history,H选项打开,可以展开历史列表中的命令,可以通过!感叹号来完成,例如“!!”返回上最近的
    一个历史命令,“!n”返回第 n 个历史命令

    范例:

    [root@centos8 ~]#echo $-
    himBHs
    [root@centos8 ~]#set +h
    [root@centos8 ~]#echo $-
    imBHs
    [root@centos8 ~]#hash
    -bash: hash: hashing disabled
    [root@centos8 ~]#echo {1..10}
    1 2 3 4 5 6 7 8 9 10
    [root@centos8 ~]#echo $-
    imBHs
    [root@centos8 ~]#set +B
    [root@centos8 ~]#echo $-
    imHs
    [root@centos8 ~]#echo {1..10}
    {1..10}
    

    6.2 set命令实现脚本安全

    -u 在扩展一个没有设置的变量时,显示错误信息, 等同set -o nounset
    -e 如果一个命令返回一个非0退出状态值(失败)就退出, 等同set -o errexit
    -o option 显示,打开或者关闭选项
    显示选项:set -o
    打开选项:set -o 选项
    关闭选项:set +o 选项
    -x 当执行命令时,打印命令及其参数,类似 bash -x
    

    范例:

    [root@centos8 ~]#set -o
    allexport off
    braceexpand on
    emacs on
    errexit off
    errtrace off
    functrace off
    hashall on
    histexpand on
    history on
    ignoreeof off
    interactive-comments on
    keyword off
    monitor on
    noclobber off
    noexec off
    noglob off
    nolog off
    notify off
    nounset off
    onecmd off
    physical off
    pipefail off
    posix off
    privileged off
    verbose off
    vi off
    xtrace off
    

    6.3 注意

    创建脚本的时候不要创建空变量,对于shell脚本来说空变量那就没有,也不会报错误。

    错误shell写法案例:

    #!/bin/bash
    DIR=/data
    rm -rf /data/tmp/$DIR1/*
    #这么写的话会直接忽略$DIR1,对于shell脚本来说就是删除/data/tmp/目录下的所有文件
    

    不过我们通过set 打开相关变量避免这种情况出现。如下

    #!/bin/bash
    set -u
    DIR=/data
    rm -rf /data/tmp/$DIR1/*
    #这样接着执行没有变量的脚本的时候会报错。也就终止执行删除命令了。基于脚本安全考虑应再开一个 -e 参数,写法:可以写两行也可以直接。set -ue 这样更加安全一点
    

    7. printf输出命令使用案例

    7.1 替换符号

    替换符号 功能
    %s 字符串
    %f 浮点格式
    %c ASCII字符,即显示对应参数的第一个字符
    %d,%i 十进制整数
    %b 相对应的参数中包含转义字符时,可以使用此替换符进行替换,对应的转义字符会被转义
    %o 八进制值
    %u 不带正负号的十进制值
    %x 十六进制值(a-f)
    %X 十六进制值(A-F)
    %% 表示%本身

    说明:%s 中的数字代表此替换符中的输出字符宽度,不足补空格,默认是右对齐,%-10s表示10个字
    符宽,- 表示左对齐

    7.2 常用转义符号:

    转义符 功能
    \a 警告字符,通常为ASCII的BEL字符
    \b 后退
    \f
    \n 换行
    \r 回车
    \t 水平制表符
    \v 垂直制表符
    \ 表示\本身

    7.3 printf范例

    [root@centos8 ~]#printf "%s\n" 1 2 3 4
    1
    2
    3
    4
    [root@centos8 ~]#printf "%f\n" 1 2 3 4
    1.000000
    2.000000
    3.000000
    4.000000
    #.2f 表示保留两位小数
    [root@centos8 ~]#printf "%.2f\n" 1 2 3 4
    1.00
    2.00
    3.00
    4.00
    [root@centos8 ~]#printf "(%s)" 1 2 3 4;echo
    (1)(2)(3)(4)
    [root@centos8 ~]#printf " (%s) " 1 2 3 4;echo ""
    (1) (2) (3) (4)
    [root@centos8 ~]#printf "(%s)\n" 1 2 3 4
    (1)
    (2)
    (3)
    (4)
    [root@centos8 ~]#printf "%s %s\n" 1 2 3 4
    1 2
    3 4
    [root@centos8 ~]#printf "%s %s %s\n" 1 2 3 4
    1 2 3
    4
    #%-10s 表示宽度10个字符,左对齐
    [root@centos8 ~]#printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男 20 70
    小红 女 18 50
    姓名 性别 年龄 体重
    小明 男 20 70
    小红 女 18 50
    #将十进制的17转换成16进制数
    [root@centos8 ~]#printf "%X" 17
    11[root@centos8 ~]#
    #将十六进制C转换成十进制
    [root@centos8 ~]#printf "%d\n" 0xC
    12
    [root@centos8 ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" $VAR
    welcome
    to
    Magedu
    [root@centos8 ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" "$VAR"
    welcome to Magedu
    

    8. shell算数运算

    shell 支持算术运算,但只支持整数,不支持小数

    bash中的算数运算

    +
    -
    *
    /
    % 取模,即取余数,示例:9%4=1,5%3=2
    ** 乘方
    #乘法符号有些场景中需要转义
    

    Linux中几种实现算数运算写法:

    let var=算术表达式
    ((var=算术表达式)) # 和上面等价
    var=$[算术表达式]
    var=$((算术表达式))
    var=$(expr arg1 arg2 arg3 ...)  #使用较少,用一些运算的时候需要转义
    declare –i var = 数值
    echo '算术表达式' | bc  
    

    8.1 取模范例

    #生成 0 - 49 之间随机数
    [root@centos8 ~]#echo $[$RANDOM%50]
    #随机字体颜色
    [root@centos8 ~]#echo -e "\033[1;$[RANDOM%7+31]mhello\033[0m"
    magedu
    

    8.2 增强型赋值:

    += i+=10 相当于 i=i+10
    -= i-=j 相当于 i=i-j
    *=
    /=
    %=
    ++ i++,++i 相当于 i=i+1
    -- i--,--i 相当于 i=i-1
    

    范例:

    [root@centos8 ~]#let i=10*2
    [root@centos8 ~]#echo $i
    20
    [root@centos8 ~]#((j=i+10))
    [root@centos8 ~]#echo $j
    30
    #自加3后复制案例👇
    [root@centos8 ~]# let count+=3
    [root@centos8 ~]# echo $count
    3
    [root@centos8 ~]#i=10
    [root@centos8 ~]#let i+=20 #相当于let i=i+20
    [root@centos8 ~]#echo $i
    30
    [root@centos8 ~]#j=20
    [root@centos8 ~]#let i*=j
    [root@centos8 ~]#echo $i
    600
    #自增,自减
    #let var+=1 结果等同于 let var++
    #let var-=1 结果等同于 let var--
    #展示i++与++i之间的效果区别。
    [root@centos8 ~]#unset i j ; i=1; let j=i++; echo "i=$i,j=$j"
    i=2,j=1
    [root@centos8 ~]#unset i j ; i=1; let j=++i; echo "i=$i,j=$j"
    i=2,j=2
    #由👆可以得出i++是先赋值在++,++i是先++后再赋值。
    

    8.3 bc计算保留小数

    #保留三位小数
    [root@TEST ~ 03:22:35]#echo "scale=3;2/3" | bc
    .666
    [root@TEST ~ 03:23:40]#echo "scale=3;100/3" | bc
    33.333
    

    8.4 范例脚本

    #!/bin/bash
    #-- - - - - - -Script comment information - - - - - - - - - -
    #Author:                               拉基
    #Email:                        helpdesk81@outlook.com
    #Creation time:                2020-12-26
    #FileName:                     Chook_Rabbit.sh
    #Blog address:                 https://www.cnblogs.com/98record/
    #Copyright (C)                  2020All rights reserved
    #- - - - - - - - - - - - - end - - - - - - - - - - - - - - - - - -
    #此脚本为计算鸡兔同笼为题,题目:今有雉兔同笼,上有三十五头,下有九十四足,问雉>兔各几何?
    HEAD=$1
    FOOT=$2
    Rabbit=$[(FOOT-HEAD*2)/2]
    Chook=$[HEAD-Rabbit]
    echo "兔子有$Rabbit只"
    echo "鸡有$Chook只"
    

    9. 逻辑运算

    true, false
    1, 0

    9.1 与

    与:&:和0相与,结果为0,和1相与,结果保留原值

    1 与 1 = 1
    1 与 0 = 0
    0 与 1 = 0
    0 与 0 = 0
    

    9.2 或

    |:和1相或结果为1,和0相或,结果保留原值

    1 或 1 = 1
    1 或 0 = 1
    0 或 1 = 1
    0 或 0 = 0
    

    9.3 值取反

    取反:!

    !1=0 !true 
    !0=1  !false
    

    9.4 异或

    异或:^
    异或的两个值,相同为假,不同为真。两个数字X,Y异或得到结果Z,Z再和任意两者之一X异或,将得出
    另一个值Y

    1 ^ 1 = 0
    1 ^ 0 = 1
    0 ^ 1 = 1
    0 ^ 0 = 0
    

    9.5 逻辑运算范例

    [root@centos8 ~]#true
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#false
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#! true
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#! false
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y
    x=20,y=10
    [root@centos8 ~]#x=10;y=20;x=$[x^y];y=$[x^y];x=$[x^y];echo x=$x,y=$y
    x=20,y=10
    

    10. 条件测试命令

    条件测试:判断某需求是否满足,需要由测试机制来实现,专用的测试表达式需要由测试命令辅助完成
    测试过程,实现评估布尔声明,以便用在条件性环境下进行执行
    若真,则状态码变量 \(? 返回0
    若假,则状态码变量 \)? 返回1

    条件测试命令:

    test EXPRESSION
    [ EXPRESSION ] #和test 等价,建议使用 [ ]
    [[ EXPRESSION ]]
    

    注意:EXPRESSION前后必须有空白字符。不是很清楚的可以查看一下系统帮助。

    type [
    help [
    help test 
    

    10.1. 变量测试

    命令:

    #判断 NAME 变量是否定义
    [ -v NAME ]
    #判断 NAME 变量是否定义并且是名称引用,bash 4.4新特性.-R参数待考证???暂不确定是何用途
    [ -R NAME ]
    

    范例:

    #删除之前定义的变量
    [root@centos8 ~]#unset x
    #测试这个变量是否还有
    [root@centos8 ~]#test -v x
    #输出返回值
    [root@centos8 ~]#echo $?
    1
    #定义变量
    [root@centos8 ~]#x=10
    [root@centos8 ~]#test -v x
    [root@centos8 ~]#echo $?
    0
    #如果变量不赋值,看看判断的时候是显示有还是显示没有。
    [root@centos8 ~]#y=
    [root@centos8 ~]#test -v y
    #变量不赋值也会提示已存在,对于Linux来说它并不在乎你的变量是否赋值。
    [root@centos8 ~]#echo $?
    0
    #注意 [ ] 需要空格,否则会报下面错误
    [root@centos8 ~]#[-v y]
    -bash: [-v: command not found
    [root@centos8 ~]#[ -v y ]
    [root@centos8 ~]#echo $?
    0
    

    10.2. 数值测试

    -eq 是否等于
    -ne 是否不等于
    -gt 是否大于
    -ge 是否大于等于
    -lt 是否小于
    -le 是否小于等于
    

    范例:

    [root@centos8 ~]#i=10
    [root@centos8 ~]#j=8
    [root@centos8 ~]#[ $i -lt $j ]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#[ $i -gt $j ]
    [root@centos8 ~]#echo $?
    0
    #错误示例
    [root@centos8 ~]#[ i -gt j ]
    -bash: [: i: integer expression expected
    

    10.3 字符串测试

    test和 [ ]用法
    -z “STRING” 字符串是否为空,没定义或空为真,不空为假,
    -n “STRING” 字符串是否不空,不空为真,空为假
    ”STRING“ 同上以上双引号可不加,但建议添加双引号,因为有时候是放变量的,所以我们将变量放在双引号里可避免一些错误。下面范例中有错误。
    
    STRING1 = STRING2 是否等于,注意 = 前后有空格
    STRING1 != STRING2 是否不等于
    > ascii码是否大于ascii码
    < 是否小于
    [[]] 用法,建议,当使用正则表达式或通配符使用,一般情况使用 [ ]
    == 左侧字符串是否和右侧的PATTERN相同
    注意:此表达式用于[[ ]]中,PATTERN为通配符
    =~ 左侧字符串是否能够被右侧的正则表达式的PATTERN所匹配
    注意: 此表达式用于[[ ]]中;扩展的正则表达式
    
    10.3.1 [ ]范例:
    [root@centos8 ~]#unset str
    [root@centos8 ~]#[ -z "$str" ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#str=""
    [root@centos8 ~]#[ -z "$str" ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#str=" "
    [root@centos8 ~]#[ -z "$str" ]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#[ -n "$str" ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#unset str
    [root@centos8 ~]#[ -n "$str" ]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#[ "$str" ]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#str=magedu
    [root@centos8 ~]#[ "$str" ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#str=magedu
    [root@centos8 ~]#[ "$str" ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#str1=magedu
    [root@centos8 ~]#str2=mage
    [root@centos8 ~]#[ $str1 = $str2 ]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#str2=magedu
    [root@centos8 ~]#[ $str1 = $str2 ]
    [root@centos8 ~]#echo $?
    0
    #在比较字符串是建议放在""中
    [root@centos8 ~]#[ "$NAME" ]
    [root@centos8 ~]#NAME="I love linux"
    [root@centos8 ~]#[ $NAME ]
    -bash: [: love: binary operator expected
    [root@centos8 ~]#[ "$NAME" ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#[ I love linux ]
    -bash: [: love: binary operator expected
    
    10.4.2 [[]]范例
    #通配符
    [root@centos8 ~]#FILE=test.log
    [root@centos8 ~]#[[ "$FILE" == *.log ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#FILE=test.txt
    [root@centos8 ~]#[[ "$FILE" == *.log ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#[[ "$FILE" != *.log ]]
    [root@centos8 ~]#echo $?
    0
    #正则表达式
    [root@centos8 ~]#[[ "$FILE" =~ \.log$ ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#FILE=test.log
    [root@centos8 ~]#[[ "$FILE" =~ \.log$ ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#N=100
    [root@centos8 ~]#[[ "$N" =~ ^[0-9]+$ ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#N=Magedu10
    [root@centos8 ~]#[[ "$N" =~ ^[0-9]+$ ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#IP=1.2.3.4
    [root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#IP=1.2.3.4567
    [root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#[[ $IP =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}
    ([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
    [root@centos8 ~]#echo $?
    1
    #由上几个例子可以得出,右侧的正则无需增加双引号。
    
    需要注意的细节

    这比较字符串时,建议变量放在""中,下面有几个范例可以参考一下

    #通配符
    [root@centos8 ~]#NAME="linux1"
    [root@centos8 ~]#[[ "$NAME" == linux* ]]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#[[ "$NAME" == "linux*" ]]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#NAME="linux*"
    [root@centos8 ~]#[[ "$NAME" == "linux*" ]]
    [root@centos8 ~]#echo $?
    0
    #结论:[[ == ]] == 右侧的 * 做为通配符,不要加“”,只想做为*, 需要加“” 或转义
    
    [root@centos8 ~]#[ "$NAME" ]
    [root@centos8 ~]#NAME="I love linux"
    [root@centos8 ~]#[ $NAME ]
    -bash: [: love: binary operator expected
    [root@centos8 ~]#[ "$NAME" ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#[ I love linux ]
    -bash: [: love: binary operator expected
    

    10.4 文件测试

    10.4.1 文件权限测试
    -r FILE:是否存在且可读
    -w FILE: 是否存在且可写
    -x FILE: 是否存在且可执行
    -u FILE:是否存在且拥有suid权限
    -g FILE:是否存在且拥有sgid权限
    -k FILE:是否存在且拥有sticky权限
    

    注意: 最终结果由用户对文件的实际权限决定,而非文件属性决定。不能单看表面哦。范例如下:

    #比如 ddd 这个文件咱们已经将它的属性改为0了。
    [root@TEST ~/Script 01:49:59]#chmod 0 ddd
    [root@TEST ~/Script 01:36:35]#ls -al
    总用量 1
    ----------. 1 root root 0 12月 30 13:49 ddd
    #然后我们使用测试命令查看一下返回值
    [root@TEST ~/Script 01:50:10]#[ -r ddd ] 
    [root@TEST ~/Script 01:50:17]#echo $?    
    0
    [root@TEST ~/Script 01:50:27]#[ -w ddd ] 
    [root@TEST ~/Script 01:50:46]#echo $?    
    0
    #由上所查结果都与我们所看到的属性不同,这也是我们说的最终结果由用户对文件的实际权限决定,而非文件属性决定。
    
    10.4.2 文件属性测试
    -s FILE #是否存在且非空
    -t fd #fd 文件描述符是否在某终端已经打开
    -N FILE #文件自从上一次被读取之后是否被修改过
    -O FILE #当前有效用户是否为文件属主
    -G FILE #当前有效用户是否为文件属组
    FILE1 -ef FILE2 #FILE1是否是FILE2的硬链接
    FILE1 -nt FILE2 #FILE1是否新于FILE2(mtime)
    FILE1 -ot FILE2 #FILE1是否旧于FILE2
    
    10.4.3 文件存在性测试
    -a FILE:同 -e
    -e FILE: 文件存在性测试,存在为真,否则为假
    -b FILE:是否存在且为块设备文件
    -c FILE:是否存在且为字符设备文件
    -d FILE:是否存在且为目录文件
    -f FILE:是否存在且为普通文件
    -h FILE 或 -L FILE:存在且为符号链接文件
    -p FILE:是否存在且为命名管道文件
    -S FILE:是否存在且为套接字文件
    

    11. 关于 ()和{}

    ()会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境, 帮助参看:man bash
    搜索(list)
    {}不会启子shell, 在当前shell中运行,会影响当前shell环境, 帮助参看:man bash 搜索{ list; }

    🤔注意

    ()里面的变量可以从父进程继承,但是不能往外传,而且子进程里的变量也不会因此昂后续的环境,属于临时生效的意思。

    范例:

    [root@centos8 ~]#name=mage;(echo $name;name=wang;echo $name );echo $name
    mage
    wang
    mage
    [root@centos8 ~]#name=mage;{ echo $name;name=wang;echo $name; } ;echo $name
    mage
    wang
    wang
    [root@centos8 ~]#umask
    0022
    [root@centos8 ~]#(umask 066;touch f1.txt)
    [root@centos8 ~]#ll f1.txt
    -rw------- 1 root root 0 Dec 23 16:58 f1.txt
    [root@centos8 ~]#umask
    0022
    [root@centos8 ~]#( cd /data;ls )
    test.log
    [root@centos8 ~]#pwd
    /root
    [root@centos8 ~]#{ cd /data;ls; }
    test.log
    [root@centos8 data]#pwd
    /data
    [root@centos8 data]#
    #()会开启子shell,不会影响你当前的环境
    [root@centos8 ~]#echo $BASHPID
    1920
    [root@centos8 ~]#( echo $BASHPID;sleep 100)
    1979
    [root@centos8 ~]#pstree -p
    ├─sshd(719)───sshd(1906)───sshd(1919)─┬─bash(1920)───bash(1979)───sleep(1980)
    #{ } 不会开启子shell,会影响你当前的环境
    [root@centos8 ~]#echo $BASHPID
    1920
    [root@centos8 ~]#{ echo $BASHPID; }
    1920
    

    12. 组合测试条件

    12.1 第一种方式[]

    [ EXPRESSION1 -a EXPRESSION2 ] 并且,EXPRESSION1和EXPRESSION2都是真,结果才为真
    [ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一个真,结果就为
    真
    [ ! EXPRESSION ]
    

    范例:

    [root@centos8 ~]#ll /data/scrips/test.sh
    -rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh
    [root@centos8 ~]#[ -f $FILE -a -x $FILE ]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#chmod +x /data/scripts/test.sh
    [root@centos8 ~]#ll /data/scripts/test.sh
    -rwxr-xr-x 1 root root 382 Dec 23 09:32 /data/script40/test.sh
    [root@centos8 ~]#[ -f $FILE -a -x $FILE ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#chmod -x /data/scripts/test.sh
    [root@centos8 ~]#ll /data/scripts/test.sh
    -rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh
    [root@centos8 ~]#[ -f $FILE -o -x $FILE ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#[ -x $FILE ]
    [root@centos8 ~]#echo $?
    1
    [root@centos8 ~]#[ ! -x $FILE ]
    [root@centos8 ~]#echo $?
    0
    [root@centos8 ~]#! [ -x $FILE ]
    0
    

    12.2 第二种方式 [[]]

    [[]]与[]区别上面有说明,这里指的是组合用法

    COMMAND1 && COMMAND2 #并且,短路与,代表条件性的AND THEN
    如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2
    COMMAND1 || COMMAND2 #或者,短路或,代表条件性的OR ELSE
    如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2
    ! COMMAND #非,取反
    

    范例:

    [root@centos8 ~]#test "A" = "B" && echo "Strings are equal"
    [root@centos8 ~]#test "A"-eq "B" && echo "Integers are equal"
    [root@centos8 ~]#[ "A" = "B" ] && echo "Strings are equal"
    [root@centos8 ~]#[ "$A" -eq "$B" ] && echo "Integers are equal"
    [root@centos8 ~]#[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
    [root@centos8 ~]#[ -z "$HOSTNAME" -o "$HOSTNAME" = "localhost.localdomain" ]&&
    hostname www.magedu.com
    [root@centos8 ~]#id wang &> /dev/null || useradd wang
    [root@centos8 ~]#id zhang &> /dev/null || useradd zhang
    [root@centos8 ~]#getent passwd zhang
    zhang:x:1002:1002::/home/zhang:/bin/bash
    [root@centos8 ~]#grep -q no_such_user /etc/passwd || echo 'No such user'
    No such user
    [root@centos8 ~]#[ -f “$FILE” ] && [[ “$FILE”=~ .*\.sh$ ]] && chmod +x $FILE
    [root@centos8 ~]#ping -c1 -W1 172.16.0.1 &> /dev/null && echo '172.16.0.1 is
    up' || (echo '172.16.0.1 is unreachable'; exit 1)
    172.16.0.1 is up
    [root@centos8 ~]#IP=10.0.0.111;ping -c1 -W1 $IP &> /dev/null && echo $IP is up
    || echo $IP is down
    10.0.0.111 is down
    [root@centos8 ~]#IP=10.0.0.1;ping -c1 -W1 $IP &> /dev/null && echo $IP is up ||
    echo $IP is down
    10.0.0.1 is up
    
    && 和 || 组合使用范例:
    #通过命令组合判断账号是否存在
    #这是短路或运算,如果 前面的命令执行不成功,那么执行后面的命令,否则反之。
    [root@TEST ~ 04:37:40]#id GGG &> /dev/null || echo "GGG账号不存在"
    GGG账号不存在
    #这是短路与运算,如果 前面的命令执行成功,那么执行后面的命令,否则反之
    [root@TEST ~ 04:37:49]#id root &> /dev/null && echo "ROOT账号存在"  
    ROOT账号存在
    #连在一块的判断,需要注意逻辑短路与运算与短路或运算的逻辑顺序不能错掉不然判断会出问题。
    #下面的逻辑是如果 `id GGG  &> /dev/null` 值为真,运行 `echo "ROOT账号存在"`,反之值为假的情况下那么运行 `echo "GGG账号不存在"`
    [root@TEST ~ 04:43:53]#id GGG  &> /dev/null  && echo "ROOT账号存在" || echo "GGG账号不存在"
    GGG账号不存在
    [root@TEST ~ 04:43:53]#id root  &> /dev/null  && echo "ROOT账号存在" || echo "GGG账号不存在"
    ROOT账号存在
    
    #错误逻辑范例
    [root@TEST ~ 04:57:17]#id GG &> /dev/null  ||  echo "账号存在" &&  echo "账号不存在"       
    账号存在
    账号不存在
    [root@TEST ~ 04:57:31]#id root &> /dev/null  ||  echo "账号存在" &&  echo "账号不存在"
    账号不存在
    

    13. 使用read命令来接收输入值

    使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变
    量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置
    变量REPLY

    格式:
    read [options] [name ...]
    常见选项:
    -p 指定要显示的提示
    -s 静默输入,一般用于密码
    -n N 指定输入的字符长度N
    -d '字符' 输入结束符
    -t N TIMEOUT为N秒
    

    13.1 常用范例:

    [root@centos8 ~]#read
    wangxiaochun
    [root@centos8 ~]#echo $REPLY
    wangxiaochun
    [root@centos8 ~]#read NAME TITLE
    wang cto
    [root@centos8 ~]#echo $NAME
    wang
    [root@centos8 ~]#echo $TITLE
    cto
    [root@centos8 ~]#read -p "Please input your name: " NAME
    Please input your name: wang
    [root@centos8 ~]#echo $NAME
    wang
    [root@centos8 ~]#read x y z <<< "I love you"
    [root@centos8 ~]#echo $x
    I
    [root@centos8 ~]#echo $y
    love
    [root@centos8 ~]#echo $z
    you
    [root@centos8 ~]#
    

    13.2 重定向写法范例

    [root@centos8 ~]#read x y z <<< "I love you"
    [root@centos8 ~]#echo $x
    I
    [root@centos8 ~]#echo $y
    love
    [root@centos8 ~]#echo $z
    you
    [root@centos8 ~]#
    

    13.3 🤔经典面试题管道符范例,需要注意一下

    在管道符运行的时候是独立的子进程。参考如下范例👇
    Each command in a pipeline is executed as a separate process (i.e., in a subshell).

    [root@centos8 scripts]#cat test.txt
    1 2
    [root@centos8 scripts]#read i j < test.txt ; echo i=$i j=$j
    i=1 j=2
    [root@centos8 scripts]#echo 1 2 | read x y ; echo x=$x y=$y
    x= y=
    #说明一下为何上面通过管道无法获取之前的值:因为通过管道连接的`echo 1 2 与read x y `都是在自己的子进程中运行;`echo x=$x y=$y`与前两个命令运行环境不同,你可理解为是当前进程环境中运行,也就是在父进程中运行。
    #那么父进程也就是 `echo x=$x y=$y`无法读取前面子进程中的变量。如何解决可通过加小括号来解决,范例如下👇
    [root@centos8 ~]#echo 1 2 | ( read x y ; echo x=$x y=$y )
    x=1 y=2
    [root@centos8 ~]#echo 1 2 | { read x y ; echo x=$x y=$y; }
    x=1 y=2
    [root@centos8 ~]#man bash
    

    14. bash配置文件

    14.1 按生效范围划分

    14.1.1 全局配置文件
    /etc/profile
    /etc/profile.d/*.sh
    /etc/bashrc
    
    14.1.2 个人配置文件
    ~/.bash_profile
    ~/.bashrc
    

    14.2 shell登陆方式分类

    14.2.1 交互式登录方式
    • 直接通过终端输入账号密码登录
    • 使用su - UserName 完全切换的用户

    配置文件生效顺序,从上到下顺序。

    /etc/profile.d/*.sh
    /etc/bashrc
    /etc/profile
    /etc/bashrc #此文件执行两次
    .bashrc
    .bash_profile
    

    不用太刻意的去记它,大致的了解一下就可以了。一般每个文件都是有分工的,每个文件里放的东西都不一样的。如果有一样的会被冲突掉,会将环境搞混乱。文件之间的调用关系,写在同一个文件的不同位置,将影响文件的执行顺序

    14.2.2 非交互式登录
    • su UserName
    • 图形界面下打开的终端
    • 执行脚本
    • 任何其它的bash实例

    配置文件执行顺序

    /etc/profile.d/*.sh
    /etc/bashrc
    .bashrc
    

    由以上两种登录方式的配置文件执行顺序可得出:/etc/profile.d/*.sh 都是会运行的,所以我们通常需要加bash环境配置的时候,都会在里面创建一个脚本文件。这样就算不需要了直接删除脚本文件不需要给执行权限即可,方便也不容易搞混环境配置。

    🤔执行脚本两种方式

    bash 脚本文件
    source 脚本文件
    

    两者区别:bash会另开一个子进程然后运行脚本,source是在当前shell进程中运行,会影响当前环境,所以改系统配置的时候都会使用source,可通过pstree -p查看是否为子进程还是父进程。

    14.3 按功能分类

    profile类和bashrc类

    14.3.1 Profile类

    profile类为交互式登录的shell提供配置

    全局:/etc/profile, /etc/profile.d/*.sh
    个人:~/.bash_profile
    

    功用:
    (1) 用于定义环境变量
    (2) 运行命令或脚本

    14.3.2 Bashrc类

    bashrc类:为非交互式和交互式登录的shell提供配置

    全局:/etc/bashrc
    个人:~/.bashrc
    

    功用:
    (1) 定义命令别名和函数
    (2) 定义本地变量

    由已上对比可得出bashrc类平常用来定义本地变量,普通变量的,profile类是定义环境变量的。虽一般情况下都可以生效,但我们还是规范一下,变量的定义可以参考一下上面的「变量定义和引用」章节。

    14.4 编辑配置文件生效

    修改profile和bashrc文件后需生效两种方法:

    1. 重新启动shell进程
    2. source|. 配置文件
      范例:
    . ~/.bashrc
    

    14.5 Bash退出任务

    保存在~/.bash_logout文件中(用户),在退出登录shell时运行
    功能:
    创建自动备份
    清除临时文件

    shell之条件判断

    1. if语句判断

    格式:

    if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else
    COMMANDS; ] fi
    

    1.1 单分支

    if 判断条件;then
    条件为真的分支代码
    fi
    

    1.2 双分支

    if 判断条件; then
    条件为真的分支代码
    else
    条件为假的分支代码
    fi
    

    1.3 多分支

    if 判断条件1; then
    条件1为真的分支代码
    elif 判断条件2; then
    条件2为真的分支代码
    elif 判断条件3; then
    条件3为真的分支代码
    ...
    else
    以上条件都为假的分支代码
    fi
    

    说明

    • 多个条件时,逐个条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
    • if 语句可嵌套

    脚本范例:

    #根据命令的退出状态来执行命令
    if ping -c1 -W2 station1 &> /dev/null; then
    echo 'station1 is UP'
    elif grep -q 'station1' ~/maintenance.txt; then
    echo 'station1 is undergoing maintenance'
    else
    echo 'station1 is unexpectedly DOWN!'
    exit 1
    fi
    

    2. case语句判断

    格式:

    case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
    
    case 变量引用 in
    PAT1)
    分支1
    ;;
    PAT2)
    分支2
    ;;
    ...
    *)
    默认分支
    ;;
    esac
    

    case支持glob风格的通配符:

    shell脚本范例

    5.1 查看系统信息
    #!/bin/bash
    #-- - - - - - -Script comment information - - - - - - - - - -
    #Author:                               拉基
    #Email:                        helpdesk81@outlook.com
    #Creation time:                2020-12-21
    #FileName:                     222.sh
    #Blog address:                 https://www.cnblogs.com/98record/
    #Copyright (C)                  2020All rights reserved
    #- - - - - - - - - - - - - end - - - - - - - - - - - - - - - - - -
    #此脚本为显示机器信息
    RED="\033[1;31m"
    GREEN="\033[1;32m"
    END="\033[0m"
    echo -e $GREEN----------------------系统信息--------------------$END
    echo -e "主机名:            $RED`hostname`$END"
    echo -e "ip地址:            $RED`ifconfig eth0 | head -2 | egrep -o '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1`$END"
    echo -e "系统版本:      $RED`cat /etc/redhat-release`$END"
    echo -e "内存:          $RED`free -h | grep ^M | tr -s " " | cut -d" " -f2`$END"
    echo -e "CPU信息:               $RED`cat /proc/cpuinfo | grep "model name" | cut -d : -f2  | head -1`$END"
    echo -e "硬盘:          $RED`lsblk | grep ^sd | tr -s " " | cut -d " " -f4`$END"
    
    5.2 查看使用率最大的硬盘
    #!/bin/bash
    #-- - - - - - -Script comment information - - - - - - - - - -
    #Author:                               拉基
    #Email:                        helpdesk81@outlook.com
    #Creation time:                2020-12-22
    #FileName:                     disk.sh
    #Blog address:                 https://www.cnblogs.com/98record/
    #Copyright (C)                  2020All rights reserved
    #- - - - - - - - - - - - - end - - - - - - - - - - - - - - - - - -
    GREEN="\033[1;32m"
    RED="\033[1;31m"
    END="\033[0m"
    BLUE="\033[1;34m"
    echo -e $GREEN---------------显示硬盘最大利用率-----------------$END
    echo -e "       `df -h | head -1 |tr -s " " | cut -d " " -f1,5`"
    echo -e "       `df -h | tail -n+2 | tr -s " " | sort -nrt" " -k5| cut -d " " -f1,5 |head -1 `"
    

    shell 面试题

    计算文本中的年龄

    [root@TEST ~/Script 05:36:46]#cat nianliang.txt 
    xiaoming=20
    xiaohong=18
    xiaoqiang=22
    [root@TEST ~/Script 05:35:32]#cat nianliang.txt | cut -d= -f2 | tr "\n" "+" | grep -Eo ".*[0-9]+" | bc
    60
    
  • posted @ 2020-12-22 13:16  自在拉基  阅读(492)  评论(0编辑  收藏  举报