Linux 基礎篇 - 學習筆記

前言

這是一份未整理過的 Linux 學習筆記
OS 系統為 GCP 上的 Linux 18.04 LTS
內容參考出處:

  1. 鳥哥的 Linux 的私房菜
  2. Internet



find

搜尋屬於特定 user 或 group 的檔案

find localtion -type f -user userName -group groupName -name fileName

搜尋屬於特定 user 或 group 的資料夾

find localtion -type d -user userName -group groupName -name fileName

搜尋 $分鐘內的檔案或資料夾, 只搜尋當層

find ./* -maxdepth 0 -type f -cmin -20



ps

  • 列出系統正在執行的 process, 並且從中搜尋關鍵字
    ps -ef | node



kill

語法

[root@study ~]# kill -signal %jobnumber
[root@study ~]# kill -l
選項與參數:
-l :這個是 L 的小寫,列出目前 kill 能夠使用的訊號 (signal) 有哪些?
signal :代表給予後面接的那個工作什麼樣的指示囉!用 man 7 signal 可知:
-1 :重新讀取一次參數的配置文件 (類似 reload);
-2 :代表與由鍵盤輸入 [ctrl]-c 同樣的動作;
-9 :立刻強制刪除一個工作;
-15:以正常的程序方式終止一項工作。與 -9 是不一樣的。

代號 | 名稱 | 內容
—-|—–|
1 | SIGHUP | 啟動被終止的程序,可讓該 PID 重新讀取自己的配置文件,類似重新啟動
2 | SIGINT | 相當於用鍵盤輸入 [ctrl]-c 來中斷一個程序的進行
9 | SIGKILL | 代表強制中斷一個程序的進行,如果該程序進行到一半, 那麼尚未完成的部分可能會有“半產品”產生,類似 vim會有 .filename.swp 保留下來。
15 | SIGTERM | 以正常的結束程序來終止該程序。由於是正常的終止, 所以後續的動作會將他完成。不過,如果該程序已經發生問題,就是無法使用正常的方法終止時, 輸入這個 signal 也是沒有用的。
19 | SIGSTOP | 相當於用鍵盤輸入 [ctrl]-z 來暫停一個程序的進行


指令

  • 立刻強制刪除一個工作
    kill -9 processID



killall

語法

[root@study ~]# killall [-iIe] [command name]
選項與參數:
-i :interactive 的意思,互動式的,若需要刪除時,會出現提示字符給使用者;
-e :exact 的意思,表示“後面接的 command name 要一致”,但整個完整的指令
不能超過 15 個字符。
-I :指令名稱(可能含參數)忽略大小寫。



ln

  • 建立一個捷徑
    ln -s sourceAbsoluteLink targetAbsoluteLink



du

  • 查檔案大小
    du -sh fileOrFolder



df

  • 查硬碟空間使用率
    df -h



[[]]

  • 回傳 true or false
    [[ -f /.dockerenv ]]
    [[]] 會將裡頭的參數結果回傳 true or false
    -f 表示 file exists
    所以意思是,如果 /.dockerenv 存在,則回傳 true



grep

  • 搜尋內容並顯示附近的行數
    gcloud command 中取得資料,並且顯示 ssh-keys 後面的 5 行
    gcloud compute project-info describe | grep -A 5 ssh-keys



groupdel

  • 刪除 group
    groupdel groupName



userdel

  • 刪除 user
    userdel userName



useradd

useradd [-u UID] [-g 初始群組] [-G 次要群組] [-mM]\
> [-c 說明欄] [-d 主文件夾絕對路徑] [-s shell] 使用者帳號名
選項與參數:
-u :後面接的是 UID ,是一組數字。直接指定一個特定的 UID 給這個帳號;
-g :後面接的那個群組名稱就是我們上面提到的 initial group 啦~
該群組的 GID 會被放置到 /etc/passwd 的第四個字段內。
-G :後面接的群組名稱則是這個帳號還可以加入的群組。
這個選項與參數會修改 /etc/group 內的相關數據喔!
-M :強制!不要創建使用者主文件夾!(系統帳號默認值)
-m :強制!要創建使用者主文件夾!(一般帳號默認值)
-c :這個就是 /etc/passwd 的第五欄的說明內容啦~可以隨便我們設置的啦~
-d :指定某個目錄成為主文件夾,而不要使用默認值。務必使用絕對路徑!
-r :創建一個系統的帳號,這個帳號的 UID 會有限制 (參考 /etc/login.defs)
-s :後面接一個 shell ,若沒有指定則默認是 /bin/bash 的啦~
-e :後面接一個日期,格式為“YYYY-MM-DD”此項目可寫入 shadow 第八字段,
亦即帳號失效日的設置項目囉;
-f :後面接 shadow 的第七字段項目,指定密碼是否會失效。0為立刻失效,
-1 為永遠不失效(密碼只會過期而強制於登陸時重新設置而已。)
  • 完全參考默認值創建一個使用者,名稱為 Ray

    useradd Ray
  • 建立一個 user, 並加到指定 group

    useradd -G groupName userName



useradd 之後,系統會幫我們做哪些事?

  1. 在 /etc/passwd 裡面創建一行與帳號相關的數據,包括創建 UID/GID/主文件夾等;
  2. 在 /etc/shadow 裡面將此帳號的密碼相關參數填入,但是尚未有密碼;
  3. 在 /etc/group 裡面加入一個與帳號名稱一模一樣的群組名稱;
  4. 在 /home 下面創建一個與帳號同名的目錄作為使用者主文件夾,且權限為 700

useradd 參考檔

  • 這個數據其實是由 /etc/default/useradd 調用出來的
useradd -D
GROUP=100 <==默認的群組
HOME=/home <==默認的主文件夾所在目錄
INACTIVE=-1 <==密碼失效日,在 shadow 內的第 7 欄
EXPIRE= <==帳號失效日,在 shadow 內的第 8 欄
SHELL=/bin/bash <==默認的 shell
SKEL=/etc/skel <==使用者主文件夾的內容數據參考目錄
CREATE_MAIL_SPOOL=yes <==是否主動幫使用者創建郵件信箱(mailbox)
  • GROUP=100:新建帳號的初始群組使用 GID 為 100 者
    系統上面 GID 為 100 者即是 users 這個群組,此設置項目指的就是讓新設使用者帳號的初始群組為 users 這一個的意思。 但是我們知道 CentOS 上面並不是這樣的,在 CentOS 上面默認的群組為與帳號名相同的群組。 舉例來說, vbird1 的初始群組為 vbird1 。怎麼會這樣啊?這是因為針對群組的角度有兩種不同的機制所致, 這兩種機制分別是:
    • 私有群組機制:
      系統會創建一個與帳號一樣的群組給使用者作為初始群組。 這種群組的設置機制會比較有保密性,這是因為使用者都有自己的群組,而且主文件夾權限將會設置為 700 (僅有自己可進入自己的主文件夾) 之故。使用這種機制將不會參考 GROUP=100 這個設置值。代表性的 distributions 有 RHEL, Fedora, CentOS 等;
    • 公共群組機制:
      就是以 GROUP=100 這個設置值作為新建帳號的初始群組,因此每個帳號都屬於 users 這個群組, 且默認主文件夾通常的權限會是“ drwxr-xr-x … username users … ”,由於每個帳號都屬於 users 群組,因此大家都可以互相分享主文件夾內的數據之故。代表 distributions 如 SuSE等。
      由於我們的 CentOS 使用私有群組機制,因此這個設置項目是不會生效的!不要太緊張啊!
  • HOME=/home:使用者主文件夾的基準目錄(basedir)
    使用者的主文件夾通常是與帳號同名的目錄,這個目錄將會擺放在此設置值的目錄後。所以 vbird1 的主文件夾就會在 /home/vbird1/ 了!很容易理解吧!
  • INACTIVE=-1:密碼過期後是否會失效的設置值
    我們在 shadow 文件結構當中談過,第七個字段的設置值將會影響到密碼過期後, 在多久時間內還可使用舊密碼登陸。這個項目就是在指定該日數啦!如果是 0 代表密碼過期立刻失效, 如果是 -1 則是代表密碼永遠不會失效,如果是數字,如 30 ,則代表過期 30 天后才失效。
  • EXPIRE=:帳號失效的日期
    就是 shadow 內的第八字段,你可以直接設置帳號在哪個日期後就直接失效,而不理會密碼的問題。 通常不會設置此項目,但如果是付費的會員制系統,或許這個字段可以設置喔!
  • SHELL=/bin/bash:默認使用的 shell 程序文件名
    系統默認的 shell 就寫在這裡。假如你的系統為 mail server ,你希望每個帳號都只能使用 email 的收發信件功能, 而不許使用者登陸系統取得 shell ,那麼可以將這裡設置為 /sbin/nologin ,如此一來,新建的使用者默認就無法登陸! 也免去後續使用 usermod 進行修改的手續!
  • SKEL=/etc/skel:使用者主文件夾參考基準目錄
    這個咚咚就是指定使用者主文件夾的參考基準目錄囉~舉我們的範例一為例, vbird1 主文件夾 /home/vbird1 內的各項數據,都是由 /etc/skel 所複製過去的~所以呢,未來如果我想要讓新增使用者時,該使用者的環境變量 ~/.bashrc 就設置妥當的話,您可以到 /etc/skel/.bashrc 去編輯一下,也可以創建 /etc/skel/www 這個目錄,那麼未來新增使用者後,在他的主文件夾下就會有 www 那個目錄了!這樣瞭呼?
  • CREATE_MAIL_SPOOL=yes:創建使用者的 mailbox
    你可以使用“ ll /var/spool/mail/vbird1 ”看一下,會發現有這個文件的存在喔!這就是使用者的郵件信箱!



UID/GID 還有密碼參數

  • 路徑 /etc/login.defs
    MAIL_DIR /var/spool/mail <==使用者默認郵件信箱放置目錄
PASS_MAX_DAYS   99999    <==/etc/shadow 內的第 5 欄,多久需變更密碼日數
PASS_MIN_DAYS 0 <==/etc/shadow 內的第 4 欄,多久不可重新設置密碼日數
PASS_MIN_LEN 5 <==密碼最短的字符長度,已被 pam 模塊取代,失去效用!
PASS_WARN_AGE 7 <==/etc/shadow 內的第 6 欄,過期前會警告的日數

UID_MIN 1000 <==使用者最小的 UID,意即小於 1000 的 UID 為系統保留
UID_MAX 60000 <==使用者能夠用的最大 UID
SYS_UID_MIN 201 <==保留給使用者自行設置的系統帳號最小值 UID
SYS_UID_MAX 999 <==保留給使用者自行設置的系統帳號最大值 UID
GID_MIN 1000 <==使用者自訂群組的最小 GID,小於 1000 為系統保留
GID_MAX 60000 <==使用者自訂群組的最大 GID
SYS_GID_MIN 201 <==保留給使用者自行設置的系統帳號最小值 GID
SYS_GID_MAX 999 <==保留給使用者自行設置的系統帳號最大值 GID

CREATE_HOME yes <==在不加 -M 及 -m 時,是否主動創建使用者主文件夾?
UMASK 077 <==使用者主文件夾創建的 umask ,因此權限會是 700
USERGROUPS_ENAB yes <==使用 userdel 刪除時,是否會刪除初始群組
ENCRYPT_METHOD SHA512 <==密碼加密的機制使用的是 sha512 這一個機制!
  • mailbox 所在目錄:
    使用者的默認 mailbox 文件放置的目錄在 /var/spool/mail,所以 vbird1 的 mailbox 就是在 /var/spool/mail/vbird1 囉!

  • shadow 密碼第 4, 5, 6 字段內容:
    通過 PASS_MAX_DAYS 等等設置值來指定的!所以你知道為何默認的 /etc/shadow 內每一行都會有“ 0:99999:7 ”的存在了嗎?^_^!不過要注意的是,由於目前我們登陸時改用 PAM 模塊來進行密碼檢驗,所以那個 PASS_MIN_LEN 是失效的!

  • UID/GID 指定數值:
    雖然 Linux 核心支持的帳號可高達 232 這麼多個,不過一部主機要作出這麼多帳號在管理上也是很麻煩的! 所以在這裡就針對 UID/GID 的範圍進行規範就是了。上表中的 UID_MIN 指的就是可登陸系統的一般帳號的最小 UID ,至於 UID_MAX 則是最大 UID 之意。

要注意的是,系統給予一個帳號 UID 時,他是 (1)先參考 UID_MIN 設置值取得最小數值; (2)由 /etc/passwd 搜尋最大的 UID 數值, 將 (1) 與 (2) 相比,找出最大的那個再加一就是新帳號的 UID 了。我們上面已經作出 UID 為 1500 的 vbird2 , 如果再使用“ useradd vbird4 ”時,你猜 vbird4 的 UID 會是多少?答案是: 1501 。 所以中間的 1004~1499 的號碼就空下來啦!

而如果我是想要創建系統用的帳號,所以使用 useradd -r sysaccount 這個 -r 的選項時,就會找“比 201 大但比 1000 小的最大的 UID ”就是了。 ^_^

  • 使用者主文件夾設置值:
    為何我們系統默認會幫使用者創建主文件夾?就是這個“CREATE_HOME = yes”的設置值啦!這個設置值會讓你在使用 useradd 時, 主動加入“ -m ”這個產生主文件夾的選項啊!如果不想要創建使用者主文件夾,就只能強制加上“ -M ”的選項在 useradd 指令執行時啦!至於創建主文件夾的權限設置呢?就通過 umask 這個設置值啊!因為是 077 的默認設置,因此使用者主文件夾默認權限才會是“ drwx—— ”哩!

  • 使用者刪除與密碼設置值:
    使用“USERGROUPS_ENAB yes”這個設置值的功能是: 如果使用 userdel 去刪除一個帳號時,且該帳號所屬的初始群組已經沒有人隸屬於該群組了, 那麼就刪除掉該群組,舉例來說,我們剛剛有創建 vbird4 這個帳號,他會主動創建 vbird4 這個群組。 若 vbird4 這個群組並沒有其他帳號將他加入支持的情況下,若使用 userdel vbird4 時,該群組也會被刪除的意思。 至於“ENCRYPT_METHOD SHA512”則表示使用 SHA512 來加密密碼明文,而不使用舊式的 MD5。
    現在你知道啦,使用 useradd 這支程序在創建 Linux 上的帳號時,至少會參考:

/etc/default/useradd
/etc/login.defs
/etc/skel/*




usermod

usermod [-cdegGlsuLU] username
選項與參數:
-c :後面接帳號的說明,即 /etc/passwd 第五欄的說明欄,可以加入一些帳號的說明。
-d :後面接帳號的主文件夾,即修改 /etc/passwd 的第六欄;
-e :後面接日期,格式是 YYYY-MM-DD 也就是在 /etc/shadow 內的第八個字段數據啦!
-f :後面接天數,為 shadow 的第七字段。
-g :後面接初始群組,修改 /etc/passwd 的第四個字段,亦即是 GID 的字段!
-G :後面接次要群組,修改這個使用者能夠支持的群組,修改的是 /etc/group 囉~
-a :與 -G 合用,可“增加次要群組的支持”而非“設置”喔!
-l :後面接帳號名稱。亦即是修改帳號名稱, /etc/passwd 的第一欄!
-s :後面接 Shell 的實際文件,例如 /bin/bash 或 /bin/csh 等等。
-u :後面接 UID 數字啦!即 /etc/passwd 第三欄的數據;
-L :暫時將使用者的密碼凍結,讓他無法登陸。其實僅改 /etc/shadow 的密碼欄。
-U :將 /etc/shadow 密碼欄的 ! 拿掉,解凍啦!
  • 增加指定 user 的次要群組
    usermod -a -G groupName userName



chmod

  • 給予一個資料夾 SGID 屬性
    chmod 2777 folderName



passwd

passwd [--stdin] [帳號名稱]  <==所有人均可使用來改自己的密碼
[root@study ~]# passwd [-l] [-u] [--stdin] [-S] \
> [-n 日數] [-x 日數] [-w 日數] [-i 日期] 帳號 <==root 功能
選項與參數:
--stdin :可以通過來自前一個管線的數據,作為密碼輸入,對 shell script 有幫助!
-l :是 Lock 的意思,會將 /etc/shadow 第二欄最前面加上 ! 使密碼失效;
-u :與 -l 相對,是 Unlock 的意思!
-S :列出密碼相關參數,亦即 shadow 文件內的大部分信息。
-n :後面接天數,shadow 的第 4 字段,多久不可修改密碼天數
-x :後面接天數,shadow 的第 5 字段,多久內必須要更動密碼
-w :後面接天數,shadow 的第 6 字段,密碼過期前的警告天數
-i :後面接“日期”,shadow 的第 7 字段,密碼失效日期



確認 OS 種類以及版本

  • 使用 lsb_release , 如果沒安裝的話,安裝它

    sudo apt-get install lsb-release
  • 查詢用法

    lsb_release --help

    輸出如下:

    -h, --help         show this help message and exit
    -v, --version show LSB modules this system supports
    -i, --id show distributor ID
    -d, --description show description of this distribution
    -r, --release show release number of this distribution
    -c, --codename show code name of this distribution
    -a, --all show all of the above information
    -s, --short show requested information in short format
  • 根據上面的資訊,想查詢明細的話

    lsb_release -a



curl

語法

curl [options] [URL...]
-X 代表 request 的方式
-H 代表 header
-d 代表傳送資料,等同於以 `Content-Type: application/x-www-form-urlencoded` 方式傳送
-k 若經由 `https` 發請求,加上 -k 可避開 HTTPS 方式
-v 代表 `verbose` , 若要顯示回覆訊息,需加上 `-v`
-L 如果 server 端回報位置已轉址, curl 會對新的位址在發請求
-T 上傳檔案
-s slient 模式

範例

假設請求如下:

curl -X POST \
https://requestedURL \
-H 'Content-Type: application/json' \
-d '{"dataA":"content of data A","dataB":"content of data B"}' -k -v
  • -X 代表 request 的方式
  • ip 請由此查詢
  • -H 代表 header
  • -d 代表傳送資料,等同於以 Content-Type: application/x-www-form-urlencoded 方式傳送
  • -k 若經由 https 發請求,需加上 -k
  • -v 代表 verbose , 若要顯示回覆訊息,需加上 -v



bash 環境配置文件

bash 會根據有沒有登入來讀取相對應的環境配置文件

  • login shell
    • /etc/profile
      • /etc/profile.d/*.sh
        • 被調用的條件如下:
        • 在 /etc/profile.d/ 這個目錄內
        • 擴展名為 .sh
        • 使用者能夠具有 r 的權限
    • ~/.bash_profile or ~/.bash_login or ~/.profile (照順序讀,只會讀其中一個)
      • ~/.bashrc (最終會讀取這一個文件)
  • non-login shell
    • ~/.bashrc
      • etc/bashrc (會調用此文件)

流程圖


不小心刪除了 ~/.bashrc, 或是沒有這個文件,想創建怎麼辦?

  • 複製預設文件

    cp /etc/skel/.bashrc ~/
  • 視需求修改

  • 使立即生效

    source ~/.bashrc

or

. ~/.bashrc



Base 64 decode

base64 --decode /tmp/encoded.txt > /tmp/decoded.txt



ncftp

ncftpput -u account -p password -P port -m -R ipOrDomain remoteLocation locationFileOrDirectory
  • -u:指定登錄FTP服務器時使用的用戶名;
  • -p:指定登錄FTP服務器時使用的密碼;
  • -P:如果FTP服務器沒有使用默認的TCP協議的21端口,則使用此選項指定FTP服務器的端口號。
  • -m:在傳之前嘗試在目錄位置創建目錄(用於傳目錄的情況)
  • -R:遞規傳子目錄



ufw

  • 啟用防火牆服務

    ufw enable
  • 關閉防火牆服務

    ufw disable
  • 打開指定 port

    ufw allow port/tcp



install

  • 使用 install 指令,我們可以在創立一個 folder 或 file 的同時,指定 owner, group 以及 mode
    install -d -o <user> -g <group> -m <mode> <path>

    • -d : directory
    • -o : owner
    • -g : group
    • -m : mode
  • 建立一個資料夾,並給予權限

    install -d -o ray -g ray -m 2770 /tmp/ray
  • 建立一個檔案,並給予權限

    install -m 777 -o ray -g ray /dev/null filename.txt



yum

whatprovides

  • 找出有提供特定 command 的 package
    yum whatprovides */commandYouAreLookingFor

install

  • 安裝特定的 package
    yum insatll packageName



regular expression (regex) (正則表達式)

特殊符號表

特殊符號 代表意義
[:alnum:] 代表英文大小寫字符及數字,亦即 0-9, A-Z, a-z
[:alpha:] 代表任何英文大小寫字符,亦即 A-Z, a-z
[:blank:] 代表空白鍵與 [Tab] 按鍵兩者
[:cntrl:] 代表鍵盤上面的控制按鍵,亦即包括 CR, LF, Tab, Del.. 等等
[:digit:] 代表數字而已,亦即 0-9
[:graph:] 除了空白字符 (空白鍵與 [Tab] 按鍵) 外的其他所有按鍵
[:lower:] 代表小寫字符,亦即 a-z
[:print:] 代表任何可以被打印出來的字符
[:punct:] 代表標點符號 (punctuation symbol),亦即:” ‘ ? ! ; : # $…
[:upper:] 代表大寫字符,亦即 A-Z
[:space:] 任何會產生空白的字符,包括空白鍵, [Tab], CR 等等
[:xdigit:] 代表 16 進位的數字類型,因此包括: 0-9, A-F, a-f 的數字與字符

表達式彙整

字元 描述
\ 將下一個字元標記為一個特殊字元(File Format Escape,見本表)、或一個原義字元(Identity Escape,有 ^ $ ( ) * + ? . [ \ { | 共計12個)、或一個向後參照(backreferences)、或一個八進位跳脫符。例如,「n」匹配字元「n」。「\n」匹配一個換行符。序列「\」匹配「\」而「(」則匹配「(」。
^ 匹配輸入字串的開始位置。如果設定了RegExp物件的Multiline屬性,^也匹配「\n」或「\r」之後的位置。
$ 匹配輸入字串的結束位置。如果設定了RegExp物件的Multiline屬性,$也匹配「\n」或「\r」之前的位置。
* 匹配前面的子表達式零次或多次。例如,zo能匹配「z」、「zo」以及「zoo」。等價於{0,}。
+ 匹配前面的子表達式一次或多次。例如,「zo+」能匹配「zo」以及「zoo」,但不能匹配「z」。+等價於{1,}。
? 匹配前面的子表達式零次或一次。例如,「do(es)?」可以匹配「does」中的「do」和「does」。?等價於{0,1}。
{n} n是一個非負整數。匹配確定的n次。例如,「o{2}」不能匹配「Bob」中的「o」,但是能匹配「food」中的兩個o。
{n,} n是一個非負整數。至少匹配n次。例如,「o{2,}」不能匹配「Bob」中的「o」,但能匹配「foooood」中的所有o。「o{1,}」等價於「o+」。「o{0,}」則等價於「o*」。
{n,m} m和n均為非負整數,其中n<=m。最少匹配n次且最多匹配m次。例如,「o{1,3}」將匹配「fooooood」中的前三個o。「o{0,1}」等價於「o?」。請注意在逗號和兩個數之間不能有空格。
? 非貪心量化(Non-greedy quantifiers):當該字元緊跟在任何一個其他重複修飾詞(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的。非貪婪模式儘可能少的匹配所搜尋的字串,而預設的貪婪模式則儘可能多的匹配所搜尋的字串。例如,對於字串「oooo」,「o+?」將匹配單個「o」,而「o+」將匹配所有「o」。
. 匹配除「\r」「\n」之外的任何單個字元。要匹配包括「\r」「\n」在內的任何字元,請使用像「(.|\r|\n)」的模式。
(pattern) 匹配pattern並取得這一匹配的子字串。該子字串用於向後參照。所取得的匹配可以從產生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性。要匹配圓括號字元,請使用「(」或「)」。可帶數量字尾。
(?:pattern) 匹配pattern但不取得匹配的子字串(shy groups),也就是說這是一個非取得匹配,不儲存匹配的子字串用於向後參照。這在使用或字元「(|)」來組合一個模式的各個部分是很有用。例如「industr(?:y|ies)」就是一個比「industry|industries」更簡略的表達式。
(?=pattern) 正向肯定預查(look ahead positive assert),在任何匹配pattern的字串開始處匹配尋找字串。這是一個非取得匹配,也就是說,該匹配不需要取得供以後使用。例如,「Windows(?=95|98|NT|2000)」能匹配「Windows2000」中的「Windows」,但不能匹配「Windows3.1」中的「Windows」。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜尋,而不是從包含預查的字元之後開始。
(?!pattern) 正向否定預查(negative assert),在任何不匹配pattern的字串開始處匹配尋找字串。這是一個非取得匹配,也就是說,該匹配不需要取得供以後使用。例如「Windows(?!95|98|NT|2000)」能匹配「Windows3.1」中的「Windows」,但不能匹配「Windows2000」中的「Windows」。預查不消耗字元,也就是說,在一個匹配發生後,在最後一次匹配之後立即開始下一次匹配的搜尋,而不是從包含預查的字元之後開始
(?<=pattern) 反向(look behind)肯定預查,與正向肯定預查類似,只是方向相反。例如,「(?<=95|98 | NT|2000)Windows」能匹配「2000Windows」中的「Windows」,但不能匹配「3.1Windows」中的「Windows」。
(?<!pattern) 反向否定預查,與正向否定預查類似,只是方向相反。例如「(?<!95 |98|NT|2000)Windows」能匹配「3.1Windows」中的「Windows」,但不能匹配「2000Windows」中的「Windows」。x|y 沒有包圍在()里,其範圍是整個正規表示式。例如,「z|food」能匹配「z」或「food」。「(?:z|f)ood」則匹配「zood」或「food」。
[xyz] 字元集合(character class)。匹配所包含的任意一個字元。例如,「[abc]」可以匹配「plain」中的「a」。特殊字元僅有反斜線\保持特殊含義,用於跳脫字元。其它特殊字元如星號、加號、各種括號等均作為普通字元。脫字元^如果出現在首位則表示負值字元集合;如果出現在字串中間就僅作為普通字元。連字元 - 如果出現在字串中間表示字元範圍描述;如果如果出現在首位(或末尾)則僅作為普通字元。右方括號應跳脫出現,也可以作為首位字元出現。
[^xyz] 排除型字元集合(negated character classes)。匹配未列出的任意字元。例如,「[^abc]」可以匹配「plain」中的「plin」。
[a-z] 字元範圍。匹配指定範圍內的任意字元。例如,「[a-z]」可以匹配「a」到「z」範圍內的任意小寫字母字元。
[^a-z] 排除型的字元範圍。匹配任何不在指定範圍內的任意字元。例如,「[^a-z]」可以匹配任何不在「a」到「z」範圍內的任意字元。
[:name:] 增加命名字元類(named character class)[註 1]中的字元到表達式。只能用於方括號表達式。
[=elt=] 增加目前locale下排序(collate)等價於字元「elt」的元素。例如,[=a=]可能會增加ä、á、à、ă、ắ、ằ、ẵ、ẳ、â、ấ、ầ、ẫ、ẩ、ǎ、å、ǻ、ä、ǟ、ã、ȧ、ǡ、ą、ā、ả、ȁ、ȃ、ạ、ặ、ậ、ḁ、ⱥ、ᶏ、ɐ、ɑ 。只能用於方括號表達式。
[.elt.] 增加排序元素(collation element)elt到表達式中。這是因為某些排序元素由多個字元組成。例如,29個字母表的西班牙語, “CH”作為單個字母排在字母C之後,因此會產生如此排序「cinco, credo, chispa」。只能用於方括號表達式。
\b 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如,「er\b」可以匹配「never」中的「er」,但不能匹配「verb」中的「er」。
\B 匹配非單詞邊界。「er\B」能匹配「verb」中的「er」,但不能匹配「never」中的「er」。
\cx 匹配由x指明的控制字元。x的值必須為A-Z或a-z之一。否則,將c視為一個原義的「c」字元。控制字元的值等於x的值最低5位元(即對3210進位的餘數)。例如,\cM匹配一個Control-M或回車字元。\ca等效於\u0001, \cb等效於\u0| 002, 等等…
\d 匹配一個數字字元。等價於[0-9]。注意Unicode正規表示式會匹配全形數字字元。
\D 匹配一個非數字字元。等價於[^0-9]。
\f 匹配一個換頁符。等價於\x0c和\cL。
\n 匹配一個換行符。等價於\x0a和\cJ。
\r 匹配一個回車字元。等價於\x0d和\cM。
\s 匹配任何空白字元,包括空格、制表符、換頁符等等。等價於[ \f\n\r\t\v]。注意Unicode正規表示式會匹配全形空格符。
\S 匹配任何非空白字元。等價於[^ \f\n\r\t\v]。
\t 匹配一個制表符。等價於\x09和\cI。
\v 匹配一個垂直制表符。等價於\x0b和\cK。
\w 匹配包括底線的任何單詞字元。等價於「[A-Za-z0-9_]」。注意Unicode正規表示式會匹配中文字元。
\W 匹配任何非單詞字元。等價於「[^A-Za-z0-9_]」。
\xnn 十六進位跳脫字元序列。匹配兩個十六進位數字nn表示的字元。例如,「\x41」匹配「A」。「\x041」則等價於「\x04&1」。正規表達式中可以使用ASCII編碼。.
\num 向後參照(back-reference)一個子字串(substring),該子字串與正規表示式的第num個用括號圍起來的捕捉群(capture group)子表達式(subexpression)匹配。其中num是從1開始的十進位正整數,其上限可能是9[註 2]、31[註 3]、99甚至無限[註 4]。例如:「(.)\1」匹配兩個連續的相同字元。
\n 標識一個八進位跳脫值或一個向後參照。如果\n之前至少n個取得的子表達式,則n為向後參照。否則,如果n為八進位數字(0-7),則n為一個八進位跳脫值。
\nm 3位八進位數字,標識一個八進位跳脫值或一個向後參照。如果\nm之前至少有nm個獲得子表達式,則nm為向後參照。如果\nm之前至少有n個取得,則n為一個後跟文字m的向後參照。如果前面的條件都不滿足,若n和m均為八進位數字(0-7),則\nm將匹配八進位跳脫值nm。
\nml 如果n為八進位數字(0-3),且m和l均為八進位數字(0-7),則匹配八進位跳脫值nml。
\un Unicode跳脫字元序列。其中n是一個用四個十六進位數字表示的Unicode字元。例如,\u00A9匹配著作權符號(©)。

基礎正規表達式字符彙整

RE 字符 意義與範例
^word 意義:待搜尋的字串(word)在行首!
範例:搜尋行首為 # 開始的那一行,並列出行號
grep -n '^#' regular_express.txt
word$ 意義:待搜尋的字串(word)在行尾!
範例:將行尾為 ! 的那一行打印出來,並列出行號
grep -n '!$' regular_express.txt
. 意義:代表“一定有一個任意字符”的字符!
範例:搜尋的字串可以是 (eve) (eae) (eee) (e e), 但不能僅有 (ee) !亦即 e 與 e 中間“一定”僅有一個字符,而空白字符也是字符!
grep -n 'e.e' regular_express.txt
\ 意義:跳脫字符,將特殊符號的特殊意義去除!
範例:搜尋含有單引號 ‘ 的那一行!
grep -n \' regular_express.txt
* 意義:重複零個到無窮多個的前一個 RE 字符
範例:找出含有 (es) (ess) (esss) 等等的字串,注意,因為 * 可以是 0 個,所以 es 也是符合帶搜尋字串。另外,因為 * 為重複“前一個 RE 字符”的符號, 因此,在 * 之前必須要緊接著一個 RE 字符喔!例如任意字符則為 “.*” !
grep -n 'ess*' regular_express.txt
[list] 意義:字符集合的 RE 字符,裡面列出想要擷取的字符!
範例:搜尋含有 (gl) 或 (gd) 的那一行,需要特別留意的是,在 [] 當中“謹代表一個待搜尋的字符”, 例如“ a[afl]y ”代表搜尋的字串可以是 aay, afy, aly 即 [afl] 代表 a 或 f 或 l 的意思!
grep -n 'g[ld]' regular_express.txt
[n1-n2] 意義:字符集合的 RE 字符,裡面列出想要擷取的字符範圍!
範例:搜尋含有任意數字的那一行!需特別留意,在字符集合 [] 中的減號 - 是有特殊意義的,他代表兩個字符之間的所有連續字符!但這個連續與否與 ASCII 編碼有關,因此,你的編碼需要設置正確(在 bash 當中,需要確定 LANG 與 LANGUAGE 的變量是否正確!) 例如所有大寫字符則為 [A-Z]
grep -n '[A-Z]' regular_express.txt
[^list] 意義:字符集合的 RE 字符,裡面列出不要的字串或範圍!
範例:搜尋的字串可以是 (oog) (ood) 但不能是 (oot) ,那個 ^ 在 [] 內時,代表的意義是“反向選擇”的意思。 例如,我不要大寫字符,則為 [^A-Z]。但是,需要特別注意的是,如果以 grep -n [^A-Z] regular_express.txt 來搜尋,卻發現該文件內的所有行都被列出,為什麼?因為這個 [^A-Z] 是“非大寫字符”的意思, 因為每一行均有非大寫字符,例如第一行的 “Open Source” 就有 p,e,n,o…. 等等的小寫字
grep -n 'oo[^t]' regular_express.txt
{n,m} 意義:連續 n 到 m 個的“前一個 RE 字符”
意義:若為 {n} 則是連續 n 個的前一個 RE 字符,
意義:若是 {n,} 則是連續 n 個以上的前一個 RE 字符! 範例:在 g 與 g 之間有 2 個到 3 個的 o 存在的字串,亦即 (goog)(gooog)
grep -n 'go\{2,3\}g' regular_express.txt

範例

驗證密碼

條件如下:

  1. 8~16字元
  2. 至少一個數字
  3. 至少一個小寫英文字母 或 大寫英文字母
  4. 至少要有一個特殊符號, 特殊符號限制在 @$%^& 這些當中, 不然可能會出現 ∆©ƒ 這種符號, 使用者想像力無限

正則如下:

^(?=.*[a-z]|.*[A-Z])(?=.*[\d])(?=.*[\W])[\w@$%\^&]{8,16}$
  1. 第一個規則為 lookahead, 目標搜尋至少一個大寫字母或小寫字母, 因為前面加了 .*, 所以就算 lookahead 的前面是空的也沒關係, 從起始處開始往後搜尋, 需符合第一個 lookahead ?= 之後的規則, 若沒找到則停止, 找到則繼續下一個規則
  2. 開始第二個 lookahead 規則, 目標尋找至少一個數字, 第一個規則通過後, 才會開始第二個規則。 第二個規則從起始處開始搜尋, 若無找到則停止, 有找到則繼續
  3. 第三個 lookahead 規則, 目標尋找至少一個特殊字符, 行為同上
  4. 三個規則都通過後, 驗證最後一個規則, 字串可以是大小寫以及有列出的特殊符號, 數量為 8~16 個字元



crontab

安裝

  • CentOS
    yum install cronie

代表意義

代表意義 分鐘 小時 日期 月份 指令
數字範圍 0-59 0-23 1-31 1-1 0-7 呀就指令啊

比較有趣的是那個“周”喔!周的數字為 0 或 7 時,都代表“星期天”的意思!另外,還有一些輔助的字符,大概有下面這些:

特殊字符 代表意義
*(星號) 代表任何時刻都接受的意思!舉例來說,範例一內那個日、月、周都是 * , 就代表著“不論何月、何日的禮拜幾的 12:00 都執行後續指令”的意思!
,(逗號) 代表分隔時段的意思。舉例來說,如果要下達的工作是 3:00 與 6:00 時,就會是:
0 3,6 * * * command
時間參數還是有五欄,不過第二欄是 3,6 ,代表 3 與 6 都適用!
-(減號) 代表一段時間範圍內,舉例來說, 8 點到 12 點之間的每小時的 20 分都進行一項工作:
20 8-12 * * * command
仔細看到第二欄變成 8-12 喔!代表 8,9,10,11,12 都適用的意思!
/n(斜線) 那個 n 代表數字,亦即是“每隔 n 單位間隔”的意思,例如每五分鐘進行一次,則:
*/5 * * * * command
很簡單吧!用 * 與 /5 來搭配,也可以寫成 0-59/5 ,相同意思!

/etc/crontab

[root@study ~]# cat /etc/crontab
SHELL=/bin/bash <==使用哪種 shell 接口
PATH=/sbin:/bin:/usr/sbin:/usr/bin <==可執行文件搜尋路徑
MAILTO=root <==若有額外STDOUT,以 email將數據送給誰

# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
  • MAILTO=root:

    • 當 /etc/crontab 這個文件中的例行性工作的指令發生錯誤時,或者是該工作的執行結果有 STDOUT/STDERR 時,會將錯誤訊息或者是屏幕顯示的訊息送的對象
    • 默認是由系統直接寄發一封 mail 給 root
    • 例如:MAILTO=dmtsai@my.host.name
  • PATH=….:
    輸入可執行文件的搜尋路徑,使用默認的路徑設置就已經很足夠了!

  • “分 時 日 月 周 身份 指令”七個字段的設置

    • 這個 /etc/crontab 可以設置的基本語法與 crontab -e 不太相同
    • 前面同樣是分、時、日、月、週五個字段, 但是在五個字段後面接的並不是指令,就是“執行後面那串指令的身份”
    • 這與使用者的 crontab -e 不相同。由於使用者自己的 crontab 並不需要指定身份

crond 服務讀取配置文件

/etc/crontab
/etc/cron.d/*
/var/spool/cron/*
  • 跟系統的運行比較有關係的兩個配置文件是放在 /etc/crontab 文件內以及 /etc/cron.d/* 目錄內的文件
  • 跟用戶自己的工作比較有關的配置文件放在 /var/spool/cron/

其他

  • 輸入 crontab job

    crontab -e
  • 確認 crontab 狀態

    /etc/init.d/cron status
  • 停止 crontab

    /etc/init.d/cron stop
  • 啟動 crontab

    /etc/init.d/cron start

anacron

語法

[root@study ~]# anacron [-sfn] [job]..
[root@study ~]# anacron -u [job]..
選項與參數:
-s :開始一連續的執行各項工作 (job),會依據時間記錄文件的數據判斷是否進行;
-f :強制進行,而不去判斷時間記錄文件的時間戳記;
-n :立刻進行未進行的任務,而不延遲 (delay) 等待時間;
-u :僅更新時間記錄文件的時間戳記,不進行任何工作。
job :由 /etc/anacrontab 定義的各項工作名稱。

配置檔

[root@study ~]# cat /etc/anacrontab
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
RANDOM_DELAY=45 # 隨機給予最大延遲時間,單位是分鐘
START_HOURS_RANGE=3-22 # 延遲多少個小時內應該要執行的任務時間

1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
天數 延遲時間 工作名稱定義 實際要進行的指令串
# 天數單位為天;延遲時間單位為分鐘;工作名稱定義可自訂,指令串則通常與 crontab 的設置相同!

[root@study ~]# more /var/spool/anacron/*
::::::::::::::
/var/spool/anacron/cron.daily
::::::::::::::
20150731
::::::::::::::
/var/spool/anacron/cron.monthly
::::::::::::::
20150703
::::::::::::::
/var/spool/anacron/cron.weekly
::::::::::::::
20150727
# 上面則是三個工作名稱的時間記錄文件以及記錄的時間戳記

拿 /etc/cron.daily/ 那一行的設置來說明,那四個字段的意義分別是:

  • 天數:anacron 執行當下與時間戳記 (/var/spool/anacron/ 內的時間紀錄檔) 相差的天數,若超過此天數,就準備開始執行,若沒有超過此天數,則不予執行後續的指令。
  • 延遲時間:若確定超過天數導致要執行調度工作了,那麼請延遲執行的時間,因為擔心立即啟動會有其他資源衝突的問題吧!
  • 工作名稱定義:這個沒啥意義,就只是會在 /var/log/cron 裡頭記載該項任務的名稱這樣!通常與後續的目錄資源名稱相同即可。
  • 實際要進行的指令串:有沒有跟 0hourly 很像啊!沒錯!相同的作法啊!通過 run-parts 來處理的!

anacron 的執行流程(以 cron.daily 為例)

  1. 由 /etc/anacrontab 分析到 cron.daily 這項工作名稱的天數為 1 天;
  2. 由 /var/spool/anacron/cron.daily 取出最近一次執行 anacron 的時間戳記;
  3. 由上個步驟與目前的時間比較,若差異天數為 1 天以上 (含 1 天),就準備進行指令;
  4. 若準備進行指令,根據 /etc/anacrontab 的設置,將延遲 5 分鐘 + 3 小時 (看 START_HOURS_RANGE 的設置);
  5. 延遲時間過後,開始執行後續指令,亦即“ run-parts /etc/cron.daily ”這串指令;
    執行完畢後, anacron 程序結束。

如此一來,放置在 /etc/cron.daily/ 內的任務就會在一天後一定會被執行的!

因為 anacron 是每個小時被執行一次嘛! 所以如果隔了一陣子將 CentOS 開機,開機過後約 1 小時左右系統會有一小段時間的忙碌!硬盤會跑個不停!那就是因為 anacron 正在執行過去 /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/ 裡頭的未進行的各項工作調度


cron 與 anacron 與目錄之間的關係

  • crond 會主動去讀取 /etc/crontab, /var/spool/cron/, /etc/cron.d/ 等配置文件,並依據“分、時、日、月、周”的時間設置去各項工作調度;
  • 根據 /etc/cron.d/0hourly 的設置,主動去 /etc/cron.hourly/ 目錄下,執行所有在該目錄下的可執行文件;
  • 因為 /etc/cron.hourly/0anacron 這個指令檔的緣故,主動的每小時執行 anacron ,並調用 /etc/anacrontab 的配置文件;
  • 根據 /etc/anacrontab 的設置,依據每天、每週、每月去分析 /etc/cron.daily/, /etc/cron.weekly/, /etc/cron.monthly/ 內的可執行文件,以進行固定週期需要執行的指令。
  • 如果你每個週日的需要執行的動作是放置於 /etc/crontab 的話,那麼該動作只要過期了就過期了,並不會被抓回來重新執行。
  • 如果是放置在 /etc/cron.weekly/ 目錄下,那麼該工作就會定期,幾乎一定會在一週內執行一次



test

測試的標誌|代表意義
——–|
|1. 關於某個文件名的“文件類型”判斷,如 test -e filename 表示存在否
-e|該“文件名”是否存在?(常用)
-f|該“文件名”是否存在且為文件(file)?(常用)
-d|該“文件名”是否存在且為目錄(directory)?(常用)
-b|該“文件名”是否存在且為一個 block device 設備?
-c|該“文件名”是否存在且為一個 character device 設備?
-S|該“文件名”是否存在且為一個 Socket 文件?
-p|該“文件名”是否存在且為一個 FIFO (pipe) 文件?
-L|該“文件名”是否存在且為一個鏈接文件?
|2. 關於文件的權限偵測,如 test -r filename 表示可讀否 (但 root 權限常有例外)
-r|偵測該文件名是否存在且具有“可讀”的權限?
-w|偵測該文件名是否存在且具有“可寫”的權限?
-x|偵測該文件名是否存在且具有“可執行”的權限?
-u|偵測該文件名是否存在且具有“SUID”的屬性?
-g|偵測該文件名是否存在且具有“SGID”的屬性?
-k|偵測該文件名是否存在且具有“Sticky bit”的屬性?
-s|偵測該文件名是否存在且為“非空白文件”?
|3. 兩個文件之間的比較,如: test file1 -nt file2
-nt|(newer than)判斷 file1 是否比 file2 新
-ot|(older than)判斷 file1 是否比 file2 舊
-ef|判斷 file1 與 file2 是否為同一文件,可用在判斷 hard link 的判定上。 主要意義在判定,兩個文件是否均指向同一個 inode 哩!
|4. 關於兩個整數之間的判定,例如 test n1 -eq n2
-eq|兩數值相等 (equal)
-ne|兩數值不等 (not equal)
-gt|n1 大於 n2 (greater than)
-lt|n1 小於 n2 (less than)
-ge|n1 大於等於 n2 (greater than or equal)
-le|n1 小於等於 n2 (less than or equal)
|5. 判定字串的數據
test -z|string 判定字串是否為 0 ?若 string 為空字串,則為 true
test -n|string 判定字串是否非為 0 ?若 string 為空字串,則為 false。 -n 亦可省略
test str1 == str2|判定 str1 是否等於 str2 ,若相等,則回傳 true
test str1 != str2|判定 str1 是否不等於 str2 ,若相等,則回傳 false
|6. 多重條件判定,例如: test -r filename -a -x filename
-a|(and)兩狀況同時成立!例如 test -r file -a -x file,則 file 同時具有 r 與 x 權限時,才回傳 true。
-o|(or)兩狀況任何一個成立!例如 test -r file -o -x file,則 file 具有 r 或 x 權限時,就可回傳 true。
!|反相狀態,如 test ! -x file ,當 file 不具有 x 時,回傳 true




變量

變量的設置

變量設置方式 str 沒有設置 str 為空字串 str 已設置非為空字串
var=${str-expr} var=expr var= var=$str
var=${str:-expr} var=expr var=expr var=$str
var=${str+expr} var= var=expr var=expr
var=${str:+expr} var= var= var=expr
var=${str=expr} str=expr
var=expr
var=expr
var=
str 不變
var=$str
var=${str:=expr} str=expr
var=expr
str=expr
var=expr
str 不變
var=$str
var=${str?expr} expr 輸出至 stderr var= var=$str
var=${str:?expr} expr 輸出至 stderr expr 輸出至 stderr var=$str

Script 變量帶入規則:

script 名稱,如 /path/to/scriptname | opt1 | opt2 | opt3 | opt4
—— | —— | —— | —— |
$0 | $1 | $2 | $3 | $4


可以在 script 裡面使用的特殊變量

$# :代表後接的參數“個數”,以上表為例這裡顯示為“ 4 ”;
$@ :代表“ “$1” “$2” “$3” “$4” ”之意,每個變量是獨立的(用雙引號括起來);
$* :代表“ “$1c$2c$3c$4” ”,其中 c 為分隔字符,默認為空白鍵, 所以本例中代表“ “$1 $2 $3 $4” ”之意。




條件判斷

單一判斷式

if [ 條件判斷式 ]; then
當條件判斷式成立時,可以進行的指令工作內容;
fi <==將 if 反過來寫,就成為 fi 啦!結束 if 之意!
  • 以下 test 的方式可改編成條件判斷式

test 方式

read -p "Please input (Y/N): " yn
[ "${yn}" == "Y" -o "${yn}" == "y" ] && echo "OK, continue" && exit 0
[ "${yn}" == "N" -o "${yn}" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don't know what your choice is" && exit 0

條件判斷式

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N): " yn

if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
echo "OK, continue"
exit 0
fi
if [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
echo "Oh, interrupt!"
exit 0
fi
echo "I don't know what your choice is" && exit 0

多重、複雜條件判斷式

一個條件判斷,分成功進行與失敗進行 (else)

if [ 條件判斷式 ]; then
當條件判斷式成立時,可以進行的指令工作內容;
else
當條件判斷式不成立時,可以進行的指令工作內容;
fi

多個條件判斷 (if … elif … elif … else) 分多種不同情況執行

if [ 條件判斷式一 ]; then
當條件判斷式一成立時,可以進行的指令工作內容;
elif [ 條件判斷式二 ]; then
當條件判斷式二成立時,可以進行的指令工作內容;
else
當條件判斷式一與二均不成立時,可以進行的指令工作內容;
fi
  • 將以下的 test 方式改成條件判斷式

改前:

read -p "Please input (Y/N): " yn
[ "${yn}" == "Y" -o "${yn}" == "y" ] && echo "OK, continue" && exit 0
[ "${yn}" == "N" -o "${yn}" == "n" ] && echo "Oh, interrupt!" && exit 0
echo "I don't know what your choice is" && exit 0

改後:

#!/bin/bash
# Program:
# This program shows the user's choice
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input (Y/N): " yn

if [ "${yn}" == "Y" ] || [ "${yn}" == "y" ]; then
echo "OK, continue"
elif [ "${yn}" == "N" ] || [ "${yn}" == "n" ]; then
echo "Oh, interrupt!"
else
echo "I don't know what your choice is"
fi

利用 case ….. esac 判斷

  • 語法:
case  $變量名稱 in   <==關鍵字為 case ,還有變量前有錢字號
"第一個變量內容") <==每個變量內容建議用雙引號括起來,關鍵字則為小括號 )
程序段
;; <==每個類別結尾使用兩個連續的分號來處理!
"第二個變量內容")
程序段
;;
*) <==最後一個變量內容都會用 * 來代表所有其他值
不包含第一個變量內容與第二個變量內容的其他程序執行段
exit 1
;;
esac <==最終的 case 結尾!“反過來寫”思考一下!
  • 範例:
#!/bin/bash
# Program:
# Show "Hello" from $1.... by using case .... esac
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

case ${1} in
"hello")
echo "Hello, how are you ?"
;;
"")
echo "You MUST input parameters, ex> {${0} someword}"
;;
*) # 其實就相當於萬用字符,0~無窮多個任意字符之意!
echo "Usage ${0} {hello}"
;;
esac

練習題

使用判斷式寫一個 script, 要可以做到以下幾件事:

  • 先讓使用者輸入他們的退伍日期;
  • 驗證輸入格式;
  • 由兩個日期的比較來顯示“還需要幾天”才能夠退伍的字樣。

解答如下:

#!/bin/bash
# Program:
# You input your demobilization date, I calculate how many days before you demobilize.
# History:
# 2015/07/16 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

# 1. 告知使用者這支程序的用途,並且告知應該如何輸入日期格式?
echo "This program will try to calculate :"
echo "How many days before your demobilization date..."
read -p "Please input your demobilization date (YYYYMMDD ex>20150716): " date2

# 2. 測試一下,這個輸入的內容是否正確?利用正則表達式囉~
date_d=$(echo ${date2} |grep '[0-9]\{8\}') # 看看是否有八個數字
if [ "${date_d}" == "" ]; then
echo "You input the wrong date format...."
exit 1
fi

# 3. 開始計算日期囉~
declare -i date_dem=$(date --date="${date2}" +%s) # 退伍日期秒數
declare -i date_now=$(date +%s) # 現在日期秒數
declare -i date_total_s=$((${date_dem}-${date_now})) # 剩餘秒數統計
declare -i date_d=$((${date_total_s}/60/60/24)) # 轉為日數
if [ "${date_total_s}" -lt "0" ]; then # 判斷是否已退伍
echo "You had been demobilization before: " $((-1*${date_d})) " ago"
else
declare -i date_h=$(($((${date_total_s}-${date_d}*60*60*24))/60/60))
echo "You will demobilize after ${date_d} days and ${date_h} hours."
fi



netstat

這個指令可以看到目前有哪些 port 是對外開放的, 有哪些是 Listen 的

語法

netstat -[atunlp]
選項與參數:
-a :將目前系統上所有的連線、監聽、Socket 數據都列出來
-t :列出 tcp 網絡封包的數據
-u :列出 udp 網絡封包的數據
-n :不以程序的服務名稱,以埠號 (port number) 來顯示;
-l :列出目前正在網絡監聽 (listen) 的服務;
-p :列出該網絡服務的程序 PID

範例

列出目前的路由表狀態,且以 IP 及 port number 顯示:

[root@www ~]# netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0
0.0.0.0 192.168.1.254 0.0.0.0 UG 0 0 0 eth0
# 其實這個參數就跟 route -n 一模一樣,對吧!這不是 netstat 的主要功能啦!

列出目前的所有網路連線狀態,使用 IP 與 port number

[root@www ~]# netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
....(中間省略)....
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp 0 52 192.168.1.100:22 192.168.1.101:1937 ESTABLISHED
tcp 0 0 :::22 :::* LISTEN
....(中間省略)....
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 11075 @/var/run/hald/dbus-uukdg1qMPh
unix 2 [ ACC ] STREAM LISTENING 10952 /var/run/dbus/system_bus_socket
unix 2 [ ACC ] STREAM LISTENING 11032 /var/run/acpid.socket
....(底下省略)....



function

語法:

function fname() {
程序段

注意:

  • 因為 shell script 的執行方式是由上而下,由左而右, 因此在 shell script 當中的 function 的設置一定要在程序的最前面
  • function 內也可置變量,但跟 shell script 的內置變量方式不同

範例:

  • 一般
#!/bin/bash
# Program:
# Use function to repeat information.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

function printit(){
echo -n "Your choice is " # 加上 -n 可以不斷行繼續在同一行顯示
}

echo "This program will print your selection !"
case ${1} in
"one")
printit; echo ${1} | tr 'a-z' 'A-Z' # 將參數做大小寫轉換!
;;
"two")
printit; echo ${1} | tr 'a-z' 'A-Z'
;;
"three")
printit; echo ${1} | tr 'a-z' 'A-Z'
;;
*)
echo "Usage ${0} {one|two|three}"
;;
esac
  • 內置變量
    #!/bin/bash
    # Program:
    # Use function to repeat information.
    # History:
    # 2015/07/17 VBird First release
    PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
    export PATH

    function printit(){
    echo "Your choice is ${1}" # 這個 $1 必須要參考下面指令的下達
    }

    echo "This program will print your selection !"
    case ${1} in
    "one")
    printit 1 # 請注意, printit 指令後面還有接參數!
    ;;
    "two")
    printit 2
    ;;
    "three")
    printit 3
    ;;
    *)
    echo "Usage ${0} {one|two|three}"
    ;;
    esac



loop

while do done, until do done (不定循環)

while do done

語法
while [ condition ]  <==中括號內的狀態就是判斷式
do <==do 是循環的開始!
程序段落
done <==done 是循環的結束

範例
#!/bin/bash
# Program:
# Repeat question until user input correct answer.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

while [ "${yn}" != "yes" -a "${yn}" != "YES" ]
do
read -p "Please input yes/YES to stop this program: " yn
done
echo "OK! you input the correct answer."
#!/bin/bash
# Program:
# Use loop to calculate "1+2+3+...+100" result.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

s=0 # 這是加總的數值變量
i=0 # 這是累計的數值,亦即是 1, 2, 3....
while [ "${i}" != "100" ]
do
i=$(($i+1)) # 每次 i 都會增加 1
s=$(($s+$i)) # 每次都會加總一次!
done
echo "The result of '1+2+3+...+100' is ==> $s"

until do done

語法
until [ condition ]
do
程序段落
done

範例
#!/bin/bash
# Program:
# Repeat question until user input correct answer.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

until [ "${yn}" == "yes" -o "${yn}" == "YES" ]
do
read -p "Please input yes/YES to stop this program: " yn
done
echo "OK! you input the correct answer."

for…do…done (固定循環)

語法

for var in con1 con2 con3 ...
do
程序段
done

範例

  • 假設我有三種動物,分別是 dog, cat, elephant 三種, 我想每一行都輸出這樣:“There are dogs…”之類的字樣,則可以:
#!/bin/bash
# Program:
# Using for .... loop to print 3 animals
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

for animal in dog cat elephant
do
echo "There are ${animal}s.... "
done
  • 系統上面的各種帳號都是寫在 /etc/passwd 內的第一個字段,所以請通過管線命令的 cut 捉出單純的帳號名稱後,以 id 分別檢查使用者的識別碼與特殊參數
#!/bin/bash
# Program
# Use id, finger command to check system account's information.
# History
# 2015/07/17 VBird first release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
users=$(cut -d ':' -f1 /etc/passwd) # 擷取帳號名稱
for username in ${users} # 開始循環進行!
do
id ${username}
done
  • 讓使用者輸入某個目錄文件名, 然後我找出某目錄內的文件名的權限
#!/bin/bash
# Program:
# User input dir name, I find the permission of files.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

# 1. 先看看這個目錄是否存在啊?
read -p "Please input a directory: " dir
if [ "${dir}" == "" -o ! -d "${dir}" ]; then
echo "The ${dir} is NOT exist in your system."
exit 1
fi

# 2. 開始測試文件囉~
filelist=$(ls ${dir}) # 列出所有在該目錄下的文件名稱
for filename in ${filelist}
do
perm=""
test -r "${dir}/${filename}" && perm="${perm} readable"
test -w "${dir}/${filename}" && perm="${perm} writable"
test -x "${dir}/${filename}" && perm="${perm} executable"
echo "The file ${dir}/${filename}'s permission is ${perm} "
done

for…do…done 的數值處理

語法

- 初始值:某個變量在循環當中的起始值,直接以類似 i=1 設置好;
- 限制值:當變量的值在這個限制值的範圍內,就繼續進行循環。例如 i<=100;
- 執行步階:每作一次循環時,變量的變化量。例如 i=i+1。
for (( 初始值; 限制值; 執行步階 ))
do
程序段
done
  • 範例
#!/bin/bash
# Program:
# Try do calculate 1+2+....+${your_input}
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

read -p "Please input a number, I will count for 1+2+...+your_input: " nu

s=0
for (( i=1; i<=${nu}; i=i+1 ))
do
s=$((${s}+${i}))
done
echo "The result of '1+2+3+...+${nu}' is ==> ${s}"

搭配亂數與陣列的實驗

範例

#!/bin/bash
# Program:
# Try do tell you what you may eat.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

eat[1]="賣噹噹漢堡包"
eat[2]="肯爺爺炸雞"
eat[3]="彩虹日式便當"
eat[4]="越油越好吃大雅"
eat[5]="想不出吃啥學餐"
eat[6]="太師父便當"
eat[7]="池上便當"
eat[8]="懷念火車便當"
eat[9]="一起吃方便麵"
eatnum=9

eated=0
while [ "${eated}" -lt 3 ]; do
check=$(( ${RANDOM} * ${eatnum} / 32767 + 1 ))
mycheck=0
if [ "${eated}" -ge 1 ]; then
for i in $(seq 1 ${eated} )
do
if [ ${eatedcon[$i]} == $check ]; then
mycheck=1
fi
done
fi
if [ ${mycheck} == 0 ]; then
echo "your may eat ${eat[${check}]}"
eated=$(( ${eated} + 1 ))
eatedcon[${eated}]=${check}
fi
done
#!/bin/bash
# Program:
# Try do tell you what you may eat.
# History:
# 2015/07/17 VBird First release
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH

eat[1]="賣噹噹漢堡包" # 寫下你所收集到的店家!
eat[2]="肯爺爺炸雞"
eat[3]="彩虹日式便當"
eat[4]="越油越好吃大雅"
eat[5]="想不出吃啥學餐"
eat[6]="太師父便當"
eat[7]="池上便當"
eat[8]="懷念火車便當"
eat[9]="一起吃方便麵"
eatnum=9 # 需要輸入有幾個可用的餐廳數!

check=$(( ${RANDOM} * ${eatnum} / 32767 + 1 ))
echo "your may eat ${eat[${check}]}"

loop array

for i in "${array[@]}"



shell script 的追蹤與 debug

語法

sh [-nvx] scripts.sh
選項與參數:
-n :不要執行 script,僅查詢語法的問題;
-v :再執行 sccript 前,先將 scripts 的內容輸出到屏幕上;
-x :將使用到的 script 內容顯示到屏幕上,這是很有用的參數!

範例

  • 測試 dir_perm.sh 有無語法的問題?
sh -n dir_perm.sh
  • 將 show_animal.sh 的執行過程全部列出來~
sh -x show_animal.sh



練習題

  1. 請創建一支 script ,當你執行該 script 的時候,該 script 可以顯示: 1. 你目前的身份 (用 whoami ) 2. 你目前所在的目錄 (用 pwd)
#!/bin/bash
echo -e "Your name is ==> $(whoami)"
echo -e "The current directory is ==> $(pwd)"
  1. 請自行創建一支程序,該程序可以用來計算“你還有幾天可以過生日”啊?
#!/bin/bash
read -p "Pleas input your birthday (MMDD, ex> 0709): " bir
now=`date +%m%d`
if [ "$bir" == "$now" ]; then
echo "Happy Birthday to you!!!"
elif [ "$bir" -gt "$now" ]; then
year=`date +%Y`
total_d=$(($((`date --date="$year$bir" +%s`-`date +%s`))/60/60/24))
echo "Your birthday will be $total_d later"
else
year=$((`date +%Y`+1))
total_d=$(($((`date --date="$year$bir" +%s`-`date +%s`))/60/60/24))
echo "Your birthday will be $total_d later"
fi
  1. 讓使用者輸入一個數字,程序可以由 1+2+3… 一直累加到使用者輸入的數字為止。
#!/bin/bash
read -p "Please input an integer number: " number
i=0
s=0
while [ "$i" != "$number" ]
do
i=$(($i+1))
s=$(($s+$i))
done
echo "the result of '1+2+3+...$number' is ==> $s"
  1. 撰寫一支程序,他的作用是: 1.) 先查看一下 /root/test/logical 這個名稱是否存在; 2.) 若不存在,則創建一個文件,使用 touch 來創建,創建完成後離開; 3.) 如果存在的話,判斷該名稱是否為文件,若為文件則將之刪除後創建一個目錄,文件名為 logical ,之後離開; 4.) 如果存在的話,而且該名稱為目錄,則移除此目錄!
#!/bin/bash
if [ ! -e logical ]; then
touch logical
echo "Just make a file logical"
exit 1
elif [ -e logical ] && [ -f logical ]; then
rm logical
mkdir logical
echo "remove file ==> logical"
echo "and make directory logical"
exit 1
elif [ -e logical ] && [ -d logical ]; then
rm -rf logical
echo "remove directory ==> logical"
exit 1
else
echo "Does here have anything?"
fi
  1. 我們知道 /etc/passwd 裡面以 : 來分隔,第一欄為帳號名稱。請寫一隻程序,可以將 /etc/passwd 的第一欄取出,而且每一欄都以一行字串“The 1 account is “root” ”來顯示,那個 1 表示行數。
#!/bin/bash
accounts=`cat /etc/passwd | cut -d':' -f1`
for account in $accounts
do
declare -i i=$i+1
echo "The $i account is \"$account\" "
done



/etc/passwd 文件架構

  1. 帳號名稱: 需要用來對應 UID, 例如 root 的 UID 對應就是 0 (第三字段)

  2. 密碼: 早期 Unix 系統的密碼就是放在這字段上!但是因為這個文件的特性是所有的程序都能夠讀取,這樣一來很容易造成密碼數據被竊取, 因此後來就將這個字段的密碼數據給他改放到 /etc/shadow 中了。所以這裡你會看到一個“ x ”

  3. UID: 使用者識別碼! Linux 對於 UID 有幾個限制:

id 範圍 | 該 ID 使用者特性
——-|
0(系統管理員)| 當 UID 是 0 時,代表這個帳號是“系統管理員”! 所以當你要讓其他的帳號名稱也具有 root 的權限時,將該帳號的 UID 改為 0 即可。 這也就是說,一部系統上面的系統管理員不見得只有 root 喔! 不過,很不建議有多個帳號的 UID 是 0 啦~容易讓系統管理員混亂!
1999(系統帳號)| 保留給系統使用的 ID,其實除了 0 之外,其他的 UID 權限與特性並沒有不一樣。默認 1000 以下的數字讓給系統作為保留帳號只是一個習慣。
由於系統上面啟動的網絡服務或背景服務希望使用較小的權限去運行,因此不希望使用 root 的身份去執行這些服務, 所以我們就得要提供這些運行中程序的擁有者帳號才行。這些系統帳號通常是不可登陸的, 所以才會有我們在第十章提到的 /sbin/nologin 這個特殊的 shell 存在。
根據系統帳號的由來,通常這類帳號又約略被區分為兩種:
1
200:由 distributions 自行創建的系統帳號;
201999:若使用者有系統帳號需求時,可以使用的帳號 UID。
1000
60000(可登陸帳號)| 給一般使用者用的。事實上,目前的 linux 核心 (3.10.x 版)已經可以支持到 4294967295 (2^32-1) 這麼大的 UID 號碼喔!

  1. GID: 這個與 /etc/group 有關!其實 /etc/group 的觀念與 /etc/passwd 差不多,只是他是用來規範群組名稱與 GID 的對應而已!

  2. 使用者信息說明欄: 這個字段基本上並沒有什麼重要用途,只是用來解釋這個帳號的意義而已!不過,如果您提供使用 finger 的功能時, 這個字段可以提供很多的訊息呢!本章後面的 chfn 指令會來解釋這裡的說明。

  3. 主文件夾: 這是使用者的主文件夾,以上面為例, root 的主文件夾在 /root ,所以當 root 登陸之後,就會立刻跑到 /root 目錄裡頭啦!呵呵! 如果你有個帳號的使用空間特別的大,你想要將該帳號的主文件夾移動到其他的硬盤去該怎麼作? 沒有錯!可以在這個字段進行修改呦!默認的使用者主文件夾在 /home/yourIDname

  4. Shell: 我們在第十章 BASH 提到很多次,當使用者登陸系統後就會取得一個 Shell 來與系統的核心溝通以進行使用者的操作任務。那為何默認 shell 會使用 bash 呢?就是在這個字段指定的囉! 這裡比較需要注意的是,有一個 shell 可以用來替代成讓帳號無法取得 shell 環境的登陸動作!那就是 /sbin/nologin 這個東西!這也可以用來製作純 pop 郵件帳號者的數據呢!




/etc/shadow 文件結構

  1. 帳號名稱:
    由於密碼也需要與帳號對應啊~因此,這個文件的第一欄就是帳號,必須要與 /etc/passwd 相同才行!

  2. 密碼:
    這個字段內的數據才是真正的密碼,而且是經過編碼的密碼 (加密) 啦! 你只會看到有一些特殊符號的字母就是了!需要特別留意的是,雖然這些加密過的密碼很難被解出來, 但是“很難”不等於“不會”,所以,這個文件的默認權限是“-rw——-”或者是“———-”,亦即只有 root 才可以讀寫就是了!你得隨時注意,不要不小心更動了這個文件的權限呢!
    另外,由於各種密碼編碼的技術不一樣,因此不同的編碼系統會造成這個字段的長度不相同。 舉例來說,舊式的 DES, MD5 編碼系統產生的密碼長度就與目前慣用的 SHA 不同[2]!SHA 的密碼長度明顯的比較長些。由於固定的編碼系統產生的密碼長度必須一致,因此“當你讓這個字段的長度改變後,該密碼就會失效(算不出來)”。 很多軟件通過這個功能,在此字段前加上 ! 或 * 改變密碼字段長度,就會讓密碼“暫時失效”了。

  3. 最近更動密碼的日期:
    這個字段記錄了“更動密碼那一天”的日期,不過,很奇怪呀!在我的例子中怎麼會是 16559 呢?呵呵,這個是因為計算 Linux 日期的時間是以 1970 年 1 月 1 日作為 1 而累加的日期,1971 年 1 月 1 日則為 366 啦! 得注意一下這個數據呦!上述的 16559 指的就是 2015-05-04 那一天啦!瞭解乎? 而想要了解該日期可以使用本章後面 chage 指令的幫忙!至於想要知道某個日期的累積日數, 可使用如下的程序計算:

echo $(($(date --date="2015/05/04" +%s)/86400+1))

上述指令中,2015/05/04 為你想要計算的日期,86400 為每一天的秒數, %s 為 1970/01/01 以來的累積總秒數。 由於 bash 僅支持整數,因此最終需要加上 1 補齊 1970/01/01 當天。

  1. 密碼不可被更動的天數:(與第 3 字段相比)
    第四個字段記錄了:這個帳號的密碼在最近一次被更改後需要經過幾天才可以再被變更!如果是 0 的話, 表示密碼隨時可以更動的意思。這的限制是為了怕密碼被某些人一改再改而設計的!如果設置為 20 天的話,那麼當你設置了密碼之後, 20 天之內都無法改變這個密碼呦!

  2. 密碼需要重新變更的天數:(與第 3 字段相比)
    經常變更密碼是個好習慣!為了強制要求使用者變更密碼,這個字段可以指定在最近一次更改密碼後, 在多少天數內需要再次的變更密碼才行。你必須要在這個天數內重新設置你的密碼,否則這個帳號的密碼將會“變為過期特性”。 而如果像上面的 99999 (計算為 273 年) 的話,那就表示,呵呵,密碼的變更沒有強制性之意。

  3. 密碼需要變更期限前的警告天數:(與第 5 字段相比)
    當帳號的密碼有效期限快要到的時候 (第 5 字段),系統會依據這個字段的設置,發出“警告”言論給這個帳號,提醒他“再過 n 天你的密碼就要過期了,請儘快重新設置你的密碼呦!”,如上面的例子,則是密碼到期之前的 7 天之內,系統會警告該用戶。

  4. 密碼過期後的帳號寬限時間(密碼失效日):(與第 5 字段相比)
    密碼有效日期為“更新日期(第3字段)”+“重新變更日期(第5字段)”,過了該期限後使用者依舊沒有更新密碼,那該密碼就算過期了。 雖然密碼過期但是該帳號還是可以用來進行其他工作的,包括登陸系統取得 bash 。不過如果密碼過期了, 那當你登陸系統時,系統會強制要求你必須要重新設置密碼才能登陸繼續使用喔,這就是密碼過期特性。

  5. 帳號失效日期:
    這個日期跟第三個字段一樣,都是使用 1970 年以來的總日數設置。這個字段表示: 這個帳號在此字段規定的日期之後,將無法再使用。 就是所謂的“帳號失效”,此時不論你的密碼是否有過期,這個“帳號”都不能再被使用! 這個字段會被使用通常應該是在“收費服務”的系統中,你可以規定一個日期讓該帳號不能再使用啦!

  6. 保留:
    最後一個字段是保留的,看以後有沒有新功能加入。


範例

假如我的使用者的密碼欄如下所示:

dmtsai:$6$M4IphgNP2TmlXaSS$B418YFroYxxmm....:16559:5:60:7:5:16679:
  • 由於密碼幾乎僅能單向運算(由明碼計算成為密碼,無法由密碼反推回明碼),因此由上表的數據我們無法得知 dmstai 的實際密碼明文 (第二個字段);

  • 此帳號最近一次更動密碼的日期是 2015/05/04 (16559);

  • 能夠再次修改密碼的時間是 5 天以後,也就是 2015/05/09 以前 dmtsai 不能修改自己的密碼;如果使用者還是嘗試要更動自己的密碼,系統就會出現這樣的訊息:

You must wait longer to change your password
passwd: Authentication token manipulation error
畫面中告訴我們:你必須要等待更久的時間才能夠變更密碼之意啦!
  • 由於密碼過期日期定義為 60 天后,亦即累積日數為: 16559+60=16619,經過計算得到此日數代表日期為 2015/07/03。 這表示:“使用者必須要在 2015/05/09 (前 5 天不能改) 到 2015/07/03 之間的 60 天限制內去修改自己的密碼,若 2015/07/03 之後還是沒有變更密碼時,該密碼就宣告為過期”了!

  • 警告日期設為 7 天,亦即是密碼過期日前的 7 天,在本例中則代表 2015/06/26 ~ 2015/07/03 這七天。 如果使用者一直沒有更改密碼,那麼在這 7 天中,只要 dmtsai 登陸系統就會發現如下的訊息:
    Warning: your password will expire in 5 days

  • 如果該帳號一直到 2015/07/03 都沒有更改密碼,那麼密碼就過期了。但是由於有 5 天的寬限天數, 因此 dmtsai 在 2015/07/08 前都還可以使用舊密碼登陸主機。 不過登陸時會出現強制更改密碼的情況,畫面有點像下面這樣:

You are required to change your password immediately (password aged)
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user dmtsai.
Changing password for dmtsai
(current) UNIX password:
  • 你必須要輸入一次舊密碼以及兩次新密碼後,才能夠開始使用系統的各項資源。如果你是在 2015/07/08 以後嘗試以 dmtsai 登陸的話,那麼就會出現如下的錯誤訊息且無法登陸,因為此時你的密碼就失效去啦!

    Your account has expired; please contact your system administrator
  • 如果使用者在 2015/07/03 以前變更過密碼,那麼第 3 個字段的那個 16559 的天數就會跟著改變,因此, 所有的限制日期也會跟著相對變動喔!^_^

  • 無論使用者如何動作,到了 16679 (大約是 2015/09/01 左右) 該帳號就失效了~


獲取 shadow 的加密機制

  • 安裝 authconfig, 如果沒有裝的話
yum install authconfig-gtk*
  • 查詢
authconfig --test | grep hashing



關於群組: 有效與初始群組、groups, newgrp

/etc/group 文件結構

如下:

root:x:0:
bin:x:1:
daemon:x:2:
sys:x:3:
  1. 群組名稱:
    就是群組名稱啦!同樣用來給人類使用的,基本上需要與第三字段的 GID 對應。

  2. 群組密碼:
    通常不需要設置,這個設置通常是給“群組管理員”使用的,目前很少有這個機會設置群組管理員啦! 同樣的,密碼已經移動到 /etc/gshadow 去,因此這個字段只會存在一個“x”而已;

  3. GID:
    就是群組的 ID 啊。我們 /etc/passwd 第四個字段使用的 GID 對應的群組名,就是由這裡對應出來的!

  4. 此群組支持的帳號名稱:
    我們知道一個帳號可以加入多個群組,那某個帳號想要加入此群組時,將該帳號填入這個字段即可。 舉例來說,如果我想要讓 dmtsai 與 alex 也加入 root 這個群組,那麼在第一行的最後面加上“dmtsai,alex”,注意不要有空格, 使成為“ root:x:0:dmtsai,alex ”就可以囉~


/etc/gshadow 文件結構

  1. 群組名稱
  2. 密碼欄,同樣的,開頭為 ! 表示無合法密碼,所以無群組管理員
  3. 群組管理員的帳號 (相關信息在 gpasswd 中介紹)
  4. 有加入該群組支持的所屬帳號 (與 /etc/group 內容相同!)



/etc/passwd 與 /etc/group 與 /etc/shadow 示意圖

談完了 /etc/passwd, /etc/shadow, /etc/group 之後,我們可以使用一個簡單的圖示來了解一下 UID / GID 與密碼之間的關係, 圖示如下。其實重點是 /etc/passwd 啦,其他相關的數據都是根據這個文件的字段去找尋出來的。 下圖中, root 的 UID 是 0 ,而 GID 也是 0 ,去找 /etc/group 可以知道 GID 為 0 時的群組名稱就是 root 哩。 至於密碼的尋找中,會找到 /etc/shadow 與 /etc/passwd 內同帳號名稱的那一行,就是密碼相關數據囉。




finger

  • Login:為使用者帳號,亦即 /etc/passwd 內的第一字段;
  • Name:為全名,亦即 /etc/passwd 內的第五字段(或稱為註解);
  • Directory:就是主文件夾了;
  • Shell:就是使用的 Shell 文件所在;
  • Never logged in.:figner 還會調查使用者登陸主機的情況喔!
  • No mail.:調查 /var/spool/mail 當中的信箱數據;
  • No Plan.:調查 ~vbird1/.plan 文件,並將該文件取出來說明!



chfn

chfn [-foph] [帳號名]
選項與參數:
-f :後面接完整的大名;
-o :您辦公室的房間號碼;
-p :辦公室的電話號碼;
-h :家裡的電話號碼!



chage

  • 更詳細的密碼參數顯示功能
  • 可讓使用者在第一次登陸時, 強制她們一定要更改密碼後才能夠使用系統資源

語法

chage [-ldEImMW] 帳號名
選項與參數:
-l :列出該帳號的詳細密碼參數;
-d :後面接日期,修改 shadow 第三字段(最近一次更改密碼的日期),格式 YYYY-MM-DD
-E :後面接日期,修改 shadow 第八字段(帳號失效日),格式 YYYY-MM-DD
-I :後面接天數,修改 shadow 第七字段(密碼失效日期)
-m :後面接天數,修改 shadow 第四字段(密碼最短保留天數)
-M :後面接天數,修改 shadow 第五字段(密碼多久需要進行變更)
-W :後面接天數,修改 shadow 第六字段(密碼過期前警告日期)

範例

範例一:列出 vbird2 的詳細密碼參數
[root@study ~]# chage -l vbird2
Last password change : Jul 20, 2015
Password expires : Sep 18, 2015
Password inactive : Sep 28, 2015
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 60
Number of days of warning before password expires : 7



chsh

語法:

chsh [-ls]
選項與參數:
-l :列出目前系統上面可用的 shell ,其實就是 /etc/shells 的內容!
-s :設置修改自己的 Shell 囉

範例

範例一:用 vbird1 的身份列出系統上所有合法的 shell,並且指定 csh 為自己的 shell
[vbird1@study ~]$ chsh -l
/bin/sh
/bin/bash
/sbin/nologin <==所謂:合法不可登陸的 Shell 就是這玩意!
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/tcsh
/bin/csh <==這就是 C shell 啦!
# 其實上面的信息就是我們在 bash 中談到的 /etc/shells 啦!

[vbird1@study ~]$ chsh -s /bin/csh; grep vbird1 /etc/passwd
Changing shell for vbird1.
Password: <==確認身份,請輸入 vbird1 的密碼
Shell changed.
vbird1:x:1003:1004:VBird Tsai test,DIC in KSU,06-2727175#356,06-1234567:/home/vbird1:/bin/csh

[vbird1@study ~]$ chsh -s /bin/bash
# 測試完畢後,立刻改回來!

[vbird1@study ~]$ ll $(which chsh)
-rws--x--x. 1 root root 23856 Mar 6 13:59 /bin/chsh



groupadd

語法

groupadd [-g gid] [-r] 群組名稱
選項與參數:
-g :後面接某個特定的 GID ,用來直接給予某個 GID ~
-r :創建系統群組啦!與 /etc/login.defs 內的 GID_MIN 有關。

範例

範例一:新建一個群組,名稱為 group1
[root@study ~]# groupadd group1
[root@study ~]# grep group1 /etc/group /etc/gshadow
/etc/group:group1:x:1503:
/etc/gshadow:group1:!::
# 群組的 GID 也是會由 1000 以上最大 GID+1 來決定!



groupmod

語法

groupmod [-g gid] [-n group_name] 群組名
選項與參數:
-g :修改既有的 GID 數字;
-n :修改既有的群組名稱

範例

範例一:將剛剛上個指令創建的 group1 名稱改為 mygroup , GID 為 201
[root@study ~]# groupmod -g 201 -n mygroup group1
[root@study ~]# grep mygroup /etc/group /etc/gshadow
/etc/group:mygroup:x:201:
/etc/gshadow:mygroup:!::



groupdel

語法

groupdel [groupname]



gpasswd

語法

系統管理員 (root)

gpasswd groupname
[root@study ~]# gpasswd [-A user1,...] [-M user3,...] groupname
[root@study ~]# gpasswd [-rR] groupname
選項與參數:
:若沒有任何參數時,表示給予 groupname 一個密碼(/etc/gshadow)
-A :將 groupname 的主控權交由後面的使用者管理(該群組的管理員)
-M :將某些帳號加入這個群組當中!
-r :將 groupname 的密碼移除
-R :讓 groupname 的密碼欄失效

群組管理員 (Group administrator)

gpasswd [-ad] user groupname
選項與參數:
-a :將某位使用者加入到 groupname 這個群組當中!
-d :將某位使用者移除出 groupname 這個群組當中。

範例

範例一:創建一個新群組,名稱為 testgroup 且群組交由 vbird1 管理:
[root@study ~]# groupadd testgroup <==先創建群組
[root@study ~]# gpasswd testgroup <==給這個群組一個密碼吧!
Changing the password for group testgroup
New Password:
Re-enter new password:
# 輸入兩次密碼就對了!
[root@study ~]# gpasswd -A vbird1 testgroup <==加入群組管理員為 vbird1
[root@study ~]# grep testgroup /etc/group /etc/gshadow
/etc/group:testgroup:x:1503:
/etc/gshadow:testgroup:$6$MnmChP3D$mrUn.Vo.buDjObMm8F2emTkvGSeuWikhRzaKHxpJ...:vbird1:
# 很有趣吧!此時 vbird1 則擁有 testgroup 的主控權喔!身份有點像板主啦!
範例二:以 vbird1 登陸系統,並且讓他加入 vbird1, vbird3 成為 testgroup 成員
[vbird1@study ~]$ id
uid=1003(vbird1) gid=1004(vbird1) groups=1004(vbird1) ...
# 看得出來,vbird1 尚未加入 testgroup 群組喔!

[vbird1@study ~]$ gpasswd -a vbird1 testgroup
[vbird1@study ~]$ gpasswd -a vbird3 testgroup
[vbird1@study ~]$ grep testgroup /etc/group
testgroup:x:1503:vbird1,vbird3



ACL

setfacl

setfacl :設置某個目錄/文件的 ACL 規範。

語法

setfacl [-bkRd] [{-m|-x} acl參數] 目標文件名
選項與參數:
-m :設置後續的 acl 參數給文件使用,不可與 -x 合用;
-x :刪除後續的 acl 參數,不可與 -m 合用;
-b :移除“所有的” ACL 設置參數;
-k :移除“默認的” ACL 參數,關於所謂的“默認”參數於後續範例中介紹;
-R :遞迴設置 acl ,亦即包括次目錄都會被設置起來;
-d :設置“默認 acl 參數”的意思!只對目錄有效,在該目錄新建的數據會引用此默認值

getfacl

語法

getfacl filename
選項與參數:
# 請列出剛剛我們設置的 acl_test1 的權限內容:
[root@study ~]# getfacl acl_test1
# file: acl_test1 <==說明文檔名而已!
# owner: root <==說明此文件的擁有者,亦即 ls -l 看到的第三使用者字段
# group: root <==此文件的所屬群組,亦即 ls -l 看到的第四群組字段
user::rwx <==使用者列表欄是空的,代表文件擁有者的權限
user:vbird1:r-x <==針對 vbird1 的權限設置為 rx ,與擁有者並不同!
group::r-- <==針對文件群組的權限設置僅有 r
mask::r-x <==此文件默認的有效權限 (mask)
other::r-- <==其他人擁有的權限囉!

-m :設置後續的 acl 參數給文件使用,不可與 -x 合用;
-x :刪除後續的 acl 參數,不可與 -m 合用;
-b :移除“所有的” ACL 設置參數;
-k :移除“默認的” ACL 參數,關於所謂的“默認”參數於後續範例中介紹;
-R :遞迴設置 acl ,亦即包括次目錄都會被設置起來;
-d :設置“默認 acl 參數”的意思!只對目錄有效,在該目錄新建的數據會引用此默認值

顯示的數據前面加上 # 的,代表這個文件的默認屬性,包括文件名、文件擁有者與文件所屬群組。user, group, mask, other 則是屬於不同使用者、群組與有效權限(mask)的設置值。




su

語法

su [-lm] [-c 指令] [username]
選項與參數:
- :單純使用 - 如“ su - ”代表使用 login-shell 的變量文件讀取方式來登陸系統;
若使用者名稱沒有加上去,則代表切換為 root 的身份。
-l :與 - 類似,但後面需要加欲切換的使用者帳號!也是 login-shell 的方式。
-m :-m 與 -p 是一樣的,表示“使用目前的環境設置,而不讀取新使用者的配置文件”
-c :僅進行一次指令,所以 -c 後面可以加上指令喔!



sudo

語法

sudo [-b] [-u 新使用者帳號]
選項與參數:
-b :將後續的指令放到背景中讓系統自行執行,而不與目前的 shell 產生影響
-u :後面可以接欲切換的使用者,若無此項則代表切換身份為 root 。



sudoers

更改設置

visodu
root    ALL=(ALL)       ALL  <==找到這一行,大約在 98 行左右
vbird1 ALL=(ALL) ALL <==這一行是你要新增的!
使用者帳號  登陸者的來源主機名稱=(可切換的身份)  可下達的指令
root ALL=(ALL) ALL <==這是默認值
  1. “使用者帳號”:系統的哪個帳號可以使用 sudo 這個指令的意思;
  2. “登陸者的來源主機名稱”:當這個帳號由哪部主機連線到本 Linux 主機,意思是這個帳號可能是由哪一部網絡主機連線過來的, 這個設置值可以指定用戶端計算機(信任的來源的意思)。默認值 root 可來自任何一部網絡主機
  3. “(可切換的身份)”:這個帳號可以切換成什麼身份來下達後續的指令,默認 root 可以切換成任何人;
  4. “可下達的指令”:可用該身份下達什麼指令?這個指令請務必使用絕對路徑撰寫。 默認 root 可以切換任何身份且進行任何指令之意。
    那個 ALL 是特殊的關鍵字,代表任何身份、主機或指令的意思。所以,我想讓 vbird1 可以進行任何身份的任何指令, 就如同上表特殊字體寫的那樣,其實就是複製上述默認值那一行,再將 root 改成 vbird1 即可啊! 此時“vbird1 不論來自哪部主機登陸,他可以變換身份成為任何人,且可以進行系統上面的任何指令”之意。 修改完請儲存後離開 vi,並以 vbird1 登陸系統後,進行如下的測試看看:



visudo

更改默認編輯器

update-alternatives --config editor



PAM 模塊設置語法

程序與 PAM 的關係圖


程序調用 PAM 的流程

  1. 使用者開始執行 /usr/bin/passwd 這支程序,並輸入密碼;
  2. passwd 調用 PAM 模塊進行驗證;
  3. PAM 模塊會到 /etc/pam.d/ 找尋與程序 (passwd) 同名的配置文件;
  4. 依據 /etc/pam.d/passwd 內的設置,引用相關的 PAM 模塊逐步進行驗證分析;
  5. 將驗證結果 (成功、失敗以及其他訊息) 回傳給 passwd 這支程序;
  6. passwd 這支程序會根據 PAM 回傳的結果決定下一個動作 (重新輸入新密碼或者通過驗證!)

配置文件內容

cat /etc/pam.d/passwd
#%PAM-1.0 <==PAM版本的說明而已!
auth include system-auth <==每一行都是一個驗證的過程
account include system-auth
password substack system-auth
-password optional pam_gnome_keyring.so use_authtok
password substack postlogin
驗證類別 控制標準 PAM 模塊與該模塊的參數

驗證類別 (type)

驗證類別主要分為四種,分別說明如下:

auth
是 authentication (認證) 的縮寫,所以這種類別主要用來檢驗使用者的身份驗證,這種類別通常是需要密碼來檢驗的, 所以後續接的模塊是用來檢驗使用者的身份。

account
account (帳號) 則大部分是在進行 authorization (授權),這種類別則主要在檢驗使用者是否具有正確的使用權限, 舉例來說,當你使用一個過期的密碼來登陸時,當然就無法正確的登陸了。

session
session 是會議期間的意思,所以 session 管理的就是使用者在這次登陸 (或使用這個指令) 期間,PAM 所給予的環境設置。 這個類別通常用在記錄使用者登陸與登出時的信息!例如,如果你常常使用 su 或者是 sudo 指令的話, 那麼應該可以在 /var/log/secure 裡面發現很多關於 pam 的說明,而且記載的數據是“session open, session close”的信息!

password
password 就是密碼嘛!所以這種類別主要在提供驗證的修訂工作,舉例來說,就是修改/變更密碼啦!
這四個驗證的類型通常是有順序的,不過也有例外就是了。 會有順序的原因是,(1)我們總是得要先驗證身份 (auth) 後, (2)系統才能夠藉由使用者的身份給予適當的授權與權限設置 (account),而且(3)登陸與登出期間的環境才需要設置, 也才需要記錄登陸與登出的信息 (session)。如果在運行期間需要密碼修訂時,(4)才給予 password 的類別。這樣說起來, 自然是需要有點順序吧!


驗證的控制旗標 (control flag)

那麼“驗證的控制旗標(control flag)”又是什麼?簡單的說,他就是“驗證通過的標準”啦! 這個字段在管控該驗證的放行方式,主要也分為四種控制方式:

required
此驗證若成功則帶有 success (成功) 的標誌,若失敗則帶有 failure 的標誌,但不論成功或失敗都會繼續後續的驗證流程。 由於後續的驗證流程可以繼續進行,因此相當有利於數據的登錄 (log) ,這也是 PAM 最常使用 required 的原因。

requisite
若驗證失敗則立刻回報原程序 failure 的標誌,並終止後續的驗證流程。若驗證成功則帶有 success 的標誌並繼續後續的驗證流程。 這個項目與 required 最大的差異,就在於失敗的時候還要不要繼續驗證下去?由於 requisite 是失敗就終止, 因此失敗時所產生的 PAM 信息就無法通過後續的模塊來記錄了。

sufficient
若驗證成功則立刻回傳 success 給原程序,並終止後續的驗證流程;若驗證失敗則帶有 failure 標誌並繼續後續的驗證流程。 這玩意兒與 requisits 剛好相反!

optional
這個模塊控制項目大多是在顯示訊息而已,並不是用在驗證方面的。
如果將這些控制旗標以圖示的方式配合成功與否的條件繪圖,會有點像下面這樣:

程序運行過程中遇到驗證時才會去調用 PAM ,而 PAM 驗證又分很多類型與控制,不同的控制旗標所回報的訊息並不相同。 如上圖所示, requisite 失敗就回報了並不會繼續,而 sufficient 則是成功就回報了也不會繼續。 至於驗證結束後所回報的信息通常是“succes 或 failure ”而已,後續的流程還需要該程序的判斷來繼續執行才行。




jobs

語法

[root@study ~]# jobs [-lrs]
選項與參數:
-l :除了列出 job number 與指令串之外,同時列出 PID 的號碼;
-r :僅列出正在背景 run 的工作;
-s :僅列出正在背景當中暫停 (stop) 的工作。



fg

語法

[root@study ~]# fg %jobnumber
選項與參數:
%jobnumber :jobnumber 為工作號碼(數字)。注意,那個 % 是可有可無的!



ps

語法

[root@study ~]# ps aux  <==觀察系統所有的程序數據
[root@study ~]# ps -lA <==也是能夠觀察所有系統的數據
[root@study ~]# ps axjf <==連同部分程序樹狀態
選項與參數:
-A :所有的 process 均顯示出來,與 -e 具有同樣的效用;
-a :不與 terminal 有關的所有 process ;
-u :有效使用者 (effective user) 相關的 process ;
x :通常與 a 這個參數一起使用,可列出較完整信息。
輸出格式規劃:
l :較長、較詳細的將該 PID 的的信息列出;
j :工作的格式 (jobs format)
-f :做一個更為完整的輸出。

觀察自己的 bash 相關程序

ps -l

輸出如下:

F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S 0 14830 13970 0 80 0 - 52686 poll_s pts/0 00:00:00 sudo
4 S 0 14835 14830 0 80 0 - 50511 wait pts/0 00:00:00 su
4 S 0 14836 14835 0 80 0 - 29035 wait pts/0 00:00:00 bash
0 R 0 15011 14836 0 80 0 - 30319 - pts/0 00:00:00 ps
# 還記得鳥哥說過,非必要不要使用 root 直接登陸吧?從這個 ps -l 的分析,你也可以發現,
# 鳥哥其實是使用 sudo 才轉成 root 的身份~否則連測試機,鳥哥都是使用一般帳號登陸的!

詳解:

系統整體的程序運行是非常多的,但如果使用 ps -l 則僅列出與你的操作環境 (bash) 有關的程序而已, 亦即最上層的父程序會是你自己的 bash 而沒有延伸到 systemd (後續會交待!) 這支程序去!那麼 ps -l 秀出來的數據有哪些呢? 我們就來觀察看看:

  • F:代表這個程序旗標 (process flags),說明這個程序的總結權限,常見號碼有:

    • 若為 4 表示此程序的權限為 root ;
    • 若為 1 則表示此子程序僅進行複製(fork)而沒有實際執行(exec)。
  • S:代表這個程序的狀態 (STAT),主要的狀態有:

    • R (Running):該程序正在運行中;
    • S (Sleep):該程序目前正在睡眠狀態(idle),但可以被喚醒(signal)。
    • D :不可被喚醒的睡眠狀態,通常這支程序可能在等待 I/O 的情況(ex>打印)
    • T :停止狀態(stop),可能是在工作控制(背景暫停)或除錯 (traced) 狀態;
    • Z (Zombie):殭屍狀態,程序已經終止但卻無法被移除至內存外。
  • UID/PID/PPID:代表“此程序被該 UID 所擁有/程序的 PID 號碼/此程序的父程序 PID 號碼”

  • C:代表 CPU 使用率,單位為百分比;

  • PRI/NI:Priority/Nice 的縮寫,代表此程序被 CPU 所執行的優先順序,數值越小代表該程序越快被 CPU 執行。詳細的 PRI 與 NI 將在下一小節說明。

  • ADDR/SZ/WCHAN:都與內存有關,ADDR 是 kernel function,指出該程序在內存的哪個部分,如果是個 running 的程序,一般就會顯示“ - ” / SZ 代表此程序用掉多少內存 / WCHAN 表示目前程序是否運行中,同樣的, 若為 - 表示正在運行中。

  • TTY:登陸者的終端機位置,若為遠端登陸則使用動態終端接口 (pts/n);

  • TIME:使用掉的 CPU 時間,注意,是此程序實際花費 CPU 運行的時間,而不是系統時間;

  • CMD:就是 command 的縮寫,造成此程序的觸發程序之指令為何。

所以你看到的 ps -l 輸出訊息中,他說明的是:“bash 的程序屬於 UID 為 0 的使用者,狀態為睡眠 (sleep), 之所以為睡眠因為他觸發了 ps (狀態為 run) 之故。此程序的 PID 為 14836,優先執行順序為 80 , 下達 bash 所取得的終端接口為 pts/0 ,運行狀態為等待 (wait) 。”這樣已經夠清楚了吧? 您自己嘗試解析一下那麼 ps 那一行代表的意義為何呢? ^_^
接下來讓我們使用 ps 來觀察一下系統內所有的程序狀態吧!


觀察系統所有程序

ps aux

輸出:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root 1 0.0 0.2 60636 7948 ? Ss Aug04 0:01 /usr/lib/systemd/systemd ...
root 2 0.0 0.0 0 0 ? S Aug04 0:00 [kthreadd]
.....(中間省略).....
root 14830 0.0 0.1 210744 3988 pts/0 S Aug04 0:00 sudo su -
root 14835 0.0 0.1 202044 2996 pts/0 S Aug04 0:00 su -
root 14836 0.0 0.1 116140 2960 pts/0 S Aug04 0:00 -bash
.....(中間省略).....
root 18459 0.0 0.0 123372 1380 pts/0 R+ 00:25 0:00 ps aux

詳解:
你會發現 ps -l 與 ps aux 顯示的項目並不相同!在 ps aux 顯示的項目中,各字段的意義為:

  • USER:該 process 屬於那個使用者帳號的?
  • PID :該 process 的程序識別碼。
  • %CPU:該 process 使用掉的 CPU 資源百分比;
  • %MEM:該 process 所佔用的實體內存百分比;
  • VSZ :該 process 使用掉的虛擬內存量 (KBytes)
  • RSS :該 process 佔用的固定的內存量 (KBytes)
  • TTY :該 process 是在那個終端機上面運行,若與終端機無關則顯示 ?,另外, tty1-tty6 是本機上面的登陸者程序,若為 pts/0 等等的,則表示為由網絡連接進主機的程序。
  • STAT:該程序目前的狀態,狀態顯示與 ps -l 的 S 旗標相同 (R/S/T/Z)
  • START:該 process 被觸發啟動的時間;
  • TIME :該 process 實際使用 CPU 運行的時間。
  • COMMAND:該程序的實際指令為何?
    一般來說,ps aux 會依照 PID 的順序來排序顯示,我們還是以 14836 那個 PID 那行來說明!該行的意義為“ root 執行的 bash PID 為 14836,佔用了 0.1% 的內存容量百分比,狀態為休眠 (S),該程序啟動的時間為 8 月 4 號,因此啟動太久了, 所以沒有列出實際的時間點。且取得的終端機環境為 pts/0 。”與 ps aux 看到的其實是同一個程序啦!這樣可以理解嗎? 讓我們繼續使用 ps 來觀察一下其他的信息吧!



top

相對於 ps 是擷取一個時間點的程序狀態, top 則可以持續偵測程序運行的狀態!使用方式如下:


語法

[root@study ~]# top [-d 數字] | top [-bnp]
選項與參數:
-d :後面可以接秒數,就是整個程序畫面更新的秒數。默認是 5 秒;
-b :以批次的方式執行 top ,還有更多的參數可以使用喔!
通常會搭配數據流重導向來將批次的結果輸出成為文件。
-n :與 -b 搭配,意義是,需要進行幾次 top 的輸出結果。
-p :指定某些個 PID 來進行觀察監測而已。
在 top 執行過程當中可以使用的按鍵指令:
? :顯示在 top 當中可以輸入的按鍵指令;
P :以 CPU 的使用資源排序顯示;
M :以 Memory 的使用資源排序顯示;
N :以 PID 來排序喔!
T :由該 Process 使用的 CPU 時間累積 (TIME+) 排序。
k :給予某個 PID 一個訊號 (signal)
r :給予某個 PID 重新制訂一個 nice 值。
q :離開 top 軟件的按鍵。



pstree

語法

[root@study ~]# pstree [-A|U] [-up]
選項與參數:
-A :各程序樹之間的連接以 ASCII 字符來連接;
-U :各程序樹之間的連接以萬國碼的字符來連接。在某些終端接口下可能會有錯誤;
-p :並同時列出每個 process 的 PID;
-u :並同時列出每個 process 的所屬帳號名稱。



nice

語法

[root@study ~]# nice [-n 數字] command
選項與參數:
-n :後面接一個數值,數值的範圍 -20 ~ 19。



renice

語法

[root@study ~]# renice [number] PID
選項與參數:
PID :某個程序的 ID 啊!



free

觀察內存使用情況


語法

[root@study ~]# free [-b|-k|-m|-g|-h] [-t] [-s N -c N]
選項與參數:
-b :直接輸入 free 時,顯示的單位是 KBytes,我們可以使用 b(Bytes), m(MBytes)
k(KBytes), 及 g(GBytes) 來顯示單位喔!也可以直接讓系統自己指定單位 (-h)
-t :在輸出的最終結果,顯示實體內存與 swap 的總量。
-s :可以讓系統每幾秒鐘輸出一次,不間斷的一直輸出的意思!對於系統觀察挺有效!
-c :與 -s 同時處理~讓 free 列出幾次的意思~

備註

[root@study ~]# free -m
total used free shared buff/cache available
Mem: 2848 346 1794 8 706 2263
Swap: 1023 0 1023

名稱 | 意義
—-|
swap | 內存交換空間的量
total | 總量
used | 已被使用的量
free | 剩餘可用的量
shared/buffers/cached | 已被使用的量中,用來作為緩衝及高速緩存的量。
這些用量中,在系統比較忙碌時,可以被釋出而繼續利用




uname

查閱系統與核心相關信息


語法

[root@study ~]# uname [-asrmpi]
選項與參數:
-a :所有系統相關的信息,包括下面的數據都會被列出來;
-s :系統核心名稱
-r :核心的版本
-m :本系統的硬件名稱,例如 i686 或 x86_64 等;
-p :CPU 的類型,與 -m 類似,只是顯示的是 CPU 的類型!
-i :硬件的平臺 (ix86)

範例一:輸出系統的基本信息
[root@study ~]# uname -a
Linux study.centos.vbird 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015
x86_64 x86_64 x86_64 GNU/Linux



uptime

觀察系統啟動時間與工作負載
這個指令很單純:

  • 顯示出目前系統已經開機多久的時間
  • 1, 5, 15 分鐘的平均負載
    這個 uptime 可以顯示出 top 畫面的最上面一行



netstat

追蹤網絡或插槽檔


語法

[root@study ~]# uname [-asrmpi]
選項與參數:
-a :所有系統相關的信息,包括下面的數據都會被列出來;
-s :系統核心名稱
-r :核心的版本
-m :本系統的硬件名稱,例如 i686 或 x86_64 等;
-p :CPU 的類型,與 -m 類似,只是顯示的是 CPU 的類型!
-i :硬件的平臺 (ix86)

備註

[root@study ~]# netstat
Active Internet connections (w/o servers) <==與網絡較相關的部分
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 172.16.15.100:ssh 172.16.220.234:48300 ESTABLISHED
Active UNIX domain sockets (w/o servers) <==與本機的程序自己的相關性(非網絡)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ] DGRAM 1902 @/org/freedesktop/systemd1/notify
unix 2 [ ] DGRAM 1944 /run/systemd/shutdownd
....(中間省略)....
unix 3 [ ] STREAM CONNECTED 25425 @/tmp/.X11-unix/X0
unix 3 [ ] STREAM CONNECTED 28893
unix 3 [ ] STREAM CONNECTED 21262

在上面的結果當中,顯示了兩個部分:

  • 網絡的連線
  • linux 上面的 socket 程序相關性部分

我們先來看看網際網絡連線情況的部分:

  • Proto :網絡的封包協定,主要分為 TCP 與 UDP 封包,相關數據請參考服務器篇
  • Recv-Q:非由使用者程序鏈接到此 socket 的複製的總 Bytes 數;
  • Send-Q:非由遠端主機傳送過來的 acknowledged 總 Bytes 數;
  • Local Address :本地端的 IP:port 情況
  • Foreign Address:遠端主機的 IP:port 情況
  • State :連線狀態,主要有創建(ESTABLISED)及監聽(LISTEN);

我們看上面僅有一條連線的數據,他的意義是:“通過 TCP 封包的連線,遠端的 172.16.220.234:48300 連線到本地端的 172.16.15.100:ssh ,這條連線狀態是創建 (ESTABLISHED) 的狀態!”至於更多的網絡環境說明, 就得到鳥哥的另一本服務器篇查閱囉!

socket file:

  • 插槽檔
  • 溝通兩個程序之間的信息

上表中 socket file 的輸出字段:

  • Proto :一般就是 unix 啦;
  • RefCnt:連接到此 socket 的程序數量;
  • Flags :連線的旗標;
  • Type :socket 存取的類型。主要有確認連線的 STREAM 與不需確認的 DGRAM 兩種;
  • State :若為 CONNECTED 表示多個程序之間已經連線創建。
  • Path :連接到此 socket 的相關程序的路徑!或者是相關數據輸出的路徑。



dmesg

分析核心產生的訊息

系統在開機的時候,核心會去偵測系統的硬件,你的某些硬件到底有沒有被捉到,那就與這個時候的偵測有關。 dmesg 可以顯示這些偵測的過程


範例

範例一:輸出所有的核心開機時的信息

dmesg | less

範例二:搜尋開機的時候,硬盤的相關信息為何?

dmesg | grep -i vda

輸出:

[    0.758551]  vda: vda1 vda2 vda3 vda4 vda5 vda6 vda7 vda8 vda9
[ 3.964134] XFS (vda2): Mounting V4 Filesystem
....(下面省略)....



vmstat

偵測系統資源變化
vmstat 可以偵測“ CPU / 內存 / 磁盤輸入輸出狀態 ”等等


語法

[root@study ~]# vmstat [-a] [延遲 [總計偵測次數]] <==CPU/內存等信息
[root@study ~]# vmstat [-fs] <==內存相關
[root@study ~]# vmstat [-S 單位] <==設置顯示數據的單位
[root@study ~]# vmstat [-d] <==與磁盤有關
[root@study ~]# vmstat [-p 分區] <==與磁盤有關
選項與參數:
-a :使用 inactive/active(活躍與否) 取代 buffer/cache 的內存輸出信息;
-f :開機到目前為止,系統複製 (fork) 的程序數;
-s :將一些事件 (開機至目前為止) 導致的內存變化情況列表說明;
-S :後面可以接單位,讓顯示的數據有單位。例如 K/M 取代 Bytes 的容量;
-d :列出磁盤的讀寫總量統計表
-p :後面列出分區,可顯示該分區的讀寫總量統計表

範例

範例一:統計目前主機 CPU 狀態,每秒一次,共計三次!

vmstat 1 3

範例輸出:


範例二:系統上面所有的磁盤的讀寫狀態

vmstat -d

範例輸出:

利用 vmstat 甚至可以進行追蹤喔!你可以使用類似“ vmstat 5 ”代表每五秒鐘更新一次,且無窮的更新!直到你按下 [ctrl]-c 為止。如果你想要實時的知道系統資源的運行狀態,這個指令就不能不知道!那麼上面的表格各項字段的意義為何? 基本說明如下:

  • 程序字段 (procs) 的項目分別為:

    • r :等待運行中的程序數量;
    • b:不可被喚醒的程序數量。這兩個項目越多,代表系統越忙碌 (因為系統太忙,所以很多程序就無法被執行或一直在等待而無法被喚醒之故)。
  • 內存字段 (memory) 項目分別為:

    • swpd:虛擬內存被使用的容量;
    • free:未被使用的內存容量;
    • buff:用於緩衝內存;
    • cache:用於高速緩存內存。 這部份則與 free 是相同的。
  • 內存交換空間 (swap) 的項目分別為:

    • si:由磁盤中將程序取出的量;
    • so:由於內存不足而將沒用到的程序寫入到磁盤的 swap 的容量。 如果 si/so 的數值太大,表示內存內的數據常常得在磁盤與內存之間傳來傳去,系統性能會很差!
  • 磁盤讀寫 (io) 的項目分別為:

    • bi:由磁盤讀入的區塊數量;
    • bo:寫入到磁盤去的區塊數量。如果這部份的值越高,代表系統的 I/O 非常忙碌!
  • 系統 (system) 的項目分別為:

    • in:每秒被中斷的程序次數;
    • cs:每秒鐘進行的事件切換次數;這兩個數值越大,代表系統與周邊設備的溝通非常頻繁! 這些周邊設備當然包括磁盤、網卡、時間鍾等。
  • CPU 的項目分別為:

    • us:非核心層的 CPU 使用狀態;
    • sy:核心層所使用的 CPU 狀態;
    • id:閒置的狀態;
    • wa:等待 I/O 所耗費的 CPU 狀態;
    • st:被虛擬機 (virtual machine) 所盜用的 CPU 使用狀態 (2.6.11 以後才支持)。

/proc

基本上,目前主機上面的各個程序的 PID 都是以目錄的型態存在於 /proc 當中。 舉例來說,我們開機所執行的第一支程序 systemd 他的 PID 是 1 , 這個 PID 的所有相關信息都寫入在 /proc/1/* 當中!若我們直接觀察 PID 為 1 的數據好了,他有點像這樣:


文件內容

文件名 | 文件內容
——|
/proc/cmdline | 載入 kernel 時所下達的相關指令與參數!查閱此文件,可瞭解指令是如何啟動的!
/proc/cpuinfo | 本機的 CPU 的相關信息,包含頻率、類型與運算功能等
/proc/devices | 這個文件記錄了系統各個主要設備的主要設備代號,與 mknod 有關呢!
/proc/filesystems | 目前系統已經載入的文件系統囉!
/proc/interrupts | 目前系統上面的 IRQ 分配狀態。
/proc/ioports | 目前系統上面各個設備所配置的 I/O 位址。
/proc/kcore | 這個就是內存的大小啦!好大對吧!但是不要讀他啦!
/proc/loadavg | 還記得 top 以及 uptime 吧?沒錯!上頭的三個平均數值就是記錄在此!
/proc/meminfo | 使用 free 列出的內存信息,嘿嘿!在這裡也能夠查閱到!
/proc/modules | 目前我們的 Linux 已經載入的模塊列表,也可以想成是驅動程序啦!
/proc/mounts | 系統已經掛載的數據,就是用 mount 這個指令調用出來的數據啦!
/proc/swaps | 到底系統掛載入的內存在哪裡?呵呵!使用掉的 partition 就記錄在此啦!
/proc/partitions | 使用 fdisk -l 會出現目前所有的 partition 吧?在這個文件當中也有紀錄喔!
/proc/uptime | 就是用 uptime 的時候,會出現的信息啦!
/proc/version | 核心的版本,就是用 uname -a 顯示的內容啦!
/proc/bus/* | 一些總線的設備,還有 USB 的設備也記錄在此喔!

fuser

藉由文件(或文件系統)找出正在使用該文件的程序


語法

[root@study ~]# fuser [-umv] [-k [i] [-signal]] file/dir
選項與參數:
-u :除了程序的 PID 之外,同時列出該程序的擁有者;
-m :後面接的那個文件名會主動的上提到該文件系統的最頂層,對 umount 不成功很有效!
-v :可以列出每個文件與程序還有指令的完整相關性!
-k :找出使用該文件/目錄的 PID ,並試圖以 SIGKILL 這個訊號給予該 PID;
-i :必須與 -k 配合,在刪除 PID 之前會先詢問使用者意願!
-signal:例如 -1 -15 等等,若不加的話,默認是 SIGKILL (-9) 囉!

範例

範例一:找出目前所在目錄的使用 PID/所屬帳號/權限 為何?
[root@study ~]# fuser -uv .
USER PID ACCESS COMMAND
/root: root 13888 ..c.. (root)bash
root 31743 ..c.. (root)bash
```

範例二:找到所有使用到 /proc 這個文件系統的程序吧!
[root@study ~]# fuser -uv /proc
/proc: root kernel mount (root)/proc
rtkit 768 .rc.. (rtkit)rtkit-daemon

數據量還不會很多,雖然這個目錄很繁忙~沒關係!我們可以繼續這樣作,看看其他的程序!

[root@study ~]# fuser -mvu /proc
USER PID ACCESS COMMAND
/proc: root kernel mount (root)/proc
root 1 f…. (root)systemd
root 2 …e. (root)kthreadd
…..(下面省略)…..

有這幾支程序在進行 /proc 文件系統的存取喔!這樣清楚了嗎?


範例三:找到所有使用到 /home 這個文件系統的程序吧!
[root@study ~]# echo $$
31743 # 先確認一下,自己的 bash PID 號碼吧!
[root@study ~]# cd /home
[root@study home]# fuser -muv .
USER PID ACCESS COMMAND
/home: root kernel mount (root)/home
dmtsai 31535 ..c.. (dmtsai)bash
root 31571 ..c.. (root)passwd
root 31737 ..c.. (root)sudo
root 31743 ..c.. (root)bash # 果然,自己的 PID 在啊!
[root@study home]# cd ~
[root@study ~]# umount /home
umount: /home: target is busy.
(In some cases useful info about processes that use
the device is found by lsof(8) or fuser(1))

從 fuser 的結果可以知道,總共有五隻 process 在該目錄下運行,那即使 root 離開了 /home,

當然還是無法 umount 的!那要怎辦?哈哈!可以通過如下方法一個一個刪除~

[root@study ~]# fuser -mki /home
/home: 31535c 31571c 31737c # 你會發現, PID 跟上面查到的相同!
Kill process 31535 ? (y/N) # 這裡會問你要不要刪除!當然不要亂刪除啦!通通取消!


<br/>

### 那個 ACCESS 的項目,那個項目代表的意義為:
- c :此程序在當前的目錄下(非次目錄);
- e :可被觸發為執行狀態;
- f :是一個被打開的文件;
- r :代表頂層目錄 (root directory);
- F :該文件被打開了,不過在等待迴應中;
- m :可能為分享的動態函數庫;

## lsof
列出被程序所打開的文件文件名

<br/>

### 語法

lsof [-aUu] [+d]
選項與參數:
-t :terse, 簡短輸出, 可以輸出符合 kill 的參數
-a :多項數據需要“同時成立”才顯示出結果時!
-U :僅列出 Unix like 系統的 socket 文件類型;
-u :後面接 username,列出該使用者相關程序所打開的文件;
+d :後面接目錄,亦即找出某個目錄下面已經被打開的文件!


## pidof
找出某支正在執行的程序的 PID

<br/>

### 語法

pidof [-sx] program_name
選項與參數:
-s :僅列出一個 PID 而不列出所有的 PID
-x :同時列出該 program name 可能的 PPID 那個程序的 PID


## systemd
### systemd 的配置文件放置目錄
`/usr/lib/systemd/system/`:每個服務最主要的啟動腳本設置,有點類似以前的 /etc/init.d 下面的文件;
`/run/systemd/system/`:系統執行過程中所產生的服務腳本,這些腳本的優先序要比 /usr/lib/systemd/system/ 高!
`/etc/systemd/system/`:管理員依據主機系統的需求所創建的執行腳本,其實這個目錄有點像以前 /etc/rc.d/rc5.d/Sxx 之類的功能!執行優先序又比 /run/systemd/system/ 高喔!


<br/>

### systemd 服務類型
擴展名 | 主要服務功能
------|
.service | 一般服務類型 (service unit):主要是系統服務,包括服務器本身所需要的本機服務以及網絡服務都是!比較經常被使用到的服務大多是這種類型! 所以,這也是最常見的類型了!
.socket | 內部程序數據交換的插槽服務 (socket unit):主要是 IPC (Inter-process communication) 的傳輸訊息插槽檔 (socket file) 功能。 這種類型的服務通常在監控訊息傳遞的插槽檔,當有通過此插槽檔傳遞訊息來說要鏈接服務時,就依據當時的狀態將該用戶的要求傳送到對應的 daemon, 若 daemon 尚未啟動,則啟動該 daemon 後再傳送用戶的要求。<br/>使用 socket 類型的服務一般是比較不會被用到的服務,因此在開機時通常會稍微延遲啟動的時間 (因為比較沒有這麼常用嘛!)。一般用於本機服務比較多,例如我們的圖形界面很多的軟件都是通過 socket 來進行本機程序數據交換的行為。 (這與早期的 xinetd 這個 super daemon 有部份的相似喔!)
.target | 執行環境類型 (target unit):其實是一群 unit 的集合,例如上面表格中談到的 multi-user.target 其實就是一堆服務的集合~也就是說, 選擇執行 multi-user.target, 就是執行一堆其他 .service 或/及 .socket 之類的服務就是了!
.mount <br/> .automount | 文件系統掛載相關的服務 (automount unit / mount unit):例如來自網絡的自動掛載、NFS 文件系統掛載等與文件系統相關性較高的程序管理。
.path | 偵測特定文件或目錄類型 (path unit):某些服務需要偵測某些特定的目錄來提供佇列服務,例如最常見的打印服務,就是通過偵測打印佇列目錄來啟動打印功能! 這時就得要 .path 的服務類型支持了!
.timer | 循環執行的服務 (timer unit):這個東西有點類似 anacrontab 喔!不過是由 systemd 主動提供的,比 anacrontab 更加有彈性!


<br/>

### systemctl
管理單一服務 (service unit) 的啟動/開機啟動與觀察狀態

<br/>

#### 語法

systemctl [command] [unit]
command 主要有:
start :立刻啟動後面接的 unit
stop :立刻關閉後面接的 unit
restart :立刻關閉後啟動後面接的 unit,亦即執行 stop 再 start 的意思
reload :不關閉後面接的 unit 的情況下,重新載入配置文件,讓設置生效
enable :設置下次開機時,後面接的 unit 會被啟動
disable :設置下次開機時,後面接的 unit 不會被啟動
status :目前後面接的這個 unit 的狀態,會列出有沒有正在執行、開機默認執行否、登錄等信息等!
is-active :目前有沒有正在運行中
is-enable :開機時有沒有默認要啟用這個 unit
is-enable :開機時有沒有默認要啟用這個 unit


systemctl [command] [–type=TYPE] [–all]
command:
list-units :依據 unit 列出目前有啟動的 unit。若加上 –all 才會列出沒啟動的。
list-unit-files :依據 /usr/lib/systemd/system/ 內的文件,將所有文件列表說明。
–type=TYPE:就是之前提到的 unit type,主要有 service, socket, target 等


<br/>

#### unit 狀態

systemctl list-units

UNIT                      | LOAD   | ACTIVE | SUB      | DESCRIPTION
---|---|---|---|
proc-sys-fs-binfmt_mis... | loaded | active | waiting | Arbitrary Executable File Formats File System||| |
sys-devices-pc...:0:1:... | loaded | active | plugged | QEMU_HARDDISK
sys-devices-pc...0:1-0... | loaded | active | plugged | QEMU_HARDDISK
sys-devices-pc...0:0-1... | loaded | active | plugged | QEMU_DVD-ROM
.....(中間省略).....vsftpd.service | loaded | active | running | Vsftpd ftp daemon
.....(中間省略).....cups.socket | loaded | failed | failed | CUPS Printing Service Sockets.....(中間省略).....

LOAD = Reflects whether the unit definition was properly loaded.

ACTIVE = The high-level unit activation state, i.e. generalization of SUB.

SUB = The low-level unit activation state, values depend on unit type.

141 loaded units listed. Pass --all to see loaded but inactive units, too.

To show all installed unit files use 'systemctl list-unit-files'.

列出的項目中,主要的意義是:
- UNIT :項目的名稱,包括各個 unit 的類別 (看擴展名)
- LOAD :開機時是否會被載入,默認 systemctl 顯示的是有載入的項目而已喔!
- ACTIVE :目前的狀態,須與後續的 SUB 搭配!就是我們用 systemctl status 觀察時,active 的項目!
- DESCRIPTION :詳細描述囉
- cups 比較有趣,因為剛剛被我們玩過,所以 ACTIVE 竟然是 failed 的喔!被玩死了! ^_^
- 另外,systemctl 都不加參數,其實默認就是 list-units 的意思!

<br/>

#### active 狀態
狀態 | 解釋
-----------------|
active (running)| 正有一隻或多隻程序正在系統中執行的意思,舉例來說,正在執行中的 vsftpd 就是這種模式。
active (exited)| 僅執行一次就正常結束的服務,目前並沒有任何程序在系統中執行。 舉例來說,開機或者是掛載時才會進行一次的 quotaon 功能,就是這種模式! quotaon 不須一直執行~只須執行一次之後,就交給文件系統去自行處理囉!通常用 bash shell 寫的小型服務,大多是屬於這種類型 (無須常駐內存)。
active (waiting)| 正在執行當中,不過還再等待其他的事件才能繼續處理。舉例來說,打印的佇列相關服務就是這種狀態! 雖然正在啟動中,不過,也需要真的有佇列進來 (打印工作) 這樣他才會繼續喚醒打印機服務來進行下一步打印的功能。
inactive| 這個服務目前沒有運行的意思。

<br/>

#### daemon 默認狀態
狀態 | 解釋
----|
enabled | 這個 daemon 將在開機時被執行
disabled | 這個 daemon 在開機時不會被執行
static | 這個 daemon 不可以自己啟動 (enable 不可),不過可能會被其他的 enabled 的服務來喚醒 (相依屬性的服務)
mask | 這個 daemon 無論如何都無法被啟動!因為已經被強制註銷 (非刪除)。可通過 systemctl unmask 方式改回原本狀態


<br/>

#### 管理不同的操作環境
```bash
systemctl list-units --type=target --all
UNIT                   LOAD   ACTIVE   SUB    DESCRIPTION
basic.target loaded active active Basic System
cryptsetup.target loaded active active Encrypted Volumes
emergency.target loaded inactive dead Emergency Mode
final.target loaded inactive dead Final Step
getty.target loaded active active Login Prompts
graphical.target loaded active active Graphical Interface
local-fs-pre.target loaded active active Local File Systems (Pre)
local-fs.target loaded active active Local File Systems
multi-user.target loaded active active Multi-User System
network-online.target loaded inactive dead Network is Online
network.target loaded active active Network
nss-user-lookup.target loaded inactive dead User and Group Name Lookups
paths.target loaded active active Paths
remote-fs-pre.target loaded active active Remote File Systems (Pre)
remote-fs.target loaded active active Remote File Systems
rescue.target loaded inactive dead Rescue Mode
shutdown.target loaded inactive dead Shutdown
slices.target loaded active active Slices
sockets.target loaded active active Sockets
sound.target loaded active active Sound Card
swap.target loaded active active Swap
sysinit.target loaded active active System Initialization
syslog.target not-found inactive dead syslog.target
time-sync.target loaded inactive dead System Time Synchronized
timers.target loaded active active Timers
umount.target loaded inactive dead Unmount All Filesystems

LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB = The low-level unit activation state, values depend on unit type.

26 loaded units listed.
To show all installed unit files use 'systemctl list-unit-files'.
  • graphical.target:就是文字加上圖形界面,這個項目已經包含了下面的 multi-user.target 項目!
  • multi-user.target:純文本模式!
  • rescue.target:在無法使用 root 登陸的情況下,systemd 在開機時會多加一個額外的暫時系統,與你原本的 系統無關。這時你可以取得 root 的權限來維護你的系統。 但是這是額外系統,因此可能需要動到 chroot 的方式來取得你原有的系統喔!
  • emergency.target:緊急處理系統的錯誤,還是需要使用 root 登陸的情況,在無法使用 rescue.target 時,可以嘗試使用這種模式!
  • shutdown.target:就是關機的流程。
  • getty.target:可以設置你需要幾個 tty 之類的,如果想要降低 tty 的項目,可以修改這個東西的配置文件!

取得目前的操作環境以及修改

systemctl [command] [unit.target]
選項與參數:
command:
get-default :取得目前的 target
set-default :設置後面接的 target 成為默認的操作模式
isolate :切換到後面接的模式

範例

範例一:我們的測試機器默認是圖形界面,先觀察是否真為圖形模式,再將默認模式轉為文字界面

[root@study ~]# systemctl get-default 
graphical.target # 果然是圖形界面喔!

[root@study ~]# systemctl set-default multi-user.target
[root@study ~]# systemctl get-default
multi-user.target

範例二:在不重新開機的情況下,將目前的操作環境改為純文本模式,關掉圖形界面

[root@study ~]# systemctl isolate multi-user.target

範例三:若需要重新取得圖形界面呢?

[root@study ~]# systemctl isolate graphical.target

要注意,改變 graphical.target 以及 multi-user.target 是通過 isolate 來處理的。

在正常的切換情況下,使用上述 isolate 的方式即可。不過為了方便起見, systemd 也提供了數個簡單的指令給我們切換操作模式之用喔! 大致上如下所示:


systemctl 針對機器操作的幾個簡單指令

[root@study ~]# systemctl poweroff  系統關機
[root@study ~]# systemctl reboot 重新開機
[root@study ~]# systemctl suspend 進入暫停模式
[root@study ~]# systemctl hibernate 進入休眠模式
[root@study ~]# systemctl rescue 強制進入救援模式
[root@study ~]# systemctl emergency 強制進入緊急救援模式
  • suspend:暫停模式會將系統的狀態數據保存到內存中,然後關閉掉大部分的系統硬件,當然,並沒有實際關機喔! 當使用者按下喚醒機器的按鈕,系統數據會重內存中回覆,然後重新驅動被大部分關閉的硬件,就開始正常運行!喚醒的速度較快。
  • hibernate:休眠模式則是將系統狀態保存到硬盤當中,保存完畢後,將計算機關機。當使用者嘗試喚醒系統時,系統會開始正常運行, 然後將保存在硬盤中的系統狀態恢復回來。因為數據是由硬盤讀出,因此喚醒的性能與你的硬盤速度有關。

通過 systemctl 分析各服務之間的相依性

[root@study ~]# systemctl list-dependencies [unit] [--reverse]
選項與參數:
--reverse :反向追蹤誰使用這個 unit 的意思!


範例
範例一:列出目前的 target 環境下,用到什麼特別的 unit 
[root@study ~]# systemctl get-default
multi-user.target

[root@study ~]# systemctl list-dependencies
default.target
├─abrt-ccpp.service
├─abrt-oops.service
├─vsftpd.service
├─basic.target
│ ├─alsa-restore.service
│ ├─alsa-state.service
.....(中間省略).....
│ ├─sockets.target
│ │ ├─avahi-daemon.socket
│ │ ├─dbus.socket
.....(中間省略).....
│ ├─sysinit.target
│ │ ├─dev-hugepages.mount
│ │ ├─dev-mqueue.mount
.....(中間省略).....
│ └─timers.target
│ └─systemd-tmpfiles-clean.timer
├─getty.target
│ └─getty@tty1.service
└─remote-fs.target

如果要查出誰會用到 multi-user.target 呢?

systemctl list-dependencies --reverse
default.target
└─graphical.target

graphical.target 又使用了多少的服務呢?

systemctl list-dependencies graphical.target
graphical.target
├─accounts-daemon.service
├─gdm.service
├─network.service
├─rtkit-daemon.service
├─systemd-update-utmp-runlevel.service
└─multi-user.target
├─abrt-ccpp.service
├─abrt-oops.service
.....(下面省略).....



process substitution <( command ) or >( command )

如果使用 >(list), 那帶入的值將會作為 list 的輸入。 若使用 <(list), 那將會是 list 的輸出


語法

<(list)

或是

>(list)

logrotate

那個 logrotate.conf 才是主要的參數文件,至於 logrotate.d 是一個目錄, 該目錄裡面的所有文件都會被主動的讀入 /etc/logrotate.conf 當中來進行!另外,在 /etc/logrotate.d/ 裡面的文件中,如果沒有規定到的一些細部設置,則以 /etc/logrotate.conf 這個文件的規定來指定為默認值!


logrotate 這個程序的參數配置文件位置

/etc/logrotate.conf
/etc/logrotate.d/

語法

logrotate [-vf] logfile
選項與參數:
-v :啟動顯示模式,會顯示 logrotate 運行的過程喔!
-f :不論是否符合配置文件的數據,強制每個登錄文件都進行 rotate 的動作!

範例一:執行一次 logrotate 看看整個流程為何?
[root@study ~]# logrotate -v /etc/logrotate.conf
reading config file /etc/logrotate.conf <==讀取主要配置文件
including /etc/logrotate.d <==調用外部的設置
reading config file chrony <==就是外部設置啊!
....(中間省略)....
Handling 18 logs <==共有 18 個登錄文件被記錄
....(中間省略)....
rotating pattern: /var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
weekly (52 rotations)
empty log files are not rotated, old logs are removed
considering log /var/log/cron
log does not need rotating
considering log /var/log/maillog
log does not need rotating
considering log /var/log/messages <==開始處理 messages
log does not need rotating <==因為時間未到,不需要更動!
....(下面省略)....

範例二:強制進行 logrotate 的動作
[root@study ~]# logrotate -vf /etc/logrotate.conf
....(前面省略)....
rotating log /var/log/messages, log->rotateCount is 52
dateext suffix '-20150820'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
compressing log with: /bin/gzip
....(下面省略)....
# 看到否?整個 rotate 的動作就是這樣一步一步進行的~

[root@study ~]# ll /var/log/messages*; lsattr /var/log/messages
-rw-------. 1 root root 143 Aug 20 01:45 /var/log/messages
-rw-------. 1 root root 167125 Aug 20 01:40 /var/log/messages-20150820
-----a---------- /var/log/messages <==主動加入 a 的隱藏屬性囉!
[root@study ~]# vim /etc/logrotate.conf
# 下面的設置是 "logrotate 的默認設置值" ,如果個別的文件設置了其他的參數,
# 則將以個別的文件設置為主,若該文件沒有設置到的參數則以這個文件的內容為默認值!

weekly <==默認每個禮拜對登錄文件進行一次 rotate 的工作
rotate 4 <==保留幾個登錄文件呢?默認是保留四個!
create <==由於登錄文件被更名,因此創建一個新的來繼續儲存之意!
dateext <==就是這個設置值!可以讓被輪替的文件名稱加上日期作為文件名喔!
#compress <==被更動的登錄文件是否需要壓縮?如果登錄文件太大則可考慮此參數啟動

include /etc/logrotate.d
# 將 /etc/logrotate.d/ 這個目錄中的所有文件都讀進來執行 rotate 的工作!

/var/log/wtmp { <==僅針對 /var/log/wtmp 所設置的參數
monthly <==每個月一次,取代每週!
create 0664 root utmp <==指定新建文件的權限與所屬帳號/群組
minsize 1M <==文件大小一定要超過 1M 後才進行 rotate (略過時間參數)
rotate 1 <==僅保留一個,亦即僅有 wtmp.1 保留而已。
}
# 這個 wtmp 可記錄登陸者與系統重新開機時的時間與來源主機及登陸期間的時間。
# 由於具有 minsize 的參數,因此不見得每個月一定會進行一次喔!要看文件大小。
# 由於僅保留一個登錄文件而已,不滿意的話可以將他改成 rotate 5 吧!

範例

範例 1

/root/.pm2/logs/run-checkEdgeAlive.log {
daily
dateext
missingok
rotate 14
compress
notifempty
}

範例 2

以 /etc/logrotate.d/syslog 這個輪替 rsyslog.service 服務的文件

vim /etc/logrotate.d/syslog
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
endscript
}
  • 文件名:被處理的登錄文件絕對路徑文件名寫在前面,可以使用空白字符分隔多個登錄文件;
  • 參數:上述文件名進行輪替的參數使用 { } 包括起來;
  • 執行腳本:可調用外部指令來進行額外的命令下達,這個設置需與 sharedscripts …. endscript 設置合用才行。至於可用的環境為:
    • prerotate:在啟動 logrotate 之前進行的指令,例如修改登錄文件的屬性等動作;
    • postrotate:在做完 logrotate 之後啟動的指令,例如重新啟動 (kill -HUP) 某個服務!
    • Prerotate 與 postrotate 對於已加上特殊屬性的文件處理上面,是相當重要的執行程序!

那麼 /etc/logrotate.d/syslog 內設置的 5 個文件的輪替功能就變成了:

  • 該設置只對 /var/log/ 內的 cron, maillog, messages, secure, spooler 有效;
  • 登錄文件輪替每週一次、保留四個、且輪替下來的登錄文件不進行壓縮(未更改默認值);
  • 輪替完畢後 (postrotate) 取得 syslog 的 PID 後,以 kill -HUP 重新啟動 syslogd

假設我們有針對 /var/log/messages 這個文件增加 chattr +a 的屬性時, 依據 logrotate 的工作原理,我們知道,這個 /var/log/messages 將會被更名成為 /var/log/messages.1 才是。但是由於加上這個 +a 的參數啊,所以更名是不可能成功的! 那怎麼辦呢?呵呵!就利用 prerotate 與 postrotate 來進行登錄文件輪替前、後所需要作的動作啊! 果真如此時,那麼你可以這樣修改一下這個文件喔!

vim /etc/logrotate.d/syslog
/var/log/cron
/var/log/maillog
/var/log/messages
/var/log/secure
/var/log/spooler
{
sharedscripts
prerotate
/usr/bin/chattr -a /var/log/messages
endscript
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
/usr/bin/chattr +a /var/log/messages
endscript
}
  • 先給他去掉 a 這個屬性,讓登錄文件 /var/log/messages 可以進行輪替的動作
  • 然後執行了輪替之後,再給他加入這個屬性
  • /bin/kill -HUP … 的意義,這一行的目的在於將系統的 rsyslogd 重新以其參數文件 (rsyslog.conf) 的數據讀入一次!也可以想成是 reload 的意思! 由於我們創建了一個新的空的記錄文件,如果不執行此一行來重新啟動服務的話, 那麼記錄的時候將會發生錯誤呦!
    • kill -HUP: 等同 kill -1, 重啟的意思

範例 3

假設你已經創建了 /var/log/admin.log 這個文件, 現在,你想要將該文件加上 +a 這個隱藏標籤,而且設置下面的相關信息:

  • 登錄文件輪替一個月進行一次;
  • 該登錄文件若大於 10MB 時,則主動進行輪替,不需要考慮一個月的期限;
  • 保存五個備份文件;
  • 備份文件需要壓縮

先創建 +a 這個屬性
[root@study ~]# chattr +a /var/log/admin.log
[root@study ~]# lsattr /var/log/admin.log
-----a---------- /var/log/admin.log
[root@study ~]# mv /var/log/admin.log /var/log/admin.log.1
mv: cannot move `/var/log/admin.log' to `/var/log/admin.log.1': Operation not permitted
# 這裡確定了加入 a 的隱藏屬性!所以 root 無法移動此登錄文件!

開始創建 logrotate 的配置文件,增加一個文件在 /etc/logrotate.d 內
[root@study ~]# vim /etc/logrotate.d/admin
# This configuration is from VBird 2015/08/19
/var/log/admin.log {
monthly <==每個月進行一次
size=10M <==文件大小大於 10M 則開始處置
rotate 5 <==保留五個!
compress <==進行壓縮工作!
sharedscripts
prerotate
/usr/bin/chattr -a /var/log/admin.log
endscript
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
/usr/bin/chattr +a /var/log/admin.log
endscript
}

測試一下 logrotate 相關功能的信息顯示:
[root@study ~]# logrotate -v /etc/logrotate.conf
....(前面省略)....
rotating pattern: /var/log/admin.log 10485760 Bytes (5 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/admin.log
log does not need rotating
not running prerotate script, since no logs will be rotated
not running postrotate script, since no logs were rotated
....(下面省略)....
# 因為還不足一個月,文件也沒有大於 10M,所以不需進行輪替!

測試一下強制 logrotate 與相關功能的信息顯示:
[root@study ~]# logrotate -vf /etc/logrotate.d/admin
reading config file /etc/logrotate.d/admin
reading config file /etc/logrotate.d/admin

Handling 1 logs

rotating pattern: /var/log/admin.log forced from command line (5 rotations)
empty log files are rotated, old logs are removed
considering log /var/log/admin.log
log needs rotating
rotating log /var/log/admin.log, log->rotateCount is 5
dateext suffix '-20150820'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
renaming /var/log/admin.log.5.gz to /var/log/admin.log.6.gz (rotatecount 5, logstart 1, i 5),
old log /var/log/admin.log.5.gz does not exist
renaming /var/log/admin.log.4.gz to /var/log/admin.log.5.gz (rotatecount 5, logstart 1, i 4),
old log /var/log/admin.log.4.gz does not exist
renaming /var/log/admin.log.3.gz to /var/log/admin.log.4.gz (rotatecount 5, logstart 1, i 3),
old log /var/log/admin.log.3.gz does not exist
renaming /var/log/admin.log.2.gz to /var/log/admin.log.3.gz (rotatecount 5, logstart 1, i 2),
old log /var/log/admin.log.2.gz does not exist
renaming /var/log/admin.log.1.gz to /var/log/admin.log.2.gz (rotatecount 5, logstart 1, i 1),
old log /var/log/admin.log.1.gz does not exist
renaming /var/log/admin.log.0.gz to /var/log/admin.log.1.gz (rotatecount 5, logstart 1, i 0),
old log /var/log/admin.log.0.gz does not exist
log /var/log/admin.log.6.gz doesn't exist -- won't try to dispose of it
running prerotate script
fscreate context set to system_u:object_r:var_log_t:s0
renaming /var/log/admin.log to /var/log/admin.log.1
running postrotate script
compressing log with: /bin/gzip

[root@study ~]# lsattr /var/log/admin.log*
-----a---------- /var/log/admin.log
---------------- /var/log/admin.log.1.gz <==有壓縮過喔!



command || true patten

目前大部分的系統遵循 set -e (Exit immediately if a command exits with a non-zero status.) 規則,所以為了避免一些小錯誤中斷了 command 的執行,所以使用 command || true patten
例如 rmdir ... || true, 這樣就算 remove directory 失敗了, command 也不會中斷執行。

timedatectl

語法

timedatectl [commamd]
選項與參數:
list-timezones :列出系統上所有支持的時區名稱
set-timezone :設置時區位置
set-time :設置時間
set-ntp :設置網絡校時系統

範例

顯示目前的時區與時間等信息

  • 指令

    timedatectl
  • 輸出

          Local time: Tue 2015-09-01 19:50:09 CST  # 本地時間
    Universal time: Tue 2015-09-01 11:50:09 UTC # UTC 時間,可稱為格林威治標準時間
    RTC time: Tue 2015-09-01 11:50:12
    Timezone: Asia/Taipei (CST, +0800) # 就是時區囉!
    NTP enabled: no
    NTP synchronized: no
    RTC in local TZ: no
    DST active: n/a

顯示出是否有 New_York 時區?若有,則請將目前的時區更新一下

  • 查詢是否有 New York 時區
    timedatectl list-timezones | grep -i new

輸出:

America/New_York
America/North_Dakota/New_Salem
  • 設定時區

    timedatectl set-timezone "America/New_York"
  • 確認結果

    timedatectl

範例輸出:

    Local time: Tue 2015-09-01 07:53:24 EDT
Universal time: Tue 2015-09-01 11:53:24 UTC
RTC time: Tue 2015-09-01 11:53:28
Timezone: America/New_York (EDT, -0400)

時間點調整

  • 指令

    timedatectl set-time "2019-09-30 09:00"
  • 時間格式: yyyy-mm-dd HH:MM

ntpdate

ntpdate tock.stdtime.gov.tw
hwclock -w

上述的 tock.stdtime.gov.tw 指的是臺灣地區國家標準實驗室提供的時間服務器,如果你在臺灣本島上,建議使用臺灣提供的時間服務器來更新你的服務器時間, 速度會比較快些~至於 hwclock 則是將正確的時間寫入你的 BIOS 時間記錄內!如果確認可以執行,未來應該可以使用 crontab 來更新系統時間吧!




locale on MacOS

  • 打開 .zshrc, 並貼上以下代碼

    export LC_ALL=en_US.UTF-8  
    export LANG=en_US.UTF-8
  • 保存離開

  • 重開一個 terminal 視窗




localectl

語法

localectl
System Locale: LANG=zh_TW.utf8 # 下面這些數據就是“系統語系”
LC_NUMERIC=zh_TW.UTF-8
LC_TIME=zh_TW.UTF-8
LC_MONETARY=zh_TW.UTF-8
LC_PAPER=zh_TW.UTF-8
LC_MEASUREMENT=zh_TW.UTF-8
VC Keymap: cn
X11 Layout: cn
X11 Options: grp:ctrl_shift_toggle

[root@study ~]# locale
LANG=zh_TW.utf8 # 下面的則是“當前這個軟件的語系”數據!
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
.....(中間省略).....
LC_ALL=en_US.utf8

範例

如何改成英文語系的登陸界面?

localectl set-locale LANG=en_US.utf8
systemctl isolate multi-user.target
systemctl isolate graphical.target

dpkg

列出所有 dpkg 安裝的套件

dpkg -l | less



tee

tee 可以讓 standard output 轉存一份到文件內並將同樣的數據繼續送到屏幕去處理! 這樣除了可以讓我們同時分析一份數據並記錄下來之外,還可以作為處理一份數據的中間暫存盤記錄之用! tee 這傢伙在很多選擇/填充的認證考試中很容易考呢!


語法

[dmtsai@study ~]$ tee [-a] file
選項與參數:
-a :以累加 (append) 的方式,將數據加入 file 當中!

[dmtsai@study ~]$ last | tee last.list | cut -d " " -f1
# 這個範例可以讓我們將 last 的輸出存一份到 last.list 文件中;

[dmtsai@study ~]$ ls -l /home | tee ~/homefile | more
# 這個範例則是將 ls 的數據存一份到 ~/homefile ,同時屏幕也有輸出訊息!

[dmtsai@study ~]$ ls -l / | tee -a ~/homefile | more
# 要注意! tee 後接的文件會被覆蓋,若加上 -a 這個選項則能將訊息累加。



sed

語法

[dmtsai@study ~]$ sed [-nefr] [動作]
選項與參數:
-n :使用安靜(silent)模式。在一般 sed 的用法中,所有來自 STDIN 的數據一般都會被列出到屏幕上。
但如果加上 -n 參數後,則只有經過 sed 特殊處理的那一行(或者動作)才會被列出來。
-e :直接在命令行界面上進行 sed 的動作編輯;
-f :直接將 sed 的動作寫在一個文件內, -f filename 則可以執行 filename 內的 sed 動作;
-r :sed 的動作支持的是延伸型正則表達式的語法。(默認是基礎正則表達式語法)
-i :直接修改讀取的文件內容,而不是由屏幕輸出。

動作說明: [n1[,n2]]function
n1, n2 :不見得會存在,一般代表“選擇進行動作的行數”,舉例來說,如果我的動作
是需要在 10 到 20 行之間進行的,則“ 10,20[動作行為] ”

function 有下面這些咚咚:
a :新增, a 的後面可以接字串,而這些字串會在新的一行出現(目前的下一行)~
c :取代, c 的後面可以接字串,這些字串可以取代 n1,n2 之間的行!
d :刪除,因為是刪除啊,所以 d 後面通常不接任何咚咚;
i :插入, i 的後面可以接字串,而這些字串會在新的一行出現(目前的上一行);
p :打印,亦即將某個選擇的數據印出。通常 p 會與參數 sed -n 一起運行~
s :取代,可以直接進行取代的工作哩!通常這個 s 的動作可以搭配正則表達式!
例如 1,20s/old/new/g 就是啦!

範例

範例一

將 /etc/passwd 的內容列出並且打印行號,同時,請將第 2~5 行刪除!

nl /etc/passwd | sed '2,5d'

輸出:

1  root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
  • 原本應要下達 sed -e ,沒有 -e 也行
  • sed 後面接的動作,請務必以 ‘’ 兩個單引號括住
  • 如果只要刪除第 2 行,可以使用 nl /etc/passwd | sed '2d'
  • 若是要刪除第 3 到最後一行,則是 nl /etc/passwd | sed '3,$d'

範例二

承上題,在第二行後(亦即是加在第三行)加上“drink tea?”字樣!

nl /etc/passwd | sed '2a drink tea'

輸出:

1  root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
drink tea
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
  • 如果是要在第二行前呢? nl /etc/passwd | sed '2i drink tea'

範例三

在第二行後面加入兩行字,例如“Drink tea or …..”與“drink beer?”

nl /etc/passwd | sed '2a Drink tea or ......\
> drink beer ?'

輸出:

1  root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ......
drink beer ?
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
  • 可以新增好幾行”但是每一行之間都必須要以反斜線 \

範例四

搜尋檔案中有 gzip_ 的每一行, 將該行中的 # 取代為空白, 簡單來說, 就是 uncomment 啦

sed -i '/gzip_/ s/#\ //g' /etc/nginx/nginx.conf

結果前後比較:




替換變量的值

將變量中的 sbin 替換成 SBIN

echo ${PATH//sbin/SBIN}

route

[root@www ~]# route [-n]
選項與參數:
-n : 將主機名稱以 IP 的方式顯示

[root@www ~]# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 * 255.255.255.0 U 0 0 0 eth0
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
default 192.168.0.254 0.0.0.0 UG 0 0 0 eth0
[root@www ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
0.0.0.0 192.168.0.254 0.0.0.0 UG 0 0 0 eth0

# 上面輸出的資料共有八個欄位,你需要注意的有幾個地方:
# Destination :其實就是 Network 的意思;
# Gateway :就是該介面的 Gateway 那個 IP 啦!若為 0.0.0.0 表示不需要額外的 IP;
# Genmask :就是 Netmask 啦!與 Destination 組合成為一部主機或網域;
# Flags :共有多個旗標可以來表示該網域或主機代表的意義:
# U:代表該路由可用;
# G:代表該網域需要經由 Gateway 來幫忙轉遞;
# H:代表該行路由為一部主機,而非一整個網域;
# Iface :就是 Interface (介面) 的意思。



jq

  • 取得來源 object 裡的一個 property, 並轉為 raw 輸出
    node test.js | jq -r '.propertyName'



arp

語法

[root@www ~]# arp -[nd] hostname
[root@www ~]# arp -s hostname(IP) Hardware_address
選項與參數:
-n :將主機名稱以 IP 的型態顯示
-d :將 hostname 的 hardware_address 由 ARP table 當中刪除掉
-s :設定某個 IP 或 hostname 的 MAC 到 ARP table 當中

範例

  • 列出目前主機上記載的 IP/MAC 對應的 ARP 表格
    arp -n
Address            HWtype  HWaddress           Flags Mask    Iface
192.168.1.100 ether 00:01:03:01:02:03 C eth0
192.168.1.240 ether 00:01:03:01:DE:0A C eth0
192.168.1.254 ether 00:01:03:55:74:AB C eth0

  • 將 192.168.1.100 那部主機的網卡卡號直接寫入 ARP 表格中
    arp -s 192.168.1.100  01:00:2D:23:A1:0E



SBIT

語法

chmod 1xxx directoryName

或是建立時給予權限

insatll -d -o ownerName -g groupName -m 1xxx directoryName
  • 只對目錄有效
  • 一般來說, 任意的使用者, 只要對該目錄有 wx 的權限, 都可以 進去該資料夾 以及 刪除該資料夾內的檔案(資料夾)
  • 加上 SBIT 的屬性之後, 只有 該目錄的擁有者, root, 檔案的建立者 才可以刪除該目錄內的檔案(或資料夾)



ifconfig

語法

ifconfig {interface} {up|down}  <== 觀察與啟動介面
ifconfig interface {options} <== 設定與修改介面
選項與參數:
interface:網路卡介面代號,包括 eth0, eth1, ppp0 等等
options :可以接的參數,包括如下:
up, down :啟動 (up) 或關閉 (down) 該網路介面(不涉及任何參數)
mtu :可以設定不同的 MTU 數值,例如 mtu 1500 (單位為 byte)
netmask :就是子遮罩網路;
broadcast:就是廣播位址啊!

範例

  • 範例一:觀察所有的網路介面(直接輸入 ifconfig)
    [root@www ~]# ifconfig
    eth0 Link encap:Ethernet HWaddr 08:00:27:71:85:BD
    inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
    inet6 addr: fe80::a00:27ff:fe71:85bd/64 Scope:Link
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
    RX packets:2555 errors:0 dropped:0 overruns:0 frame:0
    TX packets:70 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:239892 (234.2 KiB) TX bytes:11153 (10.8 KiB)

eth0: 就是網路卡的代號,也有 lo 這個 loopback ;
HWaddr: 就是網路卡的硬體位址,俗稱的 MAC 是也;
inet addr: IPv4 的 IP 位址,後續的 Bcast, Mask 分別代表的是 Broadcast 與 netmask 喔!
inet6 addr: 是 IPv6 的版本的 IP ,我們沒有使用,所以略過;
MTU: 就是第二章談到的 MTU 啊!
RX: 那一行代表的是網路由啟動到目前為止的封包接收情況, packets 代表封包數、errors 代表封包發生錯誤的數量、 dropped 代表封包由於有問題而遭丟棄的數量等等
TX: 與 RX 相反,為網路由啟動到目前為止的傳送情況;
collisions: 代表封包碰撞的情況,如果發生太多次, 表示你的網路狀況不太好;
txqueuelen: 代表用來傳輸資料的緩衝區的儲存長度;
RX bytes, TX bytes: 總接收、傳送的位元組總量


  • 範例二:暫時修改網路介面,給予 eth0 一個 192.168.100.100/24 的參數
[root@www ~]# ifconfig eth0 192.168.100.100
# 如果不加任何其他參數,則系統會依照該 IP 所在的 class 範圍,自動的計算出
# netmask 以及 network, broadcast 等 IP 參數,若想改其他參數則:

[root@www ~]# ifconfig eth0 192.168.100.100 \
> netmask 255.255.255.128 mtu 8000
# 設定不同參數的網路介面,同時設定 MTU 的數值!

[root@www ~]# ifconfig eth0 mtu 9000
# 僅修改該介面的 MTU 數值,其他的保持不動!

[root@www ~]# ifconfig eth0:0 192.168.50.50
# 仔細看那個介面是 eth0:0 喔!那就是在該實體網卡上,再模擬一個網路介面,
# 亦即是在一張網路卡上面設定多個 IP 的意思啦!

[root@www ~]# ifconfig
eth0 Link encap:Ethernet HWaddr 08:00:27:71:85:BD
inet addr:192.168.100.100 Bcast:192.168.100.127 Mask:255.255.255.128
inet6 addr: fe80::a00:27ff:fe71:85bd/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:9000 Metric:1
RX packets:2555 errors:0 dropped:0 overruns:0 frame:0
TX packets:70 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:239892 (234.2 KiB) TX bytes:11153 (10.8 KiB)

eth0:0 Link encap:Ethernet HWaddr 08:00:27:71:85:BD
inet addr:192.168.50.50 Bcast:192.168.50.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:9000 Metric:1
# 仔細看,是否與硬體有關的資訊都相同啊!沒錯!因為是同一張網卡嘛!
# 那如果想要將剛剛建立的那張 eth0:0 關閉就好,不影響原有的 eth0 呢?

[root@www ~]# ifconfig eth0:0 down
# 關掉 eth0:0 這個介面。那如果想用預設值啟動 eth1:『ifconfig eth1 up』即可達成

  • 範例三:將手動的處理全部取消,使用原有的設定值重建網路參數:
    [root@www ~]# /etc/init.d/network restart
    # 剛剛設定的資料全部失效,會以 ifcfg-ethX 的設定為主!



apt




route

語法

[root@www ~]# route [-nee]
[root@www ~]# route add [-net|-host] [網域或主機] netmask [mask] [gw|dev]
[root@www ~]# route del [-net|-host] [網域或主機] netmask [mask] [gw|dev]
觀察的參數:
-n :不要使用通訊協定或主機名稱,直接使用 IP 或 port number;
-ee :使用更詳細的資訊來顯示
增加 (add) 與刪除 (del) 路由的相關參數:
-net :表示後面接的路由為一個網域;
-host :表示後面接的為連接到單部主機的路由;
netmask :與網域有關,可以設定 netmask 決定網域的大小;
gw :gateway 的簡寫,後續接的是 IP 的數值喔,與 dev 不同;
dev :如果只是要指定由那一塊網路卡連線出去,則使用這個設定,後面接 eth0 等

範例

單純的觀察路由狀態

  • 指令1

    route -n
  • 範例輸出1

    Kernel IP routing table
    Destination Gateway Genmask Flags Metric Ref Use Iface
    192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
    169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
    0.0.0.0 192.168.1.254 0.0.0.0 UG 0 0 0 eth0
  • 指令2

    route
  • 範例輸出2

Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.1.0 * 255.255.255.0 U 0 0 0 eth0
link-local * 255.255.0.0 U 1002 0 0 eth0
default 192.168.1.254 0.0.0.0 UG 0 0 0 eth0

路由的增加與刪除

[root@www ~]# route del -net 169.254.0.0 netmask 255.255.0.0 dev eth0
# 上面這個動作可以刪除掉 169.254.0.0/16 這個網域!
# 請注意,在刪除的時候,需要將路由表上面出現的資訊都寫入
# 包括 netmask , dev 等等參數喔!注意注意

[root@www ~]# route add -net 192.168.100.0 \
> netmask 255.255.255.0 dev eth0
# 透過 route add 來增加一個路由!請注意,這個路由的設定必須要能夠與你的網路互通。
# 舉例來說,如果我下達底下的指令就會顯示錯誤:
# route add -net 192.168.200.0 netmask 255.255.255.0 gw 192.168.200.254
# 因為我的主機內僅有 192.168.1.11 這個 IP ,所以不能直接與 192.168.200.254
# 這個網段直接使用 MAC 互通!這樣說,可以理解嗎?

[root@www ~]# route add default gw 192.168.1.250
# 增加預設路由的方法!請注意,只要有一個預設路由就夠了喔!
# 同樣的,那個 192.168.1.250 的 IP 也需要能與你的 LAN 溝通才行!
# 在這個地方如果你隨便設定後,記得使用底下的指令重新設定你的網路
# /etc/init.d/network restart

輸出資訊意義

  • Destination, Genmask:這兩個玩意兒就是分別是 network 與 netmask 啦!所以這兩個咚咚就組合成為一個完整的網域囉!

  • Gateway:該網域是通過哪個 gateway 連接出去的?如果顯示 0.0.0.0 表示該路由是直接由本機傳送,亦即可以透過區域網路的 MAC 直接傳訊;如果有顯示 IP 的話,表示該路由需要經過路由器 (通訊閘) 的幫忙才能夠傳送出去。

  • Flags:總共有多個旗標,代表的意義如下:

    • U (route is up):該路由是啟動的;
    • H (target is a host):目標是一部主機 (IP) 而非網域;
    • G (use gateway):需要透過外部的主機 (gateway) 來轉遞封包;
    • R (reinstate route for dynamic routing):使用動態路由時,恢復路由資訊的旗標;
    • D (dynamically installed by daemon or redirect):已經由服務或轉 port 功能設定為動態路由
    • M (modified from routing daemon or redirect):路由已經被修改了;
    • ! (reject route):這個路由將不會被接受(用來抵擋不安全的網域!)
  • Iface:這個路由傳遞封包的介面。




ip

語法

[root@www ~]# ip [option] [動作] [指令]
選項與參數:
option :設定的參數,主要有:
-s :顯示出該裝置的統計數據(statistics),例如總接受封包數等;
動作:亦即是可以針對哪些網路參數進行動作,包括有:
link :關於裝置 (device) 的相關設定,包括 MTU, MAC 位址等等
addr/address :關於額外的 IP 協定,例如多 IP 的達成等等;
route :與路由有關的相關設定

traceroute

語法

[root@www ~]# traceroute [選項與參數] IP
選項與參數:
-n :可以不必進行主機的名稱解析,單純用 IP ,速度較快!
-U :使用 UDP 的 port 33434 來進行偵測,這是預設的偵測協定;
-I :使用 ICMP 的方式來進行偵測;
-T :使用 TCP 來進行偵測,一般使用 port 80 測試
-w :若對方主機在幾秒鐘內沒有回聲就宣告不治...預設是 5 秒
-p 埠號:若不想使用 UDP 與 TCP 的預設埠號來偵測,可在此改變埠號。
-i 裝置:用在比較複雜的環境,如果你的網路介面很多很複雜時,才會用到這個參數;
舉例來說,你有兩條 ADSL 可以連接到外部,那你的主機會有兩個 ppp,
你可以使用 -i 來選擇是 ppp0 還是 ppp1 啦!
-g 路由:與 -i 的參數相仿,只是 -g 後面接的是 gateway 的 IP 就是了。

範例

偵測本機到 yahoo 去的各節點連線狀態

[root@www ~]# traceroute -n tw.yahoo.com
traceroute to tw.yahoo.com (119.160.246.241), 30 hops max, 40 byte packets
1 192.168.1.254 0.279 ms 0.156 ms 0.169 ms
2 172.20.168.254 0.430 ms 0.513 ms 0.409 ms
3 10.40.1.1 0.996 ms 0.890 ms 1.042 ms
4 203.72.191.85 0.942 ms 0.969 ms 0.951 ms
5 211.20.206.58 1.360 ms 1.379 ms 1.355 ms
6 203.75.72.90 1.123 ms 0.988 ms 1.086 ms
7 220.128.24.22 11.238 ms 11.179 ms 11.128 ms
8 220.128.1.82 12.456 ms 12.327 ms 12.221 ms
9 220.128.3.149 8.062 ms 8.058 ms 7.990 ms
10 * * *
11 119.160.240.1 10.688 ms 10.590 ms 119.160.240.3 10.047 ms
12 * * * <==可能有防火牆裝置等情況發生所致



tcpdump

語法

[root@www ~]# tcpdump [-AennqX] [-i 介面] [-w 儲存檔名] [-c 次數] \
[-r 檔案] [所欲擷取的封包資料格式]
選項與參數:
-A :封包的內容以 ASCII 顯示,通常用來捉取 WWW 的網頁封包資料。
-e :使用資料連接層 (OSI 第二層) 的 MAC 封包資料來顯示;
-nn:直接以 IP 及 port number 顯示,而非主機名與服務名稱
-q :僅列出較為簡短的封包資訊,每一行的內容比較精簡
-X :可以列出十六進位 (hex) 以及 ASCII 的封包內容,對於監聽封包內容很有用
-i :後面接要『監聽』的網路介面,例如 eth0, lo, ppp0 等等的介面;
-w :如果你要將監聽所得的封包資料儲存下來,用這個參數就對了!後面接檔名
-r :從後面接的檔案將封包資料讀出來。那個『檔案』是已經存在的檔案,
並且這個『檔案』是由 -w 所製作出來的。
-c :監聽的封包數,如果沒有這個參數, tcpdump 會持續不斷的監聽,
直到使用者輸入 [ctrl]-c 為止。
所欲擷取的封包資料格式:我們可以專門針對某些通訊協定或者是 IP 來源進行封包擷取,
那就可以簡化輸出的結果,並取得最有用的資訊。常見的表示方法有:
'host foo', 'host 127.0.0.1' :針對單部主機來進行封包擷取
'net 192.168' :針對某個網域來進行封包的擷取;
'src host 127.0.0.1' 'dst net 192.168':同時加上來源(src)或目標(dst)限制
'tcp port 21':還可以針對通訊協定偵測,如 tcp, udp, arp, ether 等
還可以利用 and 與 or 來進行封包資料的整合顯示呢!

範例

以 IP 與 port number 捉下 eth0 這個網路卡上的封包,持續 3 秒

[root@www ~]# tcpdump -i eth0 -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
17:01:47.360523 IP 192.168.1.101.1937 > 192.168.1.100.22: Flags [.], ack 196, win 65219,
17:01:47.362139 IP 192.168.1.100.22 > 192.168.1.101.1937: Flags [P.], seq 196:472, ack 1,
17:01:47.363201 IP 192.168.1.100.22 > 192.168.1.101.1937: Flags [P.], seq 472:636, ack 1,
17:01:47.363328 IP 192.168.1.101.1937 > 192.168.1.100.22: Flags [.], ack 636, win 64779,
<==按下 [ctrl]-c 之後結束
6680 packets captured <==捉下來的封包數量
14250 packets received by filter <==由過濾所得的總封包數量
7512 packets dropped by kernel <==被核心所丟棄的封包
  • 17:01:47.362139:此封包被擷取的時間,『時:分:秒』的單位;
  • IP:透過的通訊協定是 IP ;
  • 192.168.1.100.22 > :傳送端是 192.168.1.100 這個 IP,而傳送的 port number 為 22,大於 (>) 的符號指的是封包的傳輸方向
  • 192.168.1.101.1937:接收端的 IP 是 192.168.1.101, 主機開啟 port 1937 來接收;
  • [P.], seq 196:472:這個封包帶有 PUSH 的資料傳輸標誌, 且傳輸的資料為整體資料的 196~472 byte;
  • ack 1:ACK 的相關資料。
  • 簡單來說, 該封包是由 192.168.1.100 傳到 192.168.1.101,透過的 port 是由 22 到 1937 , 使用的是 PUSH 的旗標,而不是 SYN 之類的主動連線標誌

只取 port 21

[root@www ~]# tcpdump -i eth0 -nn port 21
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
01:54:37.96 IP 192.168.1.101.1240 > 192.168.1.100.21: . ack 1 win 65535
01:54:37.96 IP 192.168.1.100.21 > 192.168.1.101.1240: P 1:21(20) ack 1 win 5840
01:54:38.12 IP 192.168.1.101.1240 > 192.168.1.100.21: . ack 21 win 65515
01:54:42.79 IP 192.168.1.101.1240 > 192.168.1.100.21: P 1:17(16) ack 21 win 65515
01:54:42.79 IP 192.168.1.100.21 > 192.168.1.101.1240: . ack 17 win 5840
01:54:42.79 IP 192.168.1.100.21 > 192.168.1.101.1240: P 21:55(34) ack 17 win 5840
  • 封包的傳遞都是雙向的, client 端發出『要求』而 server 端則予以『回應』

監聽本地 localhost 試驗

我們先在一個終端機視窗輸入『 tcpdump -i lo -nn 』 的監聽,
再另開一個終端機視窗來對本機 (127.0.0.1) 登入『ssh localhost』

[root@www ~]# tcpdump -i lo -nn
1 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
2 listening on lo, link-type EN10MB (Ethernet), capture size 96 bytes
3 11:02:54.253777 IP 127.0.0.1.32936 > 127.0.0.1.22: S 933696132:933696132(0)
win 32767 <mss 16396,sackOK,timestamp 236681316 0,nop,wscale 2>
4 11:02:54.253831 IP 127.0.0.1.22 > 127.0.0.1.32936: S 920046702:920046702(0)
ack 933696133 win 32767 <mss 16396,sackOK,timestamp 236681316 236681316,nop,
wscale 2>
5 11:02:54.253871 IP 127.0.0.1.32936 > 127.0.0.1.22: . ack 1 win 8192 <nop,
nop,timestamp 236681316 236681316>
6 11:02:54.272124 IP 127.0.0.1.22 > 127.0.0.1.32936: P 1:23(22) ack 1 win 8192
<nop,nop,timestamp 236681334 236681316>
7 11:02:54.272375 IP 127.0.0.1.32936 > 127.0.0.1.22: . ack 23 win 8192 <nop,
nop,timestamp 236681334 236681334>
  • 第 3 行顯示的是『來自 client 端,帶有 SYN 主動連線的封包』,
  • 第 4 行顯示的是『來自 server 端,除了回應 client 端之外(ACK),還帶有 SYN 主動連線的標誌;
  • 第 5 行則顯示 client 端回應 server 確定連線建立 (ACK)
  • 第 6 行以後則開始進入資料傳輸的步驟。



nmap

語法

[root@www ~]# nmap [掃瞄類型] [掃瞄參數] [hosts 位址與範圍]
選項與參數:
[掃瞄類型]:主要的掃瞄類型有底下幾種:
-sT:掃瞄 TCP 封包已建立的連線 connect() !
-sS:掃瞄 TCP 封包帶有 SYN 標籤的資料
-sP:以 ping 的方式進行掃瞄
-sU:以 UDP 的封包格式進行掃瞄
-sO:以 IP 的協定 (protocol) 進行主機的掃瞄
[掃瞄參數]:主要的掃瞄參數有幾種:
-PT:使用 TCP 裡頭的 ping 的方式來進行掃瞄,可以獲知目前有幾部電腦存活(較常用)
-PI:使用實際的 ping (帶有 ICMP 封包的) 來進行掃瞄
-p :這個是 port range ,例如 1024-, 80-1023, 30000-60000 等等的使用方式
[Hosts 位址與範圍]:這個有趣多了,有幾種類似的類型
192.168.1.100 :直接寫入 HOST IP 而已,僅檢查一部;
192.168.1.0/24 :為 C Class 的型態,
192.168.*.*  :嘿嘿!則變為 B Class 的型態了!掃瞄的範圍變廣了!
192.168.1.0-50,60-100,103,200 :這種是變形的主機範圍啦!很好用吧!

範例

使用預設參數掃瞄本機所啟用的 port (只會掃瞄 TCP)

[root@www ~]# yum install nmap
[root@www ~]# nmap localhost
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
111/tcp open rpcbind

同時掃瞄本機的 TCP/UDP 埠口

[root@www ~]# nmap -sTU localhost
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
111/tcp open rpcbind
111/udp open rpcbind <=

透過 ICMP 封包的檢測,分析區網內有幾部主機是啟動的

[root@www ~]# nmap -sP 192.168.1.0/24
Starting Nmap 5.21 ( http://nmap.org ) at 2011-07-20 17:05 CST
Nmap scan report for www.centos.vbird (192.168.1.100)
Host is up.
Nmap scan report for 192.168.1.101 <==這三行講的是 192.168.101 的範例!
Host is up (0.00024s latency).
MAC Address: 00:1B:FC:58:9A:BB (Asustek Computer)
Nmap scan report for 192.168.1.254
Host is up (0.00026s latency).
MAC Address: 00:0C:6E:85:D5:69 (Asustek Computer)
Nmap done: 256 IP addresses (3 hosts up) scanned in 3.81 seconds



dig

語法

[root@www ~]# dig [options] FQDN [@server]
選項與參數:
@server :如果不以 /etc/resolv.conf 的設定來作為 DNS 查詢,可在此填入其他的 IP
options:相關的參數很多,主要有 +trace, -t type 以及 -x 三者最常用
+trace :就是從 . 開始追蹤,在 19.1.2 裡面談過了!回頭瞧瞧去!
-t type:查詢的資料主要有 mx, ns, soa 等類型,相關類型 19.4 來介紹
-x :查詢反解資訊,非常重要的項目!

範例

使用預設值查詢 linux.vbird.org

[root@www ~]# dig linux.vbird.org
; <<>> DiG 9.7.0-P2-RedHat-9.7.0-5.P2.el6_0.1 <<>> linux.vbird.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37415
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 0

;; QUESTION SECTION: <==提出的問題的部分
;linux.vbird.org. IN A

;; ANSWER SECTION: <==主要的回答階段
linux.vbird.org. 600 IN A 140.116.44.180

;; AUTHORITY SECTION: <==其他與此次回答有關的部分
vbird.org. 600 IN NS dns.vbird.org.
vbird.org. 600 IN NS dns2.vbird.org.

;; Query time: 9 msec
;; SERVER: 168.95.1.1#53(168.95.1.1)
;; WHEN: Thu Aug 4 14:12:26 2011
;; MSG SIZE rcvd: 86

查詢 linux.vbird.org 的 SOA 相關資訊

[root@www ~]# dig -t soa linux.vbird.org
; <<>> DiG 9.7.0-P2-RedHat-9.7.0-5.P2.el6_0.1 <<>> -t soa linux.vbird.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57511
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0

;; QUESTION SECTION:
;linux.vbird.org. IN SOA

;; AUTHORITY SECTION:
vbird.org. 600 IN SOA dns.vbird.org. root.dns.vbird.org.
2007091402 28800 7200 720000 86400

;; Query time: 17 msec
;; SERVER: 168.95.1.1#53(168.95.1.1)
;; WHEN: Thu Aug 4 14:15:57 2011
;; MSG SIZE rcvd: 78


rsync

範例:

  • 同步 A 資料夾的內容到 B 資料夾, 不要同步 .git 資料夾
    rsync -avz --exclude .git sourceDirectory/ targetDirectory
    • -a: 同步權限
    • -v: 顯示過程詳細訊息
    • -z: 過程中壓縮


Q&A

  • apt 底層包的是? dpkg
  • dpkg 安裝 package 時, 會將 *.deb 放在? /var/cache/apt/archives/
  • 路由的排列有順序之分嗎? 有哦
  • 路由排列的規則? 由小網域到大網域

修改 default system editor

~/.bashrc

export SYSTEMD_EDITOR=vim

然後到 visudo 中

sudo visudo

加入以下

Defaults  env_keep += "SYSTEMD_EDITOR"

大功告成

在 Linux 上建立一個 SFTP Server Cloud Functions 初探 - Command Line

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×