Shell腳本編程—函數

函數:

    把一段獨立功能的代碼當作一個整體,并命名一個名字;命名的代碼段,此即為函數

    由若干條shell命令組成的語句塊,實現代碼重用和模式化編程

函數的作用:

    在某些場景下,我們可以將獨立功能的一段代碼定義為一個函數,用到此功能時,直接調用函數即可,而不必重復編寫代碼,節省一定的代碼量

    注意:定義函數的代碼段不會自動執行,在調用時執行;所謂調用函數,在代碼中給定函數名即可;

     函數名出線的任何位置,在代碼執行時,都會被自動替換為函數代碼

語法格式:

     語法一:

     function f_name() {

         函數代碼

        

     }

     語法二:

     f_name() {

         函數代碼

        

     }

函數的定義:

    在交互式環境下定義函數,定義完成后,直接調用即可

    把函數定義在腳本中,當中腳本的一部分

    存放在特定的函數文件當中,用到時直接調用函數文件

函數的生命周期:每次被調用時創建,返回時終止

函數的退出狀態碼:

     其狀態返回結果為函數體中運行的最后一條命令的狀態結果

     自定義狀態返回值,需要使用:return

     return [0-255]

         0:成功

         1-255:失敗

函數返回值:

     函數的執行結果返回值:

         (1) 使用echo或printf命令進行輸出

         (2)函數體中調用的命令執行結果

    函數的退出狀態碼:

         (1)默認取決于函數體中執行的最后一條命令的退出狀態碼

         (2)自定義:return

函數可以接受參數:

     在函數體當中,可以使用$1,$2,…引用傳遞給函數的參數;還可以在函數中使用$*或$@引用所有參數,$#引用傳遞參數的個數

     在調用函數時,在函數名后面以空白符分隔給定參數列表即可,例如,func arg1 arg2 arg3…

   

使用函數文件:

    可以將經常使用的函數存放在一個文件當中,然后將函數文件載入shell程序執行,一旦函數載入shell,就可以在命令行或腳本中調用函數

    可使用set命令查看當前shell所載入的所有函數

    使用unset命令可刪除所指定的函數

    

載入函數文件:

    . filename或source filename

變量作用域:

    環境變量:生效范圍為當前shell以及子shell進程

    本地變量:生效范圍為當前shell進程,隨著shell進程結束而結束

    局部變量:生效范圍為腳本中某一代碼片段,隨著函數的結束而結束

        建議在函數當中使用局部變量,因為函數是在當前shell進程中執行的,函數中所定義的變量有可能會和腳本中的變量產生沖突

        因此把函數中變量定義為局部變量,只在函數內部中生效

        局部變量定義方法;

            local NAME="value"

示例:

1.編寫服務腳本/root/bin/testsrv.sh,完成如下要求

(1) 腳本可接受參數:start, stop, restart, status

(2) 如果參數非此四者之一,提示使用格式后報錯退出

(3) 如是start:則創建/var/lock/subsys/SCRIPT_NAME, 并顯示“啟動成功”

考慮:如果事先已經啟動過一次,該如何處理?

(4) 如是stop:則刪除/var/lock/subsys/SCRIPT_NAME, 并顯示“停止完成”

考慮:如果事先已然停止過了,該如何處理?

(5) 如是restart,則先stop, 再start

考慮:如果本來沒有start,如何處理?

(6) 如是status, 則如果/var/lock/subsys/SCRIPT_NAME文件存在,則顯示“SCRIPT_NAMEis running…”

如果/var/lock/subsys/SCRIPT_NAME文件不存在,則顯示“SCRIPT_NAME is stopped…”

其中:SCRIPT_NAME為當前腳本名

[root@CentOS7 ~]# cat service.sh 
#!/bin/bash
#

NAME=$(basename $0)
SCRIPTS="/var/lock/subsys/$NAME"

function start() {
	if [ ! -e $SCRIPTS ];then
		touch $SCRIPTS
		sleep 1
		echo "start service $NAME finished."
	else
		echo "$NAME service is running..."
	fi
}

function stop() {
	if [ -e $SCRIPTS ];then
		rm -f $SCRIPTS
		sleep 1
		echo "stop service $NAME finished."
	else
		echo "service $NAME is not running..."
	fi
}

function restart() {
	if [ -e $SCRIPTS ];then
		rm -f $SCRIPTS
		touch $SCRIPTS
		sleep 1
		echo "restart service $NAME finished."
	else
		touch $SCRIPTS
		sleep 1
		echo "start service $NAME finished."
	fi
}

function status() {
	if [ -e $SCRIPTS ];then
		echo "service $NAME is running..."
	else
		echo "service $NAME is not running..."
	fi
}

function error() {
	echo "Usage: `basename $0` {start|stop|restart|status}"
	exit 1
}


case $1 in
start)
	start
	;;
stop)
	stop
	;;
restart)
	restart
	;;
status)
	status
	;;
*)
	error
	;;
esac

[root@CentOS7 ~]# ./service.sh start        #啟動服務器
start service service.sh finished.
[root@CentOS7 ~]# ./service.sh stop        #停止服務
stop service service.sh finished.
[root@CentOS7 ~]# ./service.sh restart    #如果服務處于停止狀態,則啟動服務
start service service.sh finished.
[root@CentOS7 ~]# ./service.sh restart    #如果服務處于啟動狀態,則重啟服務
restart service service.sh finished.
[root@CentOS7 ~]# ./service.sh status        #當前服務運行狀態為啟動
service service.sh is running...
[root@CentOS7 ~]# ./service.sh stop        #服務運行狀態為未啟用
stop service service.sh finished.
[root@CentOS7 ~]# ./service.sh status
service service.sh is not running...
[root@CentOS7 ~]#

2.編寫腳本/root/bin/copycmd.sh

(1) 提示用戶輸入一個可執行命令名稱

(2) 獲取此命令所依賴到的所有庫文件列表

(3) 復制命令至某目標目錄(例如/mnt/sysroot)下的對應路徑下;

如:/bin/bash ==> /mnt/sysroot/bin/bash

/usr/bin/passwd==> /mnt/sysroot/usr/bin/passwd

(4) 復制此命令依賴到的所有庫文件至目標目錄下的對應路徑下:

如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2

(5)每次復制完成一個命令后,不要退出,而是提示用戶鍵入新的要復制的命令,并重復完成上述功能;直到用戶輸入quit退出

[root@CentOS7 bin]# cat copycmd.sh 
#!/bin/bash
#

function copycmd() {
	local MKDIR=$DIR$(which --skip-alias $CMD | grep -E -o "^/.*/")	
	[ ! -e $MKDIR ] && mkdir -p $MKDIR
	cp `which --skip-alias $CMD` $MKDIR
	[ $? -eq 0 ] && echo "Copy $CMD command file finished."
}

function copylib() {
	[ ! -e $DIR$LIB ] && mkdir -p $DIR$LIB
	local LIBFILE=$(ldd `which --skip-alias $CMD` | grep -E -o "/.*" | sed -r 's@(.*) .*@\1@')
	cp $LIBFILE $DIR$LIB
	[ $? -eq 0 ] && echo "Copy $CMD command lib file finished." 
}

DIR="/mnt/sysroot"
LIB="/lib64/"

read -p "請輸入一個可執行命令:" CMD

until [ $CMD == "quit" ]
do
	if ! which --skip-alias $CMD &> /dev/null;then
		echo "$CMD不是一個可執行命令"
		read -p "請輸入一個可執行命令:" CMD
		continue
	fi
	copycmd
	copylib
	read -p "請輸入一個可執行命令:" CMD
done


[root@CentOS7 bin]# bash copycmd.sh 
請輸入一個可執行命令:ls
Copy ls command file finished.
Copy ls command lib file finished.
請輸入一個可執行命令:passwd
Copy passwd command file finished.
Copy passwd command lib file finished.
請輸入一個可執行命令:useradd
Copy useradd command file finished.
Copy useradd command lib file finished.
請輸入一個可執行命令:quit
[root@CentOS7 sysroot]# cd /mnt/sysroot/
[root@CentOS7 sysroot]# cd
[root@CentOS7 ~]# cd /mnt/sysroot/
[root@CentOS7 sysroot]# ls
lib64  usr
[root@CentOS7 sysroot]# ls lib64/ usr/sbin/ usr/bin/    #查看命令文件和庫文件是否復制成功
lib64/:
ld-linux-x86-64.so.2  libcap.so.2    libfreebl3.so        libpam_misc.so.0  libselinux.so.1
libacl.so.1           libcrypt.so.1  libglib-2.0.so.0     libpam.so.0       libsemanage.so.1
libattr.so.1          libc.so.6      libgmodule-2.0.so.0  libpcre.so.1      libsepol.so.1
libaudit.so.1         libdl.so.2     libgobject-2.0.so.0  libpopt.so.0      libuser.so.1
libbz2.so.1           libffi.so.6    liblzma.so.5         libpthread.so.0   libustr-1.0.so.1

usr/bin/:
ls  passwd

usr/sbin/:
useradd
[root@CentOS7 sysroot]#

原創文章,作者:zhai796898,如若轉載,請注明出處:http://www.www58058.com/39743

(0)
zhai796898zhai796898
上一篇 2016-08-24
下一篇 2016-08-24

相關推薦

  • Linux基于PXE實現系統全自動無人值守安裝

    前言 在生產環境中,我們時常會需要在多臺客戶端主機或服務器安裝操作系統,如果每一臺都去手動安裝,費時費力,顯然是不現實的。那么,如何高效的完成此類工作呢?文將講解如何實現Linux系統的全自動無人值守安裝。 提供PXE服務所需安裝包 dhcp:動態主機配置協議,給客戶端提供ip地址 tftp-server:tftp服務器端,提供系統安裝所需文件 xinetd…

    Linux干貨 2015-04-01
  • Linux命令格式、獲取幫助、文件系統

    一、Linux的命令     (一)、概念和意義:             發起一個命令:請求內核將某個二進制程序運行為一個進程;      &nbs…

    Linux干貨 2016-08-15
  • 【25期】Linux第一周學習知識小結

    1:設置Linux圖形界面不用輸入賬號和密碼直接登錄系統 首先在圖形化界面編輯文件:vi /etc/gdm/custom.conf 編輯如下圖: 在[daemon]下添加兩行代碼: AutomaticLoginEnable=True // 自動登陸器用 AutomaticLogin=root   //登錄賬號root 2:free命令 在終端輸入f…

    2017-07-15
  • RAID解說

    RAID(RedundantArrays of Inexpensive Disks,RAID),又叫獨立的磁盤陣列。有“價格便宜具有冗余能力的磁盤陣列”之意。原理是利用數組方式來作磁盤組,配合數據分散排列的設計,提升數據的安全性。磁盤陣列是由很多價格較便宜的磁盤,組合成一個容量巨大的磁盤組,利用個別磁盤提供數據所產生加成效果提升整個磁盤系統效能。利用這項技術…

    2017-03-14
  • 搭建路由環境

        五個虛擬機分別模擬三個路由器和兩個主機,實現不同網段的主機之間的通信。 1.規定四個網段的ip地址:分別是192.168.1.0/24;192.168.2.0/24;192.168.3.0/24;192.168.4.0/24 2.三個路由器命名為R1、R2、R3。R1的兩個網關地址為192.168.1.1和19…

    2017-08-20
  • 邏輯卷LVM

    邏輯卷LVM 簡介     在實際生產應用中,磁盤的分區的容量是固定不變的,當出現分區容量不足的情況,除了新加磁盤,還有沒有其他方法呢?    邏輯卷(LVM)的概念就出現了,全稱叫Logical Volume Manager。它的作用是允許對卷進行方便操作的抽象層,包括重新設定…

    Linux干貨 2017-08-12
欧美性久久久久