第 7 堂課:認識 bash 基礎與系統救援

http://linux.vbird.org/linux_basic_train/unit07.php

7.1:bash shell 基礎認識

7.1.1:系統與使用者的 shell

請使用 cut 這個指令,將 /etc/passwd 這個檔案的內容中,以冒號 (:) 為分隔字元 (delimiter),將第 1 及第 7 欄位 (field) 輸出到螢幕上

[root@mail ~]# cat /etc/passwd | cut -d ':' -f 1,7

承上,找到關鍵字為 daemon 的那一行,daemon 用戶所使用的 shell 是什麼?

[root@mail ~]# cat /etc/passwd | grep daemon| cut -d ':' -f 7
/sbin/nologin
/sbin/nologin

請使用 student 身份登入系統,取得終端機後,使用『 echo $BASH 』的方式查閱有沒有這個變數以及其輸出的內容

[root@mail ~]# su - student
Last login: Sun May  8 16:54:36 CST 2016 on pts/1
[student@mail ~]$ echo $BASH
/bin/bash

請輸入『 echo $shell 』觀察有沒有資料輸出?

[student@mail ~]$ echo $shell

#沒有資料輸出

使用『 /bin/csh 』切換 shell 成為 c shell

[student@mail ~]$ /bin/csh

分別使用『 echo $BASH 』與『 echo $shell 』觀察輸出的資料為何?

[student@mail ~]$ echo $BASH
BASH: Undefined variable.
[student@mail ~]$ echo $shell
/bin/tcsh

使用『 echo $0 』觀察輸出的資料是什麼?

[student@mail ~]$ echo $0
/bin/csh

先透過『 exit 』離開 c shell 之後,再次以 echo $0 觀察目前的 shell 名稱為何?

[student@mail ~]$ exit
exit
[student@mail ~]$ echo $0
-bash

執行『 /sbin/nologin 』看看輸出的資料為何?

[student@mail ~]$ /sbin/nologin
This account is currently not available.

請使用 usermod 來修改 student 的 shell 變成 /sbin/nologin

[root@mail ~]# usermod -s /sbin/nologin student

修改完畢後,請到 tty3 的終端機,嘗試使用 student 的帳號登入,看看會出現什麼情況

[root@mail ~]# su - student
Last login: Sun May  8 17:39:29 CST 2016 on pts/1
This account is currently not available.

請再次以 usermod 的方式將 student 的 shell 改回來 /bin/bash

usermod -s /bin/bash student

使用 id 這個指令檢查系統有無 bin 與 student 這兩個帳號的存在?

[root@mail ~]# id bin
uid=1(bin) gid=1(bin) groups=1(bin)
[root@mail ~]# id student
uid=1000(student) gid=1000(student) groups=1000(student)

能不能在不知道密碼的情況下,使用 root 切換成 student 這個帳號?為什麼?

可以

能不能在不知道密碼的情況下,使用 root 切換成 bin 這個帳號?為什麼?

不行,因為No Login

建立一個不可登入系統取得互動 shell 的帳號,帳號名稱為 puser1,密碼為 MyPuser1

//TODO 看不懂'互動shell'的意思

嘗試在 tty3 登入該帳號,結果是?

//TODO 看不懂'互動shell'的意思

設定一個名為 myname 的變數,變數的內容為『 peter pan 』

[root@mail ~]# myname='peter pan'

使用 echo 呼叫出 myname 的內容

[root@mail ~]# echo $myname
peter pan

是否能夠設定 2myname 的內容為『 peter pan 』呢?

#不行

設定 varsymbo 變數的內容為『 $var 』,$var 就是純文字資料不是變數。設定完畢後呼叫出來

[root@mail ~]# varsymbo=\$var
[root@mail ~]# echo $varsymbo
$var

設定 hero 變數的內容為『 I am $myname 』,其中 $myname 會依據 myname 變數的內容而變化。設定完畢請呼叫出來。

[root@mail ~]# hero="i am: $myname"
[root@mail ~]# echo $hero
i am: peter pan

使用 uname -r 秀出目前的核心版本

[root@mail ~]# uname -r
3.10.0-862.3.3.el7.x86_64

設定 kver 變數,內容為『 my kernel version is 3.xx 』,其中 3.xx 為 uname -r 輸出的資訊。請注意, kver 變數設定過程中,需要用到 uname -r 這個指令的協助。

[root@mail ~]# kver='my kernel version is '$(uname -r)
[root@mail ~]# echo $kver
my kernel version is 3.10.0-862.3.3.el7.x86_64

使用 man find 找出 -perm 的功能為何?

搜尋權限用

使用『 find /usr/bin /usr/sbin -perm /6000 』找出所有含有特殊權限的檔名

[root@mail ~]# find /usr/bin /usr/sbin -perm /6000
/usr/bin/wall
/usr/bin/fusermount
/usr/bin/su
/usr/bin/chage
/usr/bin/gpasswd
/usr/bin/newgrp
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/passwd
/usr/bin/mount
/usr/bin/crontab
/usr/bin/umount
/usr/bin/write
/usr/bin/pkexec
/usr/bin/at
/usr/bin/sudo
/usr/bin/ssh-agent
/usr/bin/locate
/usr/bin/staprun
/usr/sbin/pam_timestamp_check
/usr/sbin/unix_chkpwd
/usr/sbin/netreport
/usr/sbin/usernetctl
/usr/sbin/postdrop
/usr/sbin/postqueue
/usr/sbin/userhelper

使用『 ls -l $(find /usr/bin /usr/sbin -perm /6000) 』將所有檔名的權限列出

[root@mail ~]# ls -l $(find /usr/bin /usr/sbin -perm /6000)
-rwsr-xr-x. 1 root root      52952 Apr 11  2018 /usr/bin/at
-rwsr-xr-x. 1 root root      64240 Nov  6  2016 /usr/bin/chage
-rws--x--x. 1 root root      24048 Apr 11  2018 /usr/bin/chfn
-rws--x--x. 1 root root      23960 Apr 11  2018 /usr/bin/chsh
-rwsr-xr-x. 1 root root      57576 Apr 11  2018 /usr/bin/crontab
-rwsr-xr-x. 1 root root      32008 Apr 11  2018 /usr/bin/fusermount
-rwsr-xr-x. 1 root root      78216 Nov  6  2016 /usr/bin/gpasswd
-rwx--s--x. 1 root slocate   40520 Apr 11  2018 /usr/bin/locate
-rwsr-xr-x. 1 root root      44320 Apr 11  2018 /usr/bin/mount
-rwsr-xr-x. 1 root root      41776 Nov  6  2016 /usr/bin/newgrp
-rwsr-xr-x. 1 root root      27832 Jun 10  2014 /usr/bin/passwd
-rwsr-xr-x. 1 root root      27680 Apr 11  2018 /usr/bin/pkexec
---x--s--x. 1 root nobody   382240 Apr 11  2018 /usr/bin/ssh-agent
---s--x---. 1 root stapusr  203832 Apr 13  2018 /usr/bin/staprun
-rwsr-xr-x. 1 root root      32184 Apr 11  2018 /usr/bin/su
---s--x--x. 1 root root     143184 Apr 11  2018 /usr/bin/sudo
-rwsr-xr-x. 1 root root      32048 Apr 11  2018 /usr/bin/umount
-r-xr-sr-x. 1 root tty       15344 Jun 10  2014 /usr/bin/wall
-rwxr-sr-x. 1 root tty       19624 Apr 11  2018 /usr/bin/write
-rwxr-sr-x. 1 root root      11224 Apr 11  2018 /usr/sbin/netreport
-rwsr-xr-x. 1 root root      11216 Apr 11  2018 /usr/sbin/pam_timestamp_check
-rwxr-sr-x. 1 root postdrop 218552 Jun 10  2014 /usr/sbin/postdrop
-rwxr-sr-x. 1 root postdrop 259992 Jun 10  2014 /usr/sbin/postqueue
-rwsr-xr-x. 1 root root      36280 Apr 11  2018 /usr/sbin/unix_chkpwd
-rws--x--x. 1 root root      40312 Jun 10  2014 /usr/sbin/userhelper
-rwsr-xr-x. 1 root root      11288 Apr 11  2018 /usr/sbin/usernetctl

使用 find 的功能,找出在 /usr/sbin 及 /usr/bin 底下權限為 4755 的檔案

[root@mail ~]# ls -l $(find /usr/sbin /usr/bin -perm 4755)
-rwsr-xr-x. 1 root root 52952 Apr 11  2018 /usr/bin/at
-rwsr-xr-x. 1 root root 64240 Nov  6  2016 /usr/bin/chage
-rwsr-xr-x. 1 root root 57576 Apr 11  2018 /usr/bin/crontab
-rwsr-xr-x. 1 root root 32008 Apr 11  2018 /usr/bin/fusermount
-rwsr-xr-x. 1 root root 78216 Nov  6  2016 /usr/bin/gpasswd
-rwsr-xr-x. 1 root root 44320 Apr 11  2018 /usr/bin/mount
-rwsr-xr-x. 1 root root 41776 Nov  6  2016 /usr/bin/newgrp
-rwsr-xr-x. 1 root root 27832 Jun 10  2014 /usr/bin/passwd
-rwsr-xr-x. 1 root root 27680 Apr 11  2018 /usr/bin/pkexec
-rwsr-xr-x. 1 root root 32184 Apr 11  2018 /usr/bin/su
-rwsr-xr-x. 1 root root 32048 Apr 11  2018 /usr/bin/umount
-rwsr-xr-x. 1 root root 11216 Apr 11  2018 /usr/sbin/pam_timestamp_check
-rwsr-xr-x. 1 root root 36280 Apr 11  2018 /usr/sbin/unix_chkpwd
-rwsr-xr-x. 1 root root 11288 Apr 11  2018 /usr/sbin/usernetctl

建立 /root/findfile 目錄

[root@mail ~]# mkdir /root/findfile

將步驟 1 找到的檔案連同權限複製到 /root/findfile 目錄下。

[root@mail ~]# cp -a $(find /usr/sbin /usr/bin -perm 4755) /root/findfile

7.1.3:影響操作行為的變數

請用 root 的身份來處理底下的任務

印出 PATH 這個變數的內容,並觀察每個項目中間的分隔符號為何?

[root@mail ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

分隔符號是冒號

設定一個名為 oldpath 的變數,內容就是 ${PATH}

[root@mail ~]# oldpath=$PATH

設定 PATH 的內容成為 /bin 而已 (非常重要,不可設錯!)

[root@mail ~]# PATH='/bin'

此時輸入以前曾操作過得 useradd --help 及 usermod --help 等指令,螢幕顯示的訊息為何?

[root@mail ~]# useradd --help
-bash: useradd:命令找不到
[root@mail ~]# usermod --help
-bash: usermod:命令找不到

若使用 /sbin/usermod --help,可以正常顯示嘛?

可以

請設定 PATH 的內容成為 ${oldpath} ,恢復正常的路徑資料。

[root@mail ~]# PATH=$oldpath

請改用 student 的身份來執行下列練習

建立 ~student/cmd/ 目錄,且將 /bin/cat 複製成為 ~student/cmd/scat

[student@mail ~]$ mkdir ~student/cmd/
[student@mail ~]$ cp /bin/cat ~student/cmd/scat

輸入『 ~student/cmd/scat /etc/hosts 』確認指令正常無誤。

[student@mail ~]$ ~student/cmd/scat /etc/hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.231.8.147 mail.want-want.com

輸入『 scat /etc/hosts 』會發生什麼問題?

[student@mail ~]$ scat /etc/hosts
-bash: scat: command not found

如何讓 student 用戶直接使用 scat 而不須使用 ~student/cmd/scat 來執行?

[student@mail ~]$ PATH=$PATH:/home/student/cmd

呼叫出 PS1 這個變數的內容

[student@mail ~]$ echo $PS1
[\u@\h \W]\$

請查詢上述變數內容當中 \W 及 $ 的意義為何 (請 man bash 透過 PS1 關鍵字查詢)

\W :利用 basename 函數取得工作目錄名稱,所以僅會列出最後一個目錄名
\$ :提示字元,如果是 root 時,提示字元為 # ,否則就是 $ 囉~

假設操作者已經做了 15 個指令,則命令提示字元輸出如:『 [student@localhost 15 ~]$ 』該如何設定 PS1?

[student@mail ~]$ PS1='[\u@\h \# \w]\$ '

7.1.4:區域/全域變數、父程序與子程序

使用 set 或 env 或 export 觀察是否存在 mypp 這個變數?

沒有

設定 mypp 的內容為『 from_ppid 』,並且呼叫出來

[student@mail ~]$ mypp=from_ppid

使用 set 或 env 或 export 觀察是否存在 mypp 這個變數?

set有,env跟export沒有

執行『 /bin/bash 』進入下一個 bash 的子程序環境中

使用 set 或 env 或 export 觀察是否存在 mypp 這個變數?同時說明為什麼?

沒有,因為mypp1不是子程序變數

設定 mypp2 的內容為『 from_cpid 』,並且呼叫出來

[student@mail ~]$ mypp2=from_cpid

使用『 exit 』離開子程序回到原本的父程序

觀察是否存在 mypp2 這個變數?為什麼?

因為mypp2不是父程序的變數

使用『 export mypp 』後,使用 env 或 export 觀察是否存在?

存在

執行『 /bin/bash 』進入下一個 bash 的子程序環境中

[student@mail ~]$ /bin/bash

使用 set 或 env 或 export 觀察是否存在 mypp 這個變數?同時說明為什麼?

存在,因為mypp變成全域變數

回到原本的父程序中。

[student@mail ~]$ exit
exit

7.1.5:使用 kill 管理程序

使用 vim & 將 vim 程序放進背景中暫停

[student@mail ~]$ vim &
[1] 836

使用 jobs -l 進一步列出該程序的 PID 號碼

[student@mail ~]$ jobs -l
[1]+   836 停止 (tty 輸出)     vim

使用『 kill PID號碼 』嘗試刪除該工作,是否能夠生效?

[student@mail ~]$ kill 836
[student@mail ~]$ jobs -l
[1]+   836 停止 (tty 輸出)     vim

#不能生效

若無法刪除,請使用『 kill -9 PID號碼 』的方式來刪除,是否能夠生效?

[student@mail ~]$ kill -9 836
[student@mail ~]$ jobs -l
[1]+   836 已砍掉               vim

7.1.6:login shell and non-login shell

觀察一下 ~/.bash_profile 的內容,說明該檔案設定了什麼項目?

[student@mail ~]$ cat ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

看起來像是執行.bashrc,並且設定PATH

觀察 ~/.bashrc 的內容,說明該檔案設定了什麼項目?

[student@mail ~]$ cat ~/.bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions

看子來像執行etc底下的bashrc

請在 student 的家目錄編輯 .bashrc ,增加底下的項目:

  • 設定 history 可以輸出 10000 筆資料
  • 設定執行 cp 時,其實會主動加入 cp -i 的選項

  • 設定執行 rm 時,其實會主動加入 rm -i 的選項

  • 設定執行 mv 時,其實會主動加入 mv -i 的選項

  • 增加 PATH 的搜尋目錄在 /home/student/cmd/ 目錄

  • 設定一個變數名稱為 kver,其內容是目前的核心版本

  • 強迫語系使用 zh_TW.utf8 這個項目,且必須要設定為全域變數

  • 讓提示字元項目中,增加時間與操作指令次數的項目。

  • 使用 wc 指令分析 ~/.bash_history 的行數,將該行數紀錄於 h_start 的變數中

[student@mail ~]$ vim .bashrc
# .bashrc

export HISTSIZE=10000
export HISEFILESIZE=10000
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
PATH=$PATH:/home/student/cmd/
kver=$(uname -r)
PS1='[\u@\h \w \A #\#]\$ '
h_start=$(wc ~/.bash_history)

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions

設定完畢後,如何在不登出的情況下,讓設定生效?

[student@mail ~]$ . ~/.bashrc

每次登出 bash 時,都會:

  • 使用 date 取得『 YYYY/MM/DD HH:MM 』的格式,並且轉存到家目錄的 history.log 檔案中

  • 使用 history 加上管線命令與 wc 來分析結束時的 history 行數,將該數值設定為 h_end,搭配之前設定的 h_start 開始的行數, 計算出這次執行指令的行數號碼 (應該是 h_end - h_start +1 ),設定為 h_now,透過 history ${h_now} 將最新的指令轉存到 history.log 當中。

[student@mail ~]$ vi .bash_logout
# ~/.bash_logout

date '+%Y/%M/%d %H:%M' > ~/history.log

h_start=$(cat ~/.bash_history | wc -l)
h_end=$(history | wc -l)
h_now=$(expr $h_end - $h_start + 1)

history ${h_now} > ~/history.log

嘗試使用 su - student 來登入 student ,再隨意進行數個指令,之後登出 bash 回到原本的 bash 當中,觀察 ~/history.log 是否有資訊紀錄?

7.3:課後練習操作

請使用 root 的身份進行如下實做的任務。直接在系統上面操作,操作成功即可,上傳結果的程式會主動找到你的實做結果。

因為某些緣故,目前這個作業系統應該是無法順利開機的。請使用本節課程所介紹的方式來進行系統的救援。 根據猜測,可能的原因與管理員曾經動過 chsh 這個指令有關,同時,管理員似乎也更動過 fstab 這個設定檔。 請依據這些之前的可能舉動,來恢復系統的可登入狀態。(hint: 千萬不要忘記 .autorelabel 的動作!)

//Todo

請處理底下帳號與 shell 的相關事宜:

請將系統中的 /bin/false 與 /bin/true 這兩個檔案變成合法的 shell

將 /bin/false跟/bin/true 加到 /etc/shells

請將 examuser1 的 shell 變成 /bin/true

[root@mail ~]# chsh -s /bin/true examuser1
Changing shell for examuser1.
chsh: Warning: "/bin/true" is not listed in /etc/shells.
Shell changed.

因為你即將建立一個 FTP 伺服器,這個伺服器上面的用戶只能單純的使用 FTP 功能,因此你想要讓這些帳號無法使用 shell。 假設三個帳號 myuser1, myuser2, myuser3 的帳號,這三個帳號將無法使用互動界面操作系統,且密碼為 MyPassWordhehe

[root@mail ~]# useradd -p MyPassWordhehe -s /usr/sbin/nologin myuser1
[root@mail ~]# useradd -p MyPassWordhehe -s /usr/sbin/nologin myuser1
[root@mail ~]# useradd -p MyPassWordhehe -s /usr/sbin/nologin myuser1

透過 bash shell 的功能,進行檔案的查詢與複製

找出系統中檔案擁有者為 examuser1 的檔名,並將這些找到的檔名(含權限)複製到 /root/findout/ 目錄內

[root@mail ~]# mkdir /root/findout
[root@mail ~]# cp -a $(find -type f -user examuser1) /root/findout/

找出在 /usr/sbin 及 /usr/bin 底下權限為 4755 的檔案,並將這些檔案複製到 /root/findperm/ 目錄內

[root@mail ~]# cp $(find /usr/sbin /usr/bin -type f -perm 4755) /root/findperm/

在你的系統中,嘗試找到一個執行 sleep 的程序,並且使用各種方法,將該程序刪除。

[root@mail ~]# sleep 60d
^Z
[1]+  Stopped                 sleep 60d
[root@mail ~]# jobs -l
[1]+  3102 停止                  sleep 60d
[root@mail ~]# kill -9 3102

建立名為 examuser10 的帳號,密碼為 MyPassWordhehe,且這個帳號登入後,預設會有底下的設定:

  • 登入行為:
    1. 預設使用 bash 作為 shell
    2. 會讀入 /etc/examvar 設定檔
    3. 擁有一個名為 myip 的變數,變數內容為『 ifconfig eth0 | grep 'inet ' | cut -d 't' -f 2 | cut -d ' ' -f 2 』 的執行成果 (每個同學操作指令的結果都不會相同,但是指令會是一樣的)
    4. 使用 zh_TW.utf8 語系資料
    5. 增加 ~examuser10/scripts/ 目錄作為指令執行時所尋找的目錄位置
    6. 命令提示字元增加時間項目在裡面
    7. 預設歷史命令紀錄 5000 筆
    8. 操作 cp 時,自動給予 cp -i 的選項
    9. 透過『 wc -l ~/.bash_history | cut -d ' ' -f 1 』的指令取得前一次登入的歷史命令次數,並將該數值轉存成為 ~/.history_start
[root@mail ~]# adduser -p MyPassWordhehe examuser10
[root@mail ~]# su - examuser10
[examuser10@mail ~]$ vi ./~bashrc
# .bashrc

chsh -s /usr/bin/bash
. /etc/examvar
myip=${ifconfig eth0 | grep 'inet ' | cut -d 't' -f 2 | cut -d ' ' -f 2}
LANG=zh_TW.utf8
PATH=$PATH:~examuser10/scripts/
PS1='[\u@\h \w \A #\#]\$ '
export HISTSIZE=5000
export HISEFILESIZE=5000
alias cp='cp -i'
$(wc -l ~/.bash_history | cut -d ' ' -f 1) > ~/.history_start


# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=

# User specific aliases and functions
  • 登出的行為:
    1. 透過『 history | tail -n 1 | awk '{print $1}' 』取得最後一筆歷史紀錄,然後將該數值指定為 hist_end 變數
    2. 請使用『 cat ~/.history_start 』取得登入時記載的歷史命令筆數,將該數值指定為 hist_start 變數
    3. 設定一個名為 hist_size 的變數,內容為 hist_end - hist_start 的數值 (有多種計算方式,能成功即可!)
    4. 將離開的日期,使用『 YYYY/MM/DD HH:MM 』的格式累加寫入到 ~/history.log 檔案中
    5. 透過『 history $hist_size 』取得最後最新的數筆紀錄後,將該資料累加到 ~/history.log 檔案中。
[examuser10@mail ~]$ vi ~/.bash_logout
# ~/.bash_logout

h_end=$(history | tail -n 1 | awk '{print $1}')
h_start=$(cat ~/.bash_history | wc -l)
hist_size=$(expr $h_end - $h_start)
date '+%Y/%M/%d %H:%M' > ~/history.log
history $hist_size > ~/history.log

results matching ""

    No results matching ""