shell編程系列6--shell中的函數

shell編程系列6--shell中的函數


1.函數介紹

linux shell中的函數和大多數編程語言中的函數同樣
將類似的任務或者代碼封裝到函數中,供其餘地方調用

語法格式

第一種格式

name()
{
    command1
    command2
    ......
    commondn
}

第二種格式

function name
{
    command1
    command2
    ......
    commondn
}

2.調用函數

直接使用函數名調用,能夠將其想象成shell中的一條命令

函數內部能夠直接使用參數 $1、$2...$n

調用函數:function_name $1 $2

shell終端中定義函數

[root@es01 shell]# test()
> {
>     echo "test function"
> }
[root@es01 shell]# 
[root@es01 shell]# test
test function

[root@es01 shell]# function greeting
> {
>     echo "hello,zhangsan"
> }
[root@es01 shell]# greeting 
hello,zhangsan


練習;nginx的守護進程

[root@es01 shell]# cat nginx_daemon.sh 
#!/bin/bash
#
# 獲取腳本子進程的pid,若是腳本名稱中帶nginx,也會當成nginx進程
this_pid=$$

while true
do
ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/null


if [ $? -eq 0 ];then
    echo "Nginx is running well"
    sleep 5
else
    systemctl start nginx
    echo "Nginx is down,Start it..."
fi
done


[root@es01 shell]# nohup sh nginx_daemon.sh &
[1] 97855
[root@es01 shell]# nohup: ignoring input and appending output to ‘nohup.out’

[root@es01 shell]# tail -f nohup.out 
Nginx is running well
Nginx is running well
Nginx is running well
Nginx is running well

4.向函數傳遞參數

高級語言傳參

int example_1(int arg1,int arg2)
{
    arg1=arg2
    ...
    ...
    return null
}

高級語言函數調用

int num1=10;
int num2=20;

調用函數形式一:int num3=example_1(num1,num2);
調用函數形式二:
        int num4;
        num4=example_1(num1,num2);

shell中傳參

function name
{
    echo "Hello $1"
    echo "Hello $2"
}

shell中函數調用
函數調用:name Lily Allen


[root@es01 shell]# function greeting
> {
> echo "hello zhangsan"
> }
[root@es01 shell]# greeting
hello zhangsan

# 調用參數
[root@es01 shell]# function greeeting
> {
>     echo "hello $1"
> }
[root@es01 shell]# greeeting jack
hello jack
[root@es01 shell]# greeeting tom
hello tom

向函數傳遞參數:
函數傳參和給腳本傳參相似,都是使用$1 $2 $3 $4 $5 $6 $7這種方式

例子1:
需求描述:寫一個腳本,該腳本能夠實現計算器的功能,能夠進行+-*/四種運算。
例如:sh calculate.sh 30 + 40 | sh calucate.sh 30 - 40


[root@es01 shell]# cat calucate.sh 
#!/bin/bash
#

function calcu
{
    case $2 in
        +)
            echo "`expr $1 + $3`"
            ;;
        -)
            echo "`expr $1 - $3`"
            ;;
        \*)
            echo "`expr $1 \* $3`"
            ;;
        /)
            echo "`expr $1 / $3`"
            ;;
    esac
}

calcu $1 $2 $3


[root@es01 shell]# sh calucate.sh 20 + 30
50
[root@es01 shell]# sh calucate.sh 20 - 30
-10

5.函數的返回值

方法一 return
方法二 echo

使用return返回值
使用return返回值,只能返回1-255的整數

函數使用return返回值,一般只是用來供其餘地方調用獲取狀態,所以一般僅返回0或1;0表示成功,1表示失敗

# 判斷nginx進程是否存在
[root@es01 shell]# cat nginx.sh 
#!/bin/bash
#

this_pid=$$

function is_nginx_running
{
    ps -ef | grep nginx | grep -v grep | grep -v $this_pid &> /dev/null
    if [ $? -eq 0 ];then
        return 0
    else
        return 1
    fi
}

is_nginx_running && echo "nginx is running" || echo "nginx is stopped"

[root@es01 shell]# sh nginx.sh 
nginx is running
[root@es01 shell]# systemctl stop nginx
[root@es01 shell]# sh nginx.sh 
nginx is stopped
[root@es01 shell]# sh -x nginx.sh 
+ this_pid=101185
+ is_nginx_running
+ ps -ef
+ grep nginx
+ grep -v grep
+ grep -v 101185
+ '[' 1 -eq 0 ']'
+ return 1
+ echo 'nginx is stopped'
nginx is stopped


使用echo返回值

使用echo能夠返回任何字符串結果

一般用於返回數據,好比一個字符串值或者列表值

# 獲取系統中的用戶
[root@es01 shell]# cat get_sys_user.sh 
#!/bin/bash
#

# 獲取系統全部的用戶名
function get_users
{
    users=`cat /etc/passwd | cut -d: -f1`
    echo $users
}

# 定義一個變量將獲取用戶列表賦值給這個變量
user_list=`get_users`

index=1
for u in $user_list
do
    echo "the $index user is : $u"
    index=$(($index+1))
done


[root@es01 shell]# sh get_sys_user.sh 
the 1 user is : root
the 2 user is : bin
the 3 user is : daemon
the 4 user is : adm
the 5 user is : lp
the 6 user is : sync
the 7 user is : shutdown
the 8 user is : halt
the 9 user is : mail
the 10 user is : operator
the 11 user is : games
the 12 user is : ftp
the 13 user is : nobody
the 14 user is : systemd-network
the 15 user is : dbus
the 16 user is : polkitd
the 17 user is : sshd
the 18 user is : postfix
the 19 user is : ajie
the 20 user is : chrony
the 21 user is : elasticsearch
the 22 user is : nginx

6.shell函數中的局部變量和全局變量

不作特殊聲明,shell中變量都是全局變量

大型腳本程序函數中慎用全局變量

局部變量:

在函數內部定義局部變量時,使用local關鍵字

函數內和函數外若同時存在變量,函數內部變量會覆蓋外部變量

# 
[root@es01 shell]# cat var.sh 
#!/bin/bash
#

var1="Hello world"

function test
{
    var2=87
}

echo $var1
echo $var2

# 由於函數test沒有被調用,因此變量 $var2 沒有生效,爲空
[root@es01 shell]# sh var.sh 
Hello world

[root@es01 shell]#

# 調用test函數後,$var2就變成了全局變量
[root@es01 shell]# cat var.sh 
#!/bin/bash
#

var1="Hello world"

function test
{
    var2=87
}

echo $var1
echo $var2

test    # 調用test函數後,$var2就變成了全局變量

echo $var1
echo $var2

[root@es01 shell]# sh var.sh 
Hello world

Hello world
87

# 在函數中也能夠調用全局變量
[root@es01 shell]# cat var.sh 
#!/bin/bash
#

var1="Hello world"

function test
{
    var2=87
}

echo $var1
echo $var2

test

echo $var1
echo $var2

function test1
{
    echo $var2
}

test1
[root@es01 shell]# sh var.sh 
Hello world

Hello world
87
87

# 若是函數中聲明瞭局部變量,當函數執行完成後局部變量就會被銷燬
[root@es01 shell]# cat var.sh 
#!/bin/bash
#

var1="Hello world"

function test
{
    local var2=87    # 局部變量,只在函數內部生效,生命週期只在函數內部
}

test

echo $var1
echo $var2

[root@es01 shell]# sh var.sh 
Hello world

[root@es01 shell]# 

7.函數庫

爲何須要定義函數庫?

常常使用的重複代碼能夠封裝成函數文件,功能函數,程序工具

函數庫文件通常不直接執行,而是由其餘腳本調用

函數庫示例:

    定義一個函數庫,該函數庫實現如下幾個函數:
    1.加法函數add
        add 12 89
    2.減法函數reduce
        reduce 90 30
    3.乘法函數multiple
        multiple 12 10
    4.除法函數divide
        divide 9 3
    5.打印系統運行狀況的函數sys_load,該函數能夠顯示內存運行狀況,磁盤使用狀況


    # 定義庫函數
    [root@es01 shell]# cat lib/base_function 
    function add
    {
        echo "`expr $1 + $2`"
    }

    function reduce
    {
        echo "`expr $1 - $2`"
    }

    function multiple
    {
        echo "`expr $1 \* $2`"
    }

    function divide
    {
        echo "`expr $1 / $2`"
    }

    function sys_load
    {
        echo "Memory info"
        echo 
        free -m
        echo
        echo "Disk Usage"
        echo
        df -h
        echo
    }

    # 測試庫函數
    [root@es01 shell]# . lib/base_function 
    [root@es01 shell]# sys_load
    Memory info

              total        used        free      shared  buff/cache   available
    Mem:           3773         123        3300          11         348        3389
    Swap:          2047           0        2047

    Disk Usage

    Filesystem               Size  Used Avail Use% Mounted on
    /dev/mapper/centos-root   49G  3.3G   46G   7% /
    devtmpfs                 1.9G     0  1.9G   0% /dev
    tmpfs                    1.9G     0  1.9G   0% /dev/shm
    tmpfs                    1.9G   12M  1.9G   1% /run
    tmpfs                    1.9G     0  1.9G   0% /sys/fs/cgroup
    /dev/sda1                297M  125M  172M  43% /boot
    /dev/mapper/centos-data   49G   33M   49G   1% /data
    tmpfs                    378M     0  378M   0% /run/user/0

    # 調用庫函數
    [root@es01 shell]# cat calculate.sh 
    #!/bin/bash
    #

    # 引入庫函數,寫絕對路徑避免出錯
    . /data/shell/lib/base_function

    add 12 23

    reduce 90 30

    multiple 12 12

    divide 12 2


經驗之談:
庫文件名的後綴是任意的,但通常使用.lib

庫文件一般沒有可執行權限

庫文件無需和腳本放在同級目錄,只須要在腳本中引用時指定

第一行通常使用#!/bin/echo,輸出警告信息,避免用戶執行
相關文章
相關標籤/搜索