1.格式要求:首行shebang機制python
#!/bin/bash #!/usr/bin/python #!/usr/bin/perl
2.添加執行權限,在命令行上指定腳本的絕對或者相對路徑,也能夠運行腳本解釋器直接運行腳本linux
一、第一行通常爲調用使用的語言面試
二、程序名,避免更改文件名爲沒法找到正確的文件正則表達式
三、版本號shell
四、更改後的時間數據庫
五、做者相關信息express
六、該程序的做用,及注意事項vim
七、最後是各版本的更新簡要說明centos
[root@centos8 data]# cat shell.sh #!/bin/bash ls [root@centos8 data]# chmod +x shell.sh #相對路徑執行 [root@centos8 data]# ./shell.sh a.txt b.txt linxu.txt message passwd shell.sh systeminfo.sh test vimrc #bash執行 [root@centos8 data]# bash shell.sh a.txt b.txt linxu.txt message passwd shell.sh systeminfo.sh test vimrc #執行遠程主機的shell腳本 [root@centos8 data]# #curl -s http://10.0.0.8/hello.sh|bash [root@centos8 ~]#wget -qO - http://www.wangxiaochun.com/testdir/hello.sh |bash
腳本常見的3種錯誤:安全
bash命令
bash -n:只檢測腳本中的語法錯誤,但沒法檢查出命令錯誤,但不真正執行腳本
bash -x:調試並執行腳本
內置變量,如:PS1,PATH,UID,HOSTNAME,$$,BASHPID,PPID,$?,HISTSIZE
用戶自定義變量
變量賦值
#變量的賦值能夠是如下多種形式 直接字串:name='root' 變量引用:name="$USER" 命令引用:name=`COMMAND` 或者 name=$(COMMAND)
變量引用
$name ${name}
範例
[root@centos8 data]# name='xiaoming' [root@centos8 data]# echo $name xiaoming [root@centos8 data]# user='yonghu' [root@centos8 data]# name="$user" [root@centos8 data]# echo $name yonghu [root@centos8 data]# name=`ls -l /data/` [root@centos8 data]# echo $name total 8 -rw-r--r-- 1 root root 403 Jan 2 17:39 systeminfo.sh -rw-r--r-- 1 root root 110 Jan 3 10:17 test [root@centos8 data]# echo "$name" total 8 -rw-r--r-- 1 root root 403 Jan 2 17:39 systeminfo.sh -rw-r--r-- 1 root root 110 Jan 3 10:17 test
範例:變量追加值
[root@centos8 data]# echo $user yonghu [root@centos8 data]# user+=:xiaoming [root@centos8 data]# echo $user yonghu:xiaoming
顯示和刪除變量
#set查看全部變量 #unset <name>刪除指定變量 #使用上述方式設置變量是臨時保存於內存當中,當退出終端就會銷燬
說明
環境變量的聲明和賦值:
#聲明並賦值 export name=VALUE declare -x name=VALUE #或者分兩步實現 name=VALUE export name
變量引用:
$name ${name}
顯示全部環境變量:
env printenv export declare -x
刪除變量
unset
bash的內建環境變量
PATH SHELL USER UID HOME PWD SHLVL #shell的嵌套層數,即深度 LANG MAIL HOSTNAME HISTSIZE _ #下劃線 表示前一命令的最後一個參數
只能聲明定義,但後續不能修改和刪除,即常量;退出當前終端能夠銷燬聲明的只讀變量
聲明只讀變量:
readonly name declare -r name
查看只讀變量
readonly [-p] declare -r
在bash shell中內置的變量, 在腳本代碼中調用經過命令行傳遞給腳本的參數
$1, $2, ... 對應第1個、第2個等參數,shift [n]換位置 $0 命令自己,包括路徑 $* 傳遞給腳本的全部參數,所有參數合爲一個字符串 $@ 傳遞給腳本的全部參數,每一個參數爲獨立字符串 $# 傳遞給腳本的參數的個數 #清空全部位置變量 set --
範例
[root@centos8 data]# cat arg.sh #!/bin/bash echo "arg1 is $1" echo "arg1 is $2" echo "arg1 is $3" echo "the number of arg is $#" echo "all args is $*" echo "all args is $@" echo "the script name is `basename $0`" [root@centos8 data]# bash arg.sh {1..5} arg1 is 1 arg1 is 2 arg1 is 3 the number of arg is 5 all args is 1 2 3 4 5 all args is 1 2 3 4 5 the script name is arg.sh
rm命令修改
#用戶使用rm命令時不刪除文件而是移動到/tmp文件夾 [root@centos8 data]# cat rm.sh COLOR="echo -e \E[1;31m" END="\E[0m" DIR=/tmp/`date +%F_%H-%M-%S` mkdir $DIR mv $* $DIR $COLOR move $* to $DIR $END
$?
$?的值爲0,表明成功
$?的值是1到255 #表明失敗
注意:
$- 變量
[root@centos8 data]# echo $- himBHs
h:hashall,打開選項後,Shell 會將命令所在的路徑hash下來,避免每次都要查詢。經過set +h將h選 項關閉
i:interactive-comments,包含這個選項說明當前的 shell 是一個交互式的 shell。所謂的交互式shell, 在腳本中,i選項是關閉的 m:monitor,打開監控模式,就能夠經過Job control來控制進程的中止、繼續,後臺或者前臺執行等
B:braceexpand,大括號擴展
H:history,H選項打開,能夠展開歷史列表中的命令,能夠經過!感嘆號來完成,例如「!!」返回上最近的 一個歷史命令,「!n」返回第 n 個歷史命令
set 命令
-u 在擴展一個沒有設置的變量時,顯示錯誤信息, 等同set -o nounset
-e 若是一個命令返回一個非0退出狀態值(失敗)就退出, 等同set -o errexit
-o option 顯示,打開或者關閉選項
顯示選項:set -o
打開選項:set -o 選項
關閉選項:set +o 選項
printf:格式化要輸出的數據
printf FORMAT [ARGUMENT]...
經常使用格式替換符
%s 字符串
%f 浮點格式
%b 相對應的參數中包含轉義字符時,可使用此替換符進行替換,對應的轉義字符會被轉 義
%c ASCII字符,即顯示對應參數的第一個字符
%d,%i 十進制整數
%o 八進制值
%u 不帶正負號的十進制值
%x 十六進制值(a-f)
%X 十六進制值(A-F)
%% 表示%自己
%s 中的數字表明此替換符中的輸出字符寬度,不足補空格,默認是右對齊,%-10s表示10個字 符寬,- 表示左對齊
經常使用轉義字符
範例
[root@centos8 data]# printf "%d\n" 123 321 123 123 321 123 [root@centos8 data]# printf "(%s) " 1 2 3 (1) (2) (3) [root@centos8 data]# [root@centos8 data]# printf "(%s) " 1 2 3;echo (1) (2) (3) [root@centos8 data]# printf "(%s) " 1 2 3;echo "" (1) (2) (3) [root@centos8 data]# printf "%10s" name;echo name
shell 支持算術運算,但只支持整數,不支持小數
shell運算符
+ - * / % 取模,即取餘數,示例:9%4=1,5%3=2 ** 乘方
實現算數運算的方式
1. let var=算數表達式 2. ((var=算數表達式)) 3. var=$[算數表達式] 4. var=$((算數表達式)) 5. delare -i var = 數值 6. echo '算術表達式' | bc 7. var=$(expr arg1 arg2 arg3 ...)
範例
#生成 1 - 50 之間隨機數 [root@centos8 data]# echo $[RANDOM%50+1] 12
加強型賦值:
+= i+=10 至關於 i=i+10 -= i-=j 至關於 i=i-j *= /= %= ++ i++,++i 至關於 i=i+1 -- i--,--i 至關於 i=i-1
範例
#i++和++i [root@centos8 ~]#unset i j ; i=1; let j=i++; echo "i=$i,j=$j" i=2,j=1 [root@centos8 ~]#unset i j ; i=1; let j=++i; echo "i=$i,j=$j" i=2,j=2 #使用計算器實現浮點運算 [root@centos8 data]# echo "scale=3;20/3" | bc 6.666
與:&:和0相與,結果爲0,和1相與,結果保留原值
1 與 1 = 1 1 與 0 = 0 0 與 1 = 0 0 與 0 = 0
或:|:和1相或結果爲1,和0相或,結果保留原值
1 或 1 = 1 1 或 0 = 1 0 或 1 = 1 0 或 0 = 0
非:!
! 1 = 0 ! true ! 0 = 1 ! false
異或:^
相同爲假,不一樣爲真。
1 ^ 1 = 0 1 ^ 0 = 1 0 ^ 1 = 1 0 ^ 0 = 0
範例
#注意區分邏輯運算的二進制值與$?的返回值含義恰好相反 #利用異或能夠實現兩個變量的數值交換 [root@centos8 data]# x=30;y=20;x=$[x^y];y=$[x^y];x=$[y^x];echo "x=$x y=$y" x=20 y=30
短路運算
短路與
CMD1 短路與 CMD2
第一個CMD1結果爲假 (0),總的結果一定爲0,所以不須要執行CMD2
短路或
CMD1 短路或 CMD2
第一個CMD1結果爲真 (1),總的結果一定爲1,所以不須要執行CMD2
若真,則狀態碼變量 $? 返回0
若假,則狀態碼變量 $? 返回1
條件測試命令:
查看幫助
[root@centos8 data]# help [ [root@centos8 data]# help test 選項 -a FILE True if file exists. -b FILE True if file is block special. -c FILE True if file is character special. -d FILE True if file is a directory. -e FILE True if file exists. -f FILE True if file exists and is a regular file. -g FILE True if file is set-group-id. -h FILE True if file is a symbolic link. -L FILE True if file is a symbolic link. -k FILE True if file has its `sticky' bit set. -p FILE True if file is a named pipe. -r FILE True if file is readable by you. -s FILE True if file exists and is not empty. -S FILE True if file is a socket. -t FD True if FD is opened on a terminal. -u FILE True if the file is set-user-id. -w FILE True if the file is writable by you. -x FILE True if the file is executable by you. -O FILE True if the file is effectively owned by you. -G FILE True if the file is effectively owned by your group. -N FILE True if the file has been modified since it was last read. String operators: -z STRING True if string is empty. -n STRING STRING True if string is not empty. STRING1 = STRING2 True if the strings are equal. STRING1 != STRING2 True if the strings are not equal. STRING1 < STRING2 True if STRING1 sorts before STRING2 lexicographically. STRING1 > STRING2 True if STRING1 sorts after STRING2 lexicographically. Other operators: #變量測試 -o OPTION True if the shell option OPTION is enabled. -v VAR True if the shell variable VAR is set. -R VAR True if the shell variable VAR is set and is a name reference. ! EXPR True if expr is false. EXPR1 -a EXPR2 True if both expr1 AND expr2 are true. EXPR1 -o EXPR2 True if either expr1 OR expr2 is true. #數值測試 arg1 OP arg2 Arithmetic tests. OP is one of -eq, -ne, -lt, -le, -gt, or -ge. Arithmetic binary operators return true if ARG1 is equal, not-equal, less-than, less-than-or-equal, greater-than, or greater-than-or-equal than ARG2.
範例
#判斷 NAME 變量是否認義 [ -v NAME ] #判斷 NAME 變量是否認義而且是否引用 [ -R NAME ] [root@centos8 data]# echo $name [root@centos8 data]# [ -v name ] [root@centos8 data]# echo $? 1 [root@centos8 data]# name="xiaoming" [root@centos8 data]# [ -v name ] [root@centos8 data]# echo $? 0 [root@centos8 data]# [ -R name ] [root@centos8 data]# echo $? 1 [root@centos8 data]# [ -v name ] [root@centos8 data]# echo $? 0
範例
[root@centos8 data]# i=10;j=20; [root@centos8 data]# [ i -eq j ] -bash: [: i: integer expression expected [root@centos8 data]# [ $i -eq $j ] [root@centos8 data]# echo $? 1
範例
[root@centos8 data]# echo $name [root@centos8 data]# [ -z $name ] [root@centos8 data]# echo $? 0 [root@centos8 data]# unset name [root@centos8 data]# [ -z $name ] [root@centos8 data]# echo $? 0 [root@centos8 data]# name=xiaoming [root@centos8 data]# [ -z "$name" ] [root@centos8 data]# echo $? 1
[ ]用法
[[]] 用法,建議,當使用正則表達式或通配符使用,通常狀況使用 [ ] == 左側字符串是否和右側的PATTERN相同 注意:此表達式用於[[ ]]中,PATTERN爲通配符 =~ 左側字符串是否可以被右側的正則表達式的PATTERN所匹配 注意: 此表達式用於[[ ]]中;擴展的正則表達式
範例
[root@centos8 data]# NAME=linux [root@centos8 data]# [[ "$NAME" == linu\* ]] [root@centos8 data]# echo $? 1 [root@centos8 data]# [[ "$NAME" == linu* ]] [root@centos8 data]# echo $? 0 #結論:[[ == ]] == 右側的 * 作爲通配符,不要加「」,只想作爲*, 須要加「」 或轉義
範例
[root@centos8 data]# [ -a /data/test ] [root@centos8 data]# echo $? 0 [root@centos8 data]# ![ -a /data/test ] [ -a /data/test ] -a /data/test ] -bash: [: too many arguments [root@centos8 data]# ! [ -a /data/test ] [root@centos8 data]# echo $? 1 [root@centos8 data]# [ -w /etc/shadow ] [root@centos8 data]# echo $? 0
(CMD1;CMD2;...)和 { CMD1;CMD2;...; } 均可以將多個命令組合在一塊兒,批量執行。使用man bash能夠查看幫助
區別
( list ) 會開啓子shell,而且list中變量賦值及內部命令執行後,將再也不影響後續的環境
{ list; } 不會啓子shell, 在當前shell中運行,會影響當前shell環境
範例
[root@centos8 data]# echo $BASHPID 164220 [root@centos8 data]# ( echo $BASHPID;sleep 100) 164450 sshd(976)───sshd(164206)───sshd(164219)───bash(164220)─┬─bash(164449)───sleep(164450) [root@centos8 data]# echo $BASHPID 164220 [root@centos8 data]# { echo $BASHPID;} 16422
[ EXPRESSION1 -a EXPRESSION2 ] 而且,EXPRESSION1和EXPRESSION2都是真,結果才爲真
[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一個真,結果就爲 真
[ ! EXPRESSION ] 取反
範例
[root@centos8 data]# FILE=/data/test [root@centos8 data]# [ -f $FILE -a -x $FILE ] [root@centos8 data]# echo $? 1 [root@centos8 data]# chmod +x /data/test [root@centos8 data]# ll total 20 -rw-r--r-- 1 root root 0 Jan 9 22:28 a.log -rw-r--r-- 1 root root 181 Jan 4 18:29 arg.sh -rw-r--r-- 1 root root 1 Jan 6 19:17 lx.txt -rw-r--r-- 1 root root 116 Jan 5 15:50 rm.sh -rw-r--r-- 1 root root 403 Jan 2 17:39 systeminfo.sh -rwxr-xr-x 1 root root 110 Jan 3 10:17 test [root@centos8 data]# [ -f $FILE -a -x $FILE ] [root@centos8 data]# echo $? 0
COMMAND1 && COMMAND2 而且,短路與,表明條件性的AND THEN 若是COMMAND1 成功,將執行COMMAND2,不然,將不執行COMMAND2
COMMAND1 || COMMAND2 或者,短路或,表明條件性的OR ELSE 若是COMMAND1 成功,將不執行COMMAND2,不然,將執行COMMAND2
! COMMAND #非,取反
範例
[root@centos8 data]# test "A" = "B" && echo "string are equal" [root@centos8 data]# test "A" = "A" && echo "string are equal" string are equal [root@centos8 data]# ll -rw-r--r-- 1 root root 110 Jan 3 10:17 test.sh [root@centos8 data]# [ -f $FILE ] && [[ $FILE =~ \.sh$ ]] && chmod +x $FILE [root@centos8 data]# ll -rwxr-xr-x 1 root root 110 Jan 3 10:17 test.sh
&&與||組合使用
[root@centos8 data]# NAME=user;id $NAME && echo "$NAME is exist" || echo "$NAME is not exist" uid=1001(user) gid=1001(user) groups=1001(user) user is exist #注意:若是&& 和 || 混合使用,&& 要在前,|| 放在後。不然會出現邏輯錯誤
read:使用read來把輸入值分配給一個或多個shell變量,read從標準輸入中讀取值,給每一個單詞分配一個變 量,全部剩餘單詞都被分配給最後一個變量,若是變量名沒有指定,默認標準輸入的值賦值給系統內置 變量REPLY
read [options] [name ...]
經常使用選項
範例
[root@centos8 data]# read username [root@centos8 data]# echo $REPLY username [root@centos8 data]# read NAME SEX xiaoming boy [root@centos8 data]# echo $NAME $SEX xiaoming boy [root@centos8 data]# read -p "please input your name:" NAME please input your name:daxiong [root@centos8 data]# echo $NAME daxiong 面試題 read和輸入重定向 [root@centos8 data]# echo 1 2 | read x y;echo $x $y [root@centos8 data]# echo 1 2 | (read x y;echo $x $y) 1 2 #Each command in a pipeline is executed as a separate process (i.e., in a subshell) #管道符把每一個命令執行都在獨立的子進程中,因此第一種狀況父進程沒法讀取子進程的變量
全局生效配置文件
/etc/profile /etc/profile.d/*.sh /etc/bashrc
我的用戶生效配置文件
~/.bash_profile ~/.bashrc
配置文件加載順序
/etc/profile.d/*.sh /etc/bashrc /etc/profile /etc/bashrc #此文件執行兩次 .bashrc .bash_profile
配置文件加載順序
/etc/profile.d/*.sh /etc/bashrc .bashrc
爲交互式登陸的shell提供配置
全局:/etc/profile, /etc/profile.d/*.sh 我的:~/.bash_profile
用途:
1)用於定義環境變量
2)運行腳本或命令
爲非交互式和交互式登陸的shell提供配置
全局:/etc/bashrc 我的:~/.bashrc
用途:
1)定義命令別名和函數
2)定義本地變量
格式
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
範例
#BMI指數 [root@centos8 script]# cat bmi.sh #!/bin/bash # #******************************************************************** #Author: yuanyuan #QQ: 1136132605 #Date: 2021-01-11 #FileName: bmi.sh #URL: http://www.bestvae.cn #Description: The test script #Copyright (C): 2021 All rights reserved #******************************************************************** read -p "請輸入身高(單位m)" HIGH if [[ ! "$HIGH" =~ ^[0-2]\.?[0-9]{,2}$ ]];then echo "輸入身高錯誤" exit 1 fi read -p "請輸入體重(單位kg)" WEIGHT if [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then echo "輸入體重錯誤" exit 1 fi BMI=`echo $WEIGHT/$HIGH^2|bc` if [ "$BMI" -le 18 ];then echo "你太瘦了多吃點" elif [ "$BMI" -lt 24 ];then echo "你的身材很棒" else echo "你太胖了,增強運動" fi
格式
case: case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac Execute commands based on pattern matching. #case支持全局通配符 *: 任意長度任意字符 ?: 任意單個字符 []:指定範圍內的任意單個字符 |: 或,如 a或b
範例
#運維表 #!/bin/bash echo -en "\E[$[RANDOM%7+31];1m" cat <<EOF 1)備份數據庫 2)清理日誌 3)軟件升級 4)軟件回退 5)刪庫跑路 EOF echo -en '\E[0m' read -p "請輸入上面的數字:" MENU if [[ ! "$MENU" =~ ^[1-5]$ ]];then echo "你的輸入有誤" exit 1 fi case $MENU in 1) echo "備份成功";; 2) echo "清理日誌";; 3) echo "清理日誌";; 4) echo "清理日誌";; 5) echo "清理日誌";; esac
練習
一、編寫腳本 createuser.sh,實現以下功能:使用一個用戶名作爲參數,若是指定參數的用戶存在,就 顯示其存在,不然添加之。並設置初始密碼爲123456,顯示添加的用戶的id號等信息,在此新用戶第一 次登陸時,會提示用戶當即改密碼,若是沒有參數,就提示:請輸入用戶名
[root@centos8 script]# cat creatuser.sh #!/bin/bash if [ -z "$1" ];then echo "請輸入用戶名字格式爲$0 username" exit 1 else getent passwd $1 > /dev/null if [ "$?" -eq 0 ];then echo "$1 is exist" echo `getent passwd $1` exit 1 else useradd $1 echo '123456' | passwd --stdin $1 > /dev/null passwd -e $1 > /dev/null echo -e "$1用戶建立成功初始密碼爲123456\n`getent passwd $1`" fi fi
二、編寫生成腳本基本格式的腳本,包括做者,聯繫方式,版本,時間,描述等
[root@centos8 script]# cat /root/.vimrc set ts=4 set expandtab set ignorecase set cursorline set autoindent set showcmd autocmd BufNewFile *.sh exec ":call SetTitle()" func SetTitle() if expand("%:e") == 'sh' call setline(1,"#!/bin/bash") call setline(2,"#") call setline(3,"#********************************************************************") call setline(4,"#Author: yuanyuan") call setline(5,"#QQ: 1136132605") call setline(6,"#Date: ".strftime("%Y-%m-%d")) call setline(7,"#FileName: ".expand("%")) call setline(8,"#URL: http://www.bestvae.cn") call setline(9,"#Description: The test script") call setline(10,"#Copyright (C): ".strftime("%Y")." All rights reserved") call setline(11,"#********************************************************************") call setline(12,"") endif endfunc autocmd BufNewFile * normal G