Linux 基础学习训练教材 - RockyLinux 9.x

课程/课后例题参考解答

单纯提供一个相对的解答,并不是标准答案!

最近更新时间: 2023/05/01

单纯就是个解答的参考,写完之后再来这边查查看答案跟你想的一样不一样!?

第 08 堂课 (2023/05/01)

  • 例题 8.1.1-1:
    1. var=${变量}
    2. var=$(指令)
    3. var=$(( 加减乘除计算式 ))
    4. var="变量值,但保有 $ 功能"
    5. var='变量值,纯文本'
    6. var=`指令`
  • 例题 8.1.1-2:
    # A. 先用 which 功能
    [root@station10-101 ~]# which ifconfig chfn
    /usr/sbin/ifconfig
    /usr/bin/chfn
    
    # B. 再用 $() 的子程序功能
    [root@station10-101 ~]# ll $(which ifconfig chfn)
    -rws--x--x. 1 root root 32032 Nov 17 05:55 /usr/bin/chfn
    -rwxr-xr-x. 1 root root 81384 May 16  2022 /usr/sbin/ifconfig
    
    通过这个子程序的功能,我们就不用手动输入刚刚 which 搜索到的文件名数据了!
  • 例题 8.1.1-3:
    1. 先讨论『没有权限的文件运行』会产生什么后果:
      [root@station10-101 ~]# /etc/passwd
      -bash: /etc/passwd: Permission denied
      [root@station10-101 ~]# echo $?
      126
      # 意思是说,没有权限运行时,回传值应该会是 126 的意思!
      
    2. 再来讨论『找不到运行档』的时候,回传的消息又是什么?
      [root@station10-101 ~]# vbirdcommand
      bash: vbirdcommand: command not found...
      [root@station10-101 ~]# echo $?
      127
      # 所以,这种情况会回传 127 的数值
      
    3. 接下来,讨论一下 bash 针对这些回传值 (exit status) 的定义:
      [root@station10-101 ~]# man bash
      ......
      EXIT STATUS
             The  exit status of an executed command is the value returned by the waitpid
             system call or equivalent function.  Exit statuses fall between 0  and  255,
             though,  as  explained  below, the shell may use values above 125 specially.
             Exit statuses from shell builtins and compound commands are also limited  to
             this  range.  Under certain circumstances, the shell will use special values
             to indicate specific failure modes.
      
             For the shell's purposes, a command which exits with a zero exit status  has
             succeeded.   An exit status of zero indicates success.  A non-zero exit sta‐
             tus indicates failure.  When a command terminates on a fatal signal N,  bash
             uses the value of 128+N as the exit status.
      
             If a command is not found, the child process created to execute it returns a
             status of 127.  If a command is found but is not executable, the return sta‐
             tus is 126.
      
             If  a command fails because of an error during expansion or redirection, the
             exit status is greater than zero.
      
             Shell builtin commands return a status of 0 (true) if successful,  and  non-
             zero  (false) if an error occurs while they execute.  All builtins return an
             exit status of 2 to indicate incorrect usage, generally invalid  options  or
             missing arguments.
      
             Bash  itself  returns the exit status of the last command executed, unless a
             syntax error occurs, in which case it exits with a non-zero value.  See also
             the exit builtin command below.
      ......
      
      很简单就得到没权限是 126,而找不到文件就是 127 啰!
    4. 根据上面的说法,回传值应该要介于 0~255 之间~而 0 代表运行指令成功,非为 0 就是不成功!
    5. 要查回传值的时候,请注意到底要查谁?查那一个指令的说明这样!
      [root@station10-101 ~]# ls /vbird
      ls: cannot access '/vbird': No such file or directory
      [root@station10-101 ~]# echo $?
      2
      # 很明显,应该是要查看 ls 吧!
      
      [root@station10-101 ~]# man ls
      ......
         Exit status:
             0      if OK,
      
             1      if minor problems (e.g., cannot access subdirectory),
      
             2      if serious trouble (e.g., cannot access command-line argument).
      ......
      # 结果的 2 说的是无法取得指令列所带的参数 (args) 啊!
      
  • 例题 8.1.2-1:
    # 单纯在指令的最后面加上数据流重导向:
    [student@station10-101 15:26 1 ~]$ date; uptime; uname -r > myfile.txt
    Sun Apr 30 03:17:55 PM CST 2023
     15:17:55 up 8 min,  2 users,  load average: 0.00, 0.04, 0.03
    [student@station10-101 15:26 2 ~]$ cat myfile.txt
    5.14.0-162.12.1.el9_1.0.2.x86_64
    # 很明显的发现,上述指令分为三大部份
    # 1. date
    # 2. uptime
    # 3. uname -r > myfile.txt
    # 所以 myfile.txt 只会保留 uname -r 的结果!
    
    # 将连续输入的数据用大括号保留下来:
    [student@station10-101 15:26 3 ~]$ (date; uptime; uname -r ) > myfile.txt
    [student@station10-101 15:28 4 ~]$ cat myfile.txt
    Sun Apr 30 03:18:29 PM CST 2023
     15:18:29 up 8 min,  2 users,  load average: 0.00, 0.03, 0.03
    5.14.0-162.12.1.el9_1.0.2.x86_64
    
    大括号将连续数据报起来后,所有的输出数据最终会汇整在一起后,再传给 > 进行后续的动作!
  • 例题 8.1.2-2:
    # 先测试存在文件时的状态:
    [student@station10-101 16:35 16 ~]$ ls -d /etc &> /dev/null || echo no-exist && echo exist
    exist
    
    # 再测试不存在文件时的状态:
    [student@station10-101 16:35 16 ~]$ ls -d /vbird &> /dev/null || echo no-exist && echo exist
    no-exist
    exist
    
    我们可以很轻易的发现,若文件存在时,指令没啥问题,但是当文件不存在时,却两者会同时出现!在这里你要先注意:
    1. 指令列的连续指令都是依序运行的
    2. 回传值在每个指令之后都会改变,也就是 $? 结果会一直改变
    让我们解析一下错误的状态是什么情况?
    ls -d /vbird &> /dev/null || echo no-exist && echo exist
               $?=2                $?=0             $?=0 
              运行失败       因为失败所以运行    因为成功所以运行
    
    所以,基本上, && 一定要放在 || 之前,否则逻辑上会出现问题喔!
  • 例题 8.1.3-1:
    # A. 使用连续指令下达的方式来处理这个任务即可:
    [student@station10-101 20:27 1 ~]$ test -e /etc; echo $?
    0
    # 答案为正确,因此是存在这个文件名的
    
    # B. 判断 SUID 使用 -S 来测试
    [student@station10-101 20:28 3 ~]$ test -u /usr/bin/passwd ; echo $?
    0
    # 答案为正确,因此该文件具有 SUID 的旗标
    
    # C. 判断主机名称是否为我自己设置的样子?
    [student@station10-101 20:28 4 ~]$ test "mylocalhost" == ${HOSTNAME} ; echo $?
    1
    # 答案为不正确,所以不是 mylocalhost 的样式!让我们来检查一下:
    [student@station10-101 20:30 5 ~]$ echo ${HOSTNAME}
    station10-101.gocloud.vm
    # 果然不是!
    
    # D. 重新修改小指令:
    [root@station10-101 ~]# vim /usr/local/bin/checkfile
    #!/bin/bash
    #ls -d ${1} &> /dev/null && echo "${1} exist" || echo "${1} non-exist"
    test -e ${1} && echo "${1} exist" || echo "${1} non-exist"
    
    [root@station10-101 ~]# checkfile /etc
    /etc exist
    
    最后一题可以修改一下原本使用 ls 判断文件是否存在的方式,使用 test 会更直觉!!
  • 例题 8.1.3-2:
    这一题相对简单,所以就直接输入指令来看看即可:
    [student@station10-101 21:24 1 ~]$ [ -e /etc ]; echo $?
    0
    
    [student@station10-101 21:24 2 ~]$ [ -u /usr/bin/passwd ]; echo $?
    0
    
    [student@station10-101 21:25 3 ~]$ [ "${HOSTNAME}" == "mylocalhost" ] ; echo $?
    1
    
  • 例题 8.1.4-1:
    1. 当目标目录不存在时,第一次拷贝不需要询问是否覆盖的情境:
      [root@station10-101 ~]# cd /dev/shm
      [root@station10-101 shm]# cp -a /etc .
      [root@station10-101 shm]# ll
      总计 0
      drwxr-xr-x. 135 root root 5280  4月 19 14:34 etc
      
      简单的拷贝成功了!
    2. 第二次重复拷贝,就会发现出现是否覆盖的问题!你可以按 y 也可以 [ctrl]-c 中断
      [root@station10-101 shm]# cp -a /etc .
      cp: overwrite './etc/lvm/lvm.conf'? y
      cp: overwrite './etc/lvm/lvmlocal.conf'? y
      cp: overwrite './etc/lvm/profile/cache-mq.profile'? y
      cp: overwrite './etc/lvm/profile/cache-smq.profile'? ^C
      
    3. 绝对路径与相对路径方式,都可以运行指令。另外,通过反斜线,可以略过命令别名的设置!
      [root@station10-101 shm]# /bin/cp -a /etc .   <==这个是绝对路径
      [root@station10-101 shm]# \cp -a /etc .       <==这个是略过命令别名
      
  • 例题 8.1.4-2:
    其实就是将题目中的指令,在 .bashrc 里面加上命令别名即可!
    [student@station10-101 21:46 1 ~]$ vim .bashrc
    alias cp="cp -i"
    alias rm="rm -i"
    alias mv="mv -i"
    
  • 例题 8.1.5-1:
    # A. 创建命令别名
    [student@station10-101 21:48 3 ~]$ alias geterr=' echo "I am error" 1>&2 '
    # 这个别名的意义是,运行 echo 后,将数据丢到错误消息上面去!
    
    # B. 直接运行看看
    [student@station10-101 21:49 4 ~]$ geterr
    I am error
    # 确实有消息输出啊!
    
    # C. 将错误数据丢弃
    [student@station10-101 21:49 6 ~]$ geterr 2> /dev/null
    I am error
    # 咦!怎么还是出现消息?应该错误消息会被丢弃才对!
    
    # D. 将消息整个包起来看看:
    [student@station10-101 21:50 7 ~]$ (geterr) 2> /dev/null
    # 这次确实没数据了!
    
    alias 命令别名毕竟是转传数据过一次,因此大概是运行完毕之后,才丢到外部指令来。所以,消息已经输出了, 最后那个 2> /dev/null 就会没有消息丢弃~使用小括号将消息全部集成,那就可以将错误消息最后切给 2> 了!
  • 例题 8.2.1-1:
    # A. 找寻文件名
    [student@station10-101 22:04 9 ~]$ man find
           -name pattern
                  Base  of  file  name  (the path with the leading directories removed) matches
                  shell pattern pattern.  Because the leading directories are removed, the file
                  names considered for a match with -name will never include a slash, so `-name
                  a/b' will never match anything (you probably need to use -path  instead).   A
                  warning  is  issued  if  you  try to do this, unless the environment variable
                  POSIXLY_CORRECT is set.  The metacharacters (`*', `?', and `[]') match a  `.'
                  at  the start of the base name (this is a change in findutils-4.2.2; see sec‐
                  tion STANDARDS CONFORMANCE below).  To ignore a directory and the files under
                  it,  use  -prune; see an example in the description of -path.  Braces are not
                  recognised as being special, despite the fact that some shells including Bash
                  imbue braces with a special meaning in shell patterns.  The filename matching
                  is performed with the use of the fnmatch(3) library function.   Don't  forget
                  to enclose the pattern in quotes in order to protect it from expansion by the
                  shell.
    
    [student@station10-101 21:53 8 ~]$ find /etc -name '*passwd*'
    find: ‘/etc/lvm/archive’: 拒绝不符权限的操作
    find: ‘/etc/lvm/backup’: 拒绝不符权限的操作
    find: ‘/etc/lvm/cache’: 拒绝不符权限的操作
    /etc/pam.d/passwd
    find: ‘/etc/pki/rsyslog’: 拒绝不符权限的操作
    find: ‘/etc/sssd’: 拒绝不符权限的操作
    find: ‘/etc/sos/cleaner’: 拒绝不符权限的操作
    /etc/passwd-
    find: ‘/etc/grub.d’: 拒绝不符权限的操作
    find: ‘/etc/polkit-1/rules.d’: 拒绝不符权限的操作
    find: ‘/etc/polkit-1/localauthority’: 拒绝不符权限的操作
    /etc/passwd
    ....
    
    # B. 因为错误消息不重要,所以,将它丢弃吧!
    [student@station10-101 22:07 11 ~]$ find /etc -name '*passwd*' 2> /dev/null
    /etc/pam.d/passwd
    /etc/passwd-
    /etc/passwd
    /etc/security/opasswd
    
    # C. 转存正确消息
    [student@station10-101 22:07 12 ~]$ find /etc -name '*passwd*' 2> /dev/null > ~student/find_passwd.txt
    [student@station10-101 22:08 13 ~]$ cat ~student/find_passwd.txt
    /etc/pam.d/passwd
    /etc/passwd-
    /etc/passwd
    /etc/security/opasswd
    
    # D. 开始进行消息的累加!
    [student@station10-101 22:10 15 ~]$ find /etc -name "*shadow*" 2> /dev/null
    /etc/gshadow
    /etc/gshadow-
    /etc/pam.d/sssd-shadowutils
    /etc/shadow-
    /etc/shadow
    [student@station10-101 22:10 16 ~]$ find /etc -name "*shadow*" 2> /dev/null >> ~student/find_passwd.txt
    
    # E. 最终看看文件内容
    [student@station10-101 22:10 17 ~]$ cat ~student/find_passwd.txt
    /etc/pam.d/passwd
    /etc/passwd-
    /etc/passwd
    /etc/security/opasswd
    /etc/pam.d/sssd-shadowutils
    /etc/shadow-
    /etc/gshadow
    /etc/shadow
    /etc/gshadow-
    
  • 例题 8.2.1-2:
    # A.B. 测试 cat 的用法
    [student@station10-101 22:11 18 ~]$ cat
    I am VBird
    I am VBird
    HaHaHa
    HaHaHa
    [ctrl]+d
    
    # C. 测试输入数据转存成为文件,无须使用 vim 喔!
    [student@station10-101 22:30 19 ~]$ cat > mycat.txt
    I am vbird
    HaHaHa
    [student@station10-101 22:32 20 ~]$ cat mycat.txt
    I am vbird
    HaHaHa
    
    # D. 读入文件
    [student@station10-101 22:32 21 ~]$ cat < /etc/hosts
    127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    
    # E. 读入后转存
    [student@station10-101 22:33 22 ~]$ cat < /etc/hosts  >> mycat.txt
    [student@station10-101 22:34 23 ~]$ cat mycat.txt
    I am vbird
    HaHaHa
    127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    
  • 例题 8.2.2-1:
      # A.B. 先用简单的方法来处理文件名的搜索
      [student@station10-101 22:39 27 ~]$ find /etc -name '*.conf' 2> /dev/null
      /etc/lvm/lvm.conf
      /etc/lvm/lvmlocal.conf
      /etc/resolv.conf
      /etc/dnf/dnf.conf
      /etc/dnf/plugins/kpatch.conf
      
      [student@station10-101 22:41 31 ~]$ find /etc 2> /dev/null | grep '\.conf$'
      # 关键字的部份会多出颜色的显示!比较好!
      
      # C. 计算文件数量
      [student@station10-101 22:41 31 ~]$ find /etc 2> /dev/null | grep '\.conf$' | wc
          327     327   10415
      [student@station10-101 22:43 32 ~]$ find /etc 2> /dev/null | grep '\.conf$' | wc -l
      327
      
  • 例题 8.2.2-2:
    # A. 使用 cut 来切割具有固定分隔字符的数据即可
    [student@station10-101 22:44 34 ~]$ cut -d ':' -f 1,7 /etc/passwd
    root:/bin/bash
    bin:/sbin/nologin
    daemon:/sbin/nologin
    adm:/sbin/nologin
    lp:/sbin/nologin
    ......
    
    # B. 因为 shell 名称很多,因此需要进行排序,排序完毕再以 uniq 去计算次数即可
    [student@station10-101 22:47 35 ~]$ cut -d ':' -f 7 /etc/passwd
    [student@station10-101 22:48 36 ~]$ cut -d ':' -f 7 /etc/passwd | sort
    [student@station10-101 22:48 37 ~]$ cut -d ':' -f 7 /etc/passwd | sort | uniq -c
          8 /bin/bash
          1 /bin/sync
          1 /sbin/halt
         31 /sbin/nologin
          1 /sbin/shutdown
          2 /usr/sbin/nologin
    
    # C. 用 last 分析登录者,然后分析登录次数
    [student@station10-101 22:48 40 ~]$ last
    [student@station10-101 22:50 41 ~]$ last | awk '{print $1}'
    [student@station10-101 22:50 42 ~]$ last | awk '{print $1}' | sort
    [student@station10-101 22:51 43 ~]$ last | awk '{print $1}' | sort | uniq -c
          1
          1 myuser2
         23 reboot
         23 root
         13 student
          1 wtmp
    
    # D. 只想取出 IPv4 的 IP 数据
    [student@station10-101 22:51 44 ~]$ ip addr show
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host
           valid_lft forever preferred_lft forever
    2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
        link/ether 52:54:00:ba:0b:fc brd ff:ff:ff:ff:ff:ff
        altname enp0s3
        inet 172.16.2.253/16 brd 172.16.255.255 scope global dynamic noprefixroute ens3
           valid_lft 256870sec preferred_lft 256870sec
        inet6 fe80::5054:ff:feba:bfc/64 scope link noprefixroute
           valid_lft forever preferred_lft forever
    
    [student@station10-101 22:52 45 ~]$ ip addr show | grep 'inet '
        inet 127.0.0.1/8 scope host lo
        inet 172.16.2.253/16 brd 172.16.255.255 scope global dynamic noprefixroute ens3
    
    # E. 只想要 IP 地址,因为在第二字段,所以使用 awk 刚刚好!
    [student@station10-101 22:54 46 ~]$ ip addr show | grep 'inet ' | awk '{print $2}'
    127.0.0.1/8
    172.16.2.253/16
    
    # F. 要将数据从屏幕输出,同时输出到文件,就得要使用 tee 了!
    [student@station10-101 22:55 47 ~]$ ip addr show | grep 'inet ' | awk '{print $2}' | tee /dev/shm/myip.txt
    127.0.0.1/8
    172.16.2.253/16
    
    [student@station10-101 22:56 48 ~]$ cat /dev/shm/myip.txt
    127.0.0.1/8
    172.16.2.253/16
    
  • 例题 8.3 课后练习
    1. 简单的指令操作行为:
      # a. 计算日数
      [root@station10-101 shm]# echo $(( 100*365 ))
      36500
      [root@station10-101 shm]# echo $(( 25*366 + 75*365 ))
      36525
      
      # b. 推算回传值
      [root@station10-101 shm]# bash -c "ls /check &> /dev/null && exit 10 || exit 20"
      [root@station10-101 shm]# echo $?
      20
      
      # c. 命令别名
      [root@station10-101 shm]# alias mykver='echo "My hostname is \"${HOSTNAME}\" and kernel version is $(uname -r)"'
      [root@station10-101 shm]# mykver
      My hostname is "station2-253.gocloud.vm" and kernel version is 5.14.0-162.12.1.el9_1.0.2.x86_64
      
    2. 指纹数据的纪录
      [root@station10-101 ~]# find /usr/sbin /usr/bin -type f 
      [root@station10-101 ~]# find /usr/sbin /usr/bin -type f | sort 
      [root@station10-101 ~]# md5sum $( find /usr/sbin /usr/bin -type f | sort ) 
      b97fa724729af2bd70948884e7738392  /usr/bin/[
      85db5abdba8c1992921de8bbe4222f7d  /usr/bin/ac
      d495cf8be0fc8246a287209ec91d53a5  /usr/bin/aconnect
      24f7909265325adcfb906b130beedc60  /usr/bin/addr2line
      af1ce0b39c3ce9cbfaa63e1d7bf95e30  /usr/bin/airscan-discover
      ......
      [root@station10-101 ~]# md5sum $( find /usr/sbin /usr/bin -type f | sort ) > /root/rawdata.md5
      
    3. 进行文件的分割动作
      # a. 创建巨型文件
      [student@station10-101 ~]$ mkdir /dev/shm/check
      [student@station10-101 ~]$ cd /dev/shm/check/
      [student@station10-101 check]$ dd if=/dev/zero of=bigfile bs=200M count=1
      记录了 1+0 的读入
      记录了 1+0 的写出
      209715200字节(210 MB,200 MiB)已拷贝,0.217285 s,965 MB/s
      [root@station10-101 check]# ll
      总用量 204800
      -rw-r--r--. 1 student student 209715200  4月 30 15:59 bigfile
      
      # b. 进行分割喔!
      [root@station10-101 check]# man split
      SYNOPSIS
             split [OPTION]... [FILE [PREFIX]]
      ......
             -b, --bytes=SIZE
                    put SIZE bytes per output file
      
      [student@station10-101 check]$ split -b $(( 20*1024*1024 )) bigfile sfile
      [student@station10-101 check]$ ll
      总用量 409600
      -rw-r--r--. 1 student student 209715200  4月 30 15:59 bigfile
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileaa
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileab
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileac
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfilead
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileae
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileaf
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileag
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileah
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileai
      -rw-r--r--. 1 student student  20971520  4月 30 16:00 sfileaj
      
      # c. 将文件组合起来吧!
      [student@station10-101 check]$ cat sfile* > bigfile2
      [student@station10-101 check]$ ll bigfile*
      -rw-r--r--. 1 student student 209715200  4月 30 15:59 bigfile
      -rw-r--r--. 1 student student 209715200  4月 30 16:01 bigfile2
      
      # d. 确认两个文件的内容是一模一样的!
      [student@station10-101 check]$ cmp bigfile bigfile2
      [student@station10-101 check]$ diff bigfile bigfile2
      # 没出现任何消息,就代表两个文件内容完全一致!
      
      [student@station10-101 check]$ md5sum bigfile*
      3566de3a97906edb98d004d6b947ae9b  bigfile
      3566de3a97906edb98d004d6b947ae9b  bigfile2
      # 指纹码相同,也代表这两个文件内容一致啊!
      
修改历史:
  • 2023/02/17:RHEL 改版到 EL9 了,只好再度改版!否则教学上面挺困扰!
2023/02/17 以来统计人数
计数器
其他链接
环境工程模式篇
鸟园讨论区
鸟哥旧站

今日 人数统计
昨日 人数统计
本月 人数统计
上月 人数统计