shell腳本58問


【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.

順序 選擇 循環 總結


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM