您好,登錄后才能下訂單哦!
我的自學shell過程,中間參考過鳥哥,馬哥,老男孩等各方的學習方法和過程! shell shell編程之變量 語言轉換的設備或軟件:編譯器,解釋器 編程語言:機器語言、匯編語言、高級語言 高級語言: 靜態語言:編譯型語言 有開發環境,不需要借助額外的二進制程序,寫完代碼后,通過編譯器直接轉換成二進制后再獨立執行 特征:強類型(變量) 事先轉換成可執行格式 語言類型:C、C++、JAVA、C# 動態語言:解釋型語言 特征:弱類型 邊解釋邊執行 語言類型:PHP、SHELL、Python、perl 編程模型 面向過程:SEHLL,C 編程重點在問題解決過程本身 適合開發小型 面向對象:JAVA,Python 把要實現的項目抽象成一個個對象,定義對象之間的動作 適合開發大型應用程序 變量:內存空間,命名的內存空間 內存:編址的存儲單元 變量類型(定義存儲數據的格式和長度): 字符 數值 整型 浮點型 時間 布爾型(邏輯型、真假型) 邏輯運算:與,或,非,異或 與 運算:兩者為真才為真,只要有一個假就是假 或 運算:只要有一個為真,結果即為真 非 運算:取反 異或 運算:操作數相反為真,相同為假 強類型變量:變量在使用前,必須事先聲明,甚至還需要初始化 初始化:數值初始化默認為0,字符默認初始化為空(NULL) 弱類型變量:變量使用時聲明,不區分類型,默認為字符串 變量賦值: VAR_NAME=VALUE說明:變量名(VAR_NAME)=值(VALUE) bash變量類型: 環境變量: 本地變量:(局部變量) 位置變量: 特殊變量: 本地變量: VARNAME(變量名)=VALUE(值)作用域整個bash進程 局部變量 local VARNAME(變量名)=VALUE(值)作用域當前代碼段 環境變量:作用域為當前shell進程及其子進程 export VARNAME(變量名)=VALUE(值)export 意為”導出“,即為導出一個環境變量 腳本在執行時會啟動一個子shell進程 命令行中啟動的腳本會繼承當前shell環境變量 系統自動執行的腳本(非命令行啟動),就需要自我定義需要各環境變量 位置變量: $n 第n個位置變量 特殊變量: $?上一個命令的執行狀態返回值 示例:echo $? 程序執行,兩類返回值 程序執行結果 程序狀態返回代碼(0-255) 0:正確執行 1-255:錯誤執行 撤銷變量 unset VARNAME(變量名) 查看當前shell中的變量 set 查看當前shell中的環境變量 printenv env export 腳本:命令的堆砌,按實際需要,結合命令流程控制機制實現的源程序 第一個腳本 cat fisrt.sh #!/bin/bash # 注釋行,不執行 cat /etc/fstab la /var 保存退出 chmod +x fisrt.sh /dev/null軟件設備,bit bucket數據黑洞 引用變量:${VARNAME},括號可以省略 單引號,強引用,不作變量替換 雙引號:弱引用,內部變量做替換 變量名規則 字母、數字、下劃線,不能以數字開頭 不能同系統中已有的變量名重名 最好見名知意 練習 練習1:寫一個腳本 1、條件5個用戶,user1....user5 2、每個用戶的密碼同用戶名,而且要求,添加密碼完成后不顯示passwd命令的執行結果信息 3、每個用戶添加完成后,顯示用戶某某已經完成添加 #!/bin/bash # 說明:鍵盤輸入需創建的用戶名,執行時自動生成與用戶名相同的密碼,但不顯示passwd的執行過程信息 # 說明:添加完成后,顯示用戶某某已經完成添加 # read命令讀取鍵盤輸入 # 驗證密碼是否創建成功,用 su - read -p "input a user:" val useradd $val echo "$val" | passwd --stdin $val &> /dev/null echo "Add $val successfully!~" id $val 練習2:寫一個腳本 1、使用一個變量保存一個用戶名 2、刪除此變量中的用戶,并且一并刪除其家目錄 3、顯示”用戶刪除完成“信息 #!/bin/bash #echo "查看有哪些用戶: 'cat /etc/passwd |cut -f1 -d:'" echo -e "查看有哪些用戶: \n$(cat /etc/passwd |cut -f1 -d:)" read -p "Delete a user:" val userdel -r $val echo "Del $val successfully!~" shell編程之條件判斷 shell -n檢查shell語法是否錯誤 shell -x檢查shell執行過程 實現條件判斷 條件測試類型 整數測試:等于不等于 字符測試:是不是 文件測試:存不存在 條件測試的表達式(expression指表達式) [ expression ]中括號兩端必須有空格 [[ expression ]] test expression 整數比較(整數測試) -eq測試兩個整數是否相等,比如:$A -eq $B -ne測試連個整數是否不等,不等為真,相等為假 -gt測試一個數是否大于另一個數:大于為真,否則為假 -lt測試一個數是否小于另一個數:小于為真,否則為假 -ge大于或等于 -le小于或等于 命令間的邏輯關系 邏輯與:&& 第一條件為真時,第二條件不用再判斷,最終結果已經有 第一條件為真時,第二條件必須判斷 示例:! id user6 && useradd user6 說明:如果 ! id user6 為真,就執行 useradd user6 如果 ! id user6 為假,就不執行 useradd user6 示例:! id user6 && useradd user6說明:用戶存在就不創建,用戶不存在就創建 邏輯或:|| 示例:id user6 || useradd user6說明:用戶存在就不創建,用戶不存在就創建 條件判斷,控制結構 但分支if語句 if 判斷條件;then statement1(語句1) statement2(語句2) ... fi 雙分支if語句 if 判斷條件;then statement1(語句1) statement2(語句2) ... else statement3(語句3) statement4(語句4) ... fi exit n 表示退出 (n) 示例: 判斷用戶是否存在,如果不存在就創建用戶和密碼,并提示創建成功! #!/bin/bash # read -p "please input:" NAME if id $NAME &> /dev/null;then echo "$NAME 用戶已經存在" else useradd $NAME echo $NAME | passwd --stdin $NAME &> /dev/null echo "用戶 $NAME 添加成功。" fi 示例:如果/etc/passwd 文件的行數大于100,就顯示好大的文件 #!/bin/bash LINES=`wc -l /etc/passwd` FINLINES=`echo $LINES | cut -d' ' -f1` [ $FINLINES -gt 50 ] && echo "/etc/passwd is a big file." || echo "/etc/passwd is a small file." 示例:用戶存在,就顯示用戶已存在,否則,就添加此用戶 id user1 && echo "user1 exists" || useradd user1 示例:如果用戶不存在,就添加;否則,顯示其已經存在 ! id user1 && useradd user1 || echo "user1 exists." 示例:如果用戶不存在,添加并且給密碼;否則,表示其以已經存在 ! id user1 && useradd user1 && echo "user1" | passwd --stdin user1 || echo "user1 exists" 練習: 寫一個腳本 1、添加3個用戶user1,user2,user3.但要先判斷用戶是否存在,不存在而后添加 2、添加完成后,顯示一共添加了幾個用戶,當然,不能包括因為事先存在而沒有添加的 3、最后顯示當前系統上共有多少個用戶 #!/bin/bash # 創建用戶 ! id user1 &> /dev/null && useradd user1 && echo "user1" | passwd --stdin user1 &> /dev/null || echo "user1 exists" ! id user2 &> /dev/null && useradd user2 && echo "user2" | passwd --stdin user2 &> /dev/null || echo "user2 exists" ! id user3 &> /dev/null && useradd user3 && echo "user3" | passwd --stdin user3 &> /dev/null || echo "user3 exists" # 顯示當前用戶數 USERS=`wc -l /etc/passwd | cut -d: -f1` echo "$USERS users." 練習: 添加用戶,并判斷是否存在,存在就顯示”已經存在“,不存在就創建,并創建與用戶同名的密碼,并在創建成功后顯示”Add $val successfully!~“ #!/bin/bash read -p "input a user:" val ! id $val && useradd $val && echo "$val" | passwd --stdin $val && echo "Add $val successfully!~" || echo "$val 已經存在" 練習: 寫一個腳本,給定一個用戶 1、如果其UID為0,就顯示此為管理員 2、否則,就顯示其為普通用戶 第一種方法 #!/bin/bash read -p "請輸入用戶名: " NAME USERID=`id -u $NAME` if ! id $NAME &> /dev/null ;then echo "................ " else if [ $USERID -eq 0 ];then echo "................ " echo "$NAME為管理員." else echo "................ " echo "$NAME為普通用戶" fi echo "................ " fi 第二種方法: #!/bin/bash # 需完善 read -p "請輸入用戶名:" NAME #NAME=fan USERID=`id -u $NAME` ! id $NAME && echo "用戶不存在!" || [ $USERID -eq 0 ] && echo "admin" || echo "Common user." 練習: 判斷當前系統是否有用戶的默認shell為bash,如果有,就顯示有多少個這類用戶,否則,就顯示沒這類用戶 #!/bin/bash # grep "\<bash$" /etc/passwd &> /dev/null RETVAL=$? if [ $RETVAL -eq 0 ];then USERS=`grep "\<bash$" /etc/passwd | wc -l` echo "使用bash的用戶有 $USERS 個! " else echo "No have!~" fi 練習: 判斷當前系統是否有用戶的默認shell為bash,如果有,就顯示其中一個這類用戶,否則,就顯示沒這類用戶 #!/bin/bash # grep "\<bash$" /etc/passwd &> /dev/null RETVAL=$? if [ $RETVAL -eq 0 ];then USERS=`grep "\<bash$" /etc/passwd | head -1 | cut -d: -f1` echo "$USERS 就是一個使用bash的用戶!! " else echo "沒有該用戶!~" fi 練習: 給定一個文件,判斷文件中是否有空白行,如果有,顯示空白行數,如果沒有就顯示沒有空白行 自己的方法: #!/bin/bash read -p "please iuput file: " NAME if [ -e $NAME ];then Number=`grep '^$' $NAME | wc -l` if [ $Number -eq 0 ];then echo "文件沒有空白行!" else echo "文件有 $Number 行空白行!" fi else echo "該文件不存在!~" fi 參考馬哥的方法: #!/bin/bash read -p "please iuput file: " FILE if [ ! -e $FILE ];then echo "該文件不存在!~" exit 1 fi if grep "^$" $FILE &> /dev/null;then echo "文件有 `grep '^$' $FILE | wc -l` 行空白行!" else echo "文件沒有空白行!" fi 練習: 寫一個腳本,判斷其UID和GID是否一樣,如果一樣,此用戶為”good“;否則,為”bad” 第一種方法: #!/bin/bash read -p "請輸入用戶:" ID Uid=`id -u $ID` Gid=`id -g $ID` if [ $Uid -eq $Gid ];then echo "good!~" else echo "bad!~" fi 第二種方法: #!/bin/bash read -p "請輸入用戶:" ID if ! grep "^$ID\>" /etc/passwd $> /dev/null;then echo "用戶不存在" exit 1 fi UserID=`grep "^$ID\>" /etc/passwd | cut -d: -f3` GroupID=`grep "^$ID\>" /etc/passwd | cut -d: -f4` if [ $UserID -eq $GroupID ];then echo "good!~(UID和GID相同)" else echo "bad!~(UID和GID不同)" fi shell條件判斷和算術運算 1、let 算術運算表達式 let C=$A+$B 2、$[算術運算表達式] C=$[$A+$B] 3、$((算術運算表達式)) C=$(($A+$B)) 4、expr C=`EXPR $A + $B` 練習: 給定一個用戶,獲取其密碼警告期限,而后判斷用戶最近一次修改時間距是否已經小于警告期限 小于,則顯示“warning”,否則,顯示“find” 一方法: #!/bin/bash read -p "請輸入用戶:" ID TIMESTAMP=`date +%s` TODAY=`let today=$TIMESTAMP/86400` UserID=`grep "^$ID\>" /etc/passwd | cut -d: -f3` ti2=`let Ti1=$TODAY-$UserID` ti3=`grep "^$ID\>" /etc/passwd | cut -d: -f6` if [ $ti2 < $ti3 ];then echo " warning!!! " else echo "find!!! " fi 二方法: #!/bin/bash read -p "請輸入用戶:" ID W=`grep "^$ID\>" /etc/passwd | cut -d: -f6` S=`date +%s` T=`expr $s/86400` L=`grep "^$ID\>" /etc/passwd | cut -d: -f5` N=`grep "^$ID\>" /etc/passwd | cut -d: -f3` SY=$[$L-$[$T-$N]] if [ $SY-lt $W ];then echo " warning!!! " else echo "find!!! " fi shell 整數測試和特殊變量 整數測試 -eq測試兩個整數是否相等,比如:$A -eq $B -ne測試連個整數是否不等,不等為真,相等為假 -gt測試一個數是否大于另一個數:大于為真,否則為假 -lt測試一個數是否小于另一個數:小于為真,否則為假 -ge大于或等于 -le小于或等于 整數測試方法: [ expression ]命令測試法 [[ expression ]]關鍵字測試法 test expression 示例:比較兩個數值 [ $Num1 -eq $Num2 ] [[ $Num1 -eq $Num2 ]] test $Num1 -eq $Num2 文件測試: -e file測試文件是否存在 -f file測試文件是否為普通文件 -d file測試指定路徑是否為目錄 -r file測試當前用戶對指定文件是否有讀權限 -w file測試當前用戶對指定文件是否有寫權限 -x file測試當前用戶對指定文件是否有執行權限 示例: 測試文件是否存在 [ -e filename ] 多分支if語句 if 判斷條件1;then statement1 ... elif 判斷條件2;then statement2 ... elif 判斷條件3;then statement3 ... else statement4 ... fi 定義腳本退出碼: exit 退出腳本 exit # 測試腳本是否有語法錯誤 bash -n 腳本 腳本單步執行 bash -x 腳本 bash變量類型: 環境變量: 本地變量:(局部變量) 位置變量: 特殊變量: 位置變量: $1,$2,... shift輪替(默認為1) 特殊變量: $?上一條命令的退出狀態碼 $#參數的個數 $*參數列表 $@參數列表 練習: vim shift.sh #!/bin/bash echo $1 shift 2 echo $1 shift 2 echo $1 練習: 寫腳本,給腳本傳遞兩個參數(整數);顯示兩者之和,之積 #!/bin/bash if [ $# -lt 2 ];then echo "Usge: ./.sh ARG1,ARG2." exit 8 fi echo "The sum is: $[$1+$2]." echo "the pro is: $[$1*$2]." 練習: 寫一個腳本,接受參數,判定,此參數如果是一個存在的文件,就顯示“OK”,否則就顯示“No such file。” #!/bin/bash #說明:參數不能為空,否則會顯示幫助"Usge: ./fan3.sh ARG1...[ARG2,ARG3,...]" if [ $# -lt 1 ];then echo "Usge: ./fan3.sh ARG1...[ARG2,ARG3,...]" exit 7 fi if [ -e $1 ];then echo "OK" else echo "No such file." fi shell字符串測試和for循環 字符串比較 == 等值比較,等則為真,不等為假(等號兩端必須是空格) !=不等比較,不等為真,等則為假 -n string測試字符串是否為空,空為真,不空為假 -z string測試字符串是否為不空,不空為真,空為假 循環:進入條件,退出條件 for while until for循環 for 變量 in 列表;do 循環體 done 遍歷完成后,退出 生成列表 {1..100}表示起始為1,結束為100 `seq [起始數[步進長度]] 結束數` 循環示例: 示例: 1加到100 #!/bin/bash # declare -i SUM=0 for I in {1..100};do let SUM=$[$SUM+$I] done echo "sum is :$SUM" 字符串比較示例: 示例: 傳遞一個用戶名參數給腳本,判斷此用戶名跟基本組的組名是否一致 #!/bin/bash # if ! id $1 &> /dev/null;then echo "No such user." exit 10 fi if [ $1 == 'id -n -g $1' ];then echo "ok" else echo "No" fi 示例: 傳一個參數(單字符),參數為q,就退出腳本,否則顯示用戶的參數 示例: 傳一個參數(單字符),參數為q、Q、quit,就退出腳本,否則顯示用戶的參數 #!/bin/bash # if [ $1 = 'q' ];then echo "Quiting..." exit 1 elif [ $1 = 'Q' ];then echo "Quiting..." exit 2 elif [ $1 = 'quit' ];then echo "Quiting..." exit 3 elif [ $1 = 'Quit' ];then echo "Quiting..." exit 4 else echo $1 fi 字符串練習: 傳遞三個參數,第一個為整數,第二個為運算符,第三個為整數,顯示計算結果,要求保留兩位精度 bc用法 echo " scale=2;a/b" | bs bc <<< "scale=2;a/b" 字符串練習: 比較三個整數的大小 練習: 判斷當前主機的CPU生產商,其信息在/proc/cpuinfo文件中vendor id 一行中 如果其生產商為AuthenticAMD,就顯示其為AMD公司 如果其生產商為GenuineIntel,就顯示其為Intel公司 否則,就為非主流公司 #!/bin/bash # I=vendor_id N=`grep $I /proc/cpuinfo | sed -r 's#[[:space:]]+##g' | cut -d: -f2` if [ $N == GenuineIntel ];then echo "該CPU生產商為:Intel 公司" elif [ $N == AuthenticAMD ];then echo "該CPU生產商為 AMD 公司" else echo "該CPU生產商為非主流公司!" fi 字符串練習: 傳遞3個參數,參數均為用戶名。將此用戶的賬號信息提取出來后放置于filename 中,行號一行首有行號 #!/bin/bash # A=root B=mail C=ntp echo `grep -n ^$A /etc/passwd` >>file.txt echo `grep -n ^$B /etc/passwd` >>file.txt echo `grep -n ^$C /etc/passwd` >>file.txt for循環練習題 遍歷/etc/passwd中的用戶,并問好!并顯示對方的shell 提示: LINES=`wc -l /etc/passwd | cut -d' ' -f1` for I in `seq 1 $LINES`;do echo "hello,`head -n $I /etc/passwd | tail -l | cut -d: -f1`";done #!/bin/bash # LI=`wc -l /etc/passwd | cut -d' ' -f1` #echo "$LI" for I in `seq 1 $LI`;do echo "hello, `head -n $I /etc/passwd | tail -1 | cut -d: -f1`, 該用戶對于的shell是:`head -n $I /etc/passwd | tail -1 | cut -d: -f7`"; done for循環練習題 添加10個用戶user1到user10,密碼同用戶名;但要求只有用戶不存在才能創建 #!/bin/bash for I in {1..10};do let N=$I U=user$N if id $U &>/dev/null;then echo "$U 已經存在!~" else useradd $U echo $U | passwd --stdin $U &> /dev/null echo "$U 已經添加成功!~" fi done 擴展: 刪除用戶user1...user10 #!/bin/bash for I in {1..10};do let N=$I U=user$N if id $U &>/dev/null;then userdel -r $U echo "$U 已經刪除成功!~" else echo "$U 不存在!~" fi done 擴展:接受參數: add:添加用戶user1...user10 del:刪除用戶user1...user10 #!/bin/bash if [ $# -lt 1 ];then echo "input add or del:" exit 7 fi if [ $1 == 'add' ];then for I in {1..10};do if id user$I &> /dev/null;then echo "user$I 已存在" else useradd user$I echo user$I | passwd --stdin user$I &> /dev/null echo "user$I 添加成功!~" fi done elif [ $1 == 'del' ];then for I in {1..10};do if id user$I &> /dev/null;then userdel -r user$I echo "user$I 刪除成功" else echo "user$I 不存在" fi done else echo “Unknown ARG” exit 8 fi 執行:.sh add 添加用戶 .sh del 刪除用戶 擴展: 輸入 .sh user1,user2,user3 添加 #!/bin/bash echo $1 for I in `echo $1 | sed 's/,/ /g'`;do if id $I &>/dev/null;then echo "$I 存在" else useradd $I echo $I | passwd --stdin $I >/dev/null echo "$I 添加成功" fi done 擴展: 輸入 .sh --add user1,user2,user3 .sh --del user1,user2,user3 #!/bin/bash if [ $1 == '--add' ];then for I in `echo $2 | sed 's/,/ /g'`;do if id $I &>/dev/null;then echo "$I 存在" else useradd $I echo $I | passwd --stdin $I >/dev/null echo "$I 添加成功" fi done elif [ $1 == '--del' ];then for I in `echo $2 | sed 's/,/ /g'`;do if id $I &>/dev/null;then userdel -r $I echo "$I 刪除成功" else echo "$I 不存在" fi done elif [ $1 == '--help' ];then echo "(1).命令格式:./ sh --[options] username!~" echo "(2).--add username | --del username | --help 不能同時出現" else echo “Unknown options” fi 缺點(待完善): 無法判斷參數數 無法判斷沒有參數(忘記給參數) 無法判斷參數錯誤(--add和--del同時使用) for循環練習題 計算100以內所有能被3整除的正整數 提示:取模,取余 #!/bin/bash let "sum=0" for i in {1..10} do let "m=i%3" if [ "$m" -eq 0 ] then let "sum=sum+i" fi done echo "the sum is :$sum" for循環練習題 計算100以內所有奇數的和以及所有偶數的和,分別顯示之 #!/bin/bash declare "sum1=0" declare "sum2=0" for i in {1..100} do let "m=i%2" if [ "$m" -eq 0 ];then let "sum1=sum1+i" elif [ "$m" -eq 1 ];then let "sum2=sum2+i" fi done echo " 1-100以內的偶數和為: $sum1" echo " 1-100以內的奇數和為: $sum2" 練習題 分別顯示默認shell為bash的用戶和/sbin/nologin的用戶,并統計各類shell下的用戶總數 #!/bin/bash # FILE=/etc/passwd echo "默認shell為bash的用戶有: `grep 'bash' $FILE | wc -l` 個!分別為:" B=`sed -n '/bash/p' $FILE | cut -d: -f1` BB=`echo $B|sed 's@[[:spqce:]]@,@g'` echo "$BB" echo "默認shell為nologin的用戶有 `grep 'nologin' $FILE | wc -l` 個!分別為:" A=`sed -n '/nologin/p' $FILE | cut -d: -f1` AA=`echo $A|sed 's@[[:spqce:]]@,@g'` echo "$AA" 腳本選項·和組合條件測試 回顧: 整數測試: -eq測試兩個整數是否相等,比如:$A -eq $B -ne測試連個整數是否不等,不等為真,相等為假 -gt測試一個數是否大于另一個數:大于為真,否則為假 -lt測試一個數是否小于另一個數:小于為真,否則為假 -ge大于或等于 -le小于或等于 字符測試 ==等于 !=不等于 >大于 <小于 -n字符串是否為空 -z字符串是否為不空 文件測試 -e file測試文件是否存在 -f file測試文件是否為普通文件 -d file測試指定路徑是否為目錄 -r file測試當前用戶對指定文件是否有讀權限 -w file測試當前用戶對指定文件是否有寫權限 -x file測試當前用戶對指定文件是否有執行權限 組合測試 -o邏輯或 -a邏輯與 !邏輯非 添加10個用戶user1到user10,密碼同用戶名;但要求只有用戶不存在才能創建 #!/bin/bash for I in {1..10};do let N=$I U=user$N if id $U &>/dev/null;then echo "$U 已經存在!~" else useradd $U echo $U | passwd --stdin $U &> /dev/null echo "$U 已經添加成功!~" fi done 擴展: 刪除用戶user1...user10 #!/bin/bash for I in {1..10};do let N=$I U=user$N if id $U &>/dev/null;then userdel -r $U echo "$U 已經刪除成功!~" else echo "$U 不存在!~" fi done 擴展:接受參數: add:添加用戶user1...user10 del:刪除用戶user1...user10 #!/bin/bash if [ $# -lt 1 ];then echo "input add or del:" exit 7 fi if [ $1 == 'add' ];then for I in {1..10};do if id user$I &> /dev/null;then echo "user$I 已存在" else useradd user$I echo user$I | passwd --stdin user$I &> /dev/null echo "user$I 添加成功!~" fi done elif [ $1 == 'del' ];then for I in {1..10};do if id user$I &> /dev/null;then userdel -r user$I echo "user$I 刪除成功" else echo "user$I 不存在" fi done else echo “Unknown ARG” exit 8 fi 執行:.sh add 添加用戶 .sh del 刪除用戶 擴展: 輸入 .sh user1,user2,user3 添加 #!/bin/bash echo $1 for I in `echo $1 | sed 's/,/ /g'`;do if id $I &>/dev/null;then echo "$I 存在" else useradd $I echo $I | passwd --stdin $I >/dev/null echo "$I 添加成功" fi done 擴展: 輸入 .sh --add user1,user2,user3 .sh --del user1,user2,user3 #!/bin/bash if [ $1 == '--add' ];then for I in `echo $2 | sed 's/,/ /g'`;do if id $I &>/dev/null;then echo "$I 存在" else useradd $I echo $I | passwd --stdin $I >/dev/null echo "$I 添加成功" fi done elif [ $1 == '--del' ];then for I in `echo $2 | sed 's/,/ /g'`;do if id $I &>/dev/null;then userdel -r $I echo "$I 刪除成功" else echo "$I 不存在" fi done elif [ $1 == '--help' ];then echo "(1).命令格式:./ sh --[options] username!~" echo "(2).--add username | --del username | --help 不能同時出現" else echo “Unknown options” fi 缺點(待完善): 無法判斷參數數 無法判斷沒有參數(忘記給參數) 無法判斷參數錯誤(--add和--del同時使用) shell編程case語句和腳本選項進階 面向過程 控制接口 順序結構 選擇結構 if..slif..else..fi 循環結構 case語句:選擇結構 case SWITCH in value1) statement ... ;;#每一個選擇條件必須兩個;結束 value2) statement ... ;; *) statement ... ;; esac#case字母反過來寫表示結尾 示例: 寫一個腳本,只接受參數start,stop,restart,status其中之一 #!/bin/bash # read -p "iuput:" N case $N in 'start') echo "start server...";; 'stop') echo "stop server...";; 'restaer') echo "restart server...";; 'status') echo "Running..." *) echo "`basename $0` {start|stop|restart|status}";; esac 示例: 寫一個腳本,可以接受選項及參數,而后獲取每一個選項及參數,并能根據選項及參數作出特定的操作 比如:admin.sh --add tom,jer --del tom,jer --v|--verbose --h|--helo 選項可同時使用 例如:./test.sh -v --add tom,jer #!/bin/bash # DEBUG=0 ADD=0 DEL=0 for I in `seq 1 $#`;do if [ $# -gt 0 ]; then case $1 in -v|--verbose) DEBUG=1 shift ;; -h|--help) echo "Usage:`basename $0` --add UAERNAM --del USERNAME -v|--verbose -h|--help" exit 0 ;; --add) ADD=1 ADDUSERS=$2 shift 2 ;; --del) DEL=1 DELUSERS=$2 shift 2 ;; *) echo "Usage:`basename $0` --add UAERNAM --del USERNAME -v|--verbose -h|--help" exit 7 ;; esac fi done if [ $ADD -eq 1 ]; then for USER in `echo $ADDUSERS | sed 's@,@ @g'`; do if id $USER &> /dev/null; then [ $DEBUG -eq 1 ] && echo "$USER exists." else useradd $USER [ $DEBUG -eq 1 ] && echo "Add user $USER finished." fi done fi if [ $DEL -eq 1 ]; then for USER in `echo $DELUSERS | sed 's@,@ @g'`; do if id $USER &> /dev/null; then userdel -r $USER [ $DEBUG -eq 1 ] && echo "Delete $USER finished." else [ $DEBUG -eq 1 ] && echo "$USER not exist." fi done fi 寫一個腳本 利用RANDOM生成10個隨機數,并找出其中的最大值和最小值 #!/bin/bash declare -i MAX=0 declare -i MIN=0 for I in {1..10};do myrand=$RANDOM [ $I -eq 1 ] && MIN=$myrand if [ $I -le 9 ];then echo -n "$myrand," else echo "$myrand" fi [ $myrand -gt $MAX ] && MAX=$myrand [ $myrand -lt $MIN ] && MIN=$myrand done echo "max = $MAX" echo "min = $MIN" 示例: 寫一個腳本:showlog.sh 用法為: showlog.sh -v -c -h|--help 其中:-h選項單獨使用,用于顯示幫助信息,-c顯示當前登陸的所有用戶,如果同時使用-v,極限是同時登陸的用戶數,又顯示登陸用戶的相關信息 #!/bin/bash # declare -i SHOWNUM=0 declare -i SHOWUSERS=0 for I in `seq 1 $#`;do if [ $# -gt 0 ]; then case $1 in -h|--help) echo "Usage:`basename $0` -h|--help -c|-counts -v|--verbose" exit 0 ;; -v|--verbose) let SHOWUSERS=1 shift ;; -c|--count) let SHOWNUM=1 shift ;; *) echo "Usage:`basename $0` -h|--help -c|-counts -v|--verbose" exit 8 ;; esac fi done if [ $SHOWNUM -eq 1 ];then echo "log users:`who | wc -l`." if [ $SHOWUSERS -eq 1 ];then echo "They are:" who fi fi shell編程 while循環 while循環 適用于循環次數未知的場景 必須要有退出條件 語法格式 while CONDITON;do statement ... done 進入循環,條件滿足 退出循環,條件不滿足 循環的控制方法 break提前退出循環 continue提前進入下一循環 while特殊用法之一:死循環 while :;do done while特殊用法之二: while read LINE;do done < FILENAME 說明:whlie 循環讀取FILENAME中的每一行,放在變量LINE中,然后再循環中處理LINE中的行 示例:(待完善) 判斷/etc/passwd中的那個用戶的shell是bash,如果是bash就顯示用戶名,否則不顯示名字 #!/bin/bash # FILE=/etc/passwd let I=0 while read LINE;do [ `echo $LINE | awk -F : '{prinf $3}'` -le 505 ] && continue #用戶ID大于505就不在判斷,提前進入下一循環 [ `echo $LINE | awk -F : '{prinf $7}'` == '/bin/bash' ] && echo $LINE | awk -F : '{print $1}' && let I++ [ $I -eq 6 ] && break #只讀取前6個用戶 done < $FILE continue示例: 計算100以內所有偶數和 #!/bin/bash # let SUM=0 let I=0 while [ $I -lt 100 ];do let I++ if [ $[$I%2] -eq 0 ];then continue fi let SUM+=$I done echo $SUM break示例: 從1加到1000,知道和為5000就退出循環不再相加 #!/bin/bash # declare -i SUM=0 for I in {1..1000};do let SUM+=$I if [ $SUM -gt 5000 ];then break fi done echo "I=$I" echo "SUM=$SUM" break示例: 判斷一個文件是否存在,用戶輸入quit就退出 #!/bin/bash # while :;do read -p "input filename:"FILENAME [ $FILENAME=='quit' ] && break if [ -e $FILENAME ];then echo "$FILENAME exists." else echo "No $FILENAME" fi done echo "Quit." 寫一個腳本: 說明:此腳本能于同一個repo文件中創建多個yum源的指向 1、接受一個文件名作為參數,此文件存放至/etc/yum.repos.d目錄中,且文件名以.repo為后綴,要求此文件不能事先存,否則,報錯 2、在腳本中,提醒用戶輸出repo id ,如果為quit,則退出腳本,否則,繼續完成下面的步驟 3、repo name以及baseurl的路徑,而后以repo文件的格式將其保存到指定的文件中 4、enabled默認為1,而gpgcheck默認為0 5、此腳本會循環多次,除非用戶為repo id指定為quit #!/bin/bash # REPOFILE=/etc/yum.repos.d/$1 if [ -e $REPODILE ];then echo "$1 exists." exit 3 fi read -p "input ID:" REPOID until [ $REPOID == 'quit' ];do echo "[$REPOID]" >> $REPOFILE read -p "input name: " REPONAME echo "name=$REPONAME" >> $REPOFILE read -p "input Baseurl:" REPOURL echo -e 'enabled-1\ngpgcheck=0' >> $REPOFILE read -p "input ID:" REPOID done 示例: 計算100以內所有正整數的和 #!/bin/bash # declare -i I=1 declare -i SUM=0 while [ $I -le 100 ];do let SUM+=$I let I++ done echo "$SUM" 示例: 用戶輸入字符串,就轉換成大寫,輸入‘quit’就退出 #!/bin/bash # read -p "input something:" STRING while [ $STRING != 'quit' ];do echo $STRING | tr 'a-z' 'A-Z' read -p "input something:" STRING done 示例: 練習: 每隔5秒就來查看hadoop是否已經登陸,如登陸,顯示其已經登陸,就退出 提示:sleep sleep 3 延遲3秒 #!/bin/bash # who | grep "hadoop" &> /dev/null RETVAL=$? while [ $RETVAL -ne 0 ];do echo "`date`,hadoop not is log!" sleep 5 who | grep "hadoop" &> /dev/null RETVAL=$? done echo "`date` hadoop is logged!" 示例: 1.顯示一個菜單給用戶 d|D) show disk usages m|M) show menory usages s|S) show swap usages *) quit 2.當用戶給定選項后顯示響應的內容 #!/bin/bash cat << EOF d|D) show disk usages m|M) show menory usages s|S) show swap usages *) quit EOF read -p "Your choice:" CH case $CH in d|D) echo "Disk usages:" df -h ;; m|M) echo "Memory usages;" free -m | grep "Mem" ;; s|S) echo "Swap usages:" free -m | grep "Swap" ;; *) echo "Unknow.." exit 9 ;; esac ~ 擴展: 當用戶選擇完成,顯示響應信息后,不退出,而讓用戶再一次選擇,再次顯示響應內容,除了用戶使用quit #!/bin/bash cat << EOF d|D) show disk usages m|M) show menory usages s|S) show swap usages *) quit EOF read -p "Your choice:" CH while [ $CH != 'quit' ];do case $CH in d|D) echo "Disk usages:" df -h ;; m|M) echo "Memory usages;" free -m | grep "Mem" ;; s|S) echo "Swap usages:" free -m | grep "Swap" ;; *) echo "Unknow.." ;; esac read -p "Again,your choice:" CH done 寫一個腳本: 1、提示用戶輸入一個用戶名 2、顯示一個菜單給用戶。形如 U|u show UID G|g show GID S|s show SHELL Q|q quit 3、提醒用戶選擇一個選項,并顯示其所有選擇的內容 如果用戶給一個錯誤的選項,則提醒用戶選項錯誤,請其重新選擇 #!/bin/bash # echo "* * * * * * * * * * * * *" read -p "Please enter your user name: " US until [ $US == 'quit' ];do if id -u $US &> /dev/null;then echo "$US is OK!Please select" echo "=======options=======" cat << EOF U|u) show UID G|g) show GID S|s) show SHELL q|Q) quit EOF echo "=====================" read -p "Please select options: " SH echo "=====================" while : ;do case $SH in U|u) echo "$US uid=`grep "^$US" /etc/passwd | cut -d: -f4`" ;; G|g) echo "$US gid=`grep "^$US" /etc/passwd | cut -d: -f3`" ;; S|s) echo "$US shell=`grep "^$US" /etc/passwd | cut -d: -f7`" ;; Q|q) echo "******quiting...******" exit ;; *) echo "Wrong option.Please again" echo "=======options=======" cat << EOF U|u) show UID G|g) show GID S|s) show SHELL q|Q) quit EOF echo "=====================" ;; esac read -p "Please choose again: " SH done else echo "-------------------------------------" echo "The user name wrong.." echo "* * * * * * * * * * * * *" read -p "Please enter the username again : " US fi done shell編程until循環 until CONDITION; 進入循環,條件不滿足 退出循環,條件滿足 for循環 for ((expr1 ; expr2 ; expr3)); do 循環體 done 示例: 100以內的正整數相加 #!/bin/bash # declare -i SUM2=0 for ((J=1;J<=100;J++));do let SUM2+=$J done echo $SUM2 until循環示例: 示例: #!/bin/bash # read -p "input something:" ST until [ $ST== 'quit' ];do echo $ST | tr 'a-z' 'A-Z' read -p "input something:" ST done 示例: 練習: 每隔5秒就來查看hadoop是否已經登陸,如登陸,顯示其已經登陸,就退出 第一種方法 #!/bin/bash # who | grep "hadoop" &> /dev/null RETVAL=$? until [ $RETVAL -eq 0 ];do echo "hadoop is not come." sleep 5 who | grep "hadoop" &> /dev/null RETVAL=$? done echo "hadoop is logged in." 第二種方法 #!/bin/bash # until who | grep "hadoop" &> /dev/null;do echo "hadoop is not come." sleep 5 done echo "hadoop is logged in." 測試: 通過ping命令測試192.168.0.151到192.168.0.254直接所有主機是否在線 如果在線,就顯示ip is up,其ip要換為真正的IP動作,且顯示為綠色 如果不在線,就顯示“ip is down”,其中的IP換為真正的IP地址,且紅色顯示 分別用while,until for(兩種形式)循環實現 for循環第一種方法: for ((i=99;i<=120;i++));do if ping -c 1 -W 1 192.168.0.$i &> /dev/null;then echo "192.168.0.$i 在線" else echo "192.168.0.$i 不在線" fi done for循環第二種方法: for i in {99..120};do if ping -c 1 -W 1 192.168.0.$i &> /dev/null;then echo "192.168.0.$i 在線" else echo "192.168.0.$i 不在線" fi done while循環 #!/bin/bash # declare -i I=151 while [ $I -le 254 ];do let I++ if ping -c 1 -W 1 192.168.3.$I &> /dev/null;then echo "192.168.3.$I 在線" else echo "192.168.3.$I 不在線" fi done until循環 #!/bin/bash # declare -i I=191 until [ $I -gt 254 ];do let I++ if ping -c 1 -W 1 192.168.3.$I &> /dev/null;then echo "192.168.3.$I 在線" else echo "192.168.3.$I 不在線" fi done shell編程之:函數、功能 function 代碼重用,結構化編程,不能獨立運行,需要調用時執行,可以多次被調用 定義函數方法一 function FUNCNAME { command } 定義函數方法二 FUNCNAME() { command } 自定義執行狀態返回值 return # #的值:0-255 接受參數的函數 FUNCNAM n1 n2 $1 n1 $2 n2 示例: 多次顯示菜單 #!/bin/bash # function SHOWM {#定義函數SHOWM cat << EOF d|D) show disk usages m|M) show menory usages s|S) show swap usages *) quit EOF } SHOWM#調用函數 return示例 添加用戶test #!/bin/bash # ADDUSER() { USERNAME=test if ! id -u $USERNAME &> /dev/null;then useradd $USERNAME echo $USERNAME | passwd --stdin $USERNAME &> /dev/null return 0 else return 1 fi } ADDUSER echo $? if [ $? -eq 0 ];then echo "add user finished." else echo "Failuer." fi 擴展: 添加多個用戶 #!/bin/bash # ADDUSER() { USERNAME=$1 if ! id -u $USERNAME &> /dev/null;then useradd $USERNAME echo $USERNAME | passwd --stdin $USERNAME &> /dev/null return 0 else return 1 fi } for I in {1..10};do ADDUSER user$I if [ $? -eq 0 ];then echo "add user$I finished." else echo "add user$I Failuer." fi done 函數接受參數示例 #!/bin/bash # TWOSUM() { echo $[$1+$2] } TWOSUM 5 6 SUM=`TWOSUM 5 6`#保存函數的執行結果至一個變量,可做進一步操作 echo $SUM 示例: 10以內相鄰兩個數相加 #!/bin/bash # TWOSUM() { echo $[$1+$2] } for I in {1..10};do let J=$[$I+1] TWOSUM $I $J echo "$I + $J = `TWOSUM $I $J`" done 示例: 寫一個腳本,判定192.168.0.200-192.168.0.254之間的主機哪些在線。要求: 1、使用函數來實現一臺主機的判定過程 2、在主程序中來調用此函數判定指定范圍內的所有主機的在線情況 第一種方法: #!/bin/bash # PING() { if ping -c 1 -W 1 $1 &> /dev/null;then echo "$1 在線" else echo "$1 不在線" fi } for I in {200..254};do PING 192.168.0.$I done #for I in{200..254};do#ping另一個網段 # PING 192.168.2.$I #done 第二種方法: #!/bin/bash # PING() { if ping -c 1 -W 1 $1 &> /dev/null;then return 0 else return 1 fi } for I in {200..254};do PING 192.168.0.$I if [ $? -eq 0 ];then echo "192.168.0.$I 在線" else echo "192.168.0.$I 不在線" fi done 寫一個腳本 1、函數接受一個參數,參數為用戶名 判定一個用戶是否存在 如果存在,就返回此用戶的shell和UID,并返回正常狀態值 如果不存在,就說此用戶不存在,并返回錯誤狀態值 2、在主程序中調用函數 擴展1:在主程序中,讓用戶自己輸入用戶名后,傳遞給函數來進行判斷 擴展2:在主程序中輸入用戶名判斷后不退出腳本,而是提示用戶繼續輸入下一個用戶名,但如果用戶輸入的是q或Q就退出 #!/bin/bash # ADDUSER() { USERNAME=$1 if id -u $USERNAME &> /dev/null;then return 0 else return 1 fi } read -p "input : " U echo "===================================" until [ $U == q -o $U == Q ];do ADDUSER $U if [ $? == 0 ];then # echo "$U 存在" sh=`grep "^$U" /etc/passwd | awk -F : '{print $7}'` ui=`grep "^$U" /etc/passwd | awk -F : '{print $4}'` echo "$U 的 shell = $sh, UID = $ui" echo "===================================" read -p "input again: " U echo "===================================" else echo "$U 不存在" echo "===================================" read -p "input again: " U echo "===================================" fi done echo "quit..." echo "==================================="
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。