第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Shell 函數(shù)

1. Shell 函數(shù)概述

1.1 Shell 函數(shù)簡(jiǎn)介

Shell 和其他語言一樣,也有函數(shù),其本質(zhì)就是一段可以復(fù)用的代碼。將數(shù)據(jù)進(jìn)行抽離處理,傳遞不同的值輸出不同的結(jié)果,在指定的地方進(jìn)行調(diào)用即可。

1.2 為什么要用函數(shù)

如果我們要重復(fù)執(zhí)行一批相同的操作,不想重復(fù)去寫,可以將這一系列操作抽象為一個(gè)函數(shù),后期可以利用變量傳值調(diào)用該函數(shù),從而大大減少重復(fù)性勞動(dòng),提升效率減少代碼量,使得 Shell 腳本更加的靈活和通用。

2. Shell 函數(shù)操作

2.1 函數(shù)語法

2.1.1 標(biāo)準(zhǔn)語法

function fnname() { 
	statements
	return value
}

對(duì)各個(gè)部分的說明:

  • function 是 Shell 中的關(guān)鍵字,專門用來定義函數(shù);
  • fname 是函數(shù)名;
  • statements 是函數(shù)要執(zhí)行的代碼,也就是一組語句;
  • return value 表示函數(shù)的返回值,其中 return 是 Shell 關(guān)鍵字,專門用在函數(shù)中返回一個(gè)值,這一部分可以寫也可以不寫。

由大括號(hào)包圍的部分稱為函數(shù)體,調(diào)用一個(gè)函數(shù),實(shí)際上就是執(zhí)行函數(shù)體中的代碼。

例如:

function checkuser() { 
	echo "當(dāng)前用戶為:$USER"
	return 0
}

如上就定義了一個(gè) checkuser 函數(shù),其輸出當(dāng)前登錄系統(tǒng)的用戶名,返回值為 0。

2.1.2 簡(jiǎn)化語法

  • 函數(shù)名后無括號(hào)
#簡(jiǎn)化寫法1
function fname{ 
	statements
	return n
}
  • 函數(shù)不寫 function
#簡(jiǎn)化寫法2:
fname() {
	statements
	return n
}

上述兩種定義函數(shù)的方法都可以,但是還是建議在編寫 Shell 的時(shí)候,也不要浪費(fèi)這點(diǎn)時(shí)間,建議大家都用完整函數(shù)定義,寫 function 關(guān)鍵字,在為函數(shù)定義帶上 (),這樣更加規(guī)范,而且便于別人閱讀修改你的腳本。

Tips:在函數(shù)定義中需要函數(shù)名稱后可以有多個(gè)空格,括號(hào)內(nèi)也可以有多個(gè)空格,如果函數(shù)體寫在一行,需要在語句末尾加上 ;。

2.2 函數(shù)調(diào)用

當(dāng)函數(shù)定義好了,在需要使用函數(shù)的地方,調(diào)用其函數(shù)名稱即可,注意函數(shù)調(diào)用需要在函數(shù)定義之后。

2.2.1 無參數(shù)調(diào)用

當(dāng)函數(shù)沒有參數(shù)的時(shí)候,調(diào)用非常簡(jiǎn)單,直接寫函數(shù)名稱即可,調(diào)用函數(shù)就是在特定地方執(zhí)行函數(shù)體內(nèi)的操作。

// 定義函數(shù)
function fnname() { 
	statements
	return value
}

// 調(diào)用函數(shù)
fname

2.2.2 傳遞參數(shù)調(diào)用

  • 語法

我們之前在變量一章節(jié)介紹了 Shell 腳本的參數(shù),知道了參數(shù)的重要性質(zhì)及其各種類特征,與 Shell 腳本傳遞參數(shù)一樣,函數(shù)也可以傳遞參數(shù),例如:

// 定義函數(shù)
function fnname() { 
	statements
	return value
}

// 調(diào)用函數(shù)
fname param1 param2 param3

如上所示,在調(diào)用函數(shù) fname 的時(shí)候,我們傳遞了三個(gè)參數(shù),參數(shù)之間利用空格分割,和 Shell 腳本傳遞參數(shù)一樣,但需要注意 Shell 腳本中,函數(shù)在定義時(shí)候不能指定參數(shù),在調(diào)用的時(shí)候傳遞參數(shù)即可,并且在調(diào)用函數(shù)時(shí)傳遞什么參數(shù)函數(shù)就接受什么參數(shù)。

2.3 函數(shù)參數(shù)

上述我們了解了函數(shù)的定義,在其中無參函數(shù)調(diào)用即調(diào)用函數(shù)名即可,對(duì)于有參函數(shù),需要傳遞一定的參數(shù)來執(zhí)行對(duì)應(yīng)的操作,函數(shù)的參數(shù)和腳本的參數(shù)類型及用法一致,在此我們簡(jiǎn)單回顧下,看參數(shù)在函數(shù)中都有哪些分類,及該如何使用。

2.3.1 位置參數(shù)

位置參數(shù)顧名思義,就是傳遞給函數(shù)參數(shù)的位置,例如給一個(gè)函數(shù)傳遞一個(gè)參數(shù),我們可以在執(zhí)行 Shell 腳本獲取對(duì)應(yīng)位置的參數(shù),獲取參數(shù)的格式為:$n。n 代表一個(gè)數(shù)字,在此需要注意與腳本傳遞參數(shù)不一樣,$0 為依舊為腳本的名稱,在函數(shù)參數(shù)傳遞中,例如傳遞給函數(shù)的第一個(gè)參數(shù)獲取就為 $1,第 2 個(gè)參數(shù)就為 $2, 以此類推……,需要其 $0 為該函數(shù)的名稱。

例如:

[root@master func]# cat f1.sh 
#!/bin/bash

function f1() {
        echo "函數(shù)的第一個(gè)參數(shù)為: ${1}"
        echo "函數(shù)的第二個(gè)參數(shù)為: ${2}"
        echo "函數(shù)的第三個(gè)參數(shù)為: ${3}"
}
# 調(diào)用函數(shù)
f1 shell linux python go

[root@master func]# bash f1.sh 
函數(shù)的第一個(gè)參數(shù)為: shell
函數(shù)的第二個(gè)參數(shù)為: linux
函數(shù)的第三個(gè)參數(shù)為: python

我們可以看到傳遞給 f1 函數(shù)共 4 個(gè)位置參數(shù),在結(jié)果輸出中可以看到由于函數(shù)體內(nèi)部只對(duì)三個(gè)參數(shù)進(jìn)行了處理,后續(xù)的參數(shù)也就不再處理了。

2.3.2 特殊參數(shù)

在 Shell 中也存在特殊含義的參數(shù)如下表:

變量 含義
$# 傳遞給函數(shù)的參數(shù)個(gè)數(shù)總和
$* 傳遞給腳本或函數(shù)的所有參數(shù),當(dāng)被雙引號(hào) " " 包含時(shí),所有的位置參數(shù)被看做一個(gè)字符串
$@ 傳遞給腳本或函數(shù)的所有參數(shù),當(dāng)被雙引號(hào) " " 包含時(shí),每個(gè)位置參數(shù)被看做獨(dú)立的字符串
$? $? 表示函數(shù)的退出狀態(tài),返回為 0 為執(zhí)行成功,非 0 則為執(zhí)行失敗

示例:

[root@master func]# cat f1.sh 
#!/bin/bash

function fsum() {
        echo "函數(shù)第一個(gè)參數(shù)為: ${1}"
        echo "函數(shù)第二個(gè)參數(shù)為: ${2}"
        echo "函數(shù)第三個(gè)參數(shù)為: ${3}"
        echo "函數(shù)的參數(shù)總數(shù)為: ${#}"
        echo "函數(shù)的參數(shù)總數(shù)為: ${@}"
        local sum=0
        for num in ${@};
        do
                let sum=${sum}+${num}
        done
        echo "計(jì)算的總和為: ${sum}"
        return 0
}
# 調(diào)用函數(shù)
fsum 10 20 1 2
echo $?

[root@master func]# bash f1.sh 
函數(shù)第一個(gè)參數(shù)為: 10
函數(shù)第二個(gè)參數(shù)為: 20
函數(shù)第三個(gè)參數(shù)為: 1
函數(shù)的參數(shù)總數(shù)為: 4
函數(shù)的參數(shù)總數(shù)為: 10 20 1 2
計(jì)算的總和為: 33
0

如上可以看到特殊參數(shù)與 Shell 腳本傳遞參數(shù)一樣。

Tips:局部變量需要特別聲明在函數(shù)內(nèi)部利用 local 關(guān)鍵字來聲明。

2.4 函數(shù)返回值

函數(shù)返回值利用 $? 來接收,在上述示例中我們將計(jì)算的結(jié)果利用 echo 命令打印出來,如果我們?cè)诤罄m(xù)的腳本中需要利用此函數(shù)計(jì)算的結(jié)果,就需要得到這個(gè)返回值,此刻就需要將計(jì)算的結(jié)果不僅僅是打印而是返回了,函數(shù)中返回利用 return 關(guān)鍵字,在函數(shù)調(diào)用完成后,我們利用 $? 來接受函數(shù)的返回值,例如將我們上面的示例改造成返回結(jié)構(gòu)的函數(shù)。

注意:shell 函數(shù)的返回值,只能是整形,并且在 0-257 之間,不能是字符串或其他形式。并且在調(diào)用方法和取得返回值之間,不能有任何操作,不然取不到 return 的值。

[root@master func]# cat f1.sh 
#!/bin/bash

function fsum() {
        echo "函數(shù)第一個(gè)參數(shù)為: ${1}"
        echo "函數(shù)第二個(gè)參數(shù)為: ${2}"
        echo "函數(shù)第三個(gè)參數(shù)為: ${3}"
        echo "函數(shù)的參數(shù)總數(shù)為: ${#}"
        echo "函數(shù)的參數(shù)總數(shù)為: ${@}"
        local sum=0
        for num in ${@};
        do
                let sum=${sum}+${num}
        done
        return $sum
}


fsum 10 20 1 2
echo $?
[root@master func]# bash f1.sh 
函數(shù)第一個(gè)參數(shù)為: 10
函數(shù)第二個(gè)參數(shù)為: 20
函數(shù)第三個(gè)參數(shù)為: 1
函數(shù)的參數(shù)總數(shù)為: 4
函數(shù)的參數(shù)總數(shù)為: 10 20 1 2
33

可以看到我們將在函數(shù)內(nèi)部計(jì)算的數(shù)組之和,利用 return 作為返回,此刻在函數(shù)調(diào)用的時(shí)候,利用 $? 就可以拿到函數(shù)返回的值進(jìn)一步處理。

2.5 遞歸函數(shù)

Shell 支持遞歸函數(shù),遞歸函數(shù)也就是自己調(diào)用自己,即在函數(shù)體內(nèi)部又一次調(diào)用函數(shù)自己,例如:

[root@master func]# cat recursion.sh 
#!/bin/bash

function myecho() {
        echo "$(date)"
        sleep 1
        myecho inner
}

myecho
[root@master func]# bash recursion.sh 
Sat Mar 28 13:14:38 CST 2020
Sat Mar 28 13:14:39 CST 2020
Sat Mar 28 13:14:40 CST 2020
Sat Mar 28 13:14:41 CST 2020
Sat Mar 28 13:14:42 CST 2020
...

如上就是一個(gè)遞歸函數(shù),在函數(shù)體內(nèi)部又調(diào)用了函數(shù) myecho,在執(zhí)行的時(shí)候就會(huì)陷入無限循環(huán)。

3. 實(shí)例

3.1 需求

系統(tǒng)經(jīng)常在執(zhí)行定時(shí)腳本期間會(huì)將 Linux 系統(tǒng) CPU 利用率跑滿,導(dǎo)致其他服務(wù)受到影響,故查閱資料發(fā)現(xiàn)有大神寫的 CPU 利用率限制程序。
地址:CPU Usage Limiter for Linux

利用此工具可以,配合定時(shí)任務(wù)放置在服務(wù)器上,達(dá)到限制程序 CPU 情況,可根據(jù)自己系統(tǒng) CPU 核心數(shù)進(jìn)行參數(shù)配置,會(huì)記錄 CPU 超過閥值的日志,可供后期進(jìn)行查看分析。

3.2 思路

利用函數(shù)編寫安裝 cpulimit 工具的函數(shù),如果系統(tǒng)不存在該命令則安裝并執(zhí)行 CPU 限制,如果存在則執(zhí)行 cpulimit 函數(shù)對(duì)超過指定 CPU 的進(jìn)程進(jìn)行限制,最后執(zhí)行總體 main 函數(shù)。

3.3 實(shí)現(xiàn)

  • 實(shí)現(xiàn)腳本
#!/bin/bash
# Description: count file scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# function: count file
# Date: 2020-03-29 14:00
# Version: 1.0

[ $(id -u) -gt 0 ] && exit 1

# cpu使用超過百分之多少進(jìn)行限制
PEC_CPU=80

# 限制進(jìn)程使用百分之多少,如果程序?yàn)槎嗑€程,單個(gè)cpu限制為85,如果為多核心,就需要按照比例寫,例如cpu為2c,像限制多線程占比80%,就寫170
LIMIT_CPU=85
# 日志
LOG_DIR=/var/log/cpulimit/

# 超過閥值進(jìn)程pid
PIDARG=$(ps -aux |awk -v CPU=${PEC_CPU} '{if($3 > CPU) print $2}')

# 安裝cpulimit 函數(shù)
install_cpulimit() {
	[ ! -d /tmp ] && mkdir /tmp || cd /tmp
	wget -c https://github.com/opsengine/cpulimit/archive/v0.2.tar.gz
	tar -zxf v0.2.tar.gz
	cd cpulimit-0.2 && make
	[ $? -eq 0 ] && cp src/cpulimit /usr/bin/
}
# 執(zhí)行cpulimit
do_cpulimit() {
[ ! -d ${LOG_DIR} ] && mkdir -p ${LOG_DIR}
for i in ${PIDARG};
do
	CPULIMITCMD=$(which cpulimit)
        MSG=$(ps -aux |awk -v pid=$i '{if($2 == pid) print $0}')
        echo ${MSG}
	[ ! -d /tmp ] && mkdir /tmp || cd /tmp
	nohup ${CPULIMITCMD} -p $i -l ${LIMIT_CPU} &
        echo "$(date) -- ${MSG}" >> ${LOG_DIR}$(date +%F).log
done
}
# 主函數(shù)
main() {
	hash cpulimit
	if [ $? -eq 0 ];then
	  # 調(diào)用函數(shù)
		do_cpulimit
	else
		install_cpulimit && do_cpulimit
	fi
}

main
  • 測(cè)試

需編寫 CPU 壓力測(cè)試 python 腳本,后期可以放入計(jì)劃任務(wù)來監(jiān)控并限制 CPU 使用率。

#!/bin/env python

import math
import random

a=10000
b=10000
c=10000

sum=0

for i in range(0,a):
    for j in range(0,b):
        randomfloat=random.uniform(1,10)
        randompow=random.uniform(1,10)
        sum+=math.pow(randomfloat, randompow)

print "sum is %s" % sum

當(dāng)我們執(zhí)行 python 的 CPU 壓力測(cè)試腳本后,發(fā)現(xiàn)單核服務(wù) CPU 跑到了 100%。

之后運(yùn)行我們的 CPU 限制腳本,可以看到 CPU 被成功限制。

在此案例中,我們著重來看 Shell 函數(shù),在實(shí)例中我們編寫了安裝與執(zhí)行 CPU 限制兩個(gè)函數(shù),最后編寫主函數(shù),在主函數(shù)中調(diào)用其他函數(shù),配合定時(shí)任務(wù)就能達(dá)到限制某進(jìn)程的 CPU。

4. 注意事項(xiàng)

  • 函數(shù)定義建議使用見名知意并需要有一定原則,不僅為了美觀更是為了規(guī)范,使得其他人更好理解與閱讀你的 Shell 腳本,增強(qiáng)腳本可維護(hù)性;
  • 對(duì)于函數(shù)調(diào)用,必須在函數(shù)定義之后,Shell 運(yùn)行為順序運(yùn)行,沒有定義函數(shù)則調(diào)用函數(shù)會(huì)有異常;
  • 函數(shù)定義不能指定參數(shù),在調(diào)用的時(shí)候傳遞參數(shù)即可,并且調(diào)用函數(shù)傳遞什么參數(shù),函數(shù)就接受什么參數(shù);
  • 函數(shù)傳遞參數(shù)與 Shell 腳本傳遞參數(shù)的類型及用法一致,在此可以融會(huì)貫通,對(duì)比理解記憶;
  • shell 函數(shù)的返回值,只能是整形,并且在 0-257 之間,不能為字符串或其他形式。

5. 小結(jié)

我們編寫 Shell 就是為了實(shí)現(xiàn)簡(jiǎn)化操作,通常將數(shù)據(jù)和程序分離,我們將一組實(shí)現(xiàn)具體業(yè)務(wù)的邏輯編寫為一個(gè)函數(shù),也可以稱為一段代碼塊,將其模塊化,賦予函數(shù)名稱,利用函數(shù)可以達(dá)到代碼復(fù)用,使得數(shù)據(jù)與邏輯分離,腳本更加便于維護(hù)和管理。