shell腳本27問

【1】交互方式、非交互方式、Shell腳本是什麼?linux

常常與linux打交道,確定對shell這個詞不陌生。不明白shell意思的,能夠自行翻譯:外殼、去殼。shell

這個翻譯結果怎麼能夠與計算機系統聯繫起來呢?看不懂?小程序

爲了幫助理解shell這個詞,請看下圖:vim

計算機系統,最內層(本質)的是硬件,而後硬件會被系統核心層包住,而在系統核心外層的就是所謂的shell,再而後shell外層的就是咱們接觸最多且最容易理解的應用程序。windows

shell實際上是一個命令解釋器,做用是解釋用戶輸入的命令和程序,命令和程序能夠理解成上圖中的應用程序。安全

linux系統中的那些命令其實也都是一個個的小程序,只不過執行的是系統的應用功能。bash

當咱們在系統的終端中輸入一條命令,能夠立馬看到一條或者幾條系統回覆咱們的信息,其實就是shell在幫咱們回覆,因此shell能夠稱之爲命令解釋器。服務器

而這種從鍵盤一輸入命令,就立馬獲得相應的回覆信息,叫做交互的方式。函數

瞭解了shell以後,再來了解下shell腳本。若是咱們的命令或應用程序不在命令行直接執行,而想經過一個程序文件來執行時,這個程序文件就被稱之爲shell腳本。oop

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、一、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腳本?

使用'-x'參數(sh -x myshell.sh)能夠調試shell腳本。

如上面例子中的case.sh腳本,調試結果以下:

如上。

【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)不一樣點:只有在雙引號中體現出來。

假設在腳本運行時寫了三個參數 一、二、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】待續

 

Good Good Study, Day Day Up.

順序 選擇 循環 總結

相關文章
相關標籤/搜索