Shell 練習題(二)

變量

根據變量的生效範圍等標準劃分下面變量類型:

  • 局部變量:生效範圍爲當前shell進程;對當前shell之外的其它shell進程,包括當前shell的子shell進程均無效
  • 環境(全局)變量:生效範圍爲當前shell進程及其子進程
    變量聲明、賦值:export name=VALUE,declare -x name=VALUE
    變量引用:$name, ${name}
    顯示所有環境變量:env,printenv,export,declare -x
    刪除變量:unset name
  • 本地變量:生效範圍爲當前shell進程中某代碼片斷,通常指函數
  • 位置變量:$1, $2, …來表示,用於讓腳本在腳本代碼中調用通過命令行傳遞給它的參數
    $1, $2, …:對應第1、第2等參數,shift [n]換位置
    $0: 命令本身
    $: 傳遞給腳本的所有參數,全部參數合爲一個字符串
    $@: 傳遞給腳本的所有參數,每個參數爲獨立字符串
    $#: 傳遞給腳本的參數的個數
    $@ $
    只在被雙引號包起來的時候纔會有差異
    set – 清空所有位置變量
  • 特殊變量:$?, $0, $*, $@, KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲,$
    $? 變量保存最近的命令退出狀態。 0 代表成功,1-255代表失敗 echo $?

read

使用read來把輸入值分配給一個或多個shell變量
-p 指定要顯示的提示
-s 靜默輸入,一般用於密碼
-n N 指定輸入的字符長度N -d ‘字符’ 輸入結束符
-t N TIMEOUT爲N秒
read 從標準輸入中讀取值,給每個單詞分配一個變量
所有剩餘單詞都被分配給最後一個變量
read -p “Enter a filename: “ FILE

let

 bash中的算術運算:help let
+, -, *, /, %取模(取餘), **(乘方)
實現算術運算:
(1) let var=算術表達式
(2) var=$[算術表達式]
(3) var=$((算術表達式))
(4) var=$(expr arg1 arg2 arg3 ...)
(5) declare –i var = 數值
(6) echo ‘算術表達式’ | bc
乘法符號有些場景中需要轉義,如*  bash有內建的隨機數生成器:$RANDOM(0-32767)
echo $[$RANDOM%50] :0-49之間隨機數

 增強型賦值:
+=, -=, *=, /=, %=let varOPERvalue
例如:let count+=3
 自加3後自賦值
 自增,自減:
let var+=1
let var++
let var-=1
let var--

1、編寫腳本/root/bin/systeminfo.sh,顯示當前主機系統信息,包括主機名,IPv4地址,操作系統版本,內核版本,CPU型號,內存大小,硬盤大小

#!/bin/bash
BEGINCOLOR="\e[1;35m"
ENDCOLOR="\e[0m"
 
echo -e "My hostname is ${BEGINCOLOR}`hostname`$ENDCOLOR"
echo -e "IP address is ${BEGINCOLOR}`ifconfig ens33 |grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'|head -n1`$ENDCOLOR"
echo -e "OS version is ${BEGINCOLOR}`cat /etc/redhat-release`$ENDCOLOR"
echo -e "Kernel version is ${BEGINCOLOR}`uname -r`$ENDCOLOR"
echo -e "CPU type is ${BEGINCOLOR}`lscpu|grep "Model name" |cut -d: -f2 |tr -s " "`$ENDCOLOR"
echo -e "Memtotol is ${BEGINCOLOR}`cat /proc/meminfo |head -n1 |grep -Eo '[0-9]+.*'`$ENDCOLOR"
echo -e "Disk space is ${BEGINCOLOR}`lsblk |grep 'sda\>'|grep -Eo '[0-9]+[[:upper:]]'`$ENDCOLOR"

在這裏插入圖片描述

grep
‘[:upper:]’
大寫字母類。包括:‘A B C D E F G H I J K L M N O P Q R S T U V W X Y Z’。
-A,–after-context=NUM 輸出當前行以及向後數NUM數的所有行
-B,–before-context=NUM 輸出當前行以及向前數NUM數的所有行
-C,–context=NUM 輸出當前行以及向前向後各數NUM數的所有行
-c,–count 統計每個文件中包含指定字符串的行數
-e,–regexp=PATTERN 用PATTERN來進行匹配操作
-E,–extended-regexp PATTERN是一個可擴展的正則表達式(縮寫ERE)
-f<範本文件>,–file=FILE 指定範本文件,其內容有一個或多個範本樣式,讓grep查找符合範本條件的文件內容,格式爲每一行的範本樣式
-F,–fixed-strings PATTERN是一個由斷行符分隔的定長字符串(取消默認的基本正則表達式)
-h,–no-filename 輸出時不顯示文件名前綴
-i,–ignore-case 忽略大小寫
-l,–files-with-match 只顯示包含指定字符串的文件名
-n,–line-number 輸出的同時顯示行號
-o,–only-matching 只顯示匹配到的字符串
-q,–quiet,–silent 靜默模式,不輸出任何信息
-s,–nomessages 不顯示不存在或無法匹配的錯誤信息
-v,–invert-march 顯示不匹配的行
-V,-version 顯示版本信息
-w,–word-regexp 匹配整個單詞
–color=auto 對匹配到的文本着色顯示

2、編寫腳本/root/bin/backup.sh,可實現每日將/etc/目錄備份到/root/etcyyyy-mm-dd中

#!/bin/bash
cp -a /etc/ /root/etc`date +%F` && echo "備份完成"

3、編寫腳本/root/bin/disk.sh,顯示當前硬盤分區中空間利用率最大的值

#!/bin/bash
##編寫腳本/root/bin/disk.sh,顯示當前硬盤分區中空間利 用率最大的值
maxdisk=`df | grep "/dev/sd" | tr -s " " ":" | cut -d : -f5 | sort -nr | head -n1`
maxuse=`df | grep "/dev/sd" | tr -s " " ":" | cut -d : -f1 | sort -nr | head -n1`
echo "磁盤"$maxuse"使用量爲:"$maxdisk

4、編寫腳本/root/bin/links.sh,顯示正連接本主機的每個遠程主機的IPv4地址和連接數教並按連接數從大到小排序

#!/bin/bash
##編寫腳本/root/bin/links.sh,顯示正連接本主機的每個遠 程主機的IPv4地址和連接數,並按連接數從大到小排序
echo -e "遠程主機連接統計爲:\n\t連接數\t遠程主機IP"
netstat -nt | tr -s " " | cut -d " " -f5 | cut -d : -f1 | sort -n | uniq -c |tr -s " " "\t"| egrep '([0-9]+.){3}[0-9]+'

————————————————————————————————————————

1、編寫腳本/root/bin/sumid.sh,計算/etc/passwd文件中的第10個用戶和第20用戶的ID之和

#!/bin/bash
user10=`cat /etc/passwd | cut -d: -f3 | sed -n "10p"`
user20=`cat /etc/passwd | cut -d: -f3 | sed -n "20p"`
let Num=$user10+$user20  #如果不用let,就單單只是兩個數字的拼接爲字符串而已
echo $Num

2、編寫腳本/root/bin/sumspace.sh,傳遞兩個文件路徑作爲參數給腳本,計算這兩個文件中所有空白行之和

#!/bin/bash
File1=$(grep "^$" $1 | wc -l)  # ^代表行首 $代表行尾 ^$意思就是行首之後就是行尾,中間什麼也沒有 所以代表空行
File2=$(grep "^$" $2 | wc -l)
let Sumlink=$File1+$File2
echo "the sum of $1 and $2 spacelines is $Sumlink"

3、編寫腳本/root/bin/sumfile.sh,統計/etc,/var,/usr目錄中共有多少個一級子目錄和文件

#!/bin/bash
##寫一個腳本/root/bin/sumfile.sh,統計/etc, /var, /usr目錄中共有多少個一級子目錄和文件
num1=$(ls -l /etc | wc -l)
num2=$(ls -l /var | wc -l)
num3=$(ls -l /usr | wc -l)
let Num=$num1+$num2+$num3
echo $Num

————————————————————————————————————————

1、編寫腳本/root/bin/argsnum.sh,接受一個文件路徑作爲參數;如果參數個數小於1,則提示用戶“至少應該給一個參數”,並立即退出;如果參數個數不小於1,則顯示第一個參數所指向的文件中的空白行數

#!/bin/bash
[[ $1 == "" ]] && echo "please enter a parameter" || echo $(grep "^$" $1 | wc -l)

在這裏插入圖片描述
2、編寫腳本/root/bin/hostping.sh,接受一個主機的IPv4地址做爲參數,測試是否可連通。如果能ping通,則提示用戶“該IP地址可訪問”;如果不可ping通,則提示用戶“該IP地址不可訪問”

#!/bin/bash
# =~:正則匹配,用來判斷其左側的參數是否符合右邊的要求
ipaddr='(\<([0-9]|[1-9][0-9]|1[0-9]{2}|2([0-4][0-9]|5[0-5]))\>\.){3}\<([0-9]|[1-9][0-9]|1[0-5][1-9]|2([0-4][0-9]|5[0-4]))\>'
    read -p "please input a IPV4 addr: " ipv4
    if [[ $ipv4 =~ $ipaddr ]];then 
        echo "a legal IP."
        ping $ipv4 -c 4
        echo "這個IP可以正常訪問"
    else
        echo "unlegal IP"
        echo "請輸入正確的地址"
        exit
    fi

IPV4地址由4個組數字組成,每組數字之間以.分隔,每組數字的取值範圍是0-255。
IPV4必須滿足以下四條規則:
1、任何一個1位或2位數字,即0-99;
2、任何一個以1開頭的3位數字,即100-199;
3、任何一個以2開頭、第2位數字是0-4之間的3位數字,即200-249;
4、任何一個以25開頭,第3位數字在0-5之間的3位數字,即250-255。

注意正則表達式最後一位IP地址,如果是255的話就是廣播地址,這裏我特意省略了
如果也要包括的話就在最後改爲 2([0-4][0-9]|5[0-5])

在這裏插入圖片描述

3、編寫腳本/root/bin/checkdisk.sh,檢查磁盤分區空間和inode使用率,如果超過80%,就發廣播警告空間將滿

#!/bin/bash
a="`df |grep ^/dev/sd |tr -s " " ":"|cut -d: -f5 |cut -d% -f1 |sort -nr`"
if [ $a -gt 80 ]
then
    echo "WARING!!!"
else
    echo "Nothing.."
fi

在這裏插入圖片描述————————————————————————————————————————

存在性測試

存在性測試
-a FILE:同-e
-e FILE: 文件存在性測試,存在爲真,否則爲假

存在性及類別測試
-b FILE:是否存在且爲塊設備文件
-c FILE:是否存在且爲字符設備文件
-d FILE:是否存在且爲目錄文件
-f FILE:是否存在且爲普通文件
-h FILE 或 -L FILE:存在且爲符號鏈接文件
-p FILE:是否存在且爲命名管道文件
-S FILE:是否存在且爲套接字文件

文件權限測試:
-r FILE:是否存在且可讀
-w FILE: 是否存在且可寫
-x FILE: 是否存在且可執行

文件特殊權限測試:
-u FILE:是否存在且擁有suid權限
-g FILE:是否存在且擁有sgid權限
-k FILE:是否存在且擁有sticky權限

文件大小測試:
-s FILE: 是否存在且非空

文件是否打開:
-t fd: fd 文件描述符是否在某終端已經打開
-N FILE:文件自從上一次被讀取之後是否被修改過
-O FILE:當前有效用戶是否爲文件屬主
-G FILE:當前有效用戶是否爲文件屬組

雙目測試:
FILE1 -ef FILE2: FILE1是否是FILE2的硬鏈接
FILE1 -nt FILE2: FILE1是否新於FILE2(mtime)
FILE1 -ot FILE2: FILE1是否舊於FILE2
 
=~:正則匹配,用來判斷其左側的參數是否符合右邊的要求

1、編寫腳本/bin/per.sh,判斷當前用戶對指定的參數文件,是否不可讀並且不可寫

#!/bin/bash
##chmod -rw /tmp/file1,編寫腳本/root/bin/per.sh,判斷當前用戶對/tmp/fiile1>文件 是否不可讀且不可寫 ?
flie1=/home/soft/zuoye/file
[ -r $file1 ]
arg1=$(echo $?)
echo $arg1
[[ $arg1 -eq 0 ]] && echo "該用戶對此文件有讀的權限" || echo "該用戶對此文件沒有
讀的權限"
[ -w $file1 ]
arg2=$(echo $?)
echo $arg2
[[ $arg2 -eq 0 ]] && echo "該用戶對此文件有寫的權限" || echo "該用戶對此文件沒有
寫的權限"

2、編寫腳本/root/bin/excute.sh,判斷參數文件是否爲sh後綴的普通文件,如果是,添加所有人可執行權限,否則提示用戶非腳本文件

#!/bin/bash
# =~:正則匹配,用來判斷其左側的參數是否符合右邊的要求
read -p "Please input a filename: " file
if [[ $file =~ .*sh$ ]] ; then
        if [ -f $file ] ; then
                chmod a+x $file
                echo "success"
        fi
else
        echo '非腳本文件' 
fi

3、編寫腳本/root/bin/nologin.sh和login.sh,實現禁止和允許普通用戶登錄系統

tr命令詳解

#!/bin/bash
# tr將空白轉爲@,
read -p "請輸入禁止的用戶:" user
uid=$( id $user |tr " " @ |cut -d@ -f1 |grep -o "[0-9]\{3,\}" )
#  $( id $user  | cut -d" " -f1 |grep -o "[0-9]\{3,\}"  )

[ $uid -ge 500 ] && usermod -s /bin/nologin $user || echo '該用戶爲系統用戶,無法禁止!'
echo '該用戶已禁止登陸'
#!/bin/bash
read -p "請輸入允許登錄的用戶:" user
uid=$( id $user |tr " " @ |cut -d@ -f1 |grep -o "[0-9]\{3,\}" )
[ $uid -ge 500 ] && usermod -s /bin/bash $user || echo '該用戶爲系統用戶'
echo '該用戶已允許登陸'

cut [OPTION]… [FILE]…
cut 命令並不直接操作於源文件,而是操作輸出緩衝。
-d:指定字段分隔符,默認是空格 -d:
-f: filed 指定要顯示的字段列表 eg:-f1 顯示第一個字段 -f1,3 顯示一三字段 -f1-3顯示一到三字段,
字段從左到右 依次增大,從1開始。

————————————————————————————————————————

1、讓所有用戶的PATH環境變量的值多出一個路徑,例如:
/usr/local/apache/bin

echo "PATH=$PATH:/usr/local/apache/bin">>/etc/profile.d/path.sh
vim /etc/profile.d/env.sh
export PATH=/usr/local/apache/bin:$PATH
source /etc/profile.d/env.sh

2、用戶root登錄時,將命令指示符變成紅色,並自動啓用如下別名:
rm=‘rm –i’
cdnet=‘cd /etc/sysconfig/network-scripts/’
editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eth0’
editnet=‘vim /etc/sysconfig/network-scripts/ifcfgeno16777736 或 ifcfg-ens33 ’ (如果系統是CentOS7)

命令符紅色 和 定義別名:

在 ~/.bashrc中將放入以下命令:
PS1='\[\e[1;31m\][\u@\h \w]\$\[\e[0m\]'
alias rm='rm –i'
alias cdnet='cd /etc/sysconfig/network-scripts/'
alias editnet='vim /etc/sysconfig/network-scripts/ifcfg-eth0'
alias editnet='vim /etc/sysconfig/network-scriptsifcfg-ens33'

這裏注意要su切換
在這裏插入圖片描述
在這裏插入圖片描述
3、任意用戶登錄系統時,顯示紅色字體的警示提醒信息
“Hi,dangerous!”

在/etc/profile.d/env.sh 中添加
echo -e "\e[1;31mHi,dangerous ! \e[0m"

4、編寫生成腳本基本格式的腳本,包括作者,聯繫方式,版本,時間,描述等

vim ~/.vimrc

set nu "show line
set ts=4 "TAB 4 chars
syntax on "grammar light
set cursorline
"set mouse=a
set ai
autocmd BufNewFile *.sh exec ":call SetTitle()"
func SetTitle()
     if expand("%:e")=='sh'
             call setline(1,"#!/bin/bash")
             call setline(2,"#")
             call setline(3,"#**************")
             call setline(4,"#author:果子哥")
             call setline(5,"#QQ:xxxxxxxx")
             call setline(6,"#email:[email protected]")
             call setline(7,"#version:x.0")
             call setline(8,"#date: ".strftime("%Y-%m-%d"))
             call setline(9,"#description: script")
             call setline(10,"#*************************************")
     endif
endfunc
autocmd BufNewFile * normal G   #自動將光標定位到末尾

5、編寫用戶的環境初始化腳本reset.sh,包括別名,登錄提示符,vim的設置,環境變量等

vim reset.sh
...
cat >> ~/.bash_profile << EOF
PS1='\[\e[1;8;$[RANDOM%6+41]m\][\u@\h \w]\$\[\e[0m\]'
export REGEX_IP='(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])[.]){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'
EOF

#config bashrc
cat >> ~/.bashrc << EOF
alias cdnet='cd /etc/sysconfig/network-scripts/'
EOF

#config vimrc
cat >> ~/.vimrc << EOF
set nu "show line
set ts=4 "TAB 4 chars
syntax on "grammar light
set cursorline
"set mouse=a
set ai
autocmd BufNewFile *.sh exec ":call SetTitle()"
func SetTitle()
     if expand("%:e")=='sh'
             call setline(1,"#!/bin/bash")
             call setline(2,"#")
             call setline(3,"     #*************************************")
             call setline(4,"     #author:果子哥")
             call setline(5,"     #QQ:123456")
             call setline(6,"     #email:[email protected]")
             call setline(7,"     #version:x.0")
             call setline(8,"     #date: ".strftime("%Y-%m-%d"))
             call setline(9,"     #description: script")
             call setline(10,"     #*************************************")
     endif
endfunc
autocmd BufNewFile * normal G   #自動將光標定位到末尾
EOF

在這裏插入圖片描述

————————————————————————————————————————

1、編寫腳本/root/bin/createuser.sh,實現如下功能:使用一個用戶名做爲參數,如果指定參數的用戶存在,就顯示其存在,否則添加之;顯示添加的用戶的id號等信息

#!/bin/bash
 if [ $# -eq 0 ];then
     echo "one argument (username) is required!" 
     exit
 elif [ $# -gt 1 ];then
     echo "required 1 argument, but $# arguments were supplied!"
     exit
 fi  

useradd $1 &> /dev/nul
USER_EXIT=$?
[ $USER_EXIT  -eq 9 ] && echo "createuser.sh: user $1 already exists" && exit 9
[ ! $USER_EXIT -eq 0 ] && echo "createuser.sh: ERROR"

id $1

在這裏插入圖片描述

2、編寫腳本/root/bin/yesorno.sh,提示用戶輸入yes或no,並判斷用戶輸入的是yes還是no,或是其它信息

#!/bin/bash
read -p "Please input [Yes/No]:" YESORNO
case $YESORNO in
[Yy][Ee][Ss]|[Yy])
echo "you choose yesyes"
;;
[Nn][Oo]|[Nn])
echo "you choose no"
;;
*)
echo "you choose other"
esac

3、編寫腳本/root/bin/filetype.sh,判斷用戶輸入文件路徑,顯示其文件類型(普通,目錄,鏈接,其它文件類型)

#!/bin/bash
[ $# -lt 1 ] && echo "Please input unless one argument!" && exit
for count in `seq 1 $#`
do
CHAR=$(eval ls -dl \$$count | cut -c 1)
CO="\e[1;32m"
LOR="\e[0m"
case $CHAR in
-)
        echo -e "The file type is \e[1;32mnormal file\e[0m"
        ;;
l)
        echo -e "The file type is $CO link file $LOR"
        ;;
d)
        echo -e "The file type is $CO directory $LOR"
        ;;
*)
        echo "sorry,I still don't know the file type "
esac
done

4、編寫腳本/root/bin/checkint.sh,判斷用戶輸入的參數是否爲正整數

#!/bin/bash
[ $# -lt 1 ] && echo "Please intput unless one argument" && exit
[ $# -gt 1 ] && echo "I just can understand one argument" && exit
[[ $1 =~ ^[0-9]*$ ]] && echo "your argument is a positive integer" || echo "your argument isn't a INT"
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章