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.178linux.com/39743

(0)
zhai796898zhai796898
上一篇 2016-08-24 14:49
下一篇 2016-08-24 20:24

相关推荐

  • shell脚本之条件测试

    组合条件测试:在多个条件间实现逻辑运算     与:[ condition1 -a condition2 ]、condition1 && condition2     或:[ condition…

    Linux干货 2015-08-24
  • N28-第三周博客作业

    1、列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可。
    2、取出最后登录到当前系统的用户的相关信息。
    3、取出当前系统上被用户当作其默认shell的最多的那个shell。
    4、将/etc/passwd中的第三个字段数值最大的后10个用户的信息全部改为大写后保存至/tmp/maxusers.txt文件中。
    5、取出当前主机的IP地址,提示:对ifconfig命令的结果进行切分。
    6、列出/etc目录下所有以.conf结尾的文件的文件名,并将其名字转换为大写后保存至/tmp/etc.conf文件中。
    7、显示/var目录下一级子目录或文件的总个数。
    8、取出/etc/group文件中第三个字段数值最小的10个组的名字。
    9、将/etc/fstab和/etc/issue文件的内容合并为同一个内容后保存至/tmp/etc.test文件中。
    10、请总结描述用户和组管理类命令的使用方法并完成以下练习:
    (1)、创建组distro,其GID为2016;
    (2)、创建用户mandriva, 其ID号为1005;基本组为distro;
    (3)、创建用户mageia,其ID号为1100,家目录为/home/linux;
    (4)、给用户mageia添加密码,密码为mageedu;
    (5)、删除mandriva,但保留其家目录;
    (6)、创建用户slackware,其ID号为2002,基本组为distro,附加组peguin;
    (7)、修改slackware的默认shell为/bin/tcsh;
    (8)、为用户slackware新增附加组admins;

    Linux干货 2017-12-19
  • 常用命令总结

    ifconfig查看IP地址 date查看日期和时间 cd跳转到任何目录 useradd新建一个普通用户 passwd给用户设置密码 poweroff   halt    关机 reboot  重启 cal  查看日历 cal -y 查看一年日历 env  export&nbsp…

    Linux干货 2017-04-04
  • cp和ln命令简述

    cp和软ln命令简述 cp          备注: 1.       该命令可以自动判断你所复制的是文件还是目录 2.       当源是一个文件,目标(目的…

    2017-08-19
  • 通过view实现智能DNS

    DNS策略解析最基本的功能是可以智能的判断访问您网站的用户,然后根据不同的访问者把您的域名分别解析成不同的IP地址,然后跟DNS服务器内部的IP表匹配一下,看看用户的类型,然后给用户返回对应的IP地址。

    Linux干货 2017-10-03
  • linxu通配符

    通配符 globbing globbing:文件名通配(整体文件名匹配,而非部分) 匹配模式:元字符 *:匹配任意长度的任意字符 ab*:ab开头的单词 *ab*:包含ab的单词 *ab:ab结尾的单词 *a*b*:包含a、b的单词 ?:匹配任意单个字符 ab?:ab开头的三个字符的单词 ??ab:ab结尾四个字符的单词 a?b:a开头、b结尾三个字符的单词…

    Linux干货 2018-03-11