shell編程基礎進階

来源:https://www.cnblogs.com/zeq912/archive/2018/11/20/9991439.html
-Advertisement-
Play Games

為什麼學習shell編程 shell腳本語言是實現linux/unix 系統管理機自動化運維所必備的重要工具,linux/unix系統的底層及基礎應用軟體的核心大部分涉及shell腳本的內容。每一個合格的linux系統管理員或運維工程師,都需要熟練的編寫shell腳本語言,並能夠閱讀系統及各類軟體附 ...


 

為什麼學習shell編程

shell腳本語言是實現linux/unix 系統管理機自動化運維所必備的重要工具,linux/unix系統的底層及基礎應用軟體的核心大部分涉及shell腳本的內容。每一個合格的linux系統管理員或運維工程師,都需要熟練的編寫shell腳本語言,並能夠閱讀系統及各類軟體附帶的shell腳本內容


什麼是shell

shell是一個命令解釋器,它在操作系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操作系統,並處理各種各樣的操作系統的輸出結果,輸出到屏幕返回給用戶,這種對話方式可以是互動式(從鍵盤輸入命令,可以立即得到shell的回應),或非交互(執行腳本程式)的方式

shell種類

互動式shell
非互動式shell
登錄式shell

/etc/profile -> /etc/profile.d/*.sh -> ~/.bash_profile -> ~/.bashrc -> /etc/bashrc

非登錄式shell

~/.bashrc -> /etc/bashrc

shell執行方式

1、 bash script-name 或 sh script-name (生成一個子shell執行)

2、 path/script-name 或 ./script-name (添加執行許可權執行,預設根據腳本第一行指定的解釋器執行,如果沒有指定則以當前預設shell解釋器執行)

3、 source script-name 或 . script-name (以當前預設shell解釋器執行)

4、cat script-name |bash

子shell

子shell的本質是shell的子進程

子進程是由父進程的概念引申而來,在linux系統下,我們所運行的應用程式幾乎都是從init(systemd)(pid為1的進程)進程延伸出來的,所以這些應用程式都視為init進程的子進程,而init則為它們的父進程

shell子進程是從一個父shell進程調用shell程式而產生的一個全新的shell,我們將這種全新的shell統稱為這個父shell的子shell

產生子shell的情況

1、在父shell中執行一個shell腳本
bash ,執行環境不同,不能直接引用父shell變數,需export,定義的變數不能被父shell引用

2、在父shell中執行一條命令,在命令的末尾加上&
&,執行環境相同,直接引用父shell變數,定義的變數不能被父shell引用
STR0='123';STR0='abc' &
echo $STR0

3、在父shell中執行一條命令,使用 () 中執行
(),執行環境相同,直接引用父shell變數,定義的變數不能被父shell引用
[root@web01 shell_class_03]# STR2='123' && (STR2='abc') && echo $STR2
123

4、在父shell中執行帶管道的命令
管道,執行環境相同,直接引用父shell變數,定義的變數不能被父shell引用
[root@web01 shell_class_03]# STR1='123';echo 111 |STR1='ABC';echo $STR1
123


shell應用場景

  • 系統基礎配置
  • 部署應用服務
  • 配置應用服務
  • 部署業務代碼
  • 應用服務備份
  • 日誌分析
  • 監控應用服務

 shell基礎

  • 命令補全和文件路徑補全, 如果寫錯無法補全 table
  • 命令歷史記憶功能 history
  • 別名功能 alias、unalias
  • 常用快捷鍵 ctrl+u,k,a,e,l,c,z,d,r
  • 前後臺作業控制 bg,fg,jobs,screen
  • 輸入輸出重定向 > >> 2> 2>> < << &> cat
  • | 將前者命令的標準輸出交給後者命令的輸入
  • |& 將前者命令的錯誤輸出交給後者命令的輸入
  • 命令之間的關係; 沒有邏輯關係,無論分號前面的命令執行是否成功都執行後者命令&& 前面執行成功, 則執行後者|| 前面執行不成功, 則執行後者

shell通配符

  • 匹配任意多個字元

? 匹配任意一個字元
[] 匹配括弧中任意一個字元a-z,0-9,A-Z,a-Z
() 在子 shell 中執行(cd /boot;ls) (umask 077; touch file1000)
{} 集合 touch file{1..9}

\ 轉義符

shell模式匹配
使用shopt 內置命令啟用shell選項 (extglob) 則會識別幾個擴展模式匹配運算符。
模式列表是由 | 分割

查看shell選項 extglob

shopt |grep extglob

啟動shell選項 extglob

shopt -s extglob

關閉shell選項 extglob

shopt -u extglob
** 模式 **** 說明 **
?(pattern-list) 匹配給定模式零或一次
*(pattern-list) 匹配給定模式零次或多次
+(pattern-list) 匹配給定模式一次或多次
@(pattern-list) 匹配給定模式之一
!(pattern-list) 匹配除了給定的模式
[root@mycentos6-clone ~]# ll
total 0
-rw-r--r-- 1 root root 0 Nov  1 07:02 123
-rw-r--r-- 1 root root 0 Nov  1 07:02 aaaac
-rw-r--r-- 1 root root 0 Nov  1 06:51 aaab
-rw-r--r-- 1 root root 0 Nov  1 07:02 aad
-rw-r--r-- 1 root root 0 Nov  1 07:02 aadg
-rw-r--r-- 1 root root 0 Nov  1 07:02 bb
-rw-r--r-- 1 root root 0 Nov  1 07:02 c
 [root@mycentos6-clone ~]# ls !(c|bb|123)
aaaac  aaab  aad  aadg
[root@mycentos6-clone ~]# rm !(c|bb|123) -f
[root@mycentos6-clone ~]# ll
total 0
-rw-r--r-- 1 root root 0 Nov  1 07:02 123
-rw-r--r-- 1 root root 0 Nov  1 07:02 bb
-rw-r--r-- 1 root root 0 Nov  1 07:02 c

單引號-雙引號-沒有引號

引號和不加引號的區別1

[root@zeqtx ~]# touch a b
[root@zeqtx ~]# ll
total 0
-rw-r--r--. 1 root root 0 Jun 25 16:25 a
-rw-r--r--. 1 root root 0 Jun 25 16:25 b
[root@zeqtx ~]# touch "a b"
[root@zeqtx ~]# ll
total 0
-rw-r--r--. 1 root root 0 Jun 25 16:25 a
-rw-r--r--. 1 root root 0 Jun 25 16:25 a b
-rw-r--r--. 1 root root 0 Jun 25 16:25 b

引號和不加引號的區別2:

[root@zeq36 tmp]# ll
總用量 0
-rw-r--r-- 1 root root 0 6月  25 19:36 ?
-rw-r--r-- 1 root root 0 6月  25 19:32 *
-rw-r--r-- 1 root root 0 6月  25 19:33 aa
-rw-r--r-- 1 root root 0 6月  25 19:33 abc
-rw-r--r-- 1 root root 0 6月  25 19:33 b
[root@zeq36 tmp]# ll ?
-rw-r--r-- 1 root root 0 6月  25 19:36 ?
-rw-r--r-- 1 root root 0 6月  25 19:32 *
-rw-r--r-- 1 root root 0 6月  25 19:33 b
[root@zeq36 tmp]# ll "?"
-rw-r--r-- 1 root root 0 6月  25 19:36 ?
[root@zeq36 tmp]# ll *
-rw-r--r-- 1 root root 0 6月  25 19:36 ?
-rw-r--r-- 1 root root 0 6月  25 19:32 *
-rw-r--r-- 1 root root 0 6月  25 19:33 aa
-rw-r--r-- 1 root root 0 6月  25 19:33 abc
-rw-r--r-- 1 root root 0 6月  25 19:33 b
[root@zeq36 tmp]# ll "*"
-rw-r--r-- 1 root root 0 6月  25 19:32 *

雙引號和單引號區別1:

關於$

[root@zeqtx ~]# echo "$LANG"
en_US.UTF-8
[root@zeqtx ~]# echo '$LANG'
$LANG

雙引號和單引號區別2:

關於``

[root@zeqtx ~]# echo "`which awk`"
/bin/awk
[root@zeqtx ~]# echo '`which awk`'
`which awk`

雙引號和單引號區別3:

關於!

[root@zeqtx ~]# echo '!ll'
!ll
[root@zeqtx ~]# echo "!ll"
echo "ll /bin/awk "
ll /bin/awk 

 shell常用命令與工具

cat

cat<<-EOF
    1.[install lamp]
    2.[install lnmp]
    3.[exit]
EOF
cat >> /etc/profile <<'EOF'
$PATH
EOF

read

格式:

read [options] varible1 varible2 ...

參數:

-p 顯示提示信息
-t 超時時間
-s 取消回顯
-u 綁定文件描述符作為輸入
-a 後跟一個變數,該變數會被認為是個數組,然後給其賦值,預設是以空格為分割符

eval

  • 執行參數做為shell命令
[root@VM_153_209_centos ~]# echo $a
3
[root@VM_153_209_centos ~]# echo $b
stu
[root@VM_153_209_centos ~]# eval echo ${b}{1..$a}
stu1 stu2 stu3

tee

  • 從標準輸入讀取寫到出和文件
  • -a 追加到文件

printf

a=1
b=3
printf "%.2f" `echo "scale=2;$a/$b"|bc`

:

空命令

echo

字體顏色

echo -e "\033[30m 黑色字zeq trainning \033[0m"
echo -e "\033[31m 紅色字zeq trainning \033[0m"
echo -e "\033[32m 綠色字zeq trainning \033[0m"
echo -e "\033[33m 黃色字zeq trainning \033[0m"
echo -e "\033[34m 藍色字zeq trainning \033[0m"
echo -e "\033[35m 紫色字zeq trainning \033[0m"
echo -e "\033[36m 天藍字zeq trainning \033[0m"
echo -e "\033[37m 白色字zeq trainning \033[0m"

背景顏色

echo -e "\033[40;37m 黑底白字 welcome to ze1q\033[0m"
echo -e "\033[41;37m 紅底白字 welcome to ze2q\033[0m"
echo -e "\033[42;37m 綠底白字 welcome to ze3q\033[0m"
echo -e "\033[43;37m 黃底白字 welcome to ze4q\033[0m"
echo -e "\033[44;37m 藍底白字 welcome to ze5q\033[0m"
echo -e "\033[45;37m 紫底白字 welcome to ze6q\033[0m"
echo -e "\033[46;37m 天藍白字 welcome to ze7q\033[0m"
echo -e "\033[47;30m 白底黑字 welcome to ze8q\033[0m"

trap

trap [-lp] [ [參數] 信號 ...]

參數 : shell命令

信號

HUP(1) 掛起,通常因終端掉線或用戶退出而引發
INT(2) 中斷,通常因按下Ctrl+C組合鍵而引發
QUIT(3) 退出,通常因按下Ctrl+組合鍵而引發
ABRT(6) 中止,通常因某些嚴重的執行錯誤而引發
ALRM(14) 報警,通常用來處理超時
TERM(15) 終止,通常在系統關機時發送
SIGTSTP 停止進程 終端來的停止信號

trap ':' INT EXIT TSTP TERM HUP

jumpserver.sh

#!/bin/bash
LB02=10.0.0.6
WEB01=10.0.0.7

menu(){
cat  << EOF
	1) LB02
	2) WEB01
	6) h
EOF
}

while true
do
  trap ':' INT TSTP TERM HUP
  menu
  read -p "please input hostname num: " NUM
  case $NUM in
	1|LB02)
		ssh root@$LB02
		;;
	2|WEB01)
		ssh root@$WEB01
		;;
	h)
		menu
		;;
	exec)
		exit 1
		;;
  esac
done

expect

#!/usr/bin/expect
set ip 10.0.0.6
set user root
set password 123456
set timeout 5

spawn ssh $user@$ip

expect {
    "yes/no" { send "yes\r"; exp_continue }
    "password:" { send "$password\r" };
} 
#交互方式
interact

expect-copy-sshkey.exp

#!/usr/bin/expect
if { $argc != 1 } {
 send_user "usage: expect expect-copy-sshkey.exp host \n"
 exit
}

#define var
set host [lindex $argv 0]
set password "123456"

spawn ssh-copy-id -i /home/oldgirl/.ssh/id_dsa.pub "oldgirl@$host"
#spawn ssh -p 50718 disdata@$host /sbin/ifconfig
set timeout 60
expect {
        -timeout 20
        "yes/no"    { send "yes\r";exp_continue }
        "*password" { send "$password\r" }
        timeout  { puts "expect connect timeout,pls contact zeq."; return }
}
expect eof

exit -onexit {
  send_user "zeq say good bye to you!\n"
}

cat dis-sshkey.sh

#!/bin/sh
. /etc/init.d/functions
[ ! -f iplist ] && echo "hostlists.txt is not exist." && exit 1

for host in `cat /home/oldgirl/iplist`
do
 expect expect-copy-sshkey.exp $host &>/dev/null
 if [ $? -eq 0 ];then
    action "$host dis data" /bin/true
 else
    action "$host dis data" /bin/false
 fi
done

mkpasswd openssl

mkpasswd -l 10 -c 3 -C 3 -d 3
openssl rand -base64 80

basename dirname

basename /etc/init.d/network 
network

dirname /etc/init.d/network 

/etc/init.d


 shell腳本

腳本第一行

指定腳本解釋器

#!/bin/sh
#!/bin/bash
#! /usr/bin/awk
#! /bin/sed
#! /usr/bin/tclsh
#! /usr/bin/expect
#! /usr/bin/perl
#! /usr/bin/env python

腳本註釋

單行註釋 #
多行註釋

<<'EOF'
語句1
語句2
...
語句n
EOF

腳本構成

主腳本
模塊(子腳本)

  • 主腳本 調用模塊
  • 模塊中 有 函數
  • 先調用模塊,再調用函數

腳本執行參數

  • -x 將執行的腳本內容及輸出顯示到屏幕上
  • -n 不會執行該腳本,僅查詢腳本語法是否有問題,並給出錯誤提示。
  • -v 在執行腳本時,先將腳本的內容輸出到屏幕上然後執行腳本,如果有錯誤,也會給出錯誤提示

 變數

變數類型

自定義變數

1.定義變數變數名=變數值 ,不允許數字命名, 不能使用橫崗命名
2.引用變數$變數名 或 ${變數名}
3.查看變數echo $變數名 set顯示所有變數,包括自定義變數和環境變數

4.取消變數unset 變數名 作用範圍:僅在當前 shell 中有效

系統環境變數
1.定義環境變數 export export 變數 ,將自定義變數轉換成環境變數
2.引用環境變數 $變數名 或 ${變數名}
3.查看環境變數 echo $變數名 env |grep Name
4.取消環境變數 unset 變數名
5.作用範圍在當前shell和子shell有效

位置參數變數

$1
$2
$3

${10}

預先定義變數
$0 腳本文件名
$* 所有的參數
$@ 所有的參數

set  "I am" handsome zeq
for i in "$*" ; do echo $i; done
for i in "$@" ; do echo $i; done

$# 參數的個數
$$ 當前進程的 PID
$! 上一個後臺進程的 PID
$? 上一個命令的返回值 0 表示成功

$_ 在此之前執行的命令或腳本的最後一個參數

變數賦值方式

1.顯式賦值(變數名=變數值)

2.read從鍵盤讀入變數值

read -p "請輸入數字:"
echo $REPLY

3.定義或引用變數時註意事項: " "弱引用 ' '強引用

4.``命令替換等價於$()反引號中的shell命令會被先執行

變數子串

變數長度

${#string}

從前往後刪除變數內容

${string#substring} 從變數$string開頭開始刪除最短匹配$substring子串
${string##substring} 從變數$string開頭開始刪除最長匹配$substring子串

從後往前刪除變數內容

${string%substring} 從變數$string結尾開始刪除最短匹配$substring子串
${string%%substring} 從變數$string結尾開始刪除最長匹配$substring子串

索引及切片

${string:position} 在$string中,從$position個開始提取子串(從0開始計數)
${string:position:length} 在$string中,從位置$position之後開始提取長度為$length的子串

變數內容替換

${parameter/pattern/string} 使用string代替第一個匹配的pattern
${parameter//pattern/string} 使用string代替所有的pattern
${parameter/#pattern/string} 從開頭匹配string變數中的pattern, 用string替換匹配的pattern
${parameter/%pattern/string} 從結尾匹配string變數中的pattern, 用string替換匹配的pattern

變數替代

${value:-word} 如果變數名存在且非null,則返回變數的值。否則,返回word字元串 用途:如果變數未定義,則返回備用的值
${value:=word} 如果變數名存在且非null,則返回變數值。否則,設置這個變數值為word 並返回其值 用途:如果變數未定義,則設置變數為預設值,並返回預設值
${value:?"not defined"} 如果變數名存在且非null,則返回變數的值。否則顯示變數名:message, 並退出當前的命令或者腳本 用途:用於捕捉由於變數未定義而導致的錯誤,並退出程式
${value:+word} 如果變數名存在且非null,則返回word。 否則返回null 用途:測試變數是否存在

變數作用域

環境變數

使用 export 定義,在當前shell及其子shell中生效

本地變數

僅在當前shell中生效

局部變數

使用 local 定義 ,僅在函數中生效


 表達式

運算符

++ -- 自增 自減

  • ! ~ 正號 負號 邏輯取反 按位取反
    / % 乘 除 取餘
    • 加 減
      < <= > >= 比較符號
      == != 等於 不等於
      << >> 左移 右移
      & | ^ 按位與 按位或 按位異或
      && || 邏輯與 邏輯或
      = += -= *= /= %= &= |= ^= <<= >>= 各種賦值運算符
      ** 冪運算

算術運算(整數)

** [] test **** (()) [[]] **
-eq == 或 =
-ne !=
-gt >
-ge >=
-lt <
-le <=

自增/自減
ping.sh

#!/bin/bash
IP=223.5.5.5
i=1
while((i<=4))
do
	if ping $IP -c 1 &> /dev/null;then
		echo "ping $IP is ok!" 	
	else
		echo "ping $IP is faild..."
	fi
	let i++
done

表達式符號

[ ]
[[ ]]
(( )) 僅用於整數

((1<2&&1>3))
((1<2||1>3))

算術運算-bc

https://www.gnu.org/software/bc/manual/html_mono/bc.html

# a=1.2
# b=3
# echo "$a<$b" |bc
1
# echo "$a>$b" |bc
0
# echo "$a+$b" |bc
4.2
# x=$(echo "$a+$b" |bc)
# echo $x
4.2
[root@VM_153_209_centos scripts]# a=9.8
[root@VM_153_209_centos scripts]# b=10.1
[root@VM_153_209_centos scripts]# echo "$a>$b" |bc
0
[root@VM_153_209_centos scripts]# echo "$a<$b" |bc
1
cat test.bc 
#!/bin/bc
1+2
quit
bc -q test.bc
3
#!/bin/bc
array[1]=1
array[2]=2
array[1]+array[2]
quit
bc -q test.bc 
3

邏輯運算

** [] test **** [[]] **** 說明 **
-a && and 與
-o || or 或
! ! not 非

字元串運算

-z "str" 若串長度為0則真,-z 可以理解為zero
-n "str"  若串長度不為0則真,-n可以理解為no zero
"str1"  =  "str2" 若串1等於串2則真,可以使用  "==" 代替  "="
"str1"  !=  "str2" 若串1不等於串2則真
"str1" =~ "pattern" 字元串匹配成功則為真 [[ ]]

文件測試

[ -f 文件 ] 文件存在且為普通文件則真,條件表達式成立
[ -d 目錄 ] 目錄存在且為目錄文件則真,條件表達式成立
[ -s 文件 ] 文件存在且文件大小不為0則真,條件表達式成立
[ -e 文件 ] 文件存在則真,只要有文件就行
[ -r 文件 ] 文件存在且可讀則真,條件表達式成立
[ -w 文件 ] 文件存在且可寫則真,條件表達式成立
[ -L 文件 ] 文件存在且為鏈接文件則真,條件表達式成立
[ f1 -nt f2 ] 文件f1比文件f2新則真,條件表達式成立
[ f1 -ot f2 ] 文件f1比文件f2舊則真,條件表達式成立

 流程式控制制

順序 選擇 迴圈

條件表達式

  • 條件表達式的值只有真(非0 | 非空 | 條件成立 | $?為0(此條shell特有))、假(0 | 空 | 條件不成立 | $?不為0(此條shell特有))此規則適用於所有的電腦高級語言

算術運算
邏輯運算
Linux命令

選擇(分支)

if

if 條件表達式;then
  命令
fi
#/bin/bash
http="ss -lntup|grep nginx &> /dev/null"
if eval $http
then
  echo 1
else
  echo 0
fi

流程圖

st=>start: Start
op=>operation: 命令1
cond=>condition: 條件表達式為真?
e=>end

st->cond
cond(yes)->op->e
cond(no)->e

if else

if 條件表達式;then
  命令1
else
  命令2
fi
st=>start: Start
op=>operation: 命令1
op2=>operation: 命令2
cond=>condition: 條件表達式為真?
e=>end

st->cond
cond(yes)->op->e
cond(no)->op2->e

if elif else

if 條件表達式;then
  命令1
elif 條件表達式2;then
  命令2
else
  命令3
fi
st=>start: Start
op=>operation: 命令1
op2=>operation: 命令2
op3=>operation: 命令3
cond=>condition: 條件表達式為真?
cond2=>condition: 條件表達式2為真?
e=>end

st->cond
cond(yes)->op->e
cond(no)->cond2
cond2(yes)->op2->e
cond2(no)->op3->e

case

case 模式名 in
  模式1)
    命令1
    ;;
  模式2)
    命令2
    ;;
  模式3)
    命令3
    ;;
  *)
    其它命令
esac
st=>start: Start
io=>inputoutput: 模式名
op=>operation: 命令1
op2=>operation: 命令2
op3=>operation: 命令3
op4=>operation: 其它命令
cond=>condition: 模式名==模式1 ?
cond2=>condition: 模式名==模式2 ?
cond3=>condition: 模式名==模式3 ?
e=>end

st->io->cond
cond(yes)->op->e
cond(no)->cond2
cond2(yes)->op2->e
cond2(no)->cond3
cond3(yes)->op3->e
cond3(no)->op4->e

迴圈

for

for 變數名 in 取值列表
do
  命令
done
for ((expr1;expr2;expr3))
do
  命令
done

expr1 初值expr2 終值expr3 步長值

st=>start: Start
op=>operation: 命令
op1=>operation: expr1
op3=>operation: expr3
cond=>condition: expr2為真 ?
e=>end

st->op1->cond
cond(yes)->op->op3->cond
cond(no)->e

IFS

#!/bin/bash
data='a,b,c,d'
IFS=,
for i in $data;do
  echo $i
done

while

while 條件表達式
do
  命令
done
st=>start: Start
op=>operation: 命令
cond=>condition: 條件表達式為真 ?
e=>end

st->cond
cond(yes)->op->cond
cond(no)->e

把a.txt文件中的內容倒騰到b.txt文件中

cat a.txt
1
2
3
4
5
6
7
8
9
10

cat b.txt
10
9
8
7
6
5
4
3
2

1

#!/bin/bash
touch b.txt
while [ -n "$(cat a.txt)" ]
do
	if [ -z "$(cat b.txt)" ];then
		head -1 a.txt > b.txt
        else
		sed -i "1i `head -1 a.txt`" b.txt
        fi
	sed -i 1d a.txt

done

while read

while read -p "請輸入:"
do
  if [[ $REPLY =~ ^[0-9]+$ ]];then
    echo "輸出:$((REPLY*=${REPLY}00))"
  elif [[ "$REPLY" = "q" ]];then
    break
  fi
done

while讀取文件三種方式

1、
cat ./a.txt | while read LINE
do
  echo $LINE
done

2、
while read LINE
do
  echo $LINE
done < ./a.txt

3、
exec < ./a.txt
while read LINE
do
  echo $LINE
done

break

break n 表示跳出迴圈的層數

省略n 表示跳出整個迴圈

continue
continue n 退到第n層繼續迴圈

省略n 表示跳出本次迴圈,繼續下一次迴圈

select

#PS3=[$USER@$0]#
select VAR in var1 var2 quit
do
  case $VAR in
  var1)
    echo 1
    ;;
  var2)
    echo 2
    ;;
  quit)
    break
    ;;
  esac
done

 

函數

函數定義

function 函數名(){
  命令
}

函數參數

$1
$2
$3
$#
$*

$@

函數調用

函數名 參數1 參數2 參數3

函數返回

  • 返回數字作為函數執行狀態 返回給$? 取值範圍 0-255 (使用 return)
  • 返回數字作為函數執行結果 (使用 echo)
  • 返回字元串,作為函數執行結果 (使用 echo)

系統函數庫

系統函數庫

/etc/init.d/functions

action函數

action "xxxxx" /bin/trueaction "xxxxx" /bin/false

功能函數庫

# 腳本初始化
function scripts_init(){
  prog=`basename $0 .sh`
  LockFile=/var/lock/subsys/${prog}.lock  # 使用鎖文件
  LogFile=/var/log/${prog}.log  # 腳本記錄日誌
  PidFile=/var/run/${prog}.pid  # 記錄進程號,可以管理腳本

  [ -f $LockFile ] && echo "There $LockFile is exist!!" && exit 1 ||touch $LockFile
  [ ! -f $LogFile ] && touch $LogFile
  [ -f $PidFile ] && echo "There $PidFile is exist!!" && exit 2|| echo $$ > $PidFile
}

# 記錄日誌
function writelog(){
  Date=$(date "+%F_%T")
  ShellName=`basename $0`
  Info=$1
  echo "$Date : ${ShellName} : ${Info}" >> ${LogFile}
}

# 腳本退出掃尾
function closeout(){
  [ -f $LockFile ] && rm -f $LockFile 
  [ -f $PidFile ]&& rm -f $PidFile
}

# 判斷輸入是整數
function int_judge(){
  fun_a=$1
  expr $fun_a + 1 &>/dev/null
  RETVAL=$?
  return $RETVAL
}

# 判斷輸入非空
function input_judge(){
  RETVAL=0
  fun_a=$1
  [ ${#fun_a} -eq 0 ]&& RETVAL=1
  return $RETVAL
}

 數組

  • 數組名代表首地址

下標是從0開始的整數

普通數組(索引數組)

定義數組

array=(a b c)

獲取所有元素

${array[*]}

獲取元素下標

${!a[@]}

獲取數組長度

${#array[*]}

獲取一個元素的長度

${#name[0]}

獲取第一個元素

${array[0]}

獲取第二個元素

${array[1]}

獲取多個元素

array=(1 2 3 4 5)
echo ${array[@]:1}
2 3 4 5

#array[@]:下標:截取元素個數
echo ${array[@]:1:3}
2 3 4

添加元素

array[3]=d

添加多個元素

array+=(e f g)

刪除第一個元素

unset array[0]    # 刪除會保留元素下標

刪除數組

unset array

數組切片

${name[4]:0:7}

關聯數組

關聯數組的下標是字元串

定義關聯數組

declare -A M

關聯數組賦值

M=([a]=11 [b]=22)

獲取關聯數組元素

echo ${M[a]}
11

獲取關聯數組元素個數

echo ${#M[@]}
2

獲取關聯數組下標

echo ${!M[*]}
a b

獲取關聯數組所有元素

echo ${M[@]}
11 22

添加元素

M[c]=33

添加多個元素

M+=([d]=33 [e]=44)

綜合題

找出一個網路中最大的空閑ip地址段

#!/bin/bash
SUB_NET="10.0.0."
for NUM in {1..254}
do
{
  if ping -c 1 ${SUB_NET}${NUM} &> /dev/null;then
    echo $NUM >> ip.txt 
  fi
}&
done
wait
sort -n ip.txt -o ip.txt
if [ $(tail -1 ip.txt) -ne 254 ];then
  echo 254 >> ip.txt
fi
while read LINE
do
  array+=($LINE)
done < ip.txt

for ((i=0;i<${#array[*]}-1;i++))
do
  DIFF=$((${array[$((i+1))]}-${array[$i]}))
  echo -e "${SUB_NET}${array[$((i+1))]}\t${SUB_NET}${array[$i]}\t$DIFF" >> result.txt
done

sort -rnk3 result.txt
rm *.txt -f
#!/bin/bash
SUB_NET="10.0.0."
for NUM in {1..254}
do
{
  if ping -c 1  ${SUB_NET}${NUM} &> /dev/null;then
    echo $NUM >> ip.txt 
  fi
}&
done
wait
sort -n ip.txt -o ip.txt
if [ $(tail -1 ip.txt) -ne 254 ];then
  echo 254 >> ip.txt
fi
awk -v net=$SUB_NET '{if(NR==1){last=$1}if(NR>1){printf "%s%d\t%s%d\t%d\n",net,$1,net,last,$1-last;last=$1}}' ip.txt |sort -nrk 3
rm ip.txt -f

抓鬮

#!/bin/bash
function rand(){
  echo $((RANDOM%100+1))
}
> /tmp/user.txt
while true
do
  clear
  echo "抓鬮獲獎名單如下: "
  sort -rnk2 /tmp/user.txt |head -3
  read -p 'please input name: ' NAME
  [ -z "$NAME" ] && continue
  if [ "$NAME" = "q" ];then
    break
  fi
  if grep -w "$NAME" /tmp/user.txt &> /dev/null;then
    continue
  fi
  RAND=$(rand)
  while grep -w "$RAND" /tmp/user.txt &> /dev/null
  do
    RAND=$(rand)
  done

  echo -e "$NAME\t$RAND" >>/tmp/user.txt

done
echo "抓鬮獲獎名單如下: "
sort -rnk2 /tmp/user.txt |head -3

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 公眾號的應用,開發及調試環境搭建 花生殼要註冊 需要二十多塊錢 ,還要實名認證,估計要一兩天才能審核通過 主要就是在 windows搭建測試環境 1.微信的應用場景 360百科微信簡介 https://baike.so.com/doc/5567128-5782263.html 微信公眾號平臺 htt ...
  • 作者:依樂祝 原文地址:https://www.cnblogs.com/yilezhu/p/9977862.html 寫在前面 千呼萬喚始出來,首先,請允許我長吸一口氣!真沒想到 "一份來自28歲老程式員的自白" 這篇文章會這麼火,更沒想到的是張善友隊長的公眾號居然也轉載了這篇文章,這就導致兩天的時 ...
  • 一、前言 最近一段時間自己主要的學習計劃還是按照畢業後設定的計劃,自己一步步的搭建一個前後端分離的 ASP.NET Core 項目,目前也還在繼續學習 Vue 中,雖然中間斷了很長時間,好歹還是堅持下來了,嗯,看了看時間,原本決定的半年完成肯定是完不成了。這兩周重新拾起來學習 Vue,文章也在慢慢的 ...
  • 1 記憶體節點node 1.1 為什麼要用node來描述記憶體 這點前面是說的很明白了, NUMA結構下, 每個處理器CPU與一個本地記憶體直接相連, 而不同處理器之前則通過匯流排進行進一步的連接, 因此相對於任何一個CPU訪問本地記憶體的速度比訪問遠程記憶體的速度要快 Linux適用於各種不同的體繫結構, 而 ...
  •     迴圈語句常用於重覆執行一條命令或一組命令等,直到達到結束條件後,則終止執行。在Shell中常見的迴圈命令有 while 、 until 、 for 和 select 等。 while語句 基礎語法 while迴圈讀取文件 1、使用exec until語句的語法與while ...
  • 部分內容選自《Linux命令行與shell腳本編程大全.第3版》1 什麼是LinuxLinux可劃分為以下四部分:Linux內核GNU工具圖形化桌面環境應用程式完整的Linux系統如下圖:1.1 Linux內核Linux系統的核心就是內核,內核控制電腦系統上的所有硬體和軟體,在必要時分配硬體,並根... ...
  • 文件目錄管理 一.認識Linux文件系統的架構 在Linux中是沒有盤符這個概念的,即Linux中沒有C盤和D盤的分盤。那麼我們直接通過對目錄的操作實現對磁碟的讀寫,因為已經建立的文件系統分區被掛載到一個目錄下。 我們可以註意到Linux表示目錄是使用"/"而不是像Windows那樣的"\"。 那麼 ...
  • 筆記本配置:8G記憶體,200G SSD,先在virbox中成功安裝雙系統,能正常進入並使用 Windows 7 和 CentOS 7。 網上看到一大堆的安裝 wingrub easyBCD,折騰了一天沒安裝成功,結果還是 google 找到一篇靠譜的文章,step by step 終於在第二天搞定雙 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...