[TOC]
# 高級系統命令
## lsattr & chattr
在Linux中有一些不常用的命令,但是重要時刻它又能派上用場,譬如加固你的系統安全,今天筆者就來介紹這這兩個命令:
* lsattr 查看文件的特殊屬性
* chattr 增加或刪除文件的特殊屬性
**命令的使用**
首先你會發現有的文件,就連root也無法編輯,以下案例root用戶向test文件追加一個字符串,會報沒有權限的錯誤。
```
[djangowang@localhost ~]# echo "Tencent Cloud" >> test
-bash: test: Permission denied
```
這種情況多半可能是文件加了特殊文件位,我們可以通過lsattr命令來確認。
```
[djangowang@localhost ~]# lsattr test
----i----------- test
```
我們可以通過chattr命令,去掉這個文件特殊文件位。
```
[djangowang@localhost ~]# chattr -i test && lsattr test
---------------- test
```
這時我們就可以再次向文件追加內容了。 關于lsattr命令的參數:
* \+ :在原有參數設定基礎上,追加參數
* \- :在原有參數設定基礎上,移除參數
* \= :更新為指定參數設定
* a:即append,設定該參數后,只能向文件中添加數據,而不能刪除,多用于服務器日志文件安全,只有root才能設定這個屬性
* i:設定文件不能被刪除、改名、設定鏈接關系,同時不能寫入或新增內容
**應用場景**
1.對系統的重點文件進行加固安全,如 /etc/resolv.conf 文件 ,加固方式如下:
```
[djangowang@localhost ~]# chattr +i /etc/resolv.conf
```
這時我們就不能改此文件,從而加強了系統安全。
2.讓某個文件只能往里面追加數據,但不能刪除,適用于各種日志文件。
```
[djangowang@localhost ~]# chattr +a /var/log/messages
```
## 查看單獨IP的網絡流量
在運維服務器的過程中,我們經常會遇到這樣場景,某個IP訪問服務器流量過大,導致服務器響應過慢,這時我們就需要快速定位具體是哪個獨立IP在訪問我們的服務器,如何快速定位就需要借助工具,這里推薦iptraf-ng這個工具。iptraf是一個基于ncurses開發的網監控工具,它可以實時地監視網卡流量,可以生成各種網絡統計數據,包括TCP信息、UDP統計、ICMP和OSPF信息、以太網負載信息、節點統計和IP校驗信息等,在CentOS7.8中需要手動安裝它,方式如下。
```
[djangowang@localhost ~]# yum install iptraf-ng
```
安裝后直接在終端輸入iptraf-ng命令可以出現工具界面。

## Rsync
Rsync可以用于數據備份、增量備份和代碼發布等運維中的主要場景。
## 軟連接 & 硬連接
## 查看硬件信息
作為系統管理員當你拿到一臺服務器后總會想知道它的一些硬件信息,如果服務器是在云服務商買的可以直接在服務商的控制臺查看,但是如果給你100臺服務器或者更多,這些服務器運行在不同的云服務商,如何更快的查看它們的硬件配置,這時我們就可以使用自動化運維工具,將遠程服務器系統可識別的硬件信息錄入到本地的cmdb中,以方便我們查看。本節就來介紹,如何通過系統文件查看一些比較重要的硬件信息。
* dmidecode查看硬件信息
* 查看CPU型號
* 查看CPU核心數
* 查看網卡信息
* 查看系統位數
* 查看系統的Linux發行版本
通過dmidecode命令查看硬件信息。
```
[djangowang@localhost ~]# dmidecode | more
```
查看CPU的型號。
```
[djangowang@localhost ~]# grep name /proc/cpuinfo
model name : AMD EPYC 7K62 48-Core Processor
```
查看CPU的核數或使用lscpu命令。
```
[djangowang@localhost ~]# cat /proc/cpuinfo | grep processor
processor : 0
processor : 1
```
查看網卡信息。
```
[djangowang@localhost ~]# lspci | grep Ethernet
00:05.0 Ethernet controller: Red Hat, Inc. Virtio network device
```
查看系統位數,它會返回64或32,表示其系統位數。
```
[djangowang@localhost ~]# getconf LONG_BIT
64
```
查看操作系統的發行版本。
```
[djangowang@localhost ~]# cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
```
## 軟連接 & 硬連接
軟鏈接與硬鏈接是Linux系統中非常常用的功能類似于Windows創建快捷方式,但在Linux有著更強的應用場景。
**軟鏈接**
軟鏈接可以鏈接文件或目錄,它的格式為( ln -s oldfile slink)。軟鏈接的特點:
* 軟鏈接類似Windows系統的快捷方式
* 軟鏈接里面存放的是源文件的路徑,指向源文件
* 刪除源文件,軟鏈接依然存在,但無法訪問源文件內容
* 軟鏈接失效時一般是白字紅底閃爍
* 創建軟鏈接命令 ln -s 源文件 軟鏈接文件
* 軟鏈接和源文件是不同的文件,文件類型也不同,Inode號也不同
* 軟鏈接的文件類型是“l”,可以用rm刪除
以下分別創建目錄鏈接和文件鏈接。文件鏈接。
```
[djangowang@localhost ~]# ln -s ./passwd_link /etc/passwd
```
2. 目錄鏈接。
```
[djangowang@localhost ~]# ln -s ./etc_link /etc/
```
3. 檢查這些鏈接。
```
[djangowang@localhost ~]# ls -al etc_link passwd_link
lrwxrwxrwx 1 root root 11 1月 20 10:39 passwd_link -> /etc/passwd
lrwxrwxrwx 1 root root 5 1月 20 10:39 etc_link -> /etc/
```
**硬鏈接**
硬鏈接可以關聯兩個文件的Inode,它的格式為( ln oldfile slink)。硬鏈接的特點:
* 具有相同inode節點號的多個文件互為硬鏈接文件
* 刪除硬鏈接文件或者刪除源文件任意之一,文件實體并未被刪除
* 只有刪除了源文件和所有對應的硬鏈接文件,文件實體才會被刪除
* 硬鏈接文件是文件的另一個入口
* 可以通過給文件設置硬鏈接文件來防止重要文件被誤刪
* 可以通過ls -i看到Index
* 硬鏈接文件是普通文件,可以用rm刪除
如何創建硬鏈接。
```
[djangowang@localhost ~]# ls -al etc_link passwd_link
```
# 日志服務
# SSH
## 遠程登錄Linux
運維服務器遠程登錄分為兩種:
* 從Windows登錄Linux
* 從Linux登錄Linux
* 從Mac登錄Linux
**從Windows登錄Linux**
推薦Xshell、putty.exe或Securecrt。但需要注意建議這里工具到官網網站或正規渠道下載,早期互聯網這種工具在第三方網站下載有存在病毒木馬的情況。
**從Linux登錄Linux**
這里推薦大家使用SSH命令。譬如從A服務器登錄到B服務器,兩端均為Linux,同時B啟動了SSH服務(端口為22)我們可以執行以下命令在A服務器。
```
[djangowang@localhost ~]# ssh -l root 192.168.0.11(B服務器的IP)
```
或者
```
[djangowang@localhost ~]# ssh root@192.168.0.11(B服務器的IP)
```
**從Mac登錄Linux**
推薦iTerm2 ( https://iterm2.com/ ) 或系統自帶的終端,直接通過SSH登錄就可以。
## 服務端配置SSH
sshd_config文件是SSH守護進程的配置文件。我們來看有關sshd_config配置文件比較重要的參數:
* Port 22 # 守護進程的端口
* ListenAddress 0.0.0.0 # 監聽的IP地址
* PermitRootLogin yes # 是否允許root賬戶SSH登錄,生產環境中建議改成no,使用普通賬戶SSH登錄
* UseDNS no # 是否使用DNS反向解析
## 第三方SSH
gotty
https://github.com/xtermjs/xterm.js/
## SSH的端口轉發
端口轉發也是業務運維中比較常用的場景。關于SSH端口轉發的參數:
* -N: 不執行遠程指令
* -v: 打印更詳細信息
* -L: listen-port:host:port 指派本地的 port 到達端機器地址上的 port
* -R: listen-port:host:port 指派遠程上的 port 到本地地址上的 port
* -f: 后臺執行ssh指令
**將本地端口的流量轉發到遠程端口**
譬如遠程服務器啟動了一個Redis服務,監聽的是127.0.0.1:6379,要想在本地訪問遠程的Redis可以這樣做 。
```
ssh -N -v -L localhost:6379:localhost:6379 user@remote_ip
```
**將遠程端口流量轉發到本地端口**
比如本地啟動了一個web服務,監聽了127.0.0.1:80。想要在訪問remote\_ip:80時就能訪問到本地的80端口,可以在本地機器運行
```
ssh -N -v -R localhost:80:localhost:80 user@remote_ip
```
# 向Linux服務器傳輸數據
我們在管理服務器的過程中難免向服務器傳輸一些數據,而傳輸數據的種類有很多根據場景這里推薦一些使用的工具。
## Windows傳輸Linux服務器
如Samba、FTP、SFTP 、對象存儲、winscp和rz命令等。 如果是小文件,這里推薦使用"rz"命令,我們需要登錄Linux服務器后執行"rz -be"從服務器端將本地數據上傳到服務器上,但使用rz命令的前題是服務器需要安裝(yum install -y lrzsz)軟件包。如果大文件推薦FTP、Samba或對象存儲等工具。
使用rz命令上傳文件。
關于rz命令的參數:
* -b --binary:以二進制方式傳輸
* -e --escape:對所有控制字符轉義
通過rz命令上傳文件。
```
[djangowang@localhost ~]# rz -be
```
還有一個比較使用的命令就是sz,它和sz命令正好相反用于從服務器下載文件到本機。使用方式,譬如從服務器下載test.txt文件到本機,如下:
```
[djangowang@localhost ~]# sz -be test.xtx
```
## Linux傳輸Linux服務器
如FTP、對象存儲、scp、rsync和rz命令等。如果是小文件,仍然推薦使用(rz)命令或(scp)命令,(scp)命令有別與(rz)命令,他是本地推送數據到遠程的Linux服務器而且走的是ssh加密通道更加的安全,關于scp命令的參數:
* \-C: 允許壓縮。(將-C標志傳遞給ssh,從而打開壓縮功能)
* \-p:保留原文件的修改時間,訪問時間和訪問權限
* \-q: 不顯示傳輸進度條
* \-r: 遞歸復制整個目錄
* \-c cipher: 以cipher將數據傳輸進行加密,這個選項將直接傳遞給ssh
* \-F ssh\_config: 指定一個替代的ssh配置文件,此參數直接傳遞給ssh
* \-i identity\_file: 從指定文件中讀取傳輸時使用的密鑰文件,此參數直接傳遞給ssh
* \-l limit: 限定用戶所能使用的帶寬,以Kbit/s為單位
* \-o ssh\_option: 如果習慣于使用ssh\_config(5)中的參數傳遞方式
* \-P port:注意是大寫的P, port是指定數據傳輸用到的端口號
我們來看一個案例,在本地Linux,推動test.txt文件到遠程的Linux服務器。
```
[djangowang@localhost ~]# scp ./test.txt root@192.168.1.7:/tmp
```
因為scp是一個命令,所以我們在批量管理多臺服務器時可以配合Shell來推送數據文件。
*注:我們在A服務器傳輸test.txt文件到B服務器,這時我們登錄B服務器在A傳輸那一刻會馬上看到B創建了一個test.txt文件,這里需要了解與rsync工具不一樣,rsync工具會在B端服務器創建一個臨時文件,當整個傳輸結束后再將臨時文件更改為傳輸前的名字,而 scp直接創建文件。*
# 窗口管理工具
傳統的管理遠程服務器方式是SSH遠程服務器后,窗口的生命周期和SSH進程綁定,SSH終止后窗口會話也會終止,如果我們在辦公環境回家后還希望能看到同樣的窗口效果,默認的SSH會話窗口是不能完成的,這時我們就可以通過Tmux來管理窗口,它是一個多窗口的管理利器和它類似的功能還有Linux的Screen命令。
## tmux安裝
Tmux支持多操作系統的發行版本,具體安裝如下。
## 安裝Tmux
Tmux支持多操作系統的發行版本,具體安裝如下。
```
# Ubuntu 或 Debian
[djangowang@localhost ~]# apt-get install tmux
# CentOS 或 Fedora
[djangowang@localhost ~]# yum install tmux
# Mac
[djangowang@localhost ~]# install tmux
```
安裝后直接在終端輸入tmux命令直接進入窗口管理界面。
## tmux使用
接著我們來介紹tmux命令的詳細用法。
* 新建會話
* 退出會話
* 查看會話 && 殺死會話
* 接入會話
* 切換會話
* 重命名會話
* 會話快捷鍵
**新建會話**
創建一個新的窗口,其中-s后接窗口會話名字。
```
[djangowang@localhost ~]# tmux new -s <session-name>
```
** 退出會話**
在Tmux窗口中,輸入ctrl+b 再輸入d,或者用命令tmux detach來退出Tmux管理的窗口。 查看會話 && 殺死會話。可以輸入tmux ls 或tmux list-session來查看會話。通過以下方式殺死會話。
```
# 使用會話編號殺死會話
[djangowang@localhost ~]# tmux kill-session -t 0
# 使用會話名稱殺死會話
[djangowang@localhost ~]# tmux kill-session -t <session-name>
```
**接入會話**
```
[djangowang@localhost ~]# tmux attach -t 0 接會話ID
# 或者
[djangowang@localhost ~]# tmux attach -t <session-name> 推薦
```
**切換會話**
```
# 使用會話編號
tmux switch -t 0
# 使用會話名稱
tmux switch -t <session-name>
```
**重命名會話**
```
[djangowang@localhost ~]# tmux rename-session -t 0 <new-name>
```
**會話快捷鍵**
```
Ctrl+b d:退出當前會話
Ctrl+b s:列出所有會話。
Ctrl+b $:重命名當前會話。
```
**窗口相關快捷鍵**
```
Ctrl+b c:創建一個新窗口
Ctrl+b n:切換到下一個窗口
Ctrl+b w:從列表中選擇窗口
Ctrl+b <0~9>:切換到指定編號的窗口,編號顯示在狀態欄
Ctrl+b ,:窗口重命名
Ctrl+b %:分成左右兩個窗格
Ctrl+b ":分成上下兩個窗格
Ctrl+b z:當前窗格全屏顯示,再按一次恢復
Ctrl+b q:顯示窗格編號
Ctrl+b t:在當前窗格顯示時間
Ctrl+b <arrow key>:光標切換到其他窗格
Ctrl+b o:光標切換到下一個窗格
Ctrl+b {:左移當前窗格
Ctrl+b }:右移當前窗格
Ctrl+b Ctrl+o:上移當前窗格
Ctrl+b Alt+o:下移當前窗格
Ctrl+b space:切換窗格布局
```
# 批量登錄服務器
通常我們使用expect來批量管理服務器,expect是一個自動化交互套件。我們可以通過(
yum install -y expect)安裝它。 關于expect的常用命令如下:
```
spawn 交互程序開始后面跟命令或者指定程序
expect 獲取匹配信息匹配成功則執行expect后面的程序動作
send exp_send 用于發送指定的字符串信息
exp_continue 在expect中多次匹配就需要用到
send_user 用來打印輸出 相當于shell中的echo
exit 退出expect腳本
eof expect執行結束 退出
set 定義變量
puts 輸出變量
set timeout 設置超時時間
```
## 通過賬號密碼登錄服務器
通過(vim)編輯login.expect文件,內容如下。執行./login.expect ,其中(pass)替換為服務器密碼然后執行./login.expect來執行查看最終效果。
```
#!/usr/bin/expect
set timeout 5
spawn ssh djangowang@192.168.1.77
expect "password"
send "pass\r"
#登錄成功后在服務端執行的命令
send "touch test.txt\r"
expect eof
```
## 通過秘鑰登錄服務器
通過Vim命令編輯login.expect文件,內容如下。執行./login.expect 來最終執行并查看結果。
```
#!/usr/bin/expect
set timeout 3
set host [lindex $argv 0]
set command [lindex $argv 1]
spawn ssh -i djangowang.pem root@$host $command
expect "*connecting"
send "yes\r"
interact
```
# 批量測試服務器是否存活
當我們管理很多服務器的時候,就需要檢測這些服務器是否存活,檢測方式有很多中譬如ping服務器、telnet服務器或使用一些程序語言通過socket網絡連接檢測服務器端口連通性。這里筆者推薦一個更為簡單的工具來批量檢測服務器的聯動性,那就是(nc)命令。 在使用前請使用(yum install nc)確保服務器安裝了這個工具。
```
#!/bin/bash
port=80
while read line
do
if nc -z -w1 $line $port ;then
echo $line $port "ok"
else
echo $line $port "fail"
fi
done < iplist
```
其中iplist文件為IP地址的列表文件,這個腳本是判斷iplist中的IP端口的連通性。關于nc命令的參數:
* \-z 表示zero,表示掃描時不發送任何數據
* \-w1 超時秒數,后面跟數字
如果你檢測的服務器不是很多,我們也可以將它寫為1行,如下:
```
[djangowang@localhost ~]# if nc -z -w1 ip 80 ;then echo "ok"; else echo "fail"; fi
```
其中IP可以替換為自己的IP地址。
# 系統調優
## 如何解決time_wait狀態
* 如何查看time_wait狀態
* 如何解決time_wait狀態
**如何查看time_wait狀態**
```
[djangowang@localhost ~]# netstat -ant|awk '/^tcp/ {++S[$NF]} END {for(a in S) print (a,S[a])}'
LAST_ACK 14
SYN_RECV 348
ESTABLISHED 70
FIN_WAIT1 229
FIN_WAIT2 30
CLOSING 33
TIME_WAIT 18122
```
**如何解決time_wait狀態**
```
net.ipv4.tcp_syncookies = 1 表示開啟SYN Cookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN攻擊,默認為0,表示關閉;
net.ipv4.tcp_tw_reuse = 1 表示開啟重用。允許將TIME-WAIT sockets重新用于新的TCP連接,默認為0,表示關閉;
net.ipv4.tcp_tw_recycle = 1 表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關閉。
net.ipv4.tcp_fin_timeout 修改系默認的 TIMEOUT 時間
```
## 深入解決Buffer/Cache
我們在上一章介紹過free這個命令,在命令的回顯中有一個重要的指標Buff/Cache。其中Buffer(buff) 是用來緩存尚未“寫入”磁盤的內容,Cache(Page Cache) 是用來緩存從磁盤“讀取”出來的東西。
```
[djangowang@localhost ~]# free -m
total used free shared buff/cache available
Mem: 992 385 63 0 544 459
Swap: 0 0 0
```
Linux內核會在內存將要耗盡的時候,自動觸發內存回收的工作,以便釋放出內存給急需內存的進程使用。但在整個觸發回收的過程中也是有成本的,成本來自Cache中存在著一部分Write操作的數據,所以必須保證Cache中的數據跟對應文件中的數據一致,才能對Cache進行釋放。于是伴隨著Cache清除的行為的,一般都是系統IO飆高。這是因為內核要將Cache中緩存的Write數據進行回寫。
我們可以通過以下方式人工,觸發緩存清除的操作,Linux 提供了三種清空方式:
```
echo 1 > /proc/sys/vm/drop_caches # 僅清除頁面緩存
echo 2 > /proc/sys/vm/drop_caches # 清除目錄項和inode
echo 3 > /proc/sys/vm/drop_caches # Pagecache、Dentries和Inodes
```
在回收的過程中,我們可以通過以下兩個測試案例來深入了解Buffer/Cache。關于測試案例我們用到了dd命令和vmstat命令:
* Linux dd命令,可從標準輸入或文件中讀取數據,根據指定的格式來轉換數據,再輸出到文件、設備或標準輸出。
* vmstat命令功能強大,可以展現給定時間間隔的服務器的狀態值,包括服務器的CPU使用率,內存使用,虛擬內存交換情況,IO讀寫情況。
### 測試Cache案例
1.為避免測試時,現有系統緩存的數據影響,我們先清理Pagecache、Dentries和Inodes,清理方式如下。
```
[djangowang@localhost ~]# echo 3 > /proc/sys/vm/drop_caches
```
2. 我們分別登陸兩個終端登陸到一臺服務器,其中終端1,執行vmstat命令。
```
[djangowang@localhost ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 3412304 5196 247376 0 0 136 0 965 481 0 35 65 1 0
1 0 0 3258172 5196 400952 0 0 0 0 2089 953 1 51 49 0 0
1 0 0 3105904 5212 552940 0 0 12 122976 1914 950 0 51 48 2 0
1 0 0 2981224 5228 678220 0 0 16 122880 1460 877 1 41 48 10 0
3 0 0 2847500 5232 811796 0 0 8 122884 1279 527 0 44 48 8 0
0 4 0 2795112 5240 864020 0 0 20 168 584 740 0 19 34 48 0
1 5 0 2698032 5256 959228 0 0 116 166864 1541 1782 1 32 23 43 0
1 4 0 2623828 5424 1033208 0 0 376 105992 1061 859 0 25 6 70 0
...
```
同時在終端2中執行以下命令,隨機讀取一個1G文件。可以發現vmstat命令的回顯Cache會不斷的上漲。但buff并沒有認可變化。
```
[djangowang@localhost ~]# dd if=/dev/urandom of=/tmp/file bs=1M count=1024
```
### 測試Buff案例
1.再次執行以下命令,來清理Pagecache、Dentries和Inodes。
```
[djangowang@localhost ~]# echo 3 > /proc/sys/vm/drop_caches
```
2.我們分別登陸兩個終端登陸到一臺服務器,其中終端1,執行vmstat命令。
```
[djangowang@localhost ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 3516848 6020 143556 0 0 0 13 1 17 0 0 99 0 0
0 0 0 3515620 6020 143592 0 0 0 0 410 712 0 1 99 0 0
0 0 0 3515660 6028 143592 0 0 8 16 349 628 0 0 100 0 0
0 0 0 3515644 6064 143588 0 0 36 0 419 722 0 1 99 1 0
0 1 0 3345116 175092 143680 0 0 169104 0 784 879 0 3 61 36 0
0 1 0 3218748 302092 143604 0 0 126992 72 746 933 1 3 49 48 0
1 2 0 3086932 433180 143700 0 0 131088 0 852 1032 1 2 48 50 0
0 2 0 3042452 478256 143652 0 0 45076 284 1027 1454 0 2 44 55 0
0 1 0 2974220 547900 143836 0 0 69644 0 1095 1531 0 1 49 49 0
0 1 0 2834804 687164 144124 0 0 139264 0 621 742 0 2 50 48 0
...
```
同時在終端2中執行以下命令,向磁盤寫入1G的文件數據。
```
[djangowang@localhost ~]# dd if=/dev/vda1 of=/dev/null bs=1M count=1024
```
這次往磁盤快速寫數據與上次讀取數據正好相反。buff快速上漲,而Cache沒有變化。
# SELINUX
# 本章小結
# 習題