shell雜記1

junwind發表於2021-05-04

變數

程式結束,變數被銷燬
普通變數,子程式中是無法訪問的,得是環境變數才行
作用域:當前指令碼中得為全域性變數,環境變數為超全域性,函式內得為區域性
export varname=value  宣告並賦值一個環境變數
name=xqw  定義賦值一個普通變數  export name  再宣告為環境變數
區域性變數  local varname=val
位置變數  $1  $2  ...  引用指令碼的引數
變數的命名:僅包含數字,字母,下劃線,不能以數字開頭;不能跟已有的環境變數重名
$?   上一個程式(執行的命令)的執行狀態返回值

執行程式,有兩種返回
    結果
    狀態  $?  如果是正確被執行,則返回0, 如果是錯誤,則1~25512127系統保留)

指令碼執行時,啟動一個新bash
    命令列直接執行的,相當於當前bash的子bash,會繼承父程式的環境變數
    系統自動執行的指令碼,是需要設定環境變數的,因為執行時,並沒有上層的父bash程式

unset varname  銷燬變數
set 
printenv
env
export
export PATH=$PATH:/bin/go 

shell中變數的值預設是字串,並不能直接算術運算

執行指令碼

./xx.sh 
xx.sh  要將路徑加入到PATH中
bash xx.sh  
source xx.sh  
. xx.sh 

判斷表示式

[ expression ]
[[ expression ]]
test expression

-eq  -ne  -gt  -ge  -lt  -le 

[ $a -eq $b ]
echo $?

邏輯判斷

&&    
短路現象: a && b   a為真,則執行後面的b , a為假,則b不用執行
id user3 &> /dev/null && echo 'user3 is exists.'

|| 
短路現象: a || b    a為真,則後面的不用判斷,a為假,則需要執行後面的
id root &> /dev/null || echo 'root not exists.' && echo 'root is exists.'

如果使用者不存在,就新增使用者?
    id user2 &> /dev/null || useradd user2 
    ! id user3 &> /dev/null && useradd user3 

判斷檔案超過100行,就是大檔案?
[ `wc -l ./passwd | cut -d' ' -f1` -gt 100 ] && echo 'big file.' || echo 'small file.'

!id user1 && useradd user1 && echo 'user1' | passwd --stdin user1 || echo 'user1 exists.'

exit  退出當前程式指令碼  
exit 可以定義執行狀態結果是什麼;如果沒有定義,則預設把exit前面那一條命令的退出執行狀態當作整個指令碼的執行狀態結果  
exit #   

運算

let C=$A+$B
C=$[$A+$B]
C=$(($A+$B))
C=`expr $A + $B`   expr命令 算術運算表示式   表示式中各運算元及運算子之間要有空格,而且要使用命令引用

檔案測試

-e  -f  -d  -r  -w  -x 
[ -e file ]
[ -x file ]

指令碼除錯

bash -n xx.sh   檢查語法,不執行指令碼
bash -x xx.sh   單步,顯示每一條執行的命令

注意:如果指令碼中沒有定義退出碼,則最後執行的那一條命令的狀態碼,就是整個指令碼的退出狀態碼

shift

執行其一次,$1 $2 $3 ... 位置變數的值整體向前移動一位
shift #  向前移動#位

特殊變數

$?   
$1  $2  
$#  引數個數
$*   $@   引數列表

練習

1. 傳遞三個引數給指令碼,第一個為整數,第二個為算術運算子,第三個為整數,將計算結果顯示出來,
要求保留兩位精度,形如:./calc.sh 5 / 2
echo "scale=2;111/22" | bc
bc <<< "scale=2;111/22"

2. 傳遞3個引數給指令碼,引數均為使用者名稱,將此些使用者的賬號資訊提取出來後,放置於 /tmp/testusers.txt檔案中,並要求每一行行首有行號;

3. 判斷當前主機的cpu生產商,其資訊在/proc/cpuinfo檔案中 vendor_id 一行中,
如果其生產商為AuthenticAMD,就顯示其為AMD公司;
如果其生產商為GenuineIntel,就顯示其為Intel公司;
否則,就說其為非主流公司;
cputype=`grep 'vendor_id' /proc/cpuinfo | head -1 | cut -d':' -f2 | sed -r 's@[[:space:]]+@@g'`

case $cputype in
AuthenticAMD)
    echo "AMD."
    ;;
GenuineIntel)
    echo "intel."
    ;;
*)
    ehco "is not popular company.";;
esac

4. 給指令碼傳遞三個整數,判斷其中的最大數 和 最小數,並顯示出來;

5. 寫指令碼,新增5個使用者,user1~user5,每個使用者的密碼同使用者名稱,使用者新增完成後,顯示使用者成功新增
useradd user1 &> /dev/null && echo user1 | passwd --stdin user1 &> /dev/null && echo 'user1 add success.' || echo 'user1 exists.'

for i in {1..5}; do
    if id user$i &> /dev/null; then
        echo "user$i exists."
    else
        useradd user$i
        echo "user$i" | passwd --stdin user$i &> /dev/null
        echo "add user$i success."    
    fi
done

6. 新增3個使用者,先判斷其是否存在,不存在才新增,新增完成後,顯示一共新增了幾個使用者,最後顯示當前系統上共有多少個使用者?

7. 給定一個使用者,如果其uid為0,就顯示為管理員,否則就顯示其為普通使用者

8. 刪除某使用者,一併刪除其家目錄,顯示刪除完成

9. 判斷當前系統上是否有使用者的預設shell為bash,如果有,就顯示有多少個這類使用者;否則,就顯示沒有這類使用者;

10. 判斷當前系統上是否有使用者的預設shell為bash;如果有,就顯示其中一個的使用者名稱;否則,就顯示沒有這類使用者;
11. 給定一個檔案,判斷這個檔案中是否有空白行,如果有,則顯示其空白行數,否則,顯示沒有空白行;
12. 給定一個使用者,判斷其UIDGID是否一樣,如果一樣,就顯示此使用者為“good guy”,否則,就顯示此使用者為“bad guy” , 進一步要求,不使用id命令獲得其id號
13. 傳遞兩個引數,顯示兩者之積,之和?
14. 不使用id命令,判斷使用者是否存在,並且判斷其uid,gid是否一樣
USERNAME=user1
if ! grep "^$USERNAME\>" /etc/passwd &> /dev/null; then
  echo "No such user: $USERNAME."
  exit 1
fi

USERID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f3`
GROUPID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f4`
if [ $USERID -eq $GROUPID ]; then
  echo "Good guy."
else
  echo "Bad guy."
fi
本作品採用《CC 協議》,轉載必須註明作者和本文連結
六月的風