目錄
3. sudo命令 進程隔離 有限硬件訪問權限以及保持系統同步
第十五章 Bash Shell腳本編寫 基礎篇
1.特性與功能
假設您要查找文件名,檢查關聯文件是否存在,然後做出相應的響應,顯示一條消息,確認或不確認文件的存在。如果只需要執行一次,則只需在終端上鍵入命令序列即可。但是,如果您需要多次執行此操作,則自動化是必經之路。爲了使命令集自動化,您將需要學習如何編寫shell腳本,其中最常用的是與bash一起使用。該圖說明了部署腳本的一些好處。
注意:在本章和下一章中討論的許多主題已經在前面介紹了,同時討論了可以在命令行完成的事情。我們選擇重複其中的一些討論,以使腳本編寫各部分保持獨立,因此重複是有意的,而不僅僅是草率的編輯。
命令解釋器的任務是執行腳本中跟在其後的語句。常用的解釋器包括:/ usr / bin / perl,/ bin / bash,/ bin / csh,/ usr / bin / python 和/ bin / sh。
在終端窗口上鍵入較長的命令序列可能很複雜,耗時且容易出錯。通過部署shell腳本,使用命令行成爲啓動複雜步驟序列的有效且快速的方法。Shell腳本保存在文件中的事實也使使用它們輕鬆創建新的腳本變體並與多個用戶共享標準過程變得容易。
Linux提供了多種選擇。/ etc / shells中列出了系統上可用的確切信息。典型的選擇是:
/ bin / sh
/ bin / bash
/ bin / tcsh
/ bin / csh
/ bin / ksh
/ bin / zsh
大多數Linux用戶使用默認的bash shell,但是具有較長UNIX背景和其他shell的用戶可能要覆蓋默認的bash shell。
要了解有關UNIX Shell的更多信息,可以閱讀此簡短的“ Command Shells歷史 ”文章。
請記住,從我們前面的討論中可以看到,shell是一個命令行解釋器,它爲終端窗口提供用戶界面。即使在沒有終端窗口的非交互式會話中,它也可以用來運行腳本,就像直接鍵入命令一樣。例如,鍵入:find . -name "*.c" -ls 與執行包含以下行的腳本文件的功能相同:
#!/bin/bash
find . -name "*.c" -ls
在UNIX環境中開發了任何種類的腳本的任何人都應該識別第一行中的#!/ bin / bash。腳本的第一行以#!開頭。,包含將在文件上使用的命令解釋器的完整路徑(在本例中爲/ bin / bash)。正如我們指出的,你可以使用的腳本語言相當多的選擇 /usr/bin/perl, /bin/csh, /usr/bin/python, etc.
讓我們編寫一個簡單的bash腳本,該腳本在屏幕上顯示一行消息。兩種類型:
cat > hello.sh
#!/bin/bash
echo "Hello Linux Foundation Student"
然後按ENTER和CTRL-D保存文件,或者只是在您喜歡的文本編輯器中創建hello.sh。然後,鍵入chmod + x hello.sh以使該文件對所有用戶都可執行。
然後,您可以通過鍵入./hello.sh 或 執行以下操作來運行腳本:
bash hello.sh
Hello Linux Foundation Student
注意:如果使用第二種形式(bash <shell script>),則不必使文件可執行。
現在,讓我們看看如何使用bash腳本創建一個更具交互性的示例。系統將提示用戶輸入一個值,然後將其顯示在屏幕上。該值存儲在一個臨時變量name中。我們可以通過在變量名稱(例如$ name)前使用$來引用shell變量的值。要創建此腳本,需要在您喜歡的編輯器中創建一個名爲 getname.sh 的文件,其內容如下:
#!/bin/bash
# Interactive reading of a variable
echo "ENTER YOUR NAME"
read name
# Display variable input
echo The name given was :$name
再次通過執行chmod + x getname.sh使其可執行。
在上面的示例中,當用戶鍵入./getname.sh 並執行了腳本時,將向用戶提示字符串 ENTER YOUR NAME。然後,用戶需要輸入一個值,然後按Enter鍵。該值將被打印出來。
注意:井號/英鎊符號/數字符號(#)用於在腳本中開始註釋,可以放置在行中的任何位置(該行的其餘部分被視爲註釋)。但是,請注意#的特殊組合 #!,在第一行中,是唯一的例外。
所有Shell腳本在完成執行後都會生成一個返回值,可以使用exit 語句顯式設置該返回值。返回值允許一個進程監視另一個進程的退出狀態,通常以父子關係進行。知道過程如何終止將使您能夠採取必要的步驟,取決於成功或失敗的步驟。
在執行腳本時,可以檢查特定的值或條件,並返回成功或失敗的結果。按照約定,成功返回0,失敗返回非零值。演示成功和失敗完成的一種簡單方法是在一個存在的文件上執行ls,在不存在的文件上執行ls,返回值存儲在以$?表示的環境變量中。:
$ ls /etc/logrotate.conf
/etc/logrotate.conf
$ echo $?
0
在這個例子中,該系統能夠定位該文件/etc/logrotate.conf中 和ls 返回的值0表示成功。在不存在的文件上運行時,它返回2。應用程序通常將這些返回值轉換爲用戶容易理解的有意義的消息。
2. 腳本句法規則
腳本要求您遵循標準的語言語法。規則描述瞭如何定義變量以及如何構造和格式化允許的語句等。該表列出了bash腳本中的一些特殊字符用法:
腳本還可以理解其他特殊字符以及字符組合和構造,例如(..),{..} ,[..] , &&,|| ,', “,$((...)),其中一些我們將在後面討論。
有時,命令太長,以至於不能輕鬆地在一行上鍵入或者難以理解(即使對命令行的長度沒有實際的限制)。
在這種情況下,連接運算符(\)是反斜槓字符,用於在幾行上繼續執行長命令。
這是使用Debian軟件包管理在系統上安裝一長包軟件包的命令示例:
$~/> cd $HOME
$~/> sudo apt-get install autoconf automake bison build-essential
chrpath curl diffstat emacs flex gcc-multilib g++-multilib \
libsdl1.2-dev libtool lzop make mc patch \
screen socat sudo tar texinfo tofrodos u-boot-tools unzip \
vim wget xterm zip
該命令分爲多行,以使其易於閱讀和理解。每行末尾的\運算符使shell組合(連接)多行並將其作爲一個命令執行。
用戶有時需要組合多個命令和語句,甚至根據它們之間使用的運算符的行爲有條件地執行它們。此方法稱爲命令鏈接。
有多種執行此操作的方法,具體取決於您要執行的操作。的; (分號)字符用於分隔這些命令並順序執行它們,就好像它們是在單獨的行中鍵入的一樣。無論前面的命令是否成功,都會執行每個隨後的命令。
因此,即使下面的命令失敗,以下示例中的三個命令也將全部執行:
$ make ; make install ; make clean
但是,當較早的命令失敗時,您可能希望中止後續的命令。您可以使用&&(和)運算符執行此操作,如下所示:
$ make && make install && make clean
如果第一個命令失敗,將永遠不會執行第二個命令。最後的改進是使用||。(或)運算子,例如:
$ cat file1 || cat file2 || cat file3
在這種情況下,您將繼續進行直到成功爲止,然後停止執行任何其他步驟。
大多數操作系統接受來自鍵盤的輸入並在終端上顯示輸出。但是,在shell腳本中,您可以將輸出發送到文件。將輸出轉移到文件的過程稱爲輸出重定向。在前面有關如何使用命令行的部分中,我們已經使用了此功能。
所述 > 字符用於寫輸出到文件。例如,以下命令將free的輸出發送到 /tmp/free.out:
$ free> /tmp/free.out
要檢查/tmp/free.out的內容 ,請在命令提示符下鍵入cat /tmp/free.out。
如果文件存在,兩個>字符(>>)會將輸出追加到文件中,如果文件不存在,則其作用類似於>。
正如可以將輸出重定向到文件一樣,可以從文件中讀取命令的輸入。從文件讀取輸入的過程稱爲輸入重定向,並使用<字符。
以下三個命令(使用wc程序計算文件中的行,單詞和字符的數量)完全等效,並且涉及輸入重定向,以及一個對文件內容進行操作的命令:
$ wc < /etc/passwd
49 105 2678 /etc/passwd
$ wc /etc/passwd
49 105 2678 /etcpasswd
$ cat /etc/passwd | wc
49 105 2678
Shell腳本執行命令序列和其他類型的語句。這些命令可以是:
- 編譯的應用程序
- 內置bash命令
- Shell腳本或其他解釋語言(例如perl和Python)的腳本。
編譯的應用程序是二進制可執行文件,通常位於文件系統中的/ usr / bin等知名目錄中。Shell腳本始終可以訪問諸如rm,ls, df,vi和gzip之類的應用程序,這些應用程序是從低級編程語言(如C)編譯而成的程序。
另外,bash具有許多內置命令,這些命令只能用於顯示終端shell或shell腳本中的輸出。有時,這些命令與系統上的可執行程序具有相同的名稱,例如echo可能導致細微的問題。bash的內置命令包括和cd, pwd, echo, read, logout, printf, let,和 ulimit。 因此,與/ bin / echo相比, 命令的內置版本(例如echo)可以預期會有稍微不同的行爲 。
bash內置命令的完整列表可以在bash手冊頁中找到,也可以通過簡單地鍵入 help來找到,我們將在下一頁中進行回顧。
在我們前面的關於如何在Linux系統上獲得幫助的討論中,我們已經列舉了哪些命令內置了bash版本。再次,這是截屏,列出了哪些命令可用。
用戶通常需要將參數值傳遞給腳本,例如文件名,日期等。腳本將採用不同的路徑或根據傳遞給它們的參數(命令參數)獲得不同的值。這些值可以是文本或數字,如下所示:
$ ./script.sh / tmp
$ ./script.sh 100 200
在腳本中,參數或自變量用 $以及數字或特殊字符表示。該表列出了其中一些參數。
如果您輸入圖中所示的腳本,請使用chmod + x param.sh使該腳本可執行。然後,運行腳本,爲其提供幾個參數,如圖所示。腳本的處理過程如下:
$0 prints the script name: param.sh
$1 prints the first parameter: one
$2 prints the second parameter: two
$3 prints the third parameter: three
$* prints all parameters: one two three four five
The final statement becomes: All done with param.sh
有時,您可能需要將一個命令的結果替換爲另一個命令的一部分。它可以通過兩種方式完成:
- 通過將內部命令包含在$()中
- 通過用反引號(`)包圍內部命令
第二種是反引號形式,在新的腳本和命令中已棄用。無論使用哪種方法,都將在新啓動的Shell環境中執行指定的命令,並且將在完成命令替換的地方插入Shell的標準輸出。
實際上,任何命令都可以通過這種方式執行。雖然這兩種方法都支持命令替換,但是 $() 方法允許命令嵌套。新腳本應始終使用這種更現代的方法。例如:
$ ls / lib / modules / $(uname -r) /
在上面的示例中,命令uname -r的輸出 (將類似於4.18.2)插入到ls命令的參數中。
大多數腳本使用包含值的變量,該值可以在腳本中的任何位置使用。這些變量可以是用戶定義的,也可以是系統定義的。許多應用程序使用此類環境變量(已在第12章:用戶環境中進行了詳細介紹)來提供輸入,驗證和控制行爲。
如前所述,標準環境變量的一些示例是HOME,PATH和HOST。引用時,環境變量必須以$符號爲前綴,如 $ HOME一樣。您可以查看和設置環境變量的值。例如,以下命令顯示存儲在PATH變量中的值:
$ echo $ PATH
但是,設置或修改變量值時不需要前綴。例如,以下命令將MYCOLOR 變量的值設置爲blue:
$ MYCOLOR = blue
你可以得到的環境變量列表與env, set, 或printenv命令。
當我們 在“ 用戶環境 ” 一節中討論了環境變量的導出時,值得在編寫bash腳本的上下文中回顧此主題。
默認情況下,在腳本中創建的變量僅可用於該腳本的後續步驟。任何子進程(子外殼程序)都無法自動訪問這些變量的值。爲了使它們可用於子進程,必須使用export語句將它們提升爲環境變量,如下所示:
export VAR=value 或 VAR=value ; export VAR
雖然允許子進程修改導出變量的值,但父進程將看不到任何更改;導出的變量不共享,它們僅被複制和繼承。
鍵入不帶參數的export將給出所有當前的環境變量的列表。
函數是實現一組操作的代碼塊。函數對於多次執行過程(可能使用不同的輸入變量)很有用。函數通常也稱爲子例程。在腳本中使用函數需要兩個步驟:
- 聲明功能
- 調用函數。
函數聲明需要一個用於調用它的名稱。正確的語法是:
function_name () {
command...
}
例如,以下函數名爲 display:
display () {
echo "This is a sample function"
}
該函數可以任意長,並且可以有很多語句。定義後,以後可以根據需要多次調用該函數。在圖中所示的完整示例中,我們還展示了一個常用的改進:如何將參數傳遞給函數。第一個參數可以稱爲 $1 , 第二個參數 $2,
以此類推。
3. Shell 腳本結構
使用if語句進行條件決策 是任何有用的編程或腳本語言都必須具備的基本結構。
使用if語句時,後續操作取決於對指定條件的評估,例如:
- 數字或字符串比較
- 命令的返回值(0表示成功)
- 文件存在或權限。
緊湊形式的if 語句的語法 爲:
if TEST-COMMANDS; then CONSEQUENT-COMMANDS; fi
更一般的定義是:
if condition
then
statements
else
statements
fi
在以下示例中,一條 if語句檢查是否存在某個文件,如果找到該文件,則顯示一條消息,指示成功或失敗:
if [ -f "$1" ]
then
echo file "$1 exists"
else
echo file "$1" does not exist
fi
我們確實還應該首先檢查是否有傳遞給腳本的參數($ 1),如果沒有,則中止。
請注意,使用方括號([])來描述測試條件。您可以執行許多其他類型的測試,例如檢查兩個數字是否相等,大於或小於,然後據此做出決定。我們將討論其他測試。
在現代腳本中,您可能會在 [[-f / etc / passwd]] 中看到雙括號。這不是錯誤。這樣做絕對是沒有錯的,並且避免了一些細微的問題,例如引用空的環境變量而不用雙引號引起來;我們在這裏不會談論這個。
您可以使用 elif 語句執行更復雜的測試,並採取適當的措施。基本語法爲:
if [ sometest ] ; then
echo Passed test1
elif [ somothertest ] ; then
echo Passed test2
fi
在所示的示例中,我們使用字符串測試,稍後將對其進行說明,並顯示如何使用read 語句引入環境變量。
bash提供了一組文件條件,可與if 語句一起使用,包括表中的條件。
您可以使用if 語句測試文件屬性,例如:
- 文件或目錄的存在
- 讀寫權限
- 可執行權限。
例如,在以下示例中:
if [ -x /etc/passwd ] ; then
ACTION
fi
在if 語句檢查文件/ etc / passwd文件是可執行的,它不是。請注意以下非常普遍的做法:
; then
與if語句在同一行。
您可以鍵入以下內容查看文件條件的完整列表:
man 1 test.
布爾表達式的計算結果爲TRUE或FALSE,並使用表中列出的各種布爾運算符獲得結果。
請注意,如果您將多個條件與&& 運算符捆綁在一起,則 條件評估爲false時,處理將立即停止。例如,如果您有A && B && C並且A爲true但B爲false,則C將永遠不會執行。
同樣,如果您使用 || 運算符,只要一切正確,處理就會停止。例如,如果您有A || B || C和A爲假,B爲真,您也永遠不會執行C。
布爾表達式返回TRUE或FALSE。在處理包括字符串或數字以及文件在內的多種數據類型時,我們可以使用此類表達式。例如,要檢查文件是否存在,請使用以下條件測試:
[ -e <filename> ]
同樣,要檢查 number1的值 是否大於number2的值 ,請使用以下條件測試:
[ $number1 -gt $number2 ]
如果 number1大於 number2,則運算符 -gt返回TRUE 。
您可以使用if 語句使用運算符== (兩個等號)比較字符串。語法如下:
if [ string1 == string2 ] ; then
ACTION
fi
請注意,使用一個=符號也可以,但是有些人認爲它已被棄用。現在來看一個測試字符串的例子。
在此處所示的示例中,if語句用於比較用戶提供的輸入並相應地顯示結果。
您可以將特殊定義的運算符與if語句一起使用以比較數字。下表列出了可用的各種運算符:
比較數字的語法如下:
exp1 -op exp2
現在讓我們考慮一個使用各種運算符比較數字的示例:
算術表達式可以通過以下三種方式求值(空格很重要!):
- 使用expr 實用工具 expr 是一個標準的程序,但已過時。語法如下:
expr 8 + 8
echo $(expr 8 + 8) - 使用$((...)) 語法 這是內置的Shell格式。語法如下:
echo $((x + 1)) - 使用內置的shell命令let。 語法如下:
let x=( 1 + 2 ); echo $x
在現代的shell腳本中,使用 expr 更好地替換爲var = $((...))。
第十六章 Bash Shell腳本編寫 高級篇
1. 字符串操作
讓我們更深入地瞭解如何在腳本中使用字符串。
字符串變量包含一系列文本字符。它可以包括字母,數字,符號和標點符號。一些示例包括:
abcde, 123, abcde 123, abcde-123, &acbde=%123.
字符串運算符包括進行比較,排序和查找長度的運算符。下表演示了一些基本的字符串運算符的用法:
在第一個示例中,我們將第一個字符串與第二個字符串進行比較,並使用if 語句顯示適當的消息 。
在第二個示例中,我們傳入文件名,然後查看該文件在當前目錄中是否存在。
有時,您可能不需要比較或使用整個字符串。要提取字符串的前 n個 字符,我們可以指定: $ {string:0:n}。在這裏, 0 是字符串中的偏移量(即,從哪個字符開始),提取需要開始,而 n 是要提取的字符數。
要提取點(.)之後的字符串中的所有字符,請使用以下表達式: $ {string#*.}。
2. case條件語句
case 語句在場景中的變量的實際值可以導致不同的執行路徑使用。 case語句通常用於處理命令行選項。
以下是使用case語句的一些優點:
- 它更容易讀寫。
- 它是嵌套的多層if-then-else-fi 代碼塊的不錯選擇。
- 它使您可以一次將一個變量與多個值進行比較。
- 它降低了程序的複雜性。
case語句的基本結構如下所示:
case expression in
pattern1) execute commands;;
pattern2) execute commands;;
pattern3) execute commands;;
pattern4) execute commands;;
* ) execute some default commands or nothing ;;
esac
這是一個case的例子:
3. loop循環語句
通過使用循環構造,您通常可以在選擇數據值(例如單個文件)時重複執行一行或多行代碼。通常,您需要執行此操作,直到條件測試返回true或false爲止。
大多數編程語言通常使用三種類型的循環:
- for
- while
- until
所有這些循環都易於用於重複一組語句,直到退出條件爲真爲止。
for循環 項目列表中的每個元素進行操作。for循環的語法爲:
for variable-name in list
do
execute one iteration for each item in the list until the list is finished
done
在這種情況下,您將根據需要替換變量名和列表(請參見示例)。與其他循環構造一樣,重複的語句應該用do和done括起來。
屏幕截圖顯示了for循環的示例,該循環顯示數字1到10的和。
只要控制命令返回true ,while循環就會重複一組語句。語法爲:
while condition is true
do
Commands for execution
----
done
需要重複的命令集應該放在do和done之間。您可以使用任何命令或運算符作爲條件。通常,它包含在方括號([])中。
屏幕截圖顯示了一個while循環示例,用於計算數字的階乘。你知道爲什麼要計算21!給出錯誤的結果?
只要控制命令爲假,until 循環將重複一組語句。因此,它基本上與while循環相反。語法爲:
until condition is false
do
Commands for execution
----
done
與while循環類似,需要重複的命令集應該放在do 和 done之間 。您可以使用任何命令或運算符作爲條件。
屏幕截圖顯示了 until 循環的示例,該循環再次計算階乘;它與while 循環的測試用例僅稍有不同 。
4. 腳本調試
在使用腳本和命令時,您可能會遇到錯誤。這些可能是由於腳本中的錯誤(例如語法不正確)或其他因素(例如缺少文件或執行操作的權限不足)引起的。可能會使用特定的錯誤代碼報告這些錯誤,但通常只會產生不正確或令人困惑的輸出。那麼,您如何識別和修復錯誤?
調試可幫助您解決和解決此類錯誤,並且是系統管理員執行的最重要任務之一。
在修復錯誤(或錯誤)之前,瞭解其來源至關重要。
您可以通過執行bash –x ./script_file或在腳本的某些部分使用 set -x 和 set + x來在調試模式下運行bash腳本。調試模式有助於識別錯誤,因爲:
- 它使用+ 字符跟蹤並在每個命令前面加上前綴。
- 在執行每個命令之前,它將顯示每個命令。
- 它可以使用以下命令僅調試腳本的選定部分(如果需要):
set -x # turns on debugging
...
set +x # turns off debugging
此處顯示的屏幕快照演示了一個腳本,如果在命令行中使用任何參數運行該腳本,則該腳本將在調試模式下運行。
在UNIX / Linux中,所有運行的程序在啓動時都會得到三個打開的文件流,如下表所示:
使用重定向,我們可以將stdout和stderr輸出流保存到一個文件或兩個單獨的文件中,以便在執行程序或命令後進行後續分析。
屏幕快照顯示了一個帶有簡單錯誤的Shell腳本,然後運行該腳本並將錯誤輸出轉移到 error.log。使用cat 顯示錯誤日誌的內容會增加調試功能。您看到如何修復腳本了嗎?
5. 更多實用技巧
考慮一種情況,您要從具有10,000條記錄的文件中檢索100條記錄。在您對提取的信息進行進一步處理的同時,您將需要一個位置來將提取的信息存儲在一個臨時文件中。
臨時文件(和目錄)用於短期存儲數據。通常,將其進行排列,以使使用它們的程序終止時這些文件消失。儘管您也可以使用touch 創建臨時文件,但在某些情況下,這可能使黑客更容易獲得對您數據的訪問權限。如果臨時文件的名稱和文件位置是可預測的,則尤其如此。
最佳實踐是爲臨時存儲創建隨機且不可預測的文件名。一種方法是使用mktemp 實用程序,如以下示例所示。
該XXXXXXXX由mktemp的替換 用隨機字符實用程序以確保臨時文件的名稱不容易預測,並且只在程序中已知的。
創建臨時文件的草率行爲可能會導致意外或由於惡意行爲而造成實際損失。例如,如果有人要創建一個從root使用的已知臨時文件到/ etc / passwd文件的符號鏈接,如下所示:
$ ln -s / etc / passwd / tmp / tempfile
如果以root身份運行的腳本的行如下所示,則可能會出現大問題:
echo $VAR > /tmp/tempfile
密碼文件將被臨時文件內容覆蓋。
爲避免這種情況,請確保通過將以下行替換爲以下行來隨機化臨時文件名:
TEMP = $(mktemp /tmp/tempfile.XXXXXXXX)echo
$ VAR> $ TEMP
請注意,該屏幕截圖顯示了不同日期的類似名稱的臨時文件,但其中包含隨機生成的字符。
某些命令(如find)將產生大量的輸出,這可能會使控制檯不堪重負。爲了避免這種情況,我們可以將大型輸出重定向到名爲/ dev / null的特殊文件(設備節點) 。該僞文件也稱爲位桶或黑洞。
寫入其中的所有數據都將被丟棄,並且寫入操作絕不會返回失敗條件。使用適當的重定向運算符,它可以使輸出從通常會向stdout和/或stderr生成輸出的命令中消失:
$ ls -lR / tmp> / dev / null
在上面的命令中,將忽略整個標準輸出流,但是任何錯誤仍將出現在控制檯上。但是,如果這樣做:
$ ls -lR / tmp>&/ dev / null
這兩個 標準輸出 和 標準錯誤將被傾入 / dev / null 。
執行以下任務時生成隨機數和其他隨機數據通常很有用:
- 執行與安全相關的任務
- 重新初始化存儲設備
- 擦除和/或隱藏現有數據
- 生成無意義的數據用於測試。
可以使用 $RANDOM 環境變量(從L inux內核的內置隨機數生成器派生)或OpenSSL庫函數(使用FIPS140 (聯邦信息處理標準)算法生成隨機數)生成此類隨機數。加密數字
要了解FIPS140,請閱讀Wikipedia的“ FIPS 140-2 ”文章。
該示例說明如何輕鬆使用環境變量方法生成隨機數。
一些服務器具有硬件隨機數發生器,其將不同類型的噪聲信號作爲輸入,例如熱噪聲和光電效應。換能器將該噪聲轉換爲電信號,再由AD轉換器將其轉換爲數字。該數字被認爲是隨機的。但是,大多數普通計算機不包含此類專用硬件,而是依靠引導過程中創建的事件來創建所需的原始數據。
無論使用這兩個源中的哪一個,系統都會維護這些數字數字/隨機位的所謂熵池。從此熵池創建隨機數。
Linux內核提供了 / dev / random和/ dev / urandom設備節點,它們使用熵池提供隨機數,這些隨機數是從熵池中估計的噪聲位數中得出的。
/ dev / random 用於需要高質量隨機性的地方,例如一次性填充或密鑰生成,但是提供值相對較慢。 / dev / urandom更快且適合(足夠好)用於大多數加密目的。
此外,當熵池爲空時,/ dev / random會被阻止並且不會生成任何數字,直到收集到其他環境噪聲(網絡流量,鼠標移動等)爲止,而/ dev / urandom會重用內部池以產生更多信息僞隨機位。
第十七章 打印操作
一些打印機的操作,嘗試了,不通用。不做翻譯。
第十八章 本地安全法則
1. 瞭解Linux的安全性
Linux內核允許經過正確身份驗證的用戶訪問文件和應用程序。雖然每個用戶都由一個唯一的整數(用戶ID或UID)標識,但一個單獨的數據庫會將用戶名與每個UID關聯。創建帳戶後,新的用戶信息將添加到用戶數據庫,並且必須創建用戶的主目錄,並在其中填充一些基本文件。命令行程序(例如useradd和userdel )以及 GUI工具用於創建和刪除帳戶。
對於每個用戶,在/ etc / passwd文件中維護以下七個字段:
默認情況下,Linux區分幾種帳戶類型,以隔離進程和工作負載。Linux有四種類型的帳戶:
- root
- System
- Normal
- Network
爲了安全的工作環境,建議爲帳戶授予可能和必要的最低特權,並刪除不活動的帳戶。last實用工具顯示每個用戶最後一次登錄系統的時間,可用於幫助識別潛在的非活動帳戶,這些帳戶是系統刪除的候選對象。
請記住,在多用戶業務系統上使用的實踐比在僅影響臨時用戶的個人桌面系統上可以使用的實踐更爲嚴格。對於安全性尤其如此。我們希望向您展示適用於可在所有系統上使用的企業服務器的實踐,但是要理解,您可以選擇在自己的個人系統上放寬這些規則。
root是Linux / UNIX系統上最特權的帳戶。該帳戶可以執行系統管理的所有方面,包括添加帳戶,更改用戶密碼,檢查日誌文件,安裝軟件等。使用此帳戶時,必須格外小心。它沒有任何安全限制。
當您以root身份或以root用戶身份登錄時,shell提示符將顯示' # '(如果您使用的是bash並且您尚未自定義該提示符,則正如我們在本課程的其他地方所討論的那樣)。此約定旨在向您警告此帳戶的絕對權力。
2. 如何使用root權限
需要root用戶特權才能執行以下操作:
- 創建,刪除和管理用戶帳戶
- 管理軟件包
- 刪除或修改系統文件
- 重新啓動系統服務。
可以允許Linux發行版的普通帳戶用戶安裝軟件包,更新某些設置,使用某些外圍設備以及對系統進行各種更改。但是,需要root特權才能執行管理任務,例如重新啓動服務,手動安裝軟件包以及管理文件系統中普通用戶目錄之外的部分。
普通帳戶用戶可以執行一些需要特殊權限的操作;但是,系統配置必須允許行使這種能力。
SUID(執行時設置所有者用戶ID,類似於Windows的“運行方式”功能)是賦予文件的一種特殊的文件權限。SUID爲用戶提供臨時權限,使其可以使用文件所有者(可能是root)的權限而不是用戶所擁有的權限來運行程序。
下表提供了不需要root特權的操作示例:
3. sudo命令 進程隔離 有限硬件訪問權限以及保持系統同步
在Linux中,您可以使用su或sudo臨時向普通用戶授予root訪問權限。這些方法實際上是完全不同的。下面列出了兩個命令之間的區別:
sudo 能夠跟蹤獲得根訪問權限的失敗嘗試。用戶使用sudo的授權基於存儲在/ etc / sudoers文件和/etc/sudoers.d目錄中的配置信息。
嘗試執行sudo bash 而不成功驗證用戶身份時,系統日誌文件(通常爲/ var / log / secure) 中將顯示以下消息 :
authentication failure; logname=op uid=0 euid=0 tty=/dev/pts/6 ruser=op rhost= user=op
conversation failed
auth could not identify password for [op]
op : 1 incorrect password attempt ;
TTY=pts/6 ; PWD=/var/log ; USER=root ; COMMAND=/bin/bash
每當 調用sudo時,觸發器就會查看/ etc / sudoers 和/etc/sudoers.d 的文件,以確定用戶是否有權使用sudo以及他們的特權範圍是什麼。報告了未知的用戶請求,以及即使使用sudo 也不允許用戶執行的操作請求。您可以使用visudo編輯sudoers文件,以確保一次只有一個人在編輯該文件,具有適當的權限,並且拒絕寫出該文件並在所做的更改有錯誤時退出。
條目的基本結構是:
who where =(as_whom)what
該文件中包含許多有關如何自定義的文檔。現在,大多數Linux發行版都希望您在目錄/etc/sudoers.d 添加一個名稱與用戶相同的文件。該文件包含單個用戶的sudo配置,除了影響所有用戶的更改外,應保持主配置文件不變。
默認情況下,sudo 命令和所有失敗記錄在Debian發行系列下的/var/log/auth.log中,以及在 其他系統上的/ var / log / messages 和/或 / var / log / secure 中。這是重要的安全措施,可以跟蹤和負責sudo使用。消息的典型條目包含:
- 獲取使用者名稱
- 信息終端
- 工作目錄
- 用戶帳號被調用
- 帶參數的命令。
運行諸如sudo whoami之類的命令將生成一個日誌文件條目,例如:
Dec 8 14:20:47 server1 sudo:op:TTY = pts / 6 PWD = / var / log USER = root COMMAND = / usr / bin / whoami
Linux被認爲比許多其他操作系統更安全,因爲進程自然相互隔離。一個進程通常無法訪問另一進程的資源,即使該進程以相同的用戶權限運行。因此,Linux使得病毒和安全漏洞難以(儘管當然不是不可能)訪問和攻擊系統上的隨機資源。
最新的限制風險的其他安全機制甚至還包括:
- 控制組(cgroups)
允許系統管理員對進程進行分組,並將有限的資源關聯到每個cgroup。 - 容器
使依靠cgroups在單個系統上運行多個隔離的Linux系統(容器)成爲可能。 - 虛擬化
硬件的仿真方式不僅可以隔離進程,而且可以在一個物理主機上將整個系統作爲隔離和隔離的來賓(虛擬機)同時運行。
Linux以與常規文件訪問極爲相似的方式,限制用戶對非網絡硬件設備的訪問。應用程序通過參與文件系統層(與文件所駐留的實際設備或硬件無關)進行交互。然後,該層將在/ dev 目錄下打開與要訪問的設備相對應的設備專用文件(通常稱爲設備節點) 。每個設備專用文件都有標準的所有者,組和世界權限字段。與訪問標準文件時一樣,自然會強制執行安全性。
例如,硬盤表示爲/ dev / sd*。儘管root用戶可以原始方式讀取和寫入磁盤,例如通過執行以下操作:
$ echo hello world> / dev / sda1
如圖所示,標準權限使普通用戶無法這樣做。以這種方式寫入設備可以很容易地消除存儲在其上的文件系統,而如果不花大力氣就無法修復。應用程序對硬盤上文件的正常讀寫是通過文件系統在更高級別完成的,而不是通過直接訪問設備節點來完成的。
當發現Linux內核或應用程序和庫中的安全性問題時,Linux發行版就具有快速反應並通過更新其軟件存儲庫併發送通知以立即進行更新來對所有系統推出修復程序的良好記錄。與安全無關的錯誤修復和性能改進也是如此。
但是,衆所周知,許多系統沒有得到足夠頻繁的更新,並且已經解決的問題被允許在計算機上保留很長時間。對於專有操作系統,尤其是其中用戶不瞭解或不信任供應商的修補策略的情況尤其如此,因爲有時更新可能會導致新問題並破壞現有操作。許多最成功的攻擊媒介來自利用安全漏洞的漏洞,這些漏洞的修補程序是已知的,但並未得到普遍部署。
因此,最佳實踐是利用Linux發行版的自動更新機制,而不要推遲更新。這樣的更新將引起新的問題是非常罕見的。
4. 設置密碼
系統使用用戶憑證驗證真實性和身份。
最初,加密的密碼存儲在/ etc / passwd文件中,每個人都可以讀取。這樣就很容易破解密碼。
在現代系統上,密碼實際上以加密格式存儲在名爲/ etc / shadow的輔助文件中。只有具有root用戶訪問權限的用戶才能修改/讀取此文件。
保護密碼已成爲安全性的關鍵要素。大多數Linux發行版都依賴於由美國國家安全局(NSA)開發的稱爲SHA-512(安全哈希算法512位)的現代密碼加密算法來加密密碼。
SHA-512算法廣泛用於安全應用程序和協議。這些安全應用程序和協議包括TLS,SSL,PHP,SSH,S / MIME和IPSec。SHA-512是最受測試的哈希算法之一。
例如,如果您想嘗試使用SHA-512編碼,則可以使用sha512sum 程序對單詞“ test”進行編碼,以生成SHA-512形式(參見圖形):
IT專業人員遵循幾種保護每個用戶的數據和密碼的良好做法。
- 密碼時效是一種確保用戶在特定時間段後收到提示提醒他們創建新密碼的提示的方法。這樣可以確保密碼(如果被破解)只能在有限的時間內使用。使用chage可以實現此功能, 後者可以爲用戶配置密碼到期信息。
- 另一種方法是強制用戶使用可插入身份驗證模塊(PAM)設置強密碼。可以將PAM配置爲自動驗證使用passwd 實用程序創建或修改的密碼是否足夠強。PAM配置是使用名爲pam_cracklib.so的庫實現的,也可以用pam_passwdqc.so替換該庫以獲得更多選項。
- 還可以安裝密碼破解程序,例如John The Ripper,以保護密碼文件並檢測弱密碼條目。建議在您不擁有的任何系統上安裝此類工具之前,先獲得書面授權。
5. 保護引導進程與硬件資源
您可以使用安全密碼來保護引導過程,以防止他人繞過用戶身份驗證步驟。對於使用舊版本GRUB 引導加載程序1的系統, 您可以調用grub-md5-crypt ,該提示將提示您輸入密碼,然後進行加密。
然後,您必須通過在超時條目下方添加以下行來編輯/boot/grub/grub.conf:
password --md5 $1$74r8m1$NmkE69eAjXre.oF1k0cyk/
您也可以僅對某些引導選項而不是全部強制輸入密碼。
但是,對於GRUB 版本2(現在已經幾乎完全接管),情況變得更加複雜。當您擁有更大的靈活性時,您可以利用更高級的功能,例如特定於用戶的密碼(可以是它們的常規登錄密碼)。另外,您永遠不會直接編輯配置文件/boot/grub/grub.cfg,而是在/etc/grub.d中 編輯系統配置文件 ,然後在Linux發行版上運行update-grub或同等實用程序。
要了解更多信息,請閱讀以下文章:“ GRUB 2 Password Protection ”。
當物理上可訪問硬件時,安全性可能受到以下因素的損害:
- 按鍵記錄
記錄計算機用戶的實時活動,包括他們按下的鍵。捕獲的數據可以存儲在本地,也可以傳輸到遠程計算機。 - 網絡嗅探
在網絡上捕獲和查看網絡數據包級別的數據。 - 使用活動或救援磁盤引導
- 重新安裝和修改磁盤內容。
您的IT安全策略應從對如何正確保護對服務器和工作站的物理訪問的要求開始。對系統的物理訪問使攻擊者可以輕鬆地利用幾種攻擊媒介,從而使所有操作系統級別的建議都不相關。
安全準則是:
- 鎖定工作站和服務器。
- 保護您的網絡鏈接,以使不信任的人無法訪問它。
- 保護您輸入密碼的鍵盤,以確保不會篡改鍵盤。
- 確保密碼以某種方式保護BIOS,以致無法使用實時或應急DVD或USB密鑰引導系統。
對於單用戶計算機和家庭環境中的計算機,上述某些功能(例如防止從可移動媒體啓動)可能會過多,您可以避免實施它們。但是,如果您的系統上的敏感信息需要仔細保護,則不應該存在該敏感信息,或者應該按照上述準則對其進行更好的保護。
像所有軟件一樣,黑客有時會發現Linux生態系統中的弱點。Linux(通常是開放源代碼社區)的強項是暴露和修復此類漏洞的速度。儘管對漏洞的特定討論不在本課程的範圍內,但我們爲討論板(在“ 本地安全 ”主題下)播種了幾個相關主題,以鼓勵進一步討論。