Shell從入門到精通_第1頁
Shell從入門到精通_第2頁
Shell從入門到精通_第3頁
Shell從入門到精通_第4頁
Shell從入門到精通_第5頁
已閱讀5頁,還剩161頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

前言學習目標熟悉Linux系統(tǒng)常用命令與工具,掌握Shell腳本語言語法結構,能獨立編寫Shell腳本,完成自動化運維常規(guī)任務,提高工作效率,為以后學習其他語言打下堅實的基礎。目標人群運維工程師、開發(fā)工程師、Linux系統(tǒng)愛好者或已經具備其他編程語言的人群。操作系統(tǒng)本文檔實驗均采用CentOS7_X64系統(tǒng)。目錄第一章Shell基礎知識 81.1Shell簡介 81.2Shell基本分兩大類 91.3第一個Shell腳本 91.4Shell變量 101.5變量引用 121.6雙引號和單引號 131.7注釋 14第二章Shell字符串處理之${} 142.1獲取字符串長度 142.2字符串切片 142.3替換字符串 152.4字符串截取 152.5變量狀態(tài)賦值 162.6字符串顏色 16第三章Shell表達式與運算符 173.1條件表達式 173.2整數(shù)比較符 183.3字符串比較符 183.4文件測試 193.5布爾運算符 193.6邏輯判斷符 203.7整數(shù)運算 203.8其他運算工具(let/expr/bc) 213.9Shell括號用途總結 22第四章Shell流程控制 234.1if語句 234.2for語句 254.3while語句 264.4break和continue語句 284.5case語句 294.6select語句 30第五章Shell函數(shù)與數(shù)組 325.1函數(shù) 325.2數(shù)組 34第六章Shell正則表達式 35第七章Shell文本處理三劍客 387.1grep 387.2sed 427.2.1匹配打?。╬) 447.2.2匹配刪除(d) 467.2.3替換(s///) 477.2.4多重編輯(-e) 507.2.5添加新內容(a、i和c) 507.2.6讀取文件并追加到匹配行后(r) 527.2.7將匹配行寫到文件(w) 527.2.8讀取下一行(n和N) 537.2.9打印和刪除模式空間第一行(P和D) 557.2.10保持空間操作(h與H、g與G和x) 557.2.11標簽(:、b和t) 577.2.12忽略大小寫匹配(I) 597.2.13獲取總行數(shù)(#) 598.3awk 598.3.1選項 608.3.2模式 608.3.3內置變量 658.3.4操作符 708.3.5流程控制 748.3.6數(shù)組 778.3.7內置函數(shù) 808.3.8I/O語句 848.3.9printf語句 878.3.10自定義函數(shù) 888.3.11需求案例 89第八章Shell標準輸入、輸出和錯誤 948.1標準輸入、輸出和錯誤 948.2重定向符號 948.3重定向輸出 958.4重定向輸入 958.5重定向標準輸出和標準錯誤 958.6重定向到空設備 968.7read命令 97第九章Shell信號發(fā)送與捕捉 989.1Linux信號類型 989.2kill命令 1009.3trap命令 100第十章Shell編程時常用的系統(tǒng)文件 10210.1Linux系統(tǒng)目錄結構 10210.2環(huán)境變量文件 10310.3系統(tǒng)配置文件 10310.4/dev目錄 10410.5/proc目錄 10410.5.1/proc 10510.5.2/proc/net 10510.5.3/proc/sys 106第十一章Shell常用命令與工具 10811.1ls 10811.2echo 10911.3printf 10911.4cat 11011.5tac 11111.6rev 11111.7wc 11111.8cp 11111.9mkdir 11211.10mv 11211.11rename 11211.12dirname 11311.13basename 11311.14du 11311.15cut 11411.16tr 11411.17stat 11511.18seq 11511.19shuf 11611.20sort 11611.21uniq 11711.22tee 11811.23join 11911.24paste 11911.25head 12011.26tail 12011.27find 12011.28xargs 12211.29nl 12211.30date 12311.31wget 12411.32curl 12611.33scp 12711.34rsync 12811.35nohup 12811.36iconv 12911.37uname 12911.38sshpass 12911.39tar 13011.40logger 13011.41netstat 13111.42ss 13111.43lsof 13211.44ps 13311.45top 13411.46free 13511.47df 13611.48vmstat 13611.49iostat 13711.50sar 13711.51dstat 13811.52ip 13811.53nc 13911.54time 14011.55eval 14111.56ssh 14111.57iptables 142第十二章Shell腳本編寫實戰(zhàn) 14512.1獲取隨機字符串或數(shù)字 14512.2定義一個顏色輸出字符串函數(shù) 14612.3批量創(chuàng)建用戶 14712.4檢查軟件包是否安裝 14712.5檢查服務狀態(tài) 14712.6檢查主機存活狀態(tài) 14812.7監(jiān)控CPU、內存和硬盤利用率 14912.8批量主機磁盤利用率監(jiān)控 15012.9檢查網(wǎng)站可用性 15112.10檢查MySQL主從同步狀態(tài) 15212.11屏蔽訪問頻繁的IP 15312.12判斷輸入是否為IP 15412.13判斷輸入是否為數(shù)字 15512.14找出包含關鍵字的文件 15512.15監(jiān)控目錄,將新創(chuàng)建的文件名追加到日志中 15612.16多個網(wǎng)卡選擇 15612.17查看網(wǎng)卡實時流量 15712.18MySQL數(shù)據(jù)庫備份 15812.19Nginx啟動腳本 15812.20選擇SSH連接主機 16012.21FTP下載文件 16012.22輸入五個100數(shù)之內的字符,統(tǒng)計和、最小和最大 16112.23將結果分別賦值給變量 16112.24批量修改文件 16212.25統(tǒng)計當前目錄中以.html結尾的文件總大小 16212.26掃描主機端口狀態(tài) 16212.27Expect實現(xiàn)SSH免交互執(zhí)行命令 16312.28批量修改服務器用戶密碼 16512.29打印乘法口訣 16512.30getopts工具完善腳本命令行參數(shù) 166第一章Shell基礎知識1.1Shell簡介Shell是一個C語言編寫的腳本語言,它是用戶與Linux的橋梁,用戶輸入命令交給Shell處理,Shell將相應的操作傳遞給內核(Kernel),內核把處理的結果輸出給用戶。下面是流程示意圖:命令用戶執(zhí)行動作命令用戶執(zhí)行動作解析命令解析命令并傳遞給內核ShellShellKernelKernelShell既然是工作在Linux內核之上,那我們也有必要了解下Linux相關知識。Linux是一套免費試用和自由傳播的類Unix操作系統(tǒng),是一個基于POSIX和UNIX的多用戶、多任務、支持多線程和多CPU的操作系統(tǒng)。1983年9月27日,RichardStallman(理查德-馬修-斯托曼)發(fā)起GNU計劃,它的目標是創(chuàng)建一套完全自由的操作系統(tǒng)。為保證GNU軟件可以自由的使用、復制、修改和發(fā)布,所有的GNU軟件都有一份在禁止其他人添加任何限制的情況下授權所有權利給任何人的協(xié)議條款,GNU通用公共許可證(GNUGeneralPlubicLicense,GPL),說白了就是不能做商業(yè)用途。GNU是"GNUisNotUnix"的遞歸縮寫。UNIX是一種廣泛使用的商業(yè)操作系統(tǒng)的名稱。1985年,RichardStallman又創(chuàng)立了自由軟件基金會(FreeSoftwareFoundation,F(xiàn)SF)來為GNU計劃提供技術、法律以及財政支持。1990年,GNU計劃開發(fā)主要項目有Emacs(文本編輯器)、GCC(GNUCompilerCollection,GNU編譯器集合)、Bash等,GCC是一套GNU開發(fā)的編程語言編譯器。還有開發(fā)一些UNIX系統(tǒng)的程序庫和工具。1991年,LinuxsTorvalds(林納斯-托瓦茲)開發(fā)出了與UNIX兼容的Linux操作系統(tǒng)內核并在GPL條款下發(fā)布。1992年,Linux與其他GUN軟件結合,完全自由的GUN/Linux操作系統(tǒng)正式誕生,簡稱Linux。1995年1月,BobYoung創(chuàng)辦ACC公司,以GNU/Linux為核心,開發(fā)出了RedHatLinux商業(yè)版。Linux基本思想有兩點:第一,一切都是文件;第二,每個軟件都有確定的用途。與Unix思想十分相近。1.2Shell基本分兩大類1.2.1圖形界面Shell(GUIShell)GUI為Unix或者類Unix操作系統(tǒng)構造一個功能完善、操作簡單以及界面友好的桌面環(huán)境。主流桌面環(huán)境有KDE,Gnome等。1.2.2命令行界面Shell(CLIShell)CLI是在用戶提示符下鍵入可執(zhí)行指令的界面,用戶通過鍵盤輸入指令,完成一系列操作。在Linux系統(tǒng)上主流的CLI實現(xiàn)是Bash,是許多Linux發(fā)行版默認的Shell。還有許多Unix上Shell,例如tcsh、csh、ash、bsh、ksh等。1.3第一個Shell腳本本教程主要講解在大多Linux發(fā)行版下默認BashShell。Linux系統(tǒng)是RedHat下的CentOS操作系統(tǒng),完全免費。與其商業(yè)版RHEL(RedHatEnterpriseLinux)出自同樣的源代碼,不同的是CentOS并不包含封閉源代碼軟件和售后支持。用vi打開test.sh,編寫:#vitest.sh#!/bin/bashecho"Helloworld!"第一行指定解釋器,第二行打印Helloworld!寫好后,開始執(zhí)行,執(zhí)行Shell腳本有三種方法:方法1:直接用bash解釋器執(zhí)行#bashtest.shHelloworld!當前終端會新生成一個子bash去執(zhí)行腳本。方法2:添加可執(zhí)行權限#lltest.sh-rw-r--r--.1rootroot32Aug1801:07test.sh#chmod+xtest.sh#./test.sh

-bash:./test.sh:Permissiondenied#chmod+xtest.sh#./test.sh#./在當前目錄Helloworld!這種方式默認根據(jù)腳本第一行指定的解釋器處理,如果沒寫以當前默認Shell解釋器執(zhí)行。方法3:source命令執(zhí)行,以當前默認Shell解釋器執(zhí)行#sourcetest.shHelloworld!1.4Shell變量1.4.1系統(tǒng)變量在命令行提示符直接執(zhí)行env、set查看系統(tǒng)或環(huán)境變量。env顯示用戶環(huán)境變量,set顯示Shell預先定義好的變量以及用戶變量??梢酝ㄟ^export導出成用戶變量。一些寫Shell腳本時常用的系統(tǒng)變量:$SHELL默認Shell$HOME當前用戶家目錄$IFS內部字段分隔符$LANG默認語言$PATH默認可執(zhí)行程序路徑$PWD當前目錄$UID當前用戶ID$USER當前用戶$HISTSIZE歷史命令大小,可通過HISTTIMEFORMAT變量設置命令執(zhí)行時間$RANDOM隨機生成一個0至32767的整數(shù)$HOSTNAME主機名1.4.2普通變量與臨時環(huán)境變量普通變量定義:VAR=value臨時環(huán)境變量定義:exportVAR=value變量引用:$VAR下面看下他們之間區(qū)別:Shell進程的環(huán)境變量作用域是Shell進程,當export導入到系統(tǒng)變量時,則作用域是Shell進程及其Shell子進程。psaxjf輸出的第一列是PPID(父進程ID),第二列是PID(子進程ID)當SSH連接Shell時,當前終端PPID(-bash)是sshd守護程序的PID(root@pts/0),因此在當前終端下的所有進程的PPID都是-bash的PID,比如執(zhí)行命令、運行腳本。所以當在-bash下設置的變量,只在-bash進程下有效,而-bash下的子進程bash是無效的,當export后才有效。進一步說明:再重新連接SSH,去除上面定義的變量測試下所以在當前shell定義的變量一定要export,否則在寫腳本時,會引用不到。還需要注意的是退出終端后,所有用戶定義的變量都會清除。在/etc/profile下定義的變量就是這個原理,后面有章節(jié)會講解Linux常用變量文件。1.4.3位置變量位置變量指的是函數(shù)或腳本后跟的第n個參數(shù)。$1-$n,需要注意的是從第10個開始要用花括號調用,例如${10}shift可對位置變量控制,例如:#!/bin/bashecho"1:$1"shiftecho"2:$2"shiftecho"3:$3"#bashtest.shabc1:a2:c3:每執(zhí)行一次shift命令,位置變量個數(shù)就會減一,而變量值則提前一位。shiftn,可設置向前移動n位。1.4.4特殊變量$0腳本自身名字$?返回上一條命令是否執(zhí)行成功,0為執(zhí)行成功,非0則為執(zhí)行失敗$#位置參數(shù)總數(shù)$*所有的位置參數(shù)被看做一個字符串$@每個位置參數(shù)被看做獨立的字符串$$當前進程PID$!上一條運行后臺進程的PID1.5變量引用賦值運算符示例=變量賦值+=兩個變量相加1.5.1自定義變量與引用#VAR=123#echo$VAR123#VAR+=456#echo$VAR123456Shell中所有變量引用使用$符,后跟變量名。有時個別特殊字符會影響正常引用,那么需要使用${VAR},例如:#VAR=123#echo$VAR123#echo$VAR_

#

Shell允許VAR_為變量名,所以此引用認為這是一個有效的變量名,故此返回空#echo${VAR}123還有時候變量名與其他字符串緊礙著,也會誤認為是整個變量:#echo$VAR456#echo${VAR}4561234561.5.2將命令結果作為變量值#VAR=`echo123`

#echo$VAR123#VAR=$(echo123)#echo$VAR123這里的反撇號等效于$(),都是用于執(zhí)行Shell命令。1.6雙引號和單引號在變量賦值時,如果值有空格,Shell會把空格后面的字符串解釋為命令:#VAR=123-bash:2:commandnotfound#VAR="123"#echo$VAR123#VAR='123'#echo$VAR

123看不出什么區(qū)別,再舉個說明:#N=3#VAR="12$N"#echo$VAR123#VAR='12$N'#echo$VAR12$N單引號是告訴Shell忽略特殊字符,而雙引號則解釋特殊符號原有的意義,比如$、!。1.7注釋Shell注釋也很簡單,只要在每行前面加個#號,即表示Shell忽略解釋。第二章Shell字符串處理之${}上一章節(jié)講解了為什么用${}引用變量,${}還有一個重要的功能,就是文本處理,單行文本基本上可以滿足你所有需求。2.1獲取字符串長度#VAR='helloworld!'#echo$VARhelloworld!#echo${#VAR}122.2字符串切片格式:${parameter:offset}${parameter:offset:length}截取從offset個字符開始,向后length個字符。截取hello字符串:#VAR='helloworld!'#echo${VAR:0:5}hello截取wo字符:#echo${VAR:6:2}wo截取world!字符串:#echo${VAR:5}world!截取最后一個字符:#echo${VAR:(-1)}!截取最后二個字符:#echo${VAR:(-2)}d!截取從倒數(shù)第3個字符后的2個字符:#echo${VAR:(-3):2}ld2.3替換字符串格式:${parameter/pattern/string}#VAR='helloworldworld!'將第一個world字符串替換為WORLD:#echo${VAR/world/WORLD}helloWORLDworld!將全部world字符串替換為WORLD:#echo${VAR//world/WORLD}helloWORLDWORLD!替換正則匹配為空:#VAR=123abc#echo${VAR//[^0-9]/}123#echo${VAR//[0-9]/}abcpatterm前面開頭一個正斜杠為只匹配第一個字符串,兩個正斜杠為匹配所有字符。2.4字符串截取格式:${parameter#word}

#刪除匹配前綴${parameter##word}

${parameter%word}

#刪除匹配后綴${parameter%%word}#去掉左邊,最短匹配模式,##最長匹配模式。%去掉右邊,最短匹配模式,%%最長匹配模式。#URL="/baike/user.html"以//為分隔符截取右邊字符串:#echo${URL#*//}

/baike/user.html以/為分隔符截取右邊字符串:#echo${URL##*/}user.html以//為分隔符截取左邊字符串:#echo${URL%%//*}

http:以/為分隔符截取左邊字符串:#echo${URL%/*}/baike以.為分隔符截取左邊:#echo${URL%.*}/baike/user以.為分隔符截取右邊:#echo${URL##*.}html2.5變量狀態(tài)賦值${VAR:-string}

如果VAR變量為空則返回string${VAR:+string}

如果VAR變量不為空則返回string${VAR:=string}

如果VAR變量為空則重新賦值VAR變量值為string${VAR:?string}

如果VAR變量為空則將string輸出到stderr如果變量為空就返回helloworld!:#VAR=#echo${VAR:-'helloworld!'}helloworld!如果變量不為空就返回helloworld!:#VAR="hello"#echo${VAR:+'helloworld!'}helloworld!如果變量為空就重新賦值:#VAR=#echo${VAR:=hello}hello#echo$VARhello如果變量為空就將信息輸出stderr:#VAR=#echo${VAR:?valueisnull}

-bash:VAR:valueisnull${}主要用途大概就這么多了,另外還可以獲取數(shù)組元素,在后面章節(jié)會講到。2.6字符串顏色再介紹下字符串輸出顏色,有時候關鍵地方需要醒目,顏色是最好的方式:字體顏色字體背景顏色顯示方式30:黑31:紅32:綠33:黃34:藍色35:紫色36:深綠37:白色40:黑41:深紅42:綠43:黃色44:藍色45:紫色46:深綠47:白色0:終端默認設置1:高亮顯示4:下劃線5:閃爍7:反白顯示8:隱藏格式:\033[1;31;40m

#1是顯示方式,可選。31是字體顏色。40m是字體背景顏色。\033[0m

#恢復終端默認顏色,即取消顏色設置。示例:#!/bin/bash#字體顏色foriin{31..37};do

echo-e"\033[$i;40mHelloworld!\033[0m"done#背景顏色foriin{41..47};do

echo-e"\033[47;${i}mHelloworld!\033[0m"done#顯示方式foriin{1..8};do

echo-e"\033[$i;31;40mHelloworld!\033[0m"done第三章Shell表達式與運算符3.1條件表達式表達式示例[expression][1-eq1]

[[expression]][[1-eq1]]test

expressiontest1-eq1,等同于[]3.2整數(shù)比較符比較符描述示例-eq,equal等于[1-eq1]為true-ne,notequal不等于[1-ne1]為false-gt,greaterthan大于[2-gt1]為true-lt,lesserthan小于[2-lt1]為false-ge,greaterorequal大于或等于[2-ge

1]為true-le,lesserorequal小于或等于[2-le1]為false3.3字符串比較符運算符描述示例==等于["a"=="a"

]為true!=不等于["a"!="a"

]為false>大于,判斷字符串時根據(jù)ASCII碼表順序,不常用在[]表達式中:[2\>1]為true在[[]]表達式中:[[2>1]]為true在(())表達式中:((3>2))為true<小于,判斷字符串時根據(jù)ASCII碼表順序,不常用在[]表達式中:[2\<1]為false在[[]]表達式中:[[2<1]]為false在(())表達式中:((3<2))為false>=大于等于在(())表達式中:((3>=2))為true<=小于等于在(())表達式中:((3<=2))為false-n字符串長度不等于0為真VAR1=1;VAR2=""[-n"$VAR1"]為true[-n"$VAR2"]為false-z字符串長度等于0為真VAR1=1;VAR2=""[-z"$VAR1"]為false[-z"$VAR2"]為truestr字符串存在為真VAR1=1;VAR2=""[$VAR1]為true[$VAR2]為false需要注意的是,使用-z或-n判斷字符串長度時,變量要加雙引號。舉例說明:#[-z$a]&&echoyes||echonoyes#[-n$a]&&echoyes||echonoyes#加了雙引號才能正常判斷是否為空#[-z"$a"]&&echoyes||echonoyes#[-n"$a"]&&echoyes||echonono#使用了雙中括號就不用了雙引號#[[-n$a]]&&echoyes||echonono#[[-z$a]]&&echoyes||echonoyes3.4文件測試測試符描述示例-e文件或目錄存在為真[-epath]path存在為true-f文件存在為真[-ffile_path]文件存在為true-d目錄存在為真[-ddir_path]目錄存在為true-r有讀權限為真[-r

file_path]

file_path有讀權限為true-w有寫權限為真[-w

file_path]

file_path有寫權限為true-x有執(zhí)行權限為真[-x

file_path]

file_path有執(zhí)行權限為true-s文件存在并且大小大于0為真[-s

file_path]

file_path存在并且大小大于0為true3.5布爾運算符運算符描述示例!非關系,條件結果取反[!1-eq2]為true-a和關系,在[]表達式中使用[1-eq1-a2-eq2]為true-o或關系,在[]表達式中使用[1-eq1-o2-eq1]為true3.6邏輯判斷符判斷符描述示例&&邏輯和,在[[]]和(())表達式中或判斷表達式是否為真時使用[[1-eq1&&2-eq2]]為true((1==1&&2==2))為true[1-eq1]&&echoyes如果&&前面表達式為true則執(zhí)行后面的||邏輯或,在[[]]和(())表達式中或判斷表達式是否為真時使用[[1-eq1||2-eq1]]為true((1==1||2==2))為true[1-eq2]||echoyes如果||前面表達式為false則執(zhí)行后面的3.7整數(shù)運算運算符描述+加法-減法*乘法/除法%取余運算表達式示例$(())$((1+1))$[]$[1+1]上面兩個都不支持浮點運算。$(())表達式還有一個用途,三目運算:#如果條件為真返回1,否則返回0#echo$((1<0))

0#echo$((1>0))1指定輸出數(shù)字:#echo$((1>0?1:2))

1#echo$((1<0?1:2))2注意:返回值不支持字符串3.8其他運算工具(let/expr/bc)除了Shell本身的算數(shù)運算表達式,還有幾個命令支持復雜的算數(shù)運算:命令描述示例let賦值并運算,支持++、--letVAR=(1+2)*3;echo$VARx=10;y=5letx++;echo$x每執(zhí)行一次x加1lety--;echo$y每執(zhí)行一次y減1letx+=2每執(zhí)行一次x加2letx-=2每執(zhí)行一次x減2expr乘法*需要加反斜杠轉義\*expr1\*2

運算符兩邊必須有空格expr\(1+2\)\*2

使用雙括號時要轉義bc計算器,支持浮點運算、平方等bc本身就是一個計算器,可直接輸入命令,進入解釋器。echo1+2|bc將管道符前面標準輸出作為bc的標準輸入echo"1.2+2"|bcecho"10^10"|bc

echo'scale=2;10/3'|bc

用scale保留兩位小數(shù)點由于Shell不支持浮點數(shù)比較,可以借助bc來完成需求:#echo"1.2<2"|bc1#echo"1.2>2"|bc0#echo"1.2==2.2"|bc0#echo"1.2!=2.2"|bc1看出規(guī)律了嘛?運算如果為真返回1,否則返回0,寫一個例子:#[$(echo"2.2>2"|bc)-eq1]&&echoyes||echonoyes#[$(echo"2.2<2"|bc)-eq1]&&echoyes||echononoexpr還可以對字符串操作:獲取字符串長度:#exprlength"string"6截取字符串:#exprsubstr"string"46ing獲取字符在字符串中出現(xiàn)的位置:#exprindex"string"str1#exprindex"string"i4獲取字符串開始字符出現(xiàn)的長度:#exprmatch"string"s.*6#exprmatch"string"str33.9Shell括號用途總結看到這里,想一想里面所講的小括號、中括號的用途,是不是有點懵逼了。那我們總結一下!()用途1:在運算中,先計算小括號里面的內容用途2:數(shù)組用途3:匹配分組(())用途1:表達式,不支持-eq這類的運算符。不支持-a和-o,支持<=、>=、<、>這類比較符和&&、||用途2:C語言風格的for(())表達式$()執(zhí)行Shell命令,與反撇號等效$(())用途1:簡單算數(shù)運算用途2:支持三目運算符

$((表達式?數(shù)字:數(shù)字

))[]條件表達式,里面不支持邏輯判斷符[[]]條件表達式,里面不支持-a和-o,不支持<=和>=比較符,支持-eq、<、>這類比較符。支持=~模式匹配,也可以不用雙引號也不會影響原意,比[]更加通用$[]簡單算數(shù)運算{}對逗號(,)和點點(...)起作用,比如touch{1,2}創(chuàng)建1和2文件,touch{1..3}創(chuàng)建1、2和3文件${}用途1:引用變量用途2:字符串處理第四章Shell流程控制流程控制是改變程序運行順序的指令。4.1if語句格式:iflist;thenlist;[eliflist;thenlist;]...[elselist;]fi4.1.1單分支if條件表達式;then

命令fi示例:#!/bin/bashN=10if[$N-gt5];then

echoyesfi#bashtest.shyes4.1.2雙分支if條件表達式;then

命令else

命令fi示例1:#!/bin/bashN=10if[$N-lt5];then

echoyeselse

echonofi#bashtest.shno示例2:判斷crond進程是否運行#!/bin/bashNAME=crondNUM=$(ps-ef|grep$NAME|grep-vcgrep)if[$NUM-eq1];thenecho"$NAMErunning."elseecho"$NAMEisnotrunning!"fi示例3:檢查主機是否存活#!/bin/bashifping-c1>/dev/null;thenecho"OK."elseecho"NO!"fiif語句可以直接對命令狀態(tài)進行判斷,就省去了獲取$?這一步!4.1.3多分支if條件表達式;then

命令elif條件表達式;then命令else命令fi當不確定條件符合哪一個時,就可以把已知條件判斷寫出來,做相應的處理。示例1:#!/bin/bashN=$1if[$N-eq3];thenecho"eq3"elif[$N-eq5];thenecho"eq5"elif[$N-eq8];thenecho"eq8"elseecho"no"fi如果第一個條件符合就不再向下匹配。示例2:根據(jù)Linux不同發(fā)行版使用不同的命令安裝軟件#!/bin/bashif[-e/etc/redhat-release];thenyuminstallwget-yelif[$(cat/etc/issue|cut-d''-f1)=="Ubuntu"];thenapt-getinstallwget-yelseOperatingsystemdoesnotsupport.exitfi4.2for語句格式:forname[[in[word...]];]dolist;donefor變量名in取值列表;do

命令done示例:#!/bin/bashforiin{1..3};do

echo$idone#bashtest.sh123for的語法也可以這么寫:#!/bin/bashforiin"$@";{

#$@是將位置參數(shù)作為單個來處理

echo$i}#bashtest.sh123123默認for循環(huán)的取值列表是以空白符分隔,也就是第一章講系統(tǒng)變量里的$IFS:#!/bin/bashforiin1234;do

echo$idone#bashtest.sh1234如果想指定分隔符,可以重新賦值$IFS變量:#!/bin/bashOLD_IFS=$IFSIFS=":"foriin$(head-1/etc/passwd);doecho$idoneIFS=$OLD_IFS#恢復默認值#bashtest.shrootx00root/root/bin/bashfor循環(huán)還有一種C語言風格的語法,常用于計數(shù)、打印數(shù)字序列:for((expr1;expr2;expr3));dolist;done#!/bin/bashfor((i=1;i<=5;i++));do

#也可以i--

echo$idone示例1:檢查多個主機是否存活#!/bin/bashforipin192.168.1.{1..254};doifping-c1$ip>/dev/null;thenecho"$ipOK."elseecho"$ipNO!"fidone示例2:檢查多個域名是否可以訪問#!/bin/bashURL=""forurlin$URL;doHTTP_CODE=$(curl-o/dev/null-s-w%{http_code}http://$url)if[$HTTP_CODE-eq200-o$HTTP_CODE-eq301];thenecho"$urlOK."elseecho"$urlNO!"fidone4.3while語句格式:whilelist;dolist;donewhile條件表達式;do

命令done示例1:#!/bin/bashN=0while[$N-lt5];do

letN++

echo$Ndone#bashtest.sh12345當條件表達式為false時,終止循環(huán)。示例2:條件表達式為true,將會產生死循環(huán)#!/bin/bashwhile[1-eq1];do

echo"yes"done也可以條件表達式直接用true:#!/bin/bashwhiletrue;do

echo"yes"done還可以條件表達式用冒號,冒號在Shell中的意思是不做任何操作。但狀態(tài)是0,因此為true:#!/bin/bashwhile:;do

echo"yes"done示例3:逐行處理文本文本內容:#cata.txtabc123xyz要想使用while循環(huán)逐行讀取a.txt文件,有三種方式:方式1:#!/bin/bashcat./a.txt|whilereadLINE;do

echo$LINEdone方式2:#!/bin/bashwhilereadLINE;do

echo$LINEdone<./a.txt方式3:#!/bin/bashexec<./a.txt

#讀取文件作為標準輸出whilereadLINE;do

echo$LINEdone與while關聯(lián)的還有一個until語句,它與while不同之處在于,是當條件表達式為false時才循環(huán),實際使用中比較少,這里不再講解。4.4break和continue語句break是終止循環(huán)。continue是跳出當前循環(huán)。示例1:在死循環(huán)中,滿足條件終止循環(huán)#!/bin/bashN=0whiletrue;do

letN++

if[$N-eq5];then

break

fi

echo$Ndone#bashtest.sh1234里面用了if判斷,并用了break語句,它是跳出循環(huán)。與其關聯(lián)的還有一個continue語句,它是跳出本次循環(huán)。示例2:舉例子說明continue用法#!/bin/bashN=0while[$N-lt5];do

letN++

if[$N-eq3];then

continue

fi

echo$Ndone#bashtest.sh1245當變量N等于3時,continue跳過了當前循環(huán),沒有執(zhí)行下面的echo。注意:continue與break語句只能循環(huán)語句中使用。4.5case語句case語句一般用于選擇性來執(zhí)行對應部分塊命令。格式:casewordin[[(]pattern[|pattern]...)list;;]...esaccase模式名

in

模式1)

命令

;;

模式2)

命令

;;

*)

不符合以上模式執(zhí)行的命令esac每個模式必須以右括號結束,命令結尾以雙分號結束。示例:根據(jù)位置參數(shù)匹配不同的模式#!/bin/bashcase$1in

start)

echo"start."

;;

stop)

echo"stop."

;;

restart)

echo"restart."

;;

*)

echo"Usage:$0{start|stop|restart}"esac

#bashtest.shUsage:test.sh{start|stop|restart}#bashtest.shstartstart.#bashtest.shstopstop.#bashtest.shrestartrestart.上面例子是不是有點眼熟,在Linux下有一部分服務啟動腳本都是這么寫的。模式也支持正則,匹配哪個模式就執(zhí)行那個:#!/bin/bashcase$1in[0-9])echo"matchnumber.";;[a-z])echo"matchletter.";;'-h'|'--help')echo"help";;*)echo"Inputerror!"exitesac

#bashtest.sh1matchnumber.#bashtest.shamatchletter.#bashtest.sh-hhelp#bashtest.sh--helphelp模式支持的正則有:*、?、[]、[.-.]、|。后面有章節(jié)單獨講解Shell正則表達式。4.6select語句select是一個類似于for循環(huán)的語句。格式:selectname[inword];dolist;doneselect變量in選項1選項2;do

breakdone示例:#!/bin/bashselectmysql_versionin5.15.6;do

echo$mysql_versiondone#bashtest.sh1)5.12)5.6#?15.1#?25.6用戶輸入編號會直接賦值給變量mysql_version。作為菜單用的話,循環(huán)第二次后就不再顯示菜單了,并不能滿足需求。在外面加個死循環(huán),每次執(zhí)行一次select就break一次,這樣就能每次顯示菜單了:#!/bin/bashwhiletrue;do

selectmysql_versionin5.15.6;do

echo$mysql_version

break

donedone#bashtest.sh1)5.12)5.6#?15.11)5.12)5.6#?25.61)5.12)5.6如果再判斷對用戶輸入的編號執(zhí)行相應的命令,如果用if語句多分支的話要復雜許多,用case語句就簡單多了。#!/bin/bashPS3="Selectanumber:"whiletrue;do

selectmysql_versionin5.15.6quit;do

case$mysql_versionin

5.1)

echo"mysql5.1"

break

;;

5.6)

echo"mysql5.6"

break

;;

quit)

exit

;;

*)

echo"Inputerror,Pleaseenteragain!"

break

esac

donedone#bashtest.sh1)5.12)5.63)quitSelectanumber:1mysql5.11)5.12)5.63)quitSelectanumber:2mysql5.61)5.12)5.63)quitSelectanumber:3如果不想用默認的提示符,可以通過重新賦值變量PS3來自定義。這下就比較完美了!第五章Shell函數(shù)與數(shù)組5.1函數(shù)格式:func(){

command}function關鍵字可寫,也可不寫。示例1:#!/bin/bashfunc(){

echo"Thisisafunction."}func#bashtest.shThisisafunction.Shell函數(shù)很簡單,函數(shù)名后跟雙括號,再跟雙大括號。通過函數(shù)名直接調用,不加小括號。示例2:函數(shù)返回值#!/bin/bashfunc(){

VAR=$((1+1))

return$VAR

echo"Thisisafunction."}funcecho$?#bashtest.sh2return在函數(shù)中定義狀態(tài)返回值,返回并終止函數(shù),但返回的只能是0-255的數(shù)字,類似于exit。示例3:函數(shù)傳參#!/bin/bashfunc(){

echo"Hello$1"}funcworld#bashtest.shHelloworld通過Shell位置參數(shù)給函數(shù)傳參。函數(shù)也支持遞歸調用,也就是自己調用自己。例如:#!/bin/bashtest(){

echo$1

sleep1

testhello}test執(zhí)行會一直在調用本身打印hello,這就形成了閉環(huán)。像經典的fork炸彈就是函數(shù)遞歸調用::(){:|:&};:或

.(){.|.&};.這樣看起來不好理解,我們更改下格式::(){:|:&};:再易讀一點:bomb(){bomb|bomb&};bomb分析下::(){

}定義一個函數(shù),函數(shù)名是冒號。:調用自身函數(shù)|管道符:再一次遞歸調用自身函數(shù):|:表示每次調用函數(shù)":"的時候就會生成兩份拷貝。&放到后臺;分號是繼續(xù)執(zhí)行下一個命令,可以理解為換行。:最后一個冒號是調用函數(shù)。因此不斷生成新進程,直到系統(tǒng)資源崩潰。一般遞歸函數(shù)用的也少,了解下即可!5.2數(shù)組數(shù)組是相同類型的元素按一定順序排列的集合。格式:array=(元素1元素2元素3...)用小括號初始化數(shù)組,元素之間用空格分隔。定義方法1:初始化數(shù)組array=(abc)定義方法2:新建數(shù)組并添加元素array[下標]=元素定義方法3:將命令輸出作為數(shù)組元素array=($(command))數(shù)組操作:獲取所有元素:#echo${array[*]}

#*和@都是代表所有元素abc獲取元素下標:#echo${!a[@]}012獲取數(shù)組長度:#echo${#array[*]}3獲取第一個元素:#echo${array[0]}a獲取第二個元素:#echo${array[1]}b獲取第三個元素:#echo${array[2]}c添加元素:#array[3]=d#echo${array[*]}abcd添加多個元素:#array+=(efg)#echo${array[*]}abcdefg刪除第一個元素:#unsetarray[0]

#刪除會保留元素下標#echo${array[*]}bcdefg刪除數(shù)組:#unsetarray數(shù)組下標從0開始。示例1:講seq生成的數(shù)字序列循環(huán)放到數(shù)組里面#!/bin/bashforiin$(seq110);do

array[a]=$i

leta++doneecho${array[*]}#bashtest.sh12345678910示例2:遍歷數(shù)組元素方法1:#!/bin/bashIP=()for((i=0;i<${#IP[*]};i++));do

echo${IP[$i]}done#bashtest.sh方法2:#!/bin/bashIP=()for

IP

in${IP[*]};do

echo$IPdone

第六章Shell正則表達式正則表達式在每種語言中都會有,功能就是匹配符合你預期要求的字符串。Shell正則表達式分為兩種:基礎正則表達式:BRE(basicregularexpress)擴展正則表達式:ERE(extendregularexpress),擴展的表達式有+、?、|和()下面是一些常用的正則表達式符號,我們先拿grep工具舉例說明。符號描述示例.匹配除換行符(\n)之外的任意單個字符匹配123:echo-e"123\n456"|grep'1.3'^匹配前面字符串開頭匹配以abc開頭的行:echo-e"abc\nxyz"|grep^abc$匹配前面字符串結尾匹配以xyz結尾的行:echo-e"abc\nxyz"|grepxyz$*匹配前一個字符零個或多個匹配x、xo和xoo:echo-e"x\nxo\nxoo\no\noo"|grep"xo*"x是必須的,批量了0零個或多個+匹配前面字符1個或多個匹配abc和abcc:echo-e"abc\nabcc\nadd"|grep-E'ab+'匹配單個數(shù)字:echo"113"|grep-o'[0-9]'連續(xù)匹配多個數(shù)字:echo"113"|grep-E-o'[0-9]+'?匹配前面字符0個或1個匹配ac或abc:echo-e"ac\nabc\nadd"|grep-E'a?c'[]匹配中括號之中的任意一個字符匹配a或c:echo-e"a\nb\nc"|grep'[ac]'[.-.]匹配中括號中范圍內的任意一個字符匹配所有字母:echo-e"a\nb\nc"|grep'[a-z]'[^]匹配[^字符]之外的任意一個字符匹配a或b:echo-e"a\nb\nc"|grep'[^c-z]'匹配末尾數(shù)字:echo"abc:cde;123"|grep-E'[^;]+$'^[^]匹配不是中括號內任意一個字符開頭的行匹配不是#開頭的行:grep'^[^#]'/etc/httpd/conf/httpd.conf{n}或{n,}匹配花括號前面字符至少n個字符匹配abc字符串(至少三個字符以上字符串):echo-e"a\nabc\nc"|grep-E'[a-z]{3}'

{n,m}匹配花括號前面字符至少n個字符,最多m個字符匹配12和123(不加邊界符會匹配單個字符):echo-e"1\n12\n123\n1234"|grep-E-w-o'[0-9]{2,3}'\<邊界符,匹配字符串開始匹配開始是123和1234:echo-e"1\n12\n123\n1234"|grep'\<123'\>邊界符,匹配字符串結束匹配結束是1234:echo-e"1\n12\n123\n1234"|grep'4\>'()單元或組合:將小括號里面作為一個組合分組:匹配小括號中正則表達式或字符。\n反向引用,n是數(shù)字,從1開始編號,表示引用第n個分組匹配的內容單元:匹配123a字符串echo"123abc"|grep-E-o'([0-9a-z]){4}'分組:匹配11echo"113abc"|grep-E-o'(1)\1'匹配出現(xiàn)xo出現(xiàn)零次或多次:echo-e"x\nxo\nxoo\no\noo"|egrep"(xo)*"|匹配豎杠兩邊的任意一個匹配12和123:echo-e"1\n12\n123\n1234"|grep-E'12\>|123\>'\轉義符,將特殊符號轉成原有意義1.2,匹配1.2:1\.2,否則112也會匹配到Posix字符描述[:alnum:]等效[a-zA-Z0-9][:alpha:]等效[a-zA-Z][:lower:]等效[a-z][:upper:]等效[A-Z][:digit:]等效[0-9][:space:]匹配任意空白字符,等效[\t\n\r\f\v][:graph:]非空白字符[:blank:]空格與定位字符[:cntrl:]控制字符[:print:]可顯示的字符[:punct:]標點符號字符[:xdigit:]十六進制示例:echo-e"1\n12\n123\n1234a"|grep'[[:digit:]]'在Shell下使用這些正則表達式處理文本最多的命令有下面幾個工具:命令描述grep默認不支持擴展表達式,加-E選項開啟ERE。如果不加-E使用花括號要加轉義符\{\}egrep支持基礎和擴展表達式awk支持egrep所有的正則表達式sed默認不支持擴展表達式,加-r選項開啟ERE。如果不加-r使用花括號要加轉義符\{\}支持的特殊字符描述\w匹配任意數(shù)字和字母,等效[a-zA-Z0-9_]\W與\w相反,等效[^a-zA-Z0-9_]\b匹配字符串開始或結束,等效\<和\>\s匹配任意的空白字符\S匹配非空白字符空白符描述\n換行符\r回車符\t水平制表符\v垂直制表符\0空值符\b退后一格第七章Shell文本處理三劍客7.1grep過濾來自一個文件或標準輸入匹配模式內容。除了grep外,還有egrep、fgrep。egrep是grep的擴展,相當于grep-E。fgrep相當于grep-f,用的少。Usage:grep[OPTION]...PATTERN[FILE]...支持的正則描述-E,--extended-regexp模式是擴展正則表達式(ERE)-P,--perl-regexp模式是Perl正則表達式-e,--regexp=PATTERN使用模式匹配,可指定多個模式匹配-f,--file=FILE從文件每一行獲取匹配模式-i,--ignore-case忽略大小寫-w,--word-regexp模式匹配整個單詞-x,--line-regexp模式匹配整行-v,--invert-match打印不匹配的行輸出控制描述-m,--max-count=NUM輸出匹配的結果num數(shù)-n,--line-number打印行號-H,--with-filename打印每個匹配的文件名-h,--no-filename不輸出文件名-o,--only-matching只打印匹配的內容-q,--quiet不輸出正常信息-s,--no-messages不輸出錯誤信息-r,--recursive遞歸目錄-c,--count只打印每個文件匹配的行數(shù)--include=FILE_PATTERN--exclude=FILE_PATTERN--exclude-from=FILE--exclude-dir=PATTERN只檢索匹配的文件跳過匹配的文件跳過匹配的文件,來自文件模式跳過匹配的目錄內容行控制描述-B,--before-context=NUM打印匹配的前幾行-A,--after-context=NUM打印匹配的后幾行-C,--context=NUM打印匹配的前后幾行--color[=WHEN],匹配的字體顏色示例:1)輸出b文件中在a文件相同的行#grep-fab2)輸出b文件中在a文件不同的行#grep-v-fab3)匹配多個模式#echo"abcde"|xargs-n1|grep-e'a'-e'bc'abc4)去除空格http.conf文件空行或開頭#號的行#grep-E-v"^$|^#"/etc/httpd/conf/httpd.conf5)匹配開頭不分大小寫的單詞#echo"Aabc"|xargs-n1|grep-ia或#echo"Aabc"|xargs-n1|grep

'[Aa]'Aa6)只顯示匹配的字符串#echo"thisisatest"|grep-o'is'isis7)輸出匹配的前五個結果#seq120|grep-m5-E'[0-9]{2}'10111213148)統(tǒng)計匹配多少行#seq120|grep-c-E'[0-9]{2}'119)匹配b字符開頭的行#echo"abcde"|xargs-n1|grep'^b'bc10)匹配de字符結尾的行并輸出匹配的行#echo"aababcabcdabcde"|xargs-n1|grep-n'de$'5:abcde11)遞歸搜索/etc目錄下包含ip的conf后綴文件#grep-r''/etc--include*.conf12)排除搜索bak后綴的文件#grep-r''/opt--exclude*.bak13)排除來自file中的文件#grep-r''/opt--exclude-fromfile14)匹配41或42的數(shù)字#seq4145|grep-E'4[12]'414215)匹配至少2個字符#seq13|grep-E'[0-9]{2}'1011121316)匹配至少2個字符的單詞,最多3個字符的單詞#echo"aababcabcdabcde"|xargs-n1|grep-E-w-o'[a-z]{2,3}'ababc17)匹配所有IP#ifconfig|grep-E-o"[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"18)打印匹配結果及后3行#seq110|grep5-A3567819)打印匹配結果及前3行#seq110|grep5-B3234520)打印匹配結果及前后3行#seq110|grep5-C3234567821)不顯示輸出不顯示錯誤輸出:#grep'a'abcgrep:abc:Nosuchfileordirectory#grep-s'a'abc#echo$?2不顯示正常輸出:#grep-q'a'a.txtgrep支持上一章的基礎和擴展正則表達式字符。7.2sed流編輯器,過濾和替換文本。工作原理:sed命令將當前處理的行讀入模式空間進行處理,處理完把結果輸出,并清空模式空間。然后再將下一行讀入模式空間進行處理輸出,以此類推,直到最后一行。還有一個空間叫保持空間,又稱暫存空間,可以暫時存放一些處理的數(shù)據(jù),但不能直接輸出,只能放到模式空間輸出。這兩個空間其實就是在內存中初始化的一個內存區(qū)域,存放正在處理的數(shù)據(jù)和臨時存放的數(shù)據(jù)。Usage:sed[OPTION]...{script-only-if-no-other-script}[input-file]...sed[選項]'地址命令'file選項描述-n不打印模式空間-e執(zhí)行腳本、表達式來處理-f執(zhí)行動作從文件讀取執(zhí)行-i修改原文件-r使用擴展正則表達式命令描述s/regexp/replacement/替換字符串p打印當前模式空間P打印模式空間的第一行d刪除模式空間,開始下一個循環(huán)D刪除模式空間的第一行,開始下一個循環(huán)=打印當前行號a\text當前行追加文本i\text當前行上面插入文本c\text所選行替換新文本q立即退出sed腳本r追加文本來自文件:labellabel為b和t命令blabel分支到腳本中帶有標簽的位置,如果分支不存在則分支到腳本的末尾tlabel如果s///是一個成功的替換,才跳轉到標簽hH復制/追加模式空間到保持空間gG復制/追加保持空間到模式空間x交換模式空間和保持空間內容l打印模式空間的行,并顯示控制字符$nN讀取/追加下一行輸入到模式空間wfilename寫入當前模式空間到文件!取反、否定&引用已匹配字符串地址描述first~step步長,每step行,從第first開始$匹配最后一行/regexp/正則表達式匹配行number只匹配指定行addr1,addr2開始匹配addr1行開始,直接addr2行結束addr1,+N從addr1行開始,向后的N行addr1,~N從addr1行開始,到N行結束借助以下文本內容作為示例講解:#tail/etc/servicesnimgtw

48003/udp

#NimbusGateway3gpp-cbsp

48049/tcp

#3GPPCellBroadcastServiceProtocolisnetserv

48128/tcp

#ImageSystemsNetworkServicesisnetserv

48128/udp

#ImageSystemsNetworkServicesblp5 48129/tcp

#Bloomberglocatorblp5 48129/udp

#Bloomberglocatorcom-bardac-dw

48556/tcp

#com-bardac-dwcom-bardac-dw

48556/udp

#com-bardac-dwiqobject

48619/tcp

#iqobjectiqobject

48619/udp

#iqobject7.2.1匹配打?。╬)1)打印匹配blp5開頭的行#tail/etc/services|sed-n'/^blp5/p'blp5

48129/tcp

#Bloomberglocatorblp5

48129/udp

#Bloomberglocator2)打印第一行#tail/etc/services|sed-n'1p'

nimgtw

48003/udp

#NimbusGateway3)打印第一行至第三行#tail/etc/services|sed-n'1,3p'nimgtw

48003/udp

#NimbusGateway3gpp-cbsp

48049/tcp

#3GPPCellBroadcastServiceProtocolisnetserv

48128/tcp

#ImageSystemsNetworkServices4)打印奇數(shù)行#seq10|sed-n'1~2p'135795)打印匹配行及后一行#tail/etc/services|sed-n'/blp5/,+1p'blp5

48129/tcp

#Bloomberglocatorblp5

48129/udp

#Bloomberglocator6)打印最后一行#tail/etc/services|sed-n'$p'

iqobject

48619/udp

#iqobject7)不打印最后一行#tail/etc/services|sed-n'$!p'3gpp-cbsp

48049/tcp

#3GPPCellBroadcastServiceProtocolisnetserv

48128/tcp

#ImageSystemsNetworkServicesisnetserv

48128/udp

#ImageSystemsNetworkServicesblp5

48129/tcp

#Bloomberglocatorblp5

48129/udp

#Bloomberglocatorcom-bardac-dw

48556/tcp

#com-bardac-dwcom-bardac-dw

48556/udp

#com-bardac-dwiqobject

48619/tcp

#iqobjectiqobject

48619/udp

#iqobject感嘆號也就是對后面的命令取反。8)匹配范圍#tail/etc/services

|sed-n'/^blp5/,/^com/p'blp5

4

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論