A. linux 系統怎麼編寫一個shell腳本,檢查一個100台設備的是否都具有某項服務,如crond(定時任務
如何編寫一個shell腳本
本文結合大量實例闡述如何編寫一個shell腳本。
為什麼要進行shell編程
在Linux系統中,雖然有各種各樣的圖形化介面工具,但是sell仍然是一個非常靈活的工具。Shell不僅僅是命令的收集,而且是一門非常棒的編程語言。您可以通過使用shell使大量的任務自動化,shell特別擅長系統管理任務,尤其適合那些易用性、可維護性和便攜性比效率更重要的任務。
下面,讓我們一起來看看shell是如何工作的:
建立一個腳本
Linux中有好多中不同的shell,但是通常我們使用bash (bourne again shell) 進行shell編程,因為bash是免費的並且很容易使用。所以在本文中筆者所提供的腳本都是使用bash(但是在大多數情況下,這些腳本同樣可以在bash的大姐,bourne shell中運行)。
如同其他語言一樣,通過我們使用任意一種文字編輯器,比如nedit、kedit、emacs、vi
等來編寫我們的shell程序。
程序必須以下面的行開始(必須方在文件的第一行):
#!/bin/sh
符號#!用來告訴系統它後面的參數是用來執行該文件的程序。在這個例子中我們使用/bin/sh來執行程序。
當編輯好腳本時,如果要執行該腳本,還必須使其可執行。
要使腳本可執行:
chmod +x filename
然後,您可以通過輸入: ./filename 來執行您的腳本。
B. Linux Shell 腳本編程最佳實踐
IT路邊社
前言
與其它的編碼規范一樣,這里所討論的不僅僅是編碼格式美不美觀的問題, 同時也討論一些約定及編碼標准。這份文檔主要側重於我們所普遍遵循的規則,對於那些不是明確強制要求的,我們盡量避免提供意見。
編碼規范對於程序員而言尤為重要,有以下幾個原因:
本文檔中的准則致力於最大限度達到以下原則:
盡管本文檔涵蓋了許多基礎知識,但應注意的是,沒有編碼規范可以為我們回答所有問題,開發人員始終需要再編寫完代碼後,對上述原則做出正確的判斷。
注 :未明確指明的則默認為必須(Mandatory)
主要參考如下文檔:
僅建議Shell用作相對簡單的實用工具或者包裝腳本。因此單個shell腳本內容不宜太過復雜。
在選擇何時使用shell腳本時時應遵循以下原則:
可執行文件不建議有擴展名,庫文件必須使用 .sh 作為擴展名,且應是不可執行的。
執行一個程序時,無需知道其編寫語言,且shell腳本並不要求具有擴展名,所以更傾向可執行文件沒有擴展名。
而庫文件知道其編寫語言十分重要,使用 .sh 作為特定語言後綴的擴展名,可以和其他語言編寫的庫文件加以區分。
文件名要求全部小寫, 可以包含下劃線 _ 或連字元 - , 建議可執行文件使用連字元,庫文件使用下劃線。
正例:
反例:
源文件編碼格式為UTF-8。避免不同操作系統對文件換行處理的方式不同,一律使用 LF 。
每行最多不超過120個字元。每行代碼最大長度限制的根本原因是過長的行會導致閱讀障礙,使得縮進失效。
除了以下兩種情況例外:
如出現長度必須超過120個字元的字元串,應盡量使用here document或者嵌入的換行符等合適的方法使其變短。
示例:
除了在行結束使用換行符,空格是源文件中唯一允許出現的空白字元。
對從來沒有用到的或者被注釋的方法、變數等要堅決從代碼中清理出去,避免過多垃圾造成干擾。
Bash 是唯一被允許使用的可執行腳本shell。
可執行文件必須以 #!/bin/bash 開始。請使用 set 來設置shell的選項,使得用 bash echo "Process $: Done making $$$."
# 示例7:命令參數及路徑不需要引號 grep -li Hugo /dev/ "$1"
# 示例8:常規變數用雙引號,ccs可能為空的特殊情況可不用引號 git send-email --to "${reviewers}" ${ccs:+"--cc" "${ccs}"}
# 示例9:正則用單引號,$1可能為空的特殊情況可不用引號 grep -cP '([Ss]pecial||?characters*) ${1:+"$1"}
# 示例10:位置參數傳遞推薦帶引號的"$@",所有參數作為單字元串傳遞用帶引號的"$*" # content of t.sh func_t { echo num: $# echo args: 1:$1 2:$2 3:$3 }
func_t "$@" func_t "$*" # 當執行 ./t.sh a b c 時輸出如下: num: 3 args: 1:a 2:b 3:c num: 1 args: 1:a b c 2: 3:
使用 $(command) 而不是反引號。
因反引號如果要嵌套則要求用反斜杠轉義內部的反引號。而 $(command) 形式的嵌套無需轉義,且可讀性更高。
正例:
反例:
條件測試
使用 [[ ... ]] ,而不是 [ , test , 和 /usr/bin/[ 。
因為在 [[ 和 ]] 之間不會出現路徑擴展或單詞切分,所以使用 [[ ... ]] 能夠減少犯錯。且 [[ ... ]] 支持正則表達式匹配,而 [ ... ] 不支持。參考以下示例:
盡可能使用變數引用,而非字元串過濾。
Bash可以很好的處理空字元串測試,請使用空/非空字元串測試方法,而不是過濾字元,讓代碼具有更高的可讀性。正例:
反例:
正例:
反例:
正例:
反例:
文件名擴展
當進行文件名的通配符擴展時,請指定明確的路徑。
當目錄中有特殊文件名如以 - 開頭的文件時,使用帶路徑的擴展通配符 ./* 比不帶路徑的 * 要安全很多。
應該避免使用eval。
Eval在用於分配變數時會修改輸入內容,但設置變數的同時並不能檢查這些變數是什麼。反例:
請使用進程替換或者for循環,而不是通過管道連接while循環。
這是因為在管道之後的while循環中,命令是在一個子shell中運行的,因此對變數的修改是不能傳遞給父shell的。
這種管道連接while循環中的隱式子shell使得bug定位非常困難。反例:
如果你確定輸入中不包含空格或者其他特殊符號(通常不是來自用戶輸入),則可以用for循環代替。例如:
使用進程替換可實現重定向輸出,但是請將命令放入顯式子 shell,而非 while 循環創建的隱式子 shell。例如:
總是檢查返回值,且提供有用的返回值。
對於非管道命令,使用 $? 或直接通過 if 語句來檢查以保持其簡潔。
例如:
當內建命令可以完成相同的任務時,在shell內建命令和調用外部命令之間,應盡量選擇內建命令。
因內建命令相比外部命令而言會產生更少的依賴,且多數情況調用內建命令比調用外部命令可以獲得更好的性能(通常外部命令會產生額外的進程開銷)。
正例:
反例:
載入外部庫文件不建議用使用.,建議使用source,已提升可閱讀性。正例:
反例:
除非必要情況,盡量使用單個命令及其參數組合來完成一項任務,而非多個命令加上管道的不必要組合。常見的不建議的用法例如:cat和grep連用過濾字元串; cat和wc連用統計行數; grep和wc連用統計行數等。
正例:
除特殊情況外,幾乎所有函數都不應該使用exit直接退出腳本,而應該使用return進行返回,以便後續邏輯中可以對錯誤進行處理。正例:
反例:
推薦以下工具幫助我們進行代碼的規范:
原文鏈接:http://itxx00.github.io/blog/2020/01/03/shell-standards/
獲取更多的面試題、腳本等運維資料點擊: 運維知識社區 獲取
腳本之---簡訊轟炸機
腳本之---QQ微信轟炸機
ansible---一鍵搭建redis5.0.5集群
elk7.9真集群docker部署文檔
全球最全loki部署及配置文檔
最強安全加固腳本2.0
一鍵設置iptbales腳本
C. Linux如何編寫shell腳本
一般以#!/bin/sh開頭(不是必須要寫,但一定要單獨一行),指定執行這個腳本的shell程序(也可以用#!/bin/zsh或其他),然後就是堆命令了。
Linux的shell腳本支持很多功能,加上Linux高度模塊化的命令,完全可以用shell腳本寫出復雜的程序。
以上只是簡單介紹如何開始寫shell腳本,如果要寫復雜的腳本,還需要深入學習相關知識(如if——fi、case——esac等結構)。
當然,還需要給腳本加上可執行許可權(chmod +x ./file.sh),否則可以用sh ./file.sh方式執行腳本(這里的sh是執行腳本所需shell,命令也可以是zsh ./file.sh或其他)。
整個shell腳本,其實就相當於你在終端輸入的一系列命令,如果想在shell里做什麼,就先想想在終端可以做什麼吧,字元的的連接,就是直接用 "" 雙引號,輸出,變數定義無 $ 符號,但是使用時一定要加上 $ 符號。
"=" 賦值符號,兩邊一定不能有空格,這和其他語言有區別,尤其是你還有自己代碼美觀風格時特別注意,否則會報語法錯誤!
for 中的數組內容是以 " " 空格分隔,而非 "," 逗號分格。
條件判斷 [ true ] 中括弧 後面需要有一個空格,但是兩個中括弧之間不能有空格如 [[ true ]]。
while 條件判斷可以用 () 括弧,也可以用 [[ ]] 中括弧。
如果用windows寫shell,一定要注意換行符格式 而非 , 需要藉助一些編輯器(如notepad++)更改換行符格式!
D. 如何編寫一個shell腳本
問題:
1、請求在線api, 獲取json格式的返回結果
2、解析json裡面的一個值
3、將該值存儲到文件
開發准備:
1、shell
快速入門:
#!/bin/sh
cd ~
mkdir shell_tut
cd shell_tut
for ((i=0; i<10; i++)); do
touch test_$i.txt
done
創建一個文件夾, 並在裡面新建10個文件
2、curl
使用curl請求網路, 並獲取返回值
curl基本用法:
$ curl www.sina.com
直接返回網頁內容
$ curl -o [文件名] www.sina.com
將網頁內容存儲到文件中, 相當於wget命令
賦值操作:
response=$(curl www.sina.com)
echo $response
注意: =前後沒有空格
jq
jq是命令行解析json的很好的工具
安裝
直接到官網下載Linux64版本(我是用本地下載好後傳上伺服器的, 之前直接在伺服器用wget下載一直報錯Segmentation fault, 折騰好久~)
將其到bin目錄
cp jq-linux64 /usr/bin/jq
使用
然後就可以愉快的使用jq命令了:
可直接查看官網Tutorial
curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5'
返回的是一個json數組列表
curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.'
使用.直接指向json的根節點
curl 'https://api.github.com/repos/stedolan/jq/commits?per_page=5' | jq '.[0]'
[0]為取數組的第0位的對象
jq '.[0] | {message: .commit.message, name: .commit.committer.name}'
可用過連續的.操作獲取對應json對象中的屬性值, 上面的命令將會生成一個{message: "....", name: "...."}的json對象.
shell文件讀寫
1、寫
方式一:
將ll的內容寫入fileName這個文件中
>是覆蓋, >>是在後面追加
ll >fileName
但是在書寫.sh腳本的時候, 需要增加echo
echo ll>fileName
2、讀
while read LINE
do
echo $LINE
done<fileName
fileName是即將讀取的文件名
E. 如何在遠程伺服器上運行PowerShell命令
PowerShell在用戶管理和維護Windows方面是一個強大的命令行環境。雖然PowerShell是一個本地管理工具,但是它也用於管理遠程伺服器。事實上,管理員可以針對大量的伺服器創建PowerShell腳本來執行管理任務。Invoke-Command和New-PSSession都是在遠程伺服器中PowerShell的執行命令。
Invoke-Command
如果你只需要針對單台或者多台遠程伺服器執行一個命令(或者一系列的管道命令),那麼最便利的方法就是使用Invoke-Command命令。Microsoft的文檔列出了絕大多數的參數和語法,導致人人皆知Invoke-Command命令的復雜性。即使如此,使用Invoke-Command在遠程系統上執行命令仍然出奇地容易。
對於基本的遠程命令執行,你只需要提供遠程計算機的名稱和想要執行的代碼塊。假設你想要在名稱為Proction1的遠程伺服器上執行Get-VM命令,你可以使用下面的命令:
Invoke-Command –ComputerName Proction1 {Get-VM}
雖然這看起來很簡單,但是你也要對使用這個方法了解以下幾點。
首先,Invoke-Command命令不限制你在一個遠程系統上執行命令,你可以在多個計算機上指定命令,你需要做的就是使用命令區分開這些計算機的名稱。例如,在Proction1,Proction2和Proction3計算機上執行命令如下:
Invoke-Command –ComputerName Proction1, Proction2, Proction3 {Get-VM}
第二點,你必須要知道雖然這個方式的設計目的只是簡單地在單個遠程系統上運行的單一命令,但是你也可以運行多個命令。如果查看之前的幾行代碼,你會注意到允許在遠程計算機上運行的Get-VM命令是包含在花括弧裡面的。任何在花括弧裡面的命令都會在指定的遠程計算機行運行。同樣的,只要所有的命令都包含在花括弧裡面,你可以使用管道符號把命令把它們鏈接在一起。
第三點你必須知道上面的語法只有在所有計算機中使用了Kerberos認證才會運行,同時包括有命令輸入和已經加入了域。否則,你必須使用HTTPS傳輸,並且必須指定遠程系統是受信任的主機。