【1】交互方式、非交互方式、Shell腳本是什么?
經常與linux打交道,肯定對shell這個詞不陌生。不明白shell意思的,可以自行翻譯:外殼、去殼。
這個翻譯結果怎么可以與計算機系統聯系起來呢?看不懂?
為了幫助理解shell這個詞,請看下圖:
計算機系統,最內層(本質)的是硬件,然后硬件會被系統核心層包住,而在系統核心外層的就是所謂的shell,再然后shell外層的就是我們接觸最多且最容易理解的應用程序。
shell其實是一個命令解釋器,作用是解釋用戶輸入的命令和程序,命令和程序可以理解成上圖中的應用程序。
linux系統中的那些命令其實也都是一個個的小程序,只不過執行的是系統的應用功能。
當我們在系統的終端中輸入一條命令,可以立馬看到一條或者幾條系統回復我們的信息,其實就是shell在幫我們回復,所以shell可以稱之為命令解釋器。
而這種從鍵盤一輸入命令,就立馬得到相應的回復信息,叫作交互的方式。
了解了shell之后,再來了解下shell腳本。如果我們的命令或應用程序不在命令行直接執行,而想通過一個程序文件來執行時,這個程序文件就被稱之為shell腳本。
shell腳本里面通常內置了多條命令,有的還包含控制語句,比如if和else的條件控制語句,for的循環控制語句等。
這些內置在一個shell腳本中的命令通常是一次性執行完成,不會不停的返回信息給用戶,這種通過文件執行腳本的方式稱之為非交互方式。
shell腳本類似於windows下的批處理,但它比批處理要強大一些,現在windows下有一個叫做power shell的功能其實和linux下的shell功能媲美。
在文本中輸入一系列的命令、控制語句和變量,這一切有機的結合起來就形成了功能強大的shell腳本。
日常工作中,經常需要使用多個命令來完成一項任務,可以添加這些所有命令在一個文本文件(Shell腳本)來統一完成這些日常工作任務。
【2】什么是默認登錄shell,如何改變指定用戶的登錄shell?
登錄shell是可以用戶登錄使用的,比如/bin/bash, /bin/sh, /bin/csh......
一般Linux默認的用戶shell都是bash,也就是你可以登錄進去寫命令。
非登錄shell:經典的/bin/nologin就是一個非登錄shell,也就是說如果一個用戶默認的是它,這個用戶即使登錄進linux也無法使用linux。
shell是用戶和計算機交流的媒介,登錄shell保證用戶和計算機交流,非登錄shell無法讓計算機和用戶交流。
關於用戶的默認登錄shell是在/etc/passwd文件中記錄的。本地系統示例如下:
非登錄shell有其特定的用途:比如一個用linux搭建的ftp服務器,創建了多個用戶,可以將這些用戶默認shell改成nologin。
這樣一來,這些用戶雖然是linux上的用戶卻無法登錄進linux主機,只能進入ftp服務器,這樣也保證了安全!
在Linux操作系統,“/bin/bash”是默認登錄shell,是在創建用戶時分配的。
使用chsh命令可以改變默認的shell。示例如下所示:
# chsh <用戶名> -s <新shell>
# chsh zhangsan -s /bin/sh
當然,也可以直接通過修改/etc/passwd文件中對應用戶的默認shell。
查看系統中有哪些shell,利用命令:cat /etc/shells
示例如下(本地系統中有六種shell):
【3】可以在shell腳本中使用哪些類型的變量?
在shell腳本,我們可以使用兩種類型的變量:
(1)系統定義變量
(2)用戶定義變量
系統變量是由系統系統自己創建的。這些變量通常由大寫字母組成,可以通過“set”命令查看。
用戶變量由系統用戶來生成和定義,變量的值可以通過命令“echo $<變量名>”查看。
shell變量的作用域可以分為三種:
(1)有的變量只能在函數內部使用,叫做局部變量(local variable)
(2)有的變量可以在當前shell進程中使用,叫做全局變量(global variable)
(3)有的變量還可以在子進程中使用,叫做環境變量(environment variable)
【4】如何將標准輸出和錯誤輸出同時重定向到同一位置?
這個需求有兩種方法可以實現:
(1)方法一:2>&1
示例:# ls /usr/share/doc > log.txt 2>&1
前半部分 ls /usr/share/doc > log.txt 很容易理解,那么后面的 2>&1 是怎么回事呢?
要解釋這個問題,還得提到文件重定向。假定已經知道 > 和 < 是文件重定向符。那么1和2是什么?
在shell中,每個進程都和三個系統文件相關聯:
(0)標准輸入stdin
(1)標准輸出stdout
(2)標准錯誤stderr
三個系統文件的文件描述符分別為0、1、2。所以,這里 2>&1 的意思就是將標准錯誤也輸出到標准輸出當中。
& 表示“等同於”的意思,2>&1,表示2的輸出重定向等同於1。
實際上,> 就相當於 1> 也就是重定向標准輸出,不包括標准錯誤。
而通過 2>&1 就將標准錯誤重定向到標准輸出了(stderr已作為stdout的副本),那么再使用>重定向就會將標准輸出和標准錯誤信息一同重定向了。
如果只想重定向標准錯誤到文件中,則可以使用 2> file。
(2)方法二:&>
示例:# ls /usr/share/doc &> log.txt
& 是一個描述符,如果1或2前不加&,會被當成一個普通文件。
1>&2 把標准輸出重定向到標准錯誤。
2>&1 把標准錯誤輸出重定向到標准輸出。
&> filename 把標准輸出和標准錯誤輸出都重定向到文件filename中
摘錄同問:Linux重定向中 >&2 怎么理解?
問題補充:echo "abdefghijklmn" >&2 怎么理解?
問題解答:>&2 即 1>&2 也就是把結果輸出到和標准錯誤一樣;之前如果有定義標准錯誤重定向到某log文件,那么標准輸出也重定向到這個log文件。
如:ls 2>a1 >&2 (等同 ls >a1 2>&1)
把標准輸出和標准錯誤都重定向到a1,終端上看不到任何輸出信息。
【5】shell腳本中“if”語法如何嵌套?
基礎語法如下:
if [ 條件 ]
then
命令1
命令2
…
else
if [ 條件 ]
then
命令1
命令2
…
else
命令1
命令2
…
fi
fi
if語法示例如下:
#!/bin/bash a=100 b=200 echo "a : "$a echo "b : "$b if [ $a == $b ] then echo "a 等於 b" elif [ $a -gt $b ] then echo "a 大於 b" elif [ $a -lt $b ] then echo "a 小於 b" else echo "沒有符合的條件" fi
if語法輸出結果:
a : 100
b : 200
a 小於 b
if嵌套語法示例如下:
#!/bin/bash a=100 b=200 echo "a : "$a echo "b : "$b if [ $a == $b ] then echo "a 等於 b" else if [ $a -gt $b ] then echo "a 大於 b" else if [ $a -lt $b ] then echo "a 小於 b" else echo "沒有符合的條件" fi fi fi
if嵌套語法輸出結果:
a : 100
b : 200
a 小於 b
【6】shell腳本中“$?”標記的用途是什么?
在寫一個shell腳本時,若想要檢查前一命令是否執行成功,在if條件中使用“$?”可以來檢查前一命令的結束狀態。
簡單的例子如下:
如果結束狀態是0,說明前一個命令執行成功。
如果結束狀態不是0,說明命令執行失敗。
【7】在shell腳本中如何比較兩個數字?
在if-then中使用測試命令(-gt等)來比較兩個數字。
-gt示例如下:
#!/bin/bash x=10 y=20 if [ $x -gt $y ] then echo "x is greater than y" else echo "y is greater than x" fi # 輸出 # y is greater than x
test示例如下:
#!/bin/bash num1=$[2*3] num2=$[1+5] if test $[num1] -eq $[num2] then echo '兩個數字相等!' else echo '兩個數字不相等!' fi # 輸出 # 兩個數字相等!
【8】shell腳本中break命令的作用?
break命令一個簡單的用途是退出執行中的循環。
可以在while和until循環中使用break命令跳出循環。
從while循環中跳出,示例如下:
#!/bin/bash a=0 while [ $a -lt 10 ] do echo $a a=`expr $a + 1` if [ $a -gt 8 ] then echo "break" break fi done # 輸出 0 1 2 3 4 5 6 7 8 break
從until循環中跳出,示例如下:
#!/bin/bash a=0 until [ ! $a -lt 10 ] do echo $a a=`expr $a + 1` if [ $a -gt 8 ] then break fi done # 輸出 0 1 2 3 4 5 6 7 8
從 for 循環中跳出,示例如下:
#!/bin/bash for loop in 1 2 3 4 5 do echo "The value is: $loop" if [ $loop == 4 ] then echo "break" break fi done # 輸出 The value is: 1 The value is: 2 The value is: 3 The value is: 4 break
如上三種跳出方式。
【9】shell腳本中continue命令的作用?
continue命令不同於break命令,它只跳出當前循環的迭代,而不是整個循環。
continue命令很多時候是很有用的,例如錯誤發生,但我們依然希望繼續執行大循環的時候。
示例如下:
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i == 3 ] then continue fi echo $i done echo $i # 輸出 1 1 2 2 3 4 4 5 5 5
如上示例。
【10】shell腳本中case語句的語法?
基礎語法如下:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
case語法示例如下(用vim 新建文件cash.sh,輸入內容):
#!/bin/bash echo '輸入 1 到 4 之間的數字:' echo '你輸入的數字為:' read aNum case $aNum in 1) echo '你選擇了 1' ;; 2) echo '你選擇了 2' ;; 3) echo '你選擇了 3' ;; 4) echo '你選擇了 4' ;; *) echo '你沒有輸入 1 到 4 之間的數字' ;; esac
如上腳本,執行./case.sh 或 sh case.sh
【11】shell腳本中while循環語法?
如同for循環,while循環只要條件成立就重復它的命令塊。
不同於for循環,while循環會不斷迭代,直到它的條件不為真。
基礎語法:
while [ 條件 ]
do
命令…
done
【12】如何使腳本可執行?
使用chmod命令來使腳本可執行。示例如下:
# chmod a+x myshell.sh
【13】“#!/bin/bash”的作用?
#!/bin/bash是shell腳本的第一行,稱為釋伴(shebang)行。
這里#符號叫做hash,而!叫做bang。它的意思是命令通過 /bin/bash 來執行。
【14】shell腳本中for循環語法?
for循環的基礎語法:
for 變量 in 循環列表
do
命令1
命令2
…
最后命令
done
【15】如何調試shell腳本?
兩種方式:
(1)使用‘-x’參數(sh -x myshell.sh)可以調試shell腳本。
如上面例子中的case.sh腳本,調試結果如下:
如上。
(2)使用‘-xv’參數,但是,寫法與第一種不同,具體如下:
#!/bin/bash -xv
應用示例如下:
#!/bin/bash -xv echo '輸入 1 到 4 之間的數字:' echo '你輸入的數字為:' read aNum case $aNum in 1) echo '你選擇了 1' ;; 2) echo '你選擇了 2' ;; 3) echo '你選擇了 3' ;; 4) echo '你選擇了 4' ;; *) echo '你沒有輸入 1 到 4 之間的數字' ;; esac
輸出結果:
如上。
【16】shell腳本如何比較字符串?
test命令可以用來比較字符串。測試命令會通過比較字符串中的每一個字符來比較。
參數 說明
= 等於則為真
!= 不相等則為真
-z 字符串 字符串的長度為零則為真
-n 字符串 字符串的長度不為零則為真
示例如下(用vim新建test.sh文件,輸入如下內容):
#!/bin/bash num1="abcdef" num2="abcdefg" if test $num1 = $num2 then echo '兩個字符串相等!' else echo '兩個字符串不相等!' fi if test $num1 != $num2 then echo '兩個字符串不相等!' else echo '兩個字符串相等!' fi if test -z "$num1" then echo 'num1字符串長度為0' else echo 'num1字符串長度不為0' fi num2= if test -n "$num2" then echo 'num2字符串長度不為0' else echo 'num2字符串長度為0' fi # 輸出 # 兩個字符串不相等! # 兩個字符串不相等! # num1字符串長度不為0 # num2字符串長度為0
如上內容。
【17】Bourne shell(bash) 中有哪些特殊的變量?
下面的表列出了Bourne shell為命令行設置的特殊變量。
內建變量 解釋
$0 當前腳本的文件名
$n 傳遞給腳本或函數的參數。n是一個數字,表示第幾個參數。例如,第一個參數是$1,第二個參數是$2。
$# 傳遞給腳本或函數的參數個數。
$* 傳遞給腳本或函數的所有參數。
$@ 傳遞給腳本或函數的所有參數。被雙引號(" ")包含時,與 $* 稍有不同。可參見下文第【26】問。
$$ 當前shell進程ID。對於shell腳本,就是這些腳本所在的進程ID。
示例如下:
#!/bin/bash echo "0:$0" echo "1:$1" echo "2:$2" echo "3:$3" echo "4:$4" echo "5:$5" echo "6:$6" echo "7:$7" echo "8:$8" echo "9:$9" echo "#:$#" echo "*:$*" echo "@:$@" echo "$:$$"
輸出結果:
如上過程。
【18】在shell腳本中,如何測試文件?
test命令可以用來測試文件。
test命令基礎用法如下表格:
test 用法
-d 文件名 如果文件存在並且是目錄,返回true
-e 文件名 如果文件存在,返回true
-f 文件名 如果文件存在並且是普通文件,返回true
-r 文件名 如果文件存在並可讀,返回true
-s 文件名 如果文件存在並且不為空,返回true
-w 文件名 如果文件存在並可寫,返回true
-x 文件名 如果文件存在並可執行,返回true
示例如下:
#!/bin/bash if test -e ./shellarg.sh then echo '文件已存在!' else echo '文件不存在!' fi
輸出結果:
如上。
【19】在shell腳本中,如何寫入注釋?
注釋可以用來描述一個腳本可以做什么和它是如何工作的。每一行注釋以#開頭。
示例如下:
#!/bin/bash
# This is a command
【20】如何讓shell腳本得到來自終端的輸入?
read命令可以讀取來自終端(使用鍵盤)的數據。read命令得到用戶的輸入並置於你給出的變量中。
示例如下:
#!/bin/bash echo ‘please enter your name’ read name echo “my Name is $name”
輸出結果:
如上。
【21】如何取消變量或取消變量賦值?
“unset”命令用於取消變量或取消變量賦值。
語法如下所示:
unset [-fv] [變量或函數名稱]
-f:僅刪除函數
-v:僅刪除變量
應用示例如下:
#!/bin/bash export JAVA_HOME=/usr/local/jdk echo $JAVA_HOME unset JAVA_HOME echo $JAVA_HOME a=100 readonly PI=3.141592653 function func() { echo 'call fun()' } echo 'unset a' unset a func echo 'unset func' unset func echo 'unset PI' unset PI
輸出結果:
注意:unset 刪除不了只讀變量
如上
【22】如何執行算術運算?
有兩種方法來執行算術運算:
1.使用expr命令
# expr 5 + 2
2.用一個美元符號和方括號($[ 表達式 ])
例如:
test=$[16 + 4]
示例如下:
#!/bin/bash a=2 b=3 result1=$[a + b] result2=`expr $a + $b` echo "result1:$result1" echo "result2:$result2"
輸出結果:
如上。
【23】在shell腳本如何定義函數呢?
函數是擁有名字的代碼塊。
當我們定義代碼塊,我們就可以在我們的腳本調用函數名字,該塊就會被執行。示例如下所示:
$ diskusage () { df -h ; }
譯注:下面是我給的shell函數語法,原文沒有
[ function ] 函數名 [()]
{
命令;
[return int;]
}
示例如下:
#!/bin/bash function demoFunc() { echo "這是我的第一個shell函數!" } echo "-----函數開始執行-----" demoFunc echo "-----函數執行完畢-----"
輸出結果:
如上。
【24】shell腳本中如何退出?
利用exit退出整個腳本。
示例如下:
#!/bin/bash for i in `seq 1 5` do echo $i if [ $i == 3 ] then echo "exit" exit fi echo $i done echo "end" # 輸出 1 1 2 2 3 exit
如上示例。
【25】shell中如何判斷字符串為空?
利用test命令,上面有講過。
也可以如下示例:
#!/bin/bash string= if [ -z "$string" ]; then echo "string is empty" fi if [ -n "$string" ]; then echo "string is not empty" fi
輸出結果:
如上
【26】Shell腳本“$*”和“$@”的聯系是什么?
(1)相同點:都是引用所有參數。
(2)不同點:只有在雙引號中體現出來。
假設在腳本運行時寫了三個參數 1、2、3,則 " * " 等價於 "1 2 3"(傳遞了一個參數),而 "@" 等價於 "1" "2" "3"(傳遞了三個參數)。
(3)示例
3.1 示例如下(利用vim新建腳本文件difference.sh,輸出如下內容):
#!/bin/bash echo "-- \$* 演示 ---" for value in "$*"; do echo $value done echo "-- \$@ 演示 ---" for value in "$@"; do echo $value done
3.2 輸出結果:
如上
【27】shell 如何實現定時執行任務?
定時器可以直接利用:/bin/sleep 時間(s)
示例如下:
#!/bin/bash echo "timer invite" count=0 while [ true ]; do # 定時器 1s /bin/sleep 1 count=$[count + 1] echo "invite:$count" done
輸出結果:
如上。
【28】如何向腳本傳遞參數?
不懂shell的同事,可能不會修改shell代碼(比如測試的妹子)。
那么,為了讓腳本更通用,某些變量值需要在執行腳本時傳入即可。
因某種需要,想在腳本執行時傳入運行過程中的需要的參數。
示例如下(用vim新建文件argument.sh,輸入如下內容):
#!/bin/bash echo "第一個參數值:$1" echo "第二個參數值:$2"
輸出結果:
如上
【29】shell腳本如何讀取文件?
工作中,最常用的就是利用shell腳本讀取文件(比如日志文件log)。
shell腳本讀取(read)文件,利用循環逐行進行讀取。
示例如下:
#!/bin/bash echo "-------begin read file" while read -r line do echo $line done < $1 echo "-------end read file"
輸出結果:
如上。注意:利用上一問的腳本傳參方式將文件名作為參數傳入。
【30】如何獲取一個文件每一行的第三個元素?
使用 awk '{print $3}'
應用示例如下:
#!/bin/bash echo "-------begin read file content" while read -r line do echo $line done < $1 echo "-------end read file content" echo "---------begin read three column" awk '{print $3}' $1 echo "---------end read three column"
輸出結果:
如上。
如何獲取一個文件每一行的第三個元素 ?
作者:IT程序獅
鏈接:http://www.imooc.com/article/1131
來源:慕課網
【31】如何獲取文件的第一行和最后一行內容?
獲取首行:head -1
獲取尾行:tail -1
應用示例如下:
#!/bin/bash echo "------begin read file content" while read -r line do echo $line done < $1 echo "------end read file content" echo "------begin read head line" head -1 $1 echo "------end read head line" echo "------begin read tail line" tail -1 $1 echo "------end read tail line"
輸出結果:
如上。
【32】假如文件中某一行的第三個元素是18,如何獲取第四個元素?
使用:awk '{ if ($3 == "18") print $4}'
應用示例如下:
#!/bin/bash echo "-------begin read file content" while read -r line do echo $line done < $1 echo "-------end read file content" echo "------begin four column value" awk '{ if ($3 == "18") print $4}' $1 echo "------end four column value"
輸出結果:
如上。
【33】如何連接兩個字符串?
應用示例如下:
#!/bin/bash v1="bei" v2="jing" echo "------字符串連接前" echo "v1:$v1" echo "v2:$v2" echo "------字符串連接方式一后" v3=${v1}${v2} echo "v3:$v3" echo "------字符串連接方式二后" echo "$v1$v2"
輸出結果:
如上。
【34】shell腳本中如何進行兩數相加?
方式共有六種。
應用示例如下:
#!/bin/bash A=5 B=6 echo "------原數據" echo "A:$A" echo "B:$B" echo "------方式一" let C=$A+$B echo $C echo "------方式二" echo $(($A+$B)) echo "------方式三" echo $[$A+$B] echo "------方式四" expr $A + $B echo "------方式五" echo $A+$B | bc echo "------方式六" awk 'BEGIN{print '"$A"'+'"$B"'}'
輸出結果:
如上。
【35】每個腳本開始的 #!/bin/sh 或 #!/bin/bash 表示什么意思?
這一行說明要使用的 shell。#!/bin/bash 表示腳本使用 /bin/bash。對於 python 腳本,就是 #!/usr/bin/python。
【36】如何獲取文本文件的第2行?
使用:head -2 file | tail -1
示例應用如下:
#!/bin/bash echo "------begin read file content" while read -r line do echo $line done < $1 echo "------end read file content" echo "------begin read second line" head -2 $1 | tail -1 echo "------end read second line"
輸出結果:
如上。
【37】bash腳本文件的第一個符號是什么?
答:#
【38】命令:[ -z "" ] && echo 0 || echo 1 的輸出是什么?
關於“-z” 可參考上面第15問理解:字符串長度為零則為真
關於&& 和 ||,即分別為shell腳本的邏輯運算符AND 和 OR
所以,[ -z "" ] 的值為真,那么:[ -z "" ] && echo 0 輸出結果即為:0
示例如下:
#!/bin/bash echo " expression result" [ -z "" ] && echo 0 || echo 1 echo "end" echo "邏輯運算符演示" a=10 b=20 if [[ $a -lt 100 && $b -gt 100 ]] then echo "返回 true" else echo "返回 false" fi if [[ $a -lt 100 || $b -gt 100 ]] then echo "返回 true" else echo "返回 false" fi
輸出結果:
如上。
【39】命令 “export” 有什么用?
使父shell定義的變量在子shell進程中可以使用。
用戶登錄到linux系統后,系統將啟動一個用戶shell。
在這個shell中,可以使用shell命令或聲明變量,也可以創建並運行shell腳本程序。當運行shell腳本程序時,系統將創建一個子shell。
此時,系統中將有兩個shell,一個是登錄時系統啟動的shell,另一個是系統為運行腳本程序創建的shell。
當一個腳本程序運行完畢,腳本shell(即子shell)將終止,返回到執行該腳本之前的shell。
從這種意義上來說,用戶可以有許多shell,每個shell都是由某個shell(稱為父shell)生的。
在子shell中定義的變量只在該子shell內有效。
即在一個shell腳本程序中定義了一個變量,當該腳本程序運行時,這個定義的變量只是該腳本程序內的一個局部變量,其他的shell不能引用它。
如果要使某個變量的值可以在其他shell中被改變,可以使用export命令對已定義的變量進行輸出。
export命令將使系統在創建每一個新的shell時,定義這個變量的一個拷貝。這個過程稱之為變量輸出。
(1)修改生效范圍
腳本A中export的變量在啟動其他腳本時會復制一份傳入其他腳本。其他腳本中對此變量的修改並不會在離開腳本后生效。
(2)注意
在腳本A中定義了一個變量V賦值為1,export了變量V,在腳本A中啟動腳本B,在腳本B中變量V的值就是1,如果在腳本B中修改了V的值為2,那么腳本B結束后,腳本A中的V的值依然是1。
腳本A中export的變量在啟動其他腳本的時候會復制一份傳入其他腳本,傳入的值是調用其他腳本時的值。並不是export時的值。
在腳本A中定義了一個變量V賦值為1,export了變量V,然后修改V為2,在腳本A中啟動腳本B,在腳本B中變量V的值就是2。
應用示例如下:
使用vim創建腳本文件export_b.sh,輸入如下內容:
#!/bin/bash echo "exec export_b start" A="this is export_b A" export B="this is export_b B" ./export_a.sh echo "export_b A:$A" echo "export_b B:$B" echo "exec export_b over"
使用vim創建腳本文件export_a.sh,輸入如下內容:
#!/bin/bash echo "exec export_a start" echo "this is export_a, A=\"$A\"" echo "this is export_a, B=\"$B\"" A="this is export_a A" B="this is export_b B" echo "exec export_a over" exit 0
輸出結果:
如上。
【40】如何在后台運行腳本?
主要分為以下三種需求場景:
(1)前台轉后台運行腳本
[1] 執行腳本backrun.sh:./backrun.sh
[2] 中斷腳本backrun.sh:ctrl+c
[3] 在[1]的基礎上將運行中的backrun.sh,切換到后台並暫停:ctrl + z
[4] 執行ctrl + z 后,backrun.sh在后台是暫停狀態(stopped)。
使用命令:bg number讓其在后台開始運行(“number”是使用jobs命令查到的[ ]中的數字,不是pid)
(2)后台轉前台運行腳本
[1] 直接在后台運行腳本backrun.sh:./backrun.sh &
[2] 查看當前shell環境中已啟動的任務情況:jobs
[3] 將backrun.sh切換到前台運行:fg %number(”number”為使用jobs命令查看到的[ ]中的數字,不是pid)
[4] 中斷后台運行的backrun.sh腳本:先fg %number切換到前台,再ctrl+c;或直接kill %number
尤其注意:以上兩種在后台運行backrun.sh的方法,當遇到退出當前shell終端時,后台運行的backrun.sh也就結束了。為什么呢?
因為以上兩種方法之所以使得backrun.sh在后台運行,運行backrun.sh進程的父進程是當前shell終端進程,關閉當前shell終端時,父進程退出,會發送hangup信號給所有子進程,子進程收到hangup以后也會退出。
所以要想退出當前shell終端時backrun.sh繼續運行,則有兩種方式:
方式一:使用nohup忽略hangup信號
[1] 不中斷的在后台運行backrun.sh:nohup ./backrun.sh &(backrun.sh的打印信息會輸出到當前目錄下的nohup.out中)
[2] 使用jobs可看到backrun.sh處於running狀態
[3] 使用ps -ef | grep backrun.sh可查看到正在運行的backrun.sh腳本進程
[4] 退出當前shell終端,再重新打開,使用jobs看不到正在運行的backrun.sh,但使用ps -ef可以看到
方式二:使用setsid將其父進程改為init進程(進程號為1)
[1] 不中斷的在后台運行backrun.sh另一個命令:setsid ./backrun.sh &
[2] 使用ps -ef | grep backrun.sh可看到backrun.sh進程的父進程id為1
示例腳本程序如下:
#!/bin/bash count=1 while (( $count <= 100 )) do echo $count let "count++" sleep 1 done
自己運行體會。
【41】"chmod 500 myscript.sh" 做什么?
使腳本所有者擁有可執行權限。
對於Linux系統中的文件來說,有三種身份和四種權限,三種身份是:
u:文件的擁有者
g:文件所屬的群組
o:其他用戶
對於每個身份,又有四種權限,分別為:
r:讀取文件的權限(read)
w:寫入文件的權限(write)
x:執行的權限(execute)
s:特殊權限
說這么多,那500又是怎么回事呢?這其實也是Linux系統下一種表示文件權限的方式:
在Linux系統中,對於文件的權限有讀取、寫入、執行三種,分別用rwx表示,另一種表示權限的方式就是使用數字,讀取、寫入和執行權限分別由數字4、2和1表示:
讀取權限:r 或者4
寫入權限:w 或者2
執行權限:x 或者1
如下圖:
那么,對於此例中的文件,用數字形式表示其權限的話,則為500,如下所示:
如上。
【42】">" 和 ">>" 做什么?
重定向輸出流到文件或另一個流。
兩者的區別:
(1)> :如果文件不存在,會創建文件。如果文件存在,就將其清空。即會重寫文件,如果文件里面有內容會覆蓋。
(2)>> :如果文件不存在,會創建文件。如果文件存在,將輸出內容追加到目標文件中。
示例如下(為了便於演示,只演示>>的場景。利用上問的腳本):
#!/bin/bash count=1 while (( $count <= 100 )) do echo $count >> backrun.log let "count++" sleep 1 done
輸出結果:
注意:
因為輸出重定向到日志文件backrun.log文件中,所以啟動腳本后,shell端看不到輸入內容。
只能通過瀏覽backrun.log文件查看執行結果。
如上。
【43】“&”、“&&”和“;”有什么區別?
& :希望腳本在后台運行的時候使用它
&& :當前面的腳本執行成功后,才執行后面的腳本或命令
;:不管前面的腳本命令執行成功與否,后面的腳本或命令繼續執行
如下三種形式:
1.command1 & command2 & command3
表示:三個命令同時執行
2.command1; command2; command3
表示:不管前面命令執行成功沒有,后面的命令繼續執行
3.command1 && command2
表示:只有前面命令執行成功,后面命令才繼續執行
利用上問的腳本command1.sh,改造如下(從1開始計數):
#!/bin/bash count=1 while (( $count <= 100 )) do echo $count let "count++" sleep 1 done
command2.sh,改造如下(從100開始計數):
#!/bin/bash count=100 while (( $count <= 1000 )) do echo $count let "count++" sleep 1 done
command3.sh,改造如下(從1000開始計數):
#!/bin/bash count=1000 while (( $count <= 10000 )) do echo $count let "count++" sleep 1 done
執行命令command4.sh,內容如下(可嘗試修改三種方式運行觀察):
#!/bin/bash ./command1.sh & ./command2.sh & ./command3.sh
自己摸索體會其差異點。
【44】 ' 和 " 引號有什么區別?
' - 當我們不希望把變量轉換為值的時候使用它。
” - 會計算所有變量的值並用值代替。
應用示例如下:
#!/bin/bash name=John && echo "My name is $name" age=18 && echo 'My age is $age'
輸出結果:
如上。
【45】如何只用echo命令獲取字符串變量的一部分?
應用示例如下:
#!/bin/bash echo "----按索引截取" variable="My name is wangjun, and I am developer" echo ${variable:11:7} localpath="User:192.168.1.15:/home/wangjun" echo "----截取尾部方式一:" echo ${localpath#*:*.*.*.*:} echo "----截取尾部方式二:" echo ${localpath##*:} echo "----截取頭部方式一:" echo ${localpath%:*.*.*.*} echo "----截取頭部方式二:" echo ${localpath%%:*} echo "----截取中間字符串" data=`echo ${localpath#*User:}` ip=`echo ${data%:/home*}` echo "${ip}"
輸出結果:
如上。
【46】如何獲取變量長度且獲取變量最后10個字符?
應用示例如下:
#!/bin/bash value="abcdefghijklmnopqrstuvwxyz" echo "value length:${#value}" if [ ${#value} -gt 10 ] then echo "print tail 10:" echo ${value: -10} fi
輸出結果:
如上。
【47】${variable:-10} 和 ${variable: -10} 有什么區別?
應用示例如下:
#!/bin/bash variable= echo ${variable:-10} echo ${variable: -10} variable="abcdefghijklmn" echo ${variable:-10} echo ${variable: -10}
輸出結果:
總結:
${variable:-10} :如果之前沒有給 variable 賦值則輸出10;如果有賦值則輸出該變量。
${variable: -10}:輸出variable的最后10個字符。
如上。
【48】如何只用echo命令替換字符串的一部分?
示例如下:
#!/bin/bash variable="abcdefghijklmn" echo "方式一:${variable//def/wangqi}" echo 方式二:${variable//def/wangqi}
輸出結果:
如上。利用echo ${variable//pattern/replacement}進行替換操作。
【49】如何將文本文件中的小寫字符轉換為大寫?
tr [:lower:] [:upper:]
應用示例如下:
#!/bin/bash cat $1 | tr [:lower:] [:upper:]
輸出結果:
如上。
【50】如何列出第二個字母是a 或 b的文件?
ls -d ?[ab]*
應用示例,輸出結果:
如上。
【51】如何去除字符串中的所有空格?
echo $string | tr -d " "
應用示例如下:
#!/bin/bash var="I am wang qi and my age is 18." echo "var:$var" echo $var | tr -d " "
輸出結果:
如上。
【52】重寫這個命令,將輸出變量轉換為復數: item="car"; echo "I like $item" ?
重寫腳本如下:
#!/bin/bash item="car" echo "I like ${item}s"
輸出結果:
如上。
【53】寫出輸出數字 0 到 20 中 3 的倍數(0 3 6 9 …)的命令?
腳本如下:
#!/bin/bash echo "方式一:" for i in {0..20..3}; do echo $i done echo "方式二:" for (( i=0; i<20; i=i+3)); do echo "Welcome $i times" done
輸出結果:
如上。
【54】[ $a == $b ] 和 [ $a -eq $b ] 有什么區別?
[ $a == $b ] - 用於字符串比較
[ $a -eq $b ] - 用於數字比較
【55】[[ $string == abc* ]] 和 [[ $string == "abc" ]] 有什么區別?
[[ $string == abc* ]] - 檢查字符串是否以字母 abc 開頭
[[ $string == "abc" ]] - 檢查字符串是否完全等於 abc
應用示例如下:
#!/bin/bash string="abcdefhigk" if [[ $string == abc* ]] ; then echo "string is start with abc" else echo "string is not start with abc" fi if [[ $string == "abc" ]] ; then echo "string is abc" else echo "string is not abc" fi
輸出結果:
如上。
【56】如何打印數組中的所有元素?
應用示例如下:
#!/bin/bash array=("Hi" "my" "name" "is") echo "打印數組第一個元素" echo ${array[0]} echo "打印數組的所有元素" echo ${array[@]} echo "輸出所有數組索引" echo ${!array[@]} echo "移除數組中索引為2的元素" unset array[2] echo ${array[@]} echo "在數組中添加id為110的元素" array[110]="new_element_110" echo ${array[@]}
輸出結果:
如上。
【57】不用 wc 命令如何計算字符串中的單詞數目?
應用示例如下:
#!/bin/bash string="my name is wang qi and my age is 18" echo $string set ${string} echo count:$#
輸出結果:
如上。
【58】shell腳本如何進行數據庫操作?
以mysql數據庫為例。不用在mysql的提示符下運行mysql,在shell腳本中操作mysql的方法:
mysql -hhostname -Pport -uusername -ppassword -e 執行的sql語句
應用示例如下:
#!/bin/bash HOSTNAME="119.254.95.194" PORT="3306" USERNAME="root" PASSWORD="123456" use_sql="use billing;" mysql -h${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${use_sql}" select_sql="use billing; select * from cfg_dict into outfile '/var/lib/mysql/cfg_dict.csv' fields terminated by ',';" mysql -h${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${select_sql}"
如上。
【59】待續....
Good Good Study, Day Day Up.
順序 選擇 循環 總結