Linux 基礎學習訓練教材 - RockyLinux 9.x

課程/課後例題參考解答

單純提供一個相對的解答,並不是標準答案!

最近更新時間: 2023/05/01

單純就是個解答的參考,寫完之後再來這邊查查看答案跟你想的一樣不一樣!?

第 07 堂課 (2023/02/26)

  • 例題 7.1.1-1:
    1. 在 /etc/passwd 這個檔案內,資料是以 : 分隔,第一個欄位是帳號名稱,第七個欄位則是 shell 程式名稱。 我們可以透過 cut 來進行資料欄位的切割,先使用 man 查詢 cut 功能後,再開始處理檔案:
      [root@station10-101 ~]# man cut
      DESCRIPTION
             Print selected parts of lines from each FILE to standard output.
      
             With no FILE, or when FILE is -, read standard input.
      
             Mandatory arguments to long options are mandatory for short options too.
      
             -b, --bytes=LIST
                    select only these bytes
      
             -c, --characters=LIST
                    select only these characters
      
             -d, --delimiter=DELIM
                    use DELIM instead of TAB for field delimiter
      
             -f, --fields=LIST
                    select only these fields;  also print any line that contains no delimiter character,
                    unless the -s option is specified
      
      [root@station10-101 ~]# cut -d ':' -f 1,7 /etc/passwd
      root:/bin/bash
      bin:/sbin/nologin
      daemon:/sbin/nologin
      .......
      theuser3:/bin/bash
      theuser1:/bin/bash
      
    2. 這時,搭配 grep 即可抓到正確的資料了:
      [root@station10-101 ~]# cut -d ':' -f 1,7 /etc/passwd | grep daemon
      daemon:/sbin/nologin
      
      是 /sbin/nologin 這個 shell 喔!
  • 例題 7.1.1-2:
    1. 安裝 C shell,若登入的是圖形界面,請自行在右上角的網路工具中,啟用你的網路環境即可!底下使用文字界面來說明啟動網路的方式:
      [student@station10-101 ~]$ su -
      Password:
      [root@station10-101 ~]# yum install tcsh
      Last metadata expiration check: 1:22:34 ago on Sun 26 Feb 2023 01:24:07 PM CST.
      Dependencies resolved.
      =======================================================================================
       Package               Architecture     Version               Repository          Size
      =======================================================================================
      Installing:
       tcsh                  x86_64           6.22.03-6.el9         appstream          456 k
      
      Transaction Summary
      =======================================================================================
      Install  1 Package
      
      Total download size: 456 k
      Installed size: 1.2 M
      Is this ok [y/N]: y
      Downloading Packages:
      tcsh-6.22.03-6.el9.x86_64.rpm                               3.3 MB/s | 456 kB     00:00
      ---------------------------------------------------------------------------------------
      Total                                                       245 kB/s | 456 kB     00:01
      Rocky Linux 9 - AppStream                                   1.7 MB/s | 1.7 kB     00:00
      Importing GPG key 0x350D275D:
       Userid     : "Rocky Enterprise Software Foundation - Release key 2022 <releng@rockylinux.org>"
       Fingerprint: 21CB 256A E16F C54C 6E65 2949 702D 426D 350D 275D
       From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
      Is this ok [y/N]: y
      Key imported successfully
      Running transaction check
      Transaction check succeeded.
      Running transaction test
      Transaction test succeeded.
      Running transaction
        Preparing        :                                                       1/1
        Installing       : tcsh-6.22.03-6.el9.x86_64                             1/1
        Running scriptlet: tcsh-6.22.03-6.el9.x86_64                             1/1
        Verifying        : tcsh-6.22.03-6.el9.x86_64                             1/1
      
      Installed:
        tcsh-6.22.03-6.el9.x86_64
      
      Complete!
      
      [root@station10-101 ~]# cat /etc/shells
      /bin/sh
      /bin/bash
      /usr/bin/sh
      /usr/bin/bash
      /bin/csh
      /bin/tcsh
      /usr/bin/csh
      /usr/bin/tcsh
      # 果然,有加入 csh 及 tcsh 的 shell 指令了!
      
      [root@station10-101 ~]# exit
      logout
      
    2. 操作 bash 環境來確認一下 shell program
      [student@station10-101 ~]$ echo $BASH
      /bin/bash
      [student@station10-101 ~]$ echo $shell
      
      [student@station10-101 ~]$ echo $0
      -bash
      
      可以看得出來, bash 環境下,會具有 $BASH 以及 $0 的兩個變數,都是指令名稱!
    3. 開始切換到 csh 看看:
      [student@station10-101 ~]$ /bin/csh
      # 其實,這時已經變成 tcsh 這個強化版的 csh 了!只是提示字元看不出來!所以要用底下的方式檢查一下!
      
      [student@station10-101 ~]$ echo $BASH
      BASH: Undefined variable.
      [student@station10-101 ~]$ echo $shell
      /usr/bin/tcsh
      [student@station10-101 ~]$ echo $0
      /bin/csh
      [student@station10-101 ~]$ exit
      exit
      [student@station10-101 ~]$ echo $0
      -bash
      
      可以看到呈現的效果不太一樣~這就是 C shell 囉!由這個練習我們也會知道, echo $0 真是重要啊!
    4. 如果執行一個 /sbin/nologin 時,會很奇怪!
      [student@station10-101 ~]$ /sbin/nologin
      This account is currently not available.
      
      也就是說, /sbin/nologin 其實是一個怪怪的 shell 喔!
  • 例題 7.1.1-3:
    1. 使用之前玩過的 usermod 來修改 shell
      [student@station10-101 ~]$ su -
      Password:
      # 先來看看 student 在 /etc/passwd 當中的設定值
      [root@station10-101 ~]# grep student /etc/passwd  <==舊的方法
      [root@station10-101 ~]# getent passwd student     <==這樣比較簡單!
      student:x:1000:1000:student:/home/student:/bin/bash
      
      [root@station10-101 ~]# usermod -s /sbin/nologin student
      [root@station10-101 ~]# getent passwd student
      student:x:1000:1000:student:/home/student:/sbin/nologin
      
      可以看到使用者 student 的 shell 變成 nologin 了!
    2. 開始使用 su - student 測試:
      [root@station10-101 ~]# su - student
      This account is currently not available.
      # 直接執行 /sbin/nologin ,然後無法切換成為 student 喔!
      
    3. 改回原本的 bash 吧!
      [root@station10-101 ~]# usermod -s /bin/bash student
      [root@station10-101 ~]# getent passwd student
      student:x:1000:1000:student:/home/student:/bin/bash
      
  • 例題 7.1.1-4:
    1. 測試不同類型的帳號:
      1. 查看 UID 的模樣
        [root@station10-101 ~]# id bin
        uid=1(bin) gid=1(bin) groups=1(bin)
        [root@station10-101 ~]# id student
        uid=1000(student) gid=1000(student) groups=1000(student)
        
        可以看到兩者的 UID 號碼差異很大!一般來說,小於 1000 以下的 uid,通常是保留給系統使用的,因此, bin 這個帳號, 應該就是所謂的『系統帳號』,這種帳號是不能登入才對的!
      2. 因為是 root ,所以可以順利的切換成為 student 而無須輸入密碼!這是一般狀態!
      3. 如果是系統帳號的 bin 時:
        [root@station10-101 ~]# su - bin
        This account is currently not available.
        [root@station10-101 ~]# getent passwd bin
        bin:x:1:1:bin:/bin:/sbin/nologin
        
        不能切換成為 bin 這個用戶,因為他的 shell 是 /sbin/nologin!
    2. 建立不能取得互動 shell (就是 /sbin/nologin) 的帳號
      [root@station10-101 ~]# useradd -s /sbin/nologin puser1
      [root@station10-101 ~]# echo MyPuser1 | passwd --stdin puser1
      更改使用者 puser1 的密碼。
      passwd:所有核對代符都已成功更新。
      [root@station10-101 ~]# getent passwd bin
      puser1:x:1007:1009::/home/puser1:/sbin/nologin
      
      [root@station10-101 ~]# su - puser1
      This account is currently not available.
      
      這樣就具有無法取得互動 shell 的帳號!要注意,這種帳號雖然無法取得 shell,但是依舊可以使用 ftp / email / web service 等功能! 所以還是得注意其密碼狀態喔!
  • 例題 7.1.2-1:
    # A. 設定變數
    [student@station10-101 ~]$ myname=peter pan    <==這是錯誤的,不能直接有空白
    bash: pan: command not found...
    [student@station10-101 ~]$ myname="peter pan"  <==加上雙引號/單引號就可以!
    
    # B. 呼叫變數內容
    [student@station10-101 ~]$ echo $myname
    peter pan
    [student@station10-101 ~]$ echo ${myname}
    peter pan
    # 兩種方法都可以呼叫順利!
    
    # C. 測試數字開頭的變數
    [student@station10-101 ~]$ 2myname="peter pan"
    bash: 2myname=peter pan: command not found...
    # 不行喔!變數名稱不能以數字開頭!
    
    # D. 這個在測試單引號與雙引號的用途!
    [student@station10-101 ~]$ varsymbo="$myname"
    [student@station10-101 ~]$ echo $varsymbo
    peter pan
    [student@station10-101 ~]$ varsymbo='$myname'
    [student@station10-101 ~]$ echo $varsymbo
    $myname
    # 雙引號會保留 $var 變數的內容,而單引號會將 $ 視為純文字來處理~
    
    # E. 使用雙引號處理變數內容的疊代
    [student@station10-101 ~]$ hero="I am $myname"
    [student@station10-101 ~]$ echo ${hero}
    I am peter pan
    # 這個例子就得要使用雙引號才合理了!
    
    # F. 核心版本呼叫方式
    [student@station10-101 ~]$ uname -r
    5.14.0-162.12.1.el9_1.0.2.x86_64
    
    # G. 變數內藏著指令的協助
    [student@station10-101 ~]$ kver="my kernel version is uname -r"
    [student@station10-101 ~]$ echo $kver
    my kernel version is uname -r
    
    [student@station10-101 ~]$ kver="my kernel version is $(uname -r)"
    [student@station10-101 ~]$ echo $kver
    my kernel version is 5.14.0-162.12.1.el9_1.0.2.x86_64
    # 可以將 $() 想成四則運算的括號,要先做的意思~
    
  • 例題 7.1.2-2:
    1. 找出 find 的相關參數,這個很重要喔:
      [student@station10-101 ~]$ man find
      ......
             -perm mode
                    File's permission bits are exactly mode (octal or symbolic).
                    # 權限要剛剛好,例如 -perm 755,就是找出權限一定是 755
      
             -perm -mode
                    All of the permission bits mode are set for the file.
                    # 權限必須包含全部,例如 -perm -644 時,連 755 也會被抓出來!
      
             -perm /mode
                    Any of the permission bits mode are set for the file.
                    # 權限可以是任何一個,例如 -perm /755 代表 rwxr-xr-x 當中任一個出現都行!
      
    2. 題目中的 -perm /6000 當中, 6000 指的是『 --s--s--- 』這樣的權限,所以,任何一個 s 出現 (SUID/SGID) 都可以被抓出來!
      [student@station10-101 ~]$ find /usr/bin /usr/sbin -perm /6000 | sort
      /usr/bin/at
      /usr/bin/chage
      /usr/bin/chfn
      .....
      /usr/sbin/pam_timestamp_check
      /usr/sbin/unix_chkpwd
      
    3. 總是需要確認一下,因此使用底下的指令來列出權限資料:
      [student@station10-101 ~]$ ls -l $(find /usr/bin /usr/sbin -perm /6000)
      -rwsr-xr-x. 1 root root     57976 Oct 26 10:53 /usr/bin/at
      -rwsr-xr-x. 1 root root     74848 Nov  1 07:34 /usr/bin/chage
      -rws--x--x. 1 root root     32032 Nov 17 05:55 /usr/bin/chfn
      ....
      -rwsr-xr-x. 1 root root     16088 Oct 31 22:41 /usr/sbin/pam_timestamp_check
      -rwsr-xr-x. 1 root root     24512 Oct 31 22:41 /usr/sbin/unix_chkpwd
      
      你可以看到每個指令都有 s 出現在權限的旗標裡面!
  • 例題 7.1.2-3:
    # A. 找出適當的檔名:
    [student@station10-101 ~]$ ll $(find /usr/sbin /usr/bin -perm 4755)
    -rwsr-xr-x. 1 root root 57976 Oct 26 10:53 /usr/bin/at
    -rwsr-xr-x. 1 root root 74848 Nov  1 07:34 /usr/bin/chage
    ....
    -rwsr-xr-x. 1 root root 16088 Oct 31 22:41 /usr/sbin/pam_timestamp_check
    -rwsr-xr-x. 1 root root 24512 Oct 31 22:41 /usr/sbin/unix_chkpwd
    # 確實每一個都是 4755 的權限資料!
    
    # B.C. 建立目錄後,將檔案複製過去
    [student@station10-101 ~]$ mkdir ~/unit07
    [student@station10-101 ~]$ cp -a $(find /usr/sbin /usr/bin -perm 4755) ~/unit07
    [student@station10-101 ~]$ ll ~/unit07
    total 676
    -rwxr-xr-x. 1 student student 57976 Oct 26 10:53 at
    -rwxr-xr-x. 1 student student 74848 Nov  1 07:34 chage
    ....
    -rwxr-xr-x. 1 student student 24512 Oct 31 22:41 unix_chkpwd
    -rwxr-xr-x. 1 student student 15536 Nov 15 18:09 vmware-user-suid-wrapper
    
  • 例題 7.1.3-1:
    1. 使用系統管理員的身份執行變數的設定,其中特別注意,PATH 不可以沒有 /bin !否則系統可能會出問題!
      # a. 印出 PATH 變數內容
      [root@station10-101 ~]# echo ${PATH}
      /root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
      # 使用冒號分隔,每個間隔都是指令搜尋的路徑,先找到就先執行!
      
      # b. 將原有的設定先備份下來之意:
      [root@station10-101 ~]# oldpath=${PATH}
      [root@station10-101 ~]# echo ${oldpath}
      /root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
      
      # c. 這題在假設 PATH 設定錯誤的情況,要注意,至少含有 /bin 才行!
      [root@station10-101 ~]# PATH=/bin
      [root@station10-101 ~]# echo ${PATH}
      /bin
      
      # d. 開始執行管理員的專用指令,亦即放置到 /sbin 底下的指令:
      [root@station10-101 ~]# useradd --help
      bash: useradd: command not found...
      Similar command is: 'useradd'
      [root@station10-101 ~]# usermod --help
      bash: usermod: command not found...
      Install package 'shadow-utils' to provide command 'usermod'? [N/y] n
      # 反正,就是讓你無法順利執行位於 /sbin 底下的指令!所以, PATH 真是好重要!
      
      # e. 開始使用絕對路徑來執行,不要使用 PATH 的功能,就寫絕對路徑吧!
      [root@station10-101 ~]# /sbin/usermod --help
      Usage: usermod [options] LOGIN
      
      Options:
        -b, --badnames                allow bad names
        -c, --comment COMMENT         new value of the GECOS field
      ......
      
      # f. 測試完畢之後,請立即將 PATH 改回來,不然會出問題喔!
      [root@station10-101 ~]# PATH=${oldpath}
      [root@station10-101 ~]# echo $PATH
      /root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
      [root@station10-101 ~]# useradd --help
      
      這個題目在告訴我們,PATH 就是所有指令的來源!它相當重要啊!而如果你要使用某個指令, 若不想被 PATH 所制約,那麼使用絕對路徑,大概是你唯一可以做的事情!很重要!很重要!
    2. 透過 student 帳號進行其他任務:
      # a. 建立 student 的個人化專用目錄
      [student@station10-101 ~]$ mkdir cmd
      [student@station10-101 ~]$ cp /bin/cat cmd/scat
      [student@station10-101 ~]$ ll cmd
      total 40
      -rwxr-xr-x. 1 student student 37464 Feb 26 16:01 scat
      # 這個動作其實在模仿自己建立一隻指令在 ~/cmd/scat 的意思而已!我們使用 cat 為例!
      
      # b. 測試執行指令是正常的,就用絕對路徑/相對路徑檔名吧!
      [student@station10-101 ~]$ ./cmd/scat /etc/hosts
      127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
      ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
      # 確定指令可以正常輸出喔!
      
      # c. 測試 scat 是否可以通過預設 PATH 的搜尋找到?
      [student@station10-101 ~]$ scat /etc/hosts
      bash: scat: command not found...
      Similar commands are::
      'zcat'
      'cat'
      
      # d. 重點來了!累加 PATH 的功能在這裡!很重要!
      [student@station10-101 ~]$ PATH="${PATH}:~/cmd"
      [student@station10-101 ~]$ echo $PATH
      /home/student/.local/bin:/home/student/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:~/cmd
      [student@station10-101 ~]$ scat /etc/hosts
      127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
      ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
      
      你就知道 PATH 真是很重要了!
  • 例題 7.1.3-2:
    1. 找尋一下 PS1 這個變數與命令提示字元的相關性:
      [student@station10-101 ~]$ echo $PS1
      [\u@\h \W]\$
      
      你可以發現,命令提示字元『 [student@station10-101 ~]$ 』與 PS1 『 [\u@\h \W]\$ 』格式幾乎一模一樣!沒錯, 因為提示字元就是由 PS1 所設定的!
    2. 現在請透過 man bash 找到 PS1 這個變數的設定方式:
      [student@station10-101 ~]$ man bash
      ......
             \a     an ASCII bell character (07)
             \d     the date in "Weekday Month Date" format (e.g., "Tue May 26")
             \D{format}
                    the  format  is passed to strftime(3) and the result is inserted into the prompt string; 
                    an empty format results in a locale-specific time representation.  The braces are required
             \e     an ASCII escape character (033)
             \h     the hostname up to the first `.'
             \H     the hostname
             \j     the number of jobs currently managed by the shell
             \l     the basename of the shell's terminal device name
             \n     newline
             \r     carriage return
             \s     the name of the shell, the basename of $0 (the portion following the final slash)
             \t     the current time in 24-hour HH:MM:SS format
             \T     the current time in 12-hour HH:MM:SS format
             \@     the current time in 12-hour am/pm format
             \A     the current time in 24-hour HH:MM format
             \u     the username of the current user
             \v     the version of bash (e.g., 2.00)
             \V     the release of bash, version + patch level (e.g., 2.00.0)
             \w     the current working directory, with $HOME abbreviated with a tilde (uses the value of the PROMPT_DIRTRIM variable)
             \W     the basename of the current working directory, with $HOME abbreviated with a tilde
             \!     the history number of this command
             \#     the command number of this command
             \$     if the effective UID is 0, a #, otherwise a $
             \nnn   the character corresponding to the octal number nnn
             \\     a backslash
             \[     begin a sequence of non-printing characters, which could be used to embed a terminal control sequence into the prompt
             \]     end a sequence of non-printing characters
      ......
      
    3. 加入一些額外的設定,就是指令數『 \# 』的效果:
      [student@station10-101 ~]$ PS1="[\u@\h \# \W]\$"
      [student@station10-101 13 ~]$
      
  • 例題 7.1.4-1:
    1. 在父程序設定變數,並檢測是區域還是全域變數:
      # a. 列出變數來搜尋特定內容
      [student@station10-101 17 ~]$ set | grep mypp
      [student@station10-101 18 ~]$ env | grep mypp
      [student@station10-101 19 ~]$ export | grep mypp
      # set 可以列出全部變數 (區域、全域), env / export 只能列出全域變數
      
      # b. 設定變數
      [student@station10-101 20 ~]$ mypp="from_ppid"
      [student@station10-101 21 ~]$ echo ${mypp}
      from_ppid
      
      # c. 檢測是區域還是全域變數?
      [student@station10-101 22 ~]$ set | grep mypp
      mypp=from_ppid
      [student@station10-101 23 ~]$ env | grep mypp
      [student@station10-101 24 ~]$ export | grep mypp
      
      所以這個變數 mypp 目前是『區域變數』的意思!
    2. 在子程序討論剛剛父程序建立的變數:
      # a.b. 進入子程序,並查看 mypp 是否存在?
      [student@station10-101 25 ~]$ bash
      [student@station10-101 ~]$ set | grep mypp
      [student@station10-101 ~]$ env | grep mypp
      [student@station10-101 ~]$ export | grep mypp
      # 其實,只有全域變數的值才會繼承給子程序!所以剛剛的 mypp 這個區域變數,不會傳給子程序
      
      # c.d. 建立子程序內的變數,並且回到父程序
      [student@station10-101 ~]$ mypp2="from_cpid"
      [student@station10-101 ~]$ echo ${mypp2}
      from_cpid
      [student@station10-101 ~]$ exit
      exit
      [student@station10-101 26 ~]$
      
      區域變數沒有辦法傳給子程序的!
    3. 在父程序找子程序建立的資訊,以及將區域變數轉為全域變數:
      # a. 一定找不到子程序所設定的變數!因為是不同的程序啊!
      [student@station10-101 27 ~]$ echo $mypp2
      
      # b. 將區域變數改成全域變數!很簡單,使用 export 即可!
      [student@station10-101 28 ~]$ export mypp
      [student@station10-101 29 ~]$ export | grep mypp
      declare -x mypp="from_ppid"
      [student@station10-101 30 ~]$ set | grep mypp
      mypp=from_ppid
      [student@station10-101 31 ~]$ env | grep mypp
      mypp=from_ppid
      
      基本上, set 列出所有變數,包括區域與全域,env 與 export 只列出全域變數!
    4. 在子程序確認有全域變數的存在!
      [student@station10-101 32 ~]$ bash
      [student@station10-101 ~]$ env | grep mypp
      mypp=from_ppid
      [student@station10-101 ~]$ echo ${mypp}
      from_ppid
      [student@station10-101 ~]$ exit
      exit
      [student@station10-101 33 ~]$
      
      許多程式都有所謂的區域/全域變數的設定概念,當你某個變數要讓整體程式庫全部都使用時,就得要在父程序設定成為全域變數, 然後子程序才有辦法繼承的意思!
  • 例題 7.1.5-1:
    # A.B. 將 vim 指令丟到背景,並查看 job number 與 pid
    [student@station10-101 43 ~]$ vim checking.txt
    abc
    [ctrl]+z
    [1]+  Stopped                 vim checking.txt
    [student@station10-101 44 ~]$ jobs -l
    [1]+  6826 Stopped                 vim checking.txt
    
    # C. 嘗試『正常刪除』該程序
    [student@station10-101 45 ~]$ kill 6826
    [student@station10-101 46 ~]$ jobs -l
    [1]+  6826 Stopped                 vim checking.txt
    # 正常關閉一隻程序的方式是無法刪除 vim 程序的呢!
    [student@station10-101 47 ~]$ kill %1
    [1]+  Stopped                 vim checking.txt
    [student@station10-101 48 ~]$ jobs -l
    [1]+  6826 Stopped (tty output)    vim checking.txt
    # 使用 kill 可以刪除 PID (不加 %),或加上 %n 去刪除 n 號工作!
    # 然後,正常情況下,使用 -15 這個正常訊號,是無法結束背景中的 vim 的!
    
    # D. 嘗試使用強迫刪除
    [student@station10-101 49 ~]$ kill -9 %1
    [1]+  Killed                  vim checking.txt
    [student@station10-101 50 ~]$ jobs -l
    
    # E. 再次編輯看看:
    [student@station10-101 52 ~]$ vim checking.txt
    E325: ATTENTION
    Found a swap file by the name ".checking.txt.swp"   <==這裡!!!
              owned by: student   dated: Sun Feb 26 20:48:54 2023
             file name: ~student/checking.txt
              modified: YES
             user name: student   host name: station2-253.gocloud.vm
            process ID: 6826
    While opening file "checking.txt"
          CANNOT BE FOUND
    (1) Another program may be editing the same file.  If this is the case,
        be careful not to end up with two different instances of the same
        file when making changes.  Quit, or continue with caution.
    (2) An edit session for this file crashed.
        If this is the case, use ":recover" or "vim -r checking.txt"
        to recover the changes (see ":help recovery").
        If you did this already, delete the swap file ".checking.txt.swp"
        to avoid this message.
    
    Swap file ".checking.txt.swp" already exists!
    [O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort: R
    
    abc
    # 然後不儲存強制離開! :q! 
    
    [student@station10-101 71 ~]$ ll .checking.txt.swp
    -rw-------. 1 student student 4096 Feb 26 20:48 .checking.txt.swp
    [student@station10-101 72 ~]$ rm .checking.txt.swp
    
    事實上, vim 會建立很多編輯過程中的暫存檔,如果曾經編輯檔案到一半當掉,可以透過 r 來復原,否則就按 d 結束掉該檔案即可!
  • 例題 7.1.6-1:
    1. 先來檢查 login shell 的 ~/.bash_profile 內容
      [student@station10-101 74 ~]$ cat ~/.bash_profile
      if [ -f ~/.bashrc ]; then
              . ~/.bashrc
      fi
      
      事實上,只有讀取家目錄的 .bashrc 而已!在來看 .bashrc 的內容:
      [student@station10-101 74 ~]$ cat ~/.bashrc
      # 這裡指的是,若存在 /etc/bashrc ,就去讀入 /etc/bashrc 設定值!
      if [ -f /etc/bashrc ]; then
              . /etc/bashrc
      fi
      
      # 底下指的是,如果 PATH 裡面不含有家目錄的路徑,就加入該路徑 (可避免重複設定)
      if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]
      then
          PATH="$HOME/.local/bin:$HOME/bin:$PATH"
      fi
      export PATH
      
      # 底下指的是,可以分門別類的將各自的設定加入 ~/.bashrc.d/ 目錄內,方便使用者設計!
      if [ -d ~/.bashrc.d ]; then
              for rc in ~/.bashrc.d/*; do
                      if [ -f "$rc" ]; then
                              . "$rc"
                      fi
              done
      fi
      unset rc
      
      額外去呼叫 /etc/bashrc 這個檔案,這個檔案如果你用 vim 去看,裡面還有這一段:
          for i in /etc/profile.d/*.sh; do
              if [ -r "$i" ]; then
                  if [ "$PS1" ]; then
                      . "$i"
                  else
                      . "$i" >/dev/null
                  fi
              fi
          done
      
      又讀入不少設定檔,大多在 /etc/profile.d 目錄內的設定檔!這就是每個用戶登入時,都會去處理的整體流程!
  • 例題 7.1.6-2:
    [student@station10-101 78 ~]$ vim ~/.bashrc
    HISTSIZE=10000
    alias cp="cp -i"
    alias rm="rm -i"
    alias mv="mv -i"
    ! [[ "$PATH" =~ "~/cmd" ]] && PATH="${PATH}:~/cmd"
    kver=$( uname -r )
    export LANG=zh_TW.utf8
    PS1="[\u@\h \A \# \W]$ "
    h_start=$( wc -l ~/.bash_history | awk '{print $1}' )
    
    [student@station10-101 78 ~]$ source ~/.bashrc
    [student@station10-101 10:03 84 ~]$ echo $h_start
    555
    [student@station10-101 10:04 85 ~]$ echo $HISTSIZE
    10000
    [student@station10-101 10:04 86 ~]$ echo $PATH
    /home/student/.local/bin:/home/student/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:~/cmd
    [student@station10-101 10:04 87 ~]$ echo $kver
    5.14.0-162.12.1.el9_1.0.2.x86_64
    
  • 例題 7.1.6-3:
    1. 開始設計 ~/.bash_logout 內容
      [student@station10-101 10:04 88 ~]$ vim .bash_logout
      date +%Y/%m/%d" "%H:%M >> ~/history.log
      h_end=$( history | wc -l )
      h_now=$(( $h_end - $h_start +1 ))
      history $h_now >> ~/history.log
      
      [root@station10-101 ~]# su - student
      [student@station10-101 10:10 1 ~]$ cat .bash_logout
      [student@station10-101 10:11 2 ~]$ echo $kver
      [student@station10-101 10:11 3 ~]$ exit
      [root@station10-101 ~]# cat ~student/history.log
      2023/02/26 21:14
        649  cat .bash_logout
        650  echo $kver
        651  exit
      
      每次登入 student 的 login shell 環境下,這個 history.log 的檔案都會長大喔!
  • 例題 7.4 課後練習
    
    # a. 合法的 shell 都在 /etc/shells 當中,所以可以這樣做:
    [root@station10-101 ~]# vim /etc/shells
    ......
    /usr/bin/csh
    /usr/bin/tcsh
    /bin/false
    /bin/true
    
    [root@station10-101 ~]# chsh -l
    ......
    /bin/false
    /bin/true
    
    # b. 使用 usermod -s [tab][tab] 出現什麼?可能的意義是什麼?
    [root@station10-101 ~]# usermod -s [tab][tab]
    /bin/bash      /bin/csh       /bin/false     /bin/sh        /bin/tcsh
    /bin/true      /usr/bin/bash  /usr/bin/csh   /usr/bin/sh    /usr/bin/tcsh
    # 看起來就是自動補齊合法的 shells,亦即是取得 /etc/shells 的內容!
    
    # c. 將 /bin/false, /bin/true 移除合法 shell 的列表中。
    [root@station10-101 ~]# vim /etc/shells
    # 將剛剛加入的那兩個 shells 移除!
    
    # d. 就是找到最後面出現 /bin/bash 的那個帳號即可
    [root@station10-101 ~]# grep '/bin/bash' /etc/passwd | cut -d ',' -f1,7
    root:x:0:0:root:/root:/bin/bash
    student:x:1000:1000:student:/home/student:/bin/bash
    prouser1:x:1001:1002::/home/prouser1:/bin/bash
    prouser2:x:1002:1003::/home/prouser2:/bin/bash
    prouser3:x:1003:1004::/home/prouser3:/bin/bash
    theuser2:x:1005:1007::/home/theuser2:/bin/bash
    theuser3:x:1006:1008::/home/theuser3:/bin/bash
    theuser1:x:1004:1006::/home/theuser1:/bin/bash
    
    # e. 全域變數可用 env 或 export 查閱
    [root@station10-101 ~]# export
    declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/0/bus"
    declare -x DEBUGINFOD_URLS="https://debuginfod.centos.org/ "
    declare -x HISTCONTROL="ignoredups"
    declare -x HISTSIZE="1000"
    ......
    
    # f.g. 呼叫出 PS1 變數,然後修改 
    [root@station10-101 ~]# echo $PS1
    [\u@\h \W]\$
    [root@station10-101 ~]# PS1='C:\\win> '
    C:\win>
    C:\win> PS1='[\u@\h \W]\$ '
    [root@station10-101 ~]#
    
    # h.i. 延伸 PATH 的內容
    [root@station10-101 ~]# echo ${PATH}
    /root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
    [root@station10-101 ~]# PATH=${PATH}:/opt/bin
    [root@station10-101 ~]# echo ${PATH}
    /root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/opt/bin
    
    # j. 以子指令設定好變數內容
    [root@station10-101 ~]# kver=$( uname -r )
    [root@station10-101 ~]# echo $kver
    5.14.0-162.12.1.el9_1.0.2.x86_64
    
    # k. 設定 kver 為全域變數
    [root@station10-101 ~]# export | grep kver
    [root@station10-101 ~]# export kver
    [root@station10-101 ~]# export | grep kver
    declare -x kver="5.14.0-162.12.1.el9_1.0.2.x86_64"
    
    # l. 查詢 signal
    [root@station10-101 ~]# man 7 signal
    ......
       Standard signals
    ......
           Signal      Standard   Action   Comment
           ──────────────────────────────────
    ......
           SIGHUP       P1990      Term    Hangup detected on controlling terminal
                                           or death of controlling process
    ......
       Signal numbering for standard signals
    ......
           Signal        x86/ARM     Alpha/   MIPS   PARISC   Notes
                       most others   SPARC
           ────────────────────────────
           SIGHUP           1           1       1       1
           SIGINT           2           2       2       2
           SIGQUIT          3           3       3       3
           SIGILL           4           4       4       4
           SIGTRAP          5           5       5       5
           SIGABRT          6           6       6       6
           SIGIOT           6           6       6       6
           SIGBUS           7          10      10      10
           SIGEMT           -           7       7      -
           SIGFPE           8           8       8       8
           SIGKILL          9           9       9       9
           SIGUSR1         10          30      16      16
           SIGSEGV         11          11      11      11
           SIGUSR2         12          31      17      17
           SIGPIPE         13          13      13      13
           SIGALRM         14          14      14      14
           SIGTERM         15          15      15      15
           SIGSTKFLT       16          -       -        7
    ......
    # 這功能有點類似重新載入 (reload) 的感覺!
    
    # m. 手動變更 PID 的 hangup (reload) 功能
    [root@station10-101 ~]# ps aux | grep rsyslog
    root     748  0.0  0.3 160248  7240 ?        Ssl  23:11   0:00 /usr/sbin/rsyslogd -n
    root    1918  0.0  0.1 221796  2292 pts/0    S+   23:43   0:00 grep --color=auto rsyslog
    
    [root@station10-101 ~]# date
    Sun Feb 26 11:47:16 PM CST 2023
    
    [root@station10-101 ~]# kill -1 748
    [root@station10-101 ~]# ps aux | grep rsyslog
    root     748  0.0  0.3 160248  7240 ?        Ssl  23:11   0:00 /usr/sbin/rsyslogd -n
    root    1925  0.0  0.1 221796  2252 pts/0    S+   23:44   0:00 grep --color=auto rsyslog
    # PID 號碼沒改變,所以依舊是原本那隻 PID!只是可能狀態被改變而已!
    
    # n. 查看登錄檔資訊
    [root@station10-101 ~]# tail -n 100 /var/log/messages | grep rsyslog
    Feb 26 23:46:13 station2-253 rsyslogd[748]: [origin software="rsyslogd" swVersion="8.2102.0-105.el9" 
      x-pid="748" x-info="https://www.rsyslog.com"] rsyslogd was HUPed
    
    # o. 查詢 signal
    [root@station10-101 ~]# man 7 signal
    ......
       Standard signals
    ......
           Signal      Standard   Action   Comment
           ──────────────────────────────────
    ......
           SIGINT       P1990      Term    Interrupt from keyboard
    ......
           SIGTSTP      P1990      Stop    Stop typed at terminal
    ......
           Signal        x86/ARM     Alpha/   MIPS   PARISC   Notes
                       most others   SPARC
           ─────────────────────────────
           SIGINT           2           2       2       2
           SIGTSTP         20          18      24      25
    # 各有說明的意義!
    
    # p.q. 直接開另一個視窗並啟用 vim 軟體,假設完成後,查閱該軟體之後處理
    [root@station10-101 ~]# ps aux | grep vim
    root        2031  0.0  0.5 229400  9168 tty3     S+   23:51   0:00 vim
    root        2038  0.0  0.1 221664  2232 pts/0    S+   23:51   0:00 grep --color=auto vim
    [root@station10-101 ~]# kill -20 2031
    [root@station10-101 ~]# ps aux | grep vim
    root        2031  0.0  0.5 229400  9168 tty3     T    23:51   0:00 vim
    root        2099  0.0  0.1 221664  2272 pts/0    S+   23:58   0:00 grep --color=auto vim
    
    # r. 使用 bash 計算整數!
    [root@station10-101 ~]# echo $(( 60*60*24 ))
    86400
    
修改歷史:
  • 2023/02/17:RHEL 改版到 EL9 了,只好再度改版!否則教學上面挺困擾!
2023/02/17 以來統計人數
計數器
其他連結
環境工程模式篇
鳥園討論區
鳥哥舊站

今日 人數統計
昨日 人數統計
本月 人數統計
上月 人數統計