shell基礎(六)指令碼規範及Linux訊號知識
一、shell指令碼規範事項
1.指令碼第一行加指令碼直譯器:#!/bin/bash 或 #!/bin/sh
2.若指令碼中有中文,則需要在系統中加"export LANG="zh_CN.UTF-8"",並且在指令碼中重新定義字符集,使其和系統中的字符集一致
3.shell指令碼以.sh結尾,並且放到制定位置:例如"/server/scripts"
4.所以成對的符號,和迴圈語句的關鍵詞,要一次性寫完,防止遺漏
5.全域性變數全部大寫,區域性變數可以全部小寫或者使用駝峰語法進行書寫,例如:"myBook"
6.函式命名可採用首字母大寫,並且語義要清晰,例如:"createFile"
7.儘量在函式最後加上返回值,有些不會用到返回值的也一樣
二、高階命名規範:
1.常規shell用.sh結尾:例如:shell.sh
2.模組的啟動和停止指令碼統一命名為start_模組名.sh和stop_模組名.sh
_mon.sh結尾
4.控制指令碼一般以
_ctl.sh為字尾三、shell指令碼的變數和檔案檢查規範
在指令碼中要檢查配置項是否為空、是否可執行等,尤其是對於一些重要的、會影響下面指令碼正常執行的配置項,需要進行是否為空的檢查。
字元子串的特殊用法: ${變數:-word}:若變數值為空或未賦值,則返回word字串並代替變數的值 用於:如果變數未定義,則返回備用值,防止因為變數未定義或為空而導致異常 ${變數:=word}:若變數值為空或未賦值,則設定這個變數的值為word,並且返回其值,位置變數和特殊變數不適用 用於:基本上同第一個,只是在第一個的基礎上又額外給了“變數賦值” ${變數:?word}:若變數值為空或未賦值,則word字串將被作為標準錯誤輸出,否則輸出變數的值 用於:捕捉由於變數未定義而導致的錯誤,並退出程式 ${變數:+word}:若變數值為空或未賦值,則什麼也不做,否則word字串將代替變數的值 注: 若將":"去掉,則將定義中的"若變數值為空或未賦值"改為"未賦值",用於測試變數是否賦值
例一: [centos@mycentos ~]$ echo $test #變數為空 [centos@mycentos ~]$ res=${test:-UNSET} [centos@mycentos ~]$ echo $res#列印res變數,返回UNSET,因為test沒有賦值 UNSET [centos@mycentos ~]$ echo $test#test仍然沒有值 對於${test:-UNSET},當test變數沒有值時,就返回變數結尾設定的UNSET字串,有值時就返回test的值。 例子二: [centos@mycentos ~]$ unset test#test為空 [centos@mycentos ~]$ unset res#res為空 [centos@mycentos ~]$ echo $res [centos@mycentos ~]$ res=${test:=UNSET}#對res變數進行賦值 [centos@mycentos ~]$ echo $res#因為test為空,所以列印UNSET UNSET [centos@mycentos ~]$ echo $test#此處test被賦值,原來是沒有定義的,與例一有所不同 UNSET 結論: ${變數:=word} 當變數(res)和變數(test)值沒有定義時,會給變數(res)賦值":="後面的內容,同時會把":="後面的內容賦值給變數test,此方法可以解決變數沒有定義的問題,確保沒有定義的變數始終有值 例子三: [centos@mycentos ~]$ echo ${key:?not defined} -bash: key: not defined [centos@mycentos ~]$ key=1 [centos@mycentos ~]$ echo ${key:?not defined} 1 [centos@mycentos ~]$ unset key [centos@mycentos ~]$ echo ${key:?not defined} -bash: key: not defined ${變數:?word}此例可以用於設定變數未定義二報錯的具體內容,如"not defined" 例子四: [centos@mycentos ~]$ oldboy=${oldgirl:+word} [centos@mycentos ~]$ echo $oldboy#oldgril沒有賦值,所以列印變數oldboy為空 [centos@mycentos ~]$ oldgirl=19 [centos@mycentos ~]$ oldboy=${oldgirl:+word} #此處需要重新定義 [centos@mycentos ~]$ echo $oldboy#oldgirl有值後,打印出來":+"後面的內容 word 此例可用於測試變數(oldboy位置)是否存在,若oldboy的值為word,則證明oldgirl變數有值存在
在系統指令碼中看防止變數為空的應用:
在apache1服務啟動指令碼/etc/init.d/httpd中 1 #!/bin/bash 2 # 3 # httpdStartup script for the Apache HTTP Server 4 # 5 # chkconfig: - 85 15 6 # description: The Apache HTTP Server is an efficient and extensible\ 7 #server implementing the current HTTP standards. 8 # processname: httpd 9 # config: /etc/httpd/conf/httpd.conf 10 # config: /etc/sysconfig/httpd 11 # pidfile: /var/run/httpd/httpd.pid 12 # 13 ### BEGIN INIT INFO 14 # Provides: httpd 15 # Required-Start: $local_fs $remote_fs $network $named 16 # Required-Stop: $local_fs $remote_fs $network 17 # Should-Start: distcache 18 # Short-Description: start and stop Apache HTTP Server 19 # Description: The Apache HTTP Server is an extensible server 20 #implementing the current HTTP standards. 21 ### END INIT INFO 22 23 # Source function library. 24 . /etc/rc.d/init.d/functions 25 26 if [ -f /etc/sysconfig/httpd ]; then 27. /etc/sysconfig/httpd 28 fi 29 30 # Start httpd in the C locale by default. 31 HTTPD_LANG=${HTTPD_LANG-"C"}#若HTTPD_LANG變數沒有賦值(沒有定義),則將HTTPD_LANG值變,此處為":"省略的情況 33 # This will prevent initlog from swallowing up a pass-phrase prompt if 34 # mod_ssl needs a pass-phrase from the user. 35 INITLOG_ARGS="" 36 37 # Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server 38 # with the thread-based "worker" MPM; BE WARNED that some modules may not 39 # work correctly with a thread-based MPM; notably PHP will refuse to start. 40 41 # Path to the apachectl script, server binary, and short-form for messages. 42 apachectl=/usr/sbin/apachectl 43 httpd=${HTTPD-/usr/sbin/httpd} #若HTTPD沒有賦值(沒有定義):則將httpd賦值為"/usr/sbin/httpd" 44 prog=httpd 注: 1.在企業中,針對目錄路徑情況等的處理就可以採用上述變數不存在的方式,防止因目錄不存在而導致的異常
實戰一:刪除7天前的過期資料備份
[centos@mycentos shell]$ cat 1.sh #!/bin/bash sudo find ${path-/tmp} -name "*.tar.gz" -type f -mtime +7 |xargs rm -f 1.如果忘記了定義path路徑變數,又不希望其為空,就可以定義/tmp代替path空值返回值. 2.若忘記了定義path路徑變數,還沒有做特殊變數定義,此條命令會出現異常
補充:http指令碼變數的定義方式:
httpd=${HTTPD-/usr/sbin/httpd} prog=httpd pidfile=${PIDFILE-/var/run/httpd/httpd.pid} lockfile=${LOCKFILE-/var/lock/subsys/httpd} 此定義方式可以防止出現空值
四、shell除錯技巧
1、使用dos2unix命令處理在Windows下開發的指令碼 #!/bin/bash i=1 sum=0 while((i<=100)) do let i++ ((sum+=i)) done 使用dos2unix進行格式化,會去除一些Windows的一些格式(例如空格)錯誤 --------------------------------------------------------------------------------------- 2.bash命令除錯 sh [-nvx] scripts.sh -n :不會執行指令碼,僅僅檢查語法是否有問題,並且給出錯誤提示 -v :在執行指令碼時,先將指令碼的內容輸出到螢幕上,然後執行指令碼,如果有錯誤,也會給出錯誤提示 -x :將執行的指令碼內容輸出顯示到螢幕上。 printf "totalsum is $sum" export PS4='+${LINENO}' #此命令可以使追蹤命令顯示每行的行號
五、vim編輯器的配置
1.編輯vim相關檔案
.viminfo使用者使用vim的操作歷史記錄 .vimrc當前使用者的配置檔案 /etc/vimrc系統全域性vim的配置檔案 /usr/share/vim/vim74/colors 配色魔板檔案存放路徑 注: 1.當配置/etc/vimrc檔案時,所有使用者的vim均會受影響 2.當編輯個人使用者家目錄下的隱藏檔案.vimrc,則只有此使用者的vim編輯受影響。
以下是個人的vim的配置,直接複製到家使用者目錄下的.vimrc即可
set nocompatible set history=100 filetype on filetype plugin on filetype indent on set autoread set mouse=a syntax enable set nofen set fdl=0 set expandtab set tabstop=4 set shiftwidth=4 set softtabstop=4 set smarttab set ai set si set wrap set sw=4 set wildmenu set nu set cmdheight=1 set lz set backspace=eol,start,indent set whichwrap+=<,>,h,l set magic set noerrorbells set novisualbell set showmatch set mat=2 set hlsearch set ignorecase set encoding=utf-8 set fileencodings=utf-8 set termencoding=utf-8 set smartindent set cin set showmatch set guioptions-=T set guioptions-=m set vb t_vb= set laststatus=2 set pastetoggle=<F9> set background=dark highlight Search ctermbg=black ctermfg=white guifg=white guibg=black autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()" func SetTitle() if expand("%:e") == 'sh' call setline(1, "#!/bin/bash") call setline(2, "#Auther:itboy") call setline(3, "#Time:".strftime("%F %T")) call setline(4, "#Name:".expand("%")) call setline(5, "#Version:V1.0") call setline(6, "#Description:this is a test script.") endif endfunc
2.vim的高階命令
ngg :調到n行 0 :到行開頭 $ :到行結尾 L :移動到當前視窗最後一行 == G ,然後點"o",開始下一行編輯 H :移動到當前視窗最前面一行 ==gg 命令列模式下:"ctrl+:"後 /old:從上向下找"old" %s/A/B/g :A全部替換為B "/"可以換成"#或@" n1,n2 w filename : 將n1到n2行的內容儲存到filename檔案裡 n1,n2 co n3 : 將n1到n2行的內容複製到n3的位置下 n1,n2 m n3 : 將n1到n2行的內容剪下到到n3的位置下 ! “命令”:暫且退出vi,執行“命令” vs filename: 豎直分屏顯示filename ,q!退出分屏 1.多行註釋: 1). 首先按esc進入命令列模式下,按下Ctrl + v,進入列(也叫區塊)模式; 2). 在行首使用上下鍵選擇需要註釋的多行; 3). 按下鍵盤(大寫)“I”鍵,進入插入模式; 4). 然後輸入註釋符(“//”、“#”等); 5). 最後按下“Esc”鍵。 注:在按下esc鍵後,會稍等一會才會出現註釋,不要著急~~時間很短的 2.刪除多行註釋: 1). 首先按esc進入命令列模式下,按下Ctrl + v, 進入列模式; 2). 選定要取消註釋的多行; 3). 按下“x”或者“d”. 注意:如果是“//”註釋,那需要執行兩次該操作,如果是“#”註釋,一次即可 3.多行刪除 1).首先在命令模式下,輸入“:set nu”顯示行號; 2).通過行號確定你要刪除的行; 3).命令輸入“:32,65d”,回車鍵,32-65行就被刪除了,很快捷吧 如果無意中刪除錯了,可以使用‘u’鍵恢復(命令模式下) 也可以用"del"在視覺化中全刪選擇的內容 4.多行縮排 1). 首先按esc進入命令列模式下,按下Ctrl + v,進入列(也叫區塊)模式; 2). 在行首使用上下鍵選擇需要縮排的多行; 3). 最後按"="即可
六、Linux訊號相關知識
一、現象描述:
1.當執行shell指令碼時,如果按下Ctrl+c 或Ctrl+x(x為其他字元),程式會終止執行。
2.當不希望shell在執行時被終止,則可以使用遮蔽訊號手段,讓程式忽略使用者輸入的訊號指令,從而繼續執行shell程式。
二、訊號含義:
訊號是由一個整數構成的非同步訊息,它可以由某個程序發給其他程序,也可以在使用者按下特定按鍵發生某種異常事件時,由系統發給某個程序。
1.Linux重要訊號
HUP(1)掛起,通常因終端掉線或使用者退出而引發 INT(2)中斷,通常因為按ctrl + c組合鍵而引發 QUIT(3) 退出,通常因為按ctrl + \ 組合鍵而引發 ABRT(6)中止 , 通常因為某些嚴重的執行錯誤而引發 ALRM(14) 報警 , 通常用來處理超時 TERM(15) 終止 ,通常在系統關機時傳送 TSTP(20) 停止程序的執行,但該訊號可以被處理和忽略,通常是Ctrl + z鍵而引發 注: shell指令碼中可以用數字來代表訊號,也可以用訊號的名字代表訊號
2.trap命令
trap命令: 1.用於在接受到訊號後將要採取的行動 2.常用於在指令碼程式被中斷時完成清理工作,或者遮蔽使用者非法使用的某些訊號 注: 使用訊號名時需要省略字首"SIG" 用法: trap command signal signal是接受到的訊號 , command是接收到訊號後應該採取的行動 trap "命令;命令" 訊號名或者 trap "命令;命令" 訊號編號
例一:
處理單個訊號: [centos@mycentos ~]$ trap "" 2#若執行動作為空,則可以用來遮蔽與數字對應的Ctrl+c訊號 [centos@mycentos ~]$ trap ":" 2 #此處恢復Ctrl + c 的訊號 [centos@mycentos ~]$ ^C#已恢復
例二:
同時處理多個訊號: [centos@mycentos ~]$ trap "" 1 2 3 20 #<==執行這些數字訊號,什麼都不做,即遮蔽這些訊號 [centos@mycentos ~]$ trap ":" 1 2 3 20 #<==執行這些訊號,恢復對應的功能 [centos@mycentos ~]$ ^C [centos@mycentos ~]$ trap "" HUP INT QUIT TSTP #<==執行這些名稱訊號,什麼都不做,即遮蔽這些訊號 [centos@mycentos ~]$ trap ":" HUP INT QUIT TSTP #<==執行這些名稱訊號,恢復對應的功能 [centos@mycentos ~]$ ^C [centos@mycentos ~]$ trap "" `echo {1..64}` #<==遮蔽1-64所有的數字訊號
實戰二:
開發指令碼實現觸發訊號後清理檔案功能(訊號觸發後就會執行將新建的檔案刪除命令)
#!/bin/bash #Auther:itboy #Time:2018-11-20 10:09:42 #Name:3.sh #Version:V1.0 #Description:this is a test script. #<==捕獲ctrl+c 鍵後即執行find刪除命令,後退出指令碼 trap "find /tmp -type f -name "old_*" | xargs rm -f && exit" INT while true do touch /tmp/old_$(date +%F-%T) #<==在/tmp建立檔案 sleep 5#<==休息3秒 ls -la /tmp/old*#<==檢視檔案建立情況 done
實戰三:
開發指令碼,練習QUIT、TSTP、INT
#!/bin/sh #捕獲ctrl+c訊號時,執行echo命令 trap 'echo "you are typing ctrl-c ,sorry,script will not terminate"' INT #捕獲Ctrl+\訊號,執行echo trap 'echo "you are typing ctrl-\ ,sorry,script will not terminate"' QUIT #捕獲ctrl+z訊號,就會執行echo命令 (實測此處沒有執行echo命令) trap 'echo "you are typing ctrl-z ,sorry,script will not terminate"' TSTP while true do echo "now , test signal $(date)" sleep 5 done
效果如圖:
[root@mycentos ~]# sh 2.sh now , test signal Tue Nov 20 11:02:06 CST 2018 ^Cyou are typing ctrl-c ,sorry,script will not terminate#按下ctrl+c執行 now , test signal Tue Nov 20 11:02:11 CST 2018 now , test signal Tue Nov 20 11:02:16 CST 2018 now , test signal Tue Nov 20 11:02:21 CST 2018 ^\Quit (core dumped) you are typing ctrl-\ ,sorry,script will not terminate #按下ctrl+\執行 now , test signal Tue Nov 20 11:02:25 CST 2018 now , test signal Tue Nov 20 11:02:30 CST 2018 ^Z^Z#按下ctrl +z 鍵沒有列印提示,但是程式停止運行了