自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

編寫可靠 bash 腳本的一些技巧

新聞 前端
寫過很多 bash 腳本的人都知道,bash 的坑不是一般的多。其實(shí) bash 本身并不是一個(gè)很嚴(yán)謹(jǐn)?shù)恼Z言,但是很多時(shí)候也不得不用。以下總結(jié)了一些編寫可靠的 bash 腳本的小 tips。

 [[322070]]

寫過很多 bash 腳本的人都知道,bash 的坑不是一般的多。其實(shí) bash 本身并不是一個(gè)很嚴(yán)謹(jǐn)?shù)恼Z言,但是很多時(shí)候也不得不用。以下總結(jié)了一些編寫可靠的 bash 腳本的小 tips。

0. set -x -e -u -o pipefail

在寫腳本時(shí),在一開始(Shebang 之后)加上下面這一句,或者它的縮略版,能避免很多問題,更重要的是能讓很多隱藏的問題暴露出來:

  1. set -xeuo pipefail 

下面說明每個(gè)參數(shù)的作用,以及一些例外的處理方式 :

-x :在執(zhí)行每一個(gè)命令之前把經(jīng)過變量展開之后的命令打印出來。

這個(gè)對于 debug 腳本、輸出 Log 時(shí)非常有用。正式運(yùn)行的腳本也可以不加。

-e :遇到一個(gè)命令失?。ǚ祷卮a非零)時(shí),立即退出。

bash 跟其它的腳本語言最大的不同點(diǎn)之一,應(yīng)該就是遇到異常時(shí)繼續(xù)運(yùn)行下一條命令。這在很多時(shí)候會遇到意想不到的問題。加上 -e ,會讓 bash 在遇到一個(gè)命令失敗時(shí),立即退出。

如果有時(shí)確實(shí)需要忽略個(gè)別命令的返回碼,可以用 || true 。如:

  1. some_cmd || true        # 即使some_cmd失敗了,仍然會繼續(xù)運(yùn)行some_cmd || RET=$?      # 或者可以這樣來收集some_cmd的返回碼,供后面的邏輯判斷使用 

但是在管道串起多條命令的情況下,只有最后一條命令失敗時(shí)才會退出。如果想讓管道中任意一條命令失敗就退出,就要用后面提到的-o pipefail 了。

加-e 有時(shí)候可能會不太方便,動不動就退出。但還是應(yīng)該堅(jiān)持所謂的fail-fast 原則,也就是有異常時(shí)停止正常運(yùn)行,而不是繼續(xù)嘗試運(yùn)行可能存在缺陷的過程。如果有命令可以明確忽略異常,那可以用上面提到的 || true 等方式明確地忽略之。

-u :試圖使用未定義的變量,就立即退出。

如果在 bash 里使用一個(gè)未定義的變量,默認(rèn)是會展開成一個(gè)空串。有時(shí)這種行為會導(dǎo)致問題,比如:

  1. rm -rf $MYDIR/data 

如果 MYDIR 變量因?yàn)槟撤N原因沒有賦值,這條命令就會變成 rm -rf /data 。這就比較搞笑了。。使用 -u 可以避免這種情況。

但有時(shí)候在已經(jīng)設(shè)置了-u 后,某些地方還是希望能把未定義變量展開為空串,可以這樣寫:

  1. ${SOME_VAR:-}#  bash變量展開語法,可以參考:https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html 

-o pipefail :只要管道中的一個(gè)子命令失敗,整個(gè)管道命令就失敗。

pipefail 與-e 結(jié)合使用的話,就可以做到管道中的一個(gè)子命令失敗,就退出腳本。

1. 防止重疊運(yùn)行

在一些場景中,我們通常不希望一個(gè)腳本有多個(gè)實(shí)例在同時(shí)運(yùn)行。比如用 crontab 周期性運(yùn)行腳本時(shí),有時(shí)不希望上一個(gè)輪次還沒運(yùn)行完,下一個(gè)輪次就開始運(yùn)行了。這時(shí)可以用 flock 命令來解決。flock 通過文件鎖的方式來保證獨(dú)占運(yùn)行,并且還有一個(gè)好處是進(jìn)程退出時(shí),文件鎖也會自動釋放,不需要額外處理。

用法 1:假設(shè)你的入口腳本是 myscript.sh,可以新建一個(gè)腳本,通過 flock 來運(yùn)行它:

  1. # flock --wait 超時(shí)時(shí)間   -e 鎖文件   -c "要執(zhí)行的命令" 
  2.  
  3. # 例如: 
  4.  
  5. flock  --wait 5  -e "lock_myscript"  -c "bash myscript.sh" 

用法 2:也可以在原有腳本里使用 flock。可以把文件打開為一個(gè)文件描述符,然后使用 flock 對它上鎖(flock 可以接受文件描述符參數(shù))。

  1. exec 123<>lock_myscript   # 把lock_myscript打開為文件描述符123 
  2.  
  3. flock  --wait 5  123 || { echo 'cannot get lock, exit'; exit 1; } 

2. 意外退出時(shí)殺掉所有子進(jìn)程

我們的腳本通常會啟動好多子腳本和子進(jìn)程,當(dāng)父腳本意外退出時(shí),子進(jìn)程其實(shí)并不會退出,而是繼續(xù)運(yùn)行著。如果腳本是周期性運(yùn)行的,有可能發(fā)生一些意想不到的問題。

在 stackoverflow 上找到的一個(gè)方法,原理就是利用 trap 命令在腳本退出時(shí) kill 掉它整個(gè)進(jìn)程組。把下面的代碼加在腳本開頭區(qū),實(shí)測管用:

  1. trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 

不過如果父進(jìn)程是用 SIGKILL (kill -9) 殺掉的,就不行了。因?yàn)?SIGKILL 時(shí),進(jìn)程是沒有機(jī)會運(yùn)行任何代碼的。

3. timeout 限制運(yùn)行時(shí)間

有時(shí)候需要對命令設(shè)置一個(gè)超時(shí)時(shí)間。這時(shí)可以使用 timeout 命令,用法很簡單:

  1. timeout 600s  some_command arg1 arg2 

命令在超時(shí)時(shí)間內(nèi)運(yùn)行結(jié)束時(shí),返回碼為 0,否則會返回一個(gè)非零返回碼。

timeout 在超時(shí)時(shí)默認(rèn)會發(fā)送 TERM 信號,也可以用 -s 參數(shù)讓它發(fā)送其它信號。

4. 連續(xù)管道時(shí),考慮使用 tee 將中間結(jié)果落盤,以便查問題

有時(shí)候我們會用到把好多條命令用管道串在一起的情況。如 cmd1 | cmd2 | cmd3 | ...這樣會讓問題變得難以排查,因?yàn)橹虚g數(shù)據(jù)我們都看不到。

如果改成這樣的格式:

  1. cmd1 > out1.dat 
  2.  
  3. cat out1 | cmd2 > out2.dat 
  4.  
  5. cat out2 | cmd3 > out3.dat 

性能又不太好,因?yàn)檫@樣 cmd1, cmd2, cmd3 是串行運(yùn)行的,這時(shí)可以用 tee 命令:

  1. cmd1 | tee out1.dat | cmd2 | tee out2.dat | cmd3 > out3.dat 

 

責(zé)任編輯:張燕妮 來源: 騰訊技術(shù)工程
相關(guān)推薦

2020-04-08 10:21:58

bash腳本語言

2023-02-10 09:46:04

bash腳本變量

2017-06-19 15:46:08

LinuxBash腳本技巧

2017-08-15 11:32:21

LinuxBash腳本技巧

2019-12-12 10:23:34

Linux 代碼 開發(fā)

2012-05-21 10:13:05

XCode調(diào)試技巧

2013-03-29 13:17:53

XCode調(diào)試技巧iOS開發(fā)

2011-06-01 16:50:21

JAVA

2011-05-23 18:06:24

站內(nèi)優(yōu)化SEO

2021-10-12 23:10:58

UnsafeJavaJDK

2011-10-26 20:55:43

ssh 安全

2011-07-12 09:47:53

WebService

2020-09-21 06:58:56

TS 代碼建議

2022-04-14 10:22:44

故事卡業(yè)務(wù)

2022-12-02 14:58:27

JavaScript技巧編程

2022-05-30 10:31:34

Bash腳本Linux

2017-04-13 10:51:17

Bash建議

2017-09-20 15:07:32

數(shù)據(jù)庫SQL注入技巧分享

2022-02-17 13:58:38

Linux技巧文件

2017-05-10 15:30:30

skynet崩潰程序
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號