Linux知识之--函数

函数

systemV风格的服务管理脚本

例子

给脚本传递一些参数:start, stop, restart, status

myservice.sh

#!/bin/bash

#

lockfile="/var/lock/subsys/$(basename$0)"

case $1 in

start)

if[ -f $lockfile ] ; then

echo"服务已经启动...."

else

touch$lockfile

echo"服务正在启动...."

fi

;;

stop)

if[ -f $lockfile ] ; then

rm-f $lockfile

echo"服务已经停止...."

else

echo"服务尚未启动..."

fi

;;

restart)

if[ -f $lockfile ] ; then

rm-f $lockfile

echo"服务已经停止...."

else

echo"服务尚未启动..."

fi

if[ -f $lockfile ] ; then

echo"服务已经启动...."

else

touch$lockfile

echo"服务正在启动...."

fi

;;

status)

if[ -f $lockfile ] ; then

echo"服务已经启动...."

else

echo"服务已经停止...."

fi

;;

*)

echo"Usage: $(basename $0) start|stop|restart|status"

exit5

;;

esac

把那些在脚本中重复出现并且没有任何改变的代码,封装起来,在适当的场景下调用执行

程序员将这种被封装起来的代码称为功能体,或叫模块。

function--函数

在shell脚本编程中,函数是由若干条shell命令组成的语句块,通常用于代码重用和模块化封装。

函数里面的内容和shell程序形式上是一致的,不同之处,shell代码可以直接被执行,而函数中的内容,不能直独立执行,只有被调用的时候才运行。

函数是在shell程序的当前shell中运行的

定义函数:

函数是由两部分组成的,一部分是函数名,一部分是函数体(能够实现独立功能的shell语句块)

语法1

function func_name{

函数体

}

语法2

func_name(){

函数体

}

注意:函数名和()之间不能加空白字符。

注意:函数可以在交互式环境下定义,也可以在脚本中定义。

函数的使用:

函数在定义的时候,其函数体中包含的所有命令均不会被执行。只有函数被调用的时候才会执行其中的命令语句。

调用方式:

通过直接给出函数名称的方式调用

有很多的函数是存放于专门用于保存函数的文件中。如果想要调用这样的文件中保存的函数,使用source命令(.)加载文件,然后再以直接给出函数名称的方式调用函数。

使用set命令可以查看当前shell中生效的函数。使用unset命令可以撤销已经定义的函数。

函数的返回值:

两种返回值:

函数执行结果的返回值

1.在函数体中使用了echo或printf命令输出的结果

2.在函数体中的某些命令输出的结果

函数的状态返回值

1.函数中最后一条命令的执行状态返回值

2.自定义退出状态码

return [n]

n:0-255 (1 2 127尽可能不用)

0 表示无错误返回

1-255 有错误返回

注意:只要函数在执行时,遇到return命令,不管函数中的命令语句是否全部执行完成,立刻退出函数。

函数的生命周期:

从被调用的那一刻开始,到遇到return命令或者全部的语句执行完成为止。

函数的实参

在函数体中,可以使用$1,$2...位置变量为函数提供参数,还可以使用$*或者[email protected]的方式引用所有位置参数,还可以使用$#计算为函数传递的参数的个数。

在调用函数的时候,直接在函数名称后面以空白字符分隔多个参数即可,比如:fuc_name arg1 arg2...

传递给函数参数的位置参数是调用函数的时候,函数名称后面的以空白字符分隔的字符串的序列,跟脚本的位置参数不是一回事。

变量:

shell中的变量为弱变量

1.无需事先声明

2.无需指定变量类型,默认为字符型

变量分类:

环境变量

当前shell和子shell

本地变量

当前shell

局部变量

当前函数体

local VAR_NAME=VALUE

位置变量

特殊变量

建议:手动撤销自己定义或声明的所有变量

函数的递归调用:

简单来说,就是在函数体中调用函数自身

阶乘:

N!=N*(N-1)!=N*(N-1)*(N-2)!=...=N*(N-1)*(N-2)*...*2*1

shell代码:

#!/bin/bash

# Author: Tianyu.Zhao

#

fact(){

if[ $1 -eq 0 ] || [ $1 -eq 1 ] ; then

echo 1

else

echo "$[$1*$(fact $[$1-1])]"

fi

}

echo -n "$1!="

fact $1

斐波那契数列(黄金分隔数列):

11 2 3 5 8 13 21 34 55 ...

假设兔子出生一个月之后才会有繁殖能力:

N=N-1+ N-2

shell代码:

#!/bin/bash

# Author: Tianyu.Zhao

#

fabonacci(){

if[ $1 -eq 1 ] ; then

echo 1

elif [ $1 -eq 2 ] ; then

echo 1

else

echo $[$(fabonacci $[$1-1])+$(fabonacci $[$1-2])]

fi

}

#列出所有的斐波那契数列的项

for I in `seq 0 $1` ; do

fabonacci $I

done

汉诺塔(又称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。

利用函数,实现N片盘的汉诺塔的移动步骤

#!/bin/bash

# Author: Tianyu.Zhao

#

step=0

move(){

let step++

echo "$step:  move disk $1 $2 -----> $3"

}

hanoi(){

if [ $1 -eq 1 ];then

move $1 $2 $4

else

hanoi "$[$1-1]" $2 $4 $3

move $1 $2 $4

hanoi "$[$1-1]" $3 $2 $4

fi

}

hanoi $1 A B C

文件abc.txt的内容如下:

2,3,4,5,6

B,c,d,e,f

6,7,8,9,10

f,g,h,i,j

写一个脚本,利用任一循环结构,输出每一行的第二个和第四个字符(以逗号分隔)

练习:

写一个脚本:

1.允许用户通过命令行传递参数,实现用户账户的管理;

2.如果给出-a|--add选项,就创建该选项后面的用户账户;

3.如果给出-d|--del选项,就删除该选项后面的用户账户;

4.如果用户给出-v|--verbose选项,就显示删除或创建用户的信息;

5.如果用户给出-h|--help选项,就显示帮助信息,并且以0作为退出状态码退出脚本的运行;

6.如果用户给出其他选项,显示帮助信息,并以5作为退出状态码鬼畜脚本的运行;

#!/bin/bash

#Author: Link

#Description: administrate users

#5: no enough args

#6: error args

#

DEBUG=0

ADDUSER=0

DEUSER=0

usage(){

echo"Usage: $(basename $0) -a|--add user1,user2,... | -d|--del user1,user2,...| [-v|-verbose] | [-h|--help]"

echo

echo "Options: "

echo -e "  -a, --add\vCreateuser from list."

echo -e "  -d, --del\vDeleteuser from list."

echo -e "  -v,--verbose\vDisplay infomation for your operating."

echo -e "  -h,--help\vDisplay this menu."

}

createuser() {

ADDUSER_LIST=$(echo$1 | tr ‘,‘ ‘ ‘)

forI in $ADDUSER_LIST ; do

ifid $I &> /dev/null ; then

[$DEBUG -eq 1 ] && echo "$I exists."

else

useradd$I &> /dev/null

echo$I | passwd --stdin $I &> /dev/null

[$DEBUG -eq 1 ] && echo "Create $I successfully."

fi

done

}

deleteuser() {

DELUSER_LIST=$(echo$1 | tr ‘,‘ ‘ ‘)

forJ in $DELUSER_LIST ; do

ifid $J &> /dev/null ; then

userdel-r $J &> /dev/null

[$DEBUG -eq 1 ] && echo "Delete $J finished."

else

[$DEBUG -eq 1 ] && echo "$I not exists."

fi

done

}

if [ $# -le 0 ] ; then

usage

exit5

fi

while [ $# -ne 0 ] ; do

case$1 in

-h|--help)

usage

exit

;;

-v|--verbose)

DEBUG=1

shift

;;

-a|--add)

ADDUSER=1

ALIST=$2

shift2

;;

-d|--del)

DELUSER=1

DLIST=$2

shift2

;;

*)

usage

exit6

;;

esac

done

if [ $ADDUSER -eq 1 ] ; then

createuser$ALIST

fi

if [ $DELUSER -eq 1 ] ; then

deleteuser$DLIST

fi

总结:

写一个脚本的步骤:

1.构建程序主体

默认是顺序执行结构

根据需求添加相应的选择结构和循环结构

2.确定完成某功能所需的命令

3.调试(bash -x/PATH/TO/SCRIPT_FILE)

4.写明帮助信息

时间: 2024-08-09 02:05:29

Linux知识之--函数的相关文章

linux中fork()函数详解[zz]

转载自:http://www.cnblogs.com/york-hust/archive/2012/11/23/2784534.html 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事. 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间.然后把原来的进程的所有值都复制到新的新进程中,只有

对于linux下system()函数的深度理解(整理)

对于linux下system()函数的深度理解(整理) (2013-02-07 08:58:54) 这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为是其他的代码影响到这个,或是内核驱动文件系统什么的异常导致,昨天有出现了这个问题,就随手百了一下度,问题出现了,很多人都说system()函数要慎用要少用要能不用则不用,system()函数不稳定?

Linux下Kill函数用法

http://www.cnblogs.com/winnxm/archive/2010/01/22/1654502.html [ KILL ]功能描述: 用于向任何进程组或进程发送信号. 1 #include <sys/types.h> 2 3 #include <signal.h> 4 5 int kill(pid_t pid, int sig); 6 7 参数: pid:可能选择有以下四种 1. pid大于零时,pid是信号欲送往的进程的标识. 2. pid等于零时,信号将送往所

【C/C++】Linux下system()函数引发的错误

http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食  恋恋美食 发布时间: 2012/04/21 11:33 阅读: 11393 收藏: 21 点赞: 8 评论: 4 今天,一个运行了近一年的程序突然挂掉了,问题定位到是system()函数出的问题,关于该函数的简单使用在我上篇文章做过介绍: http://my.oschina.net/renhc/blog/53580 先看一下问题 简单封装了一下sys

Linux知识:/root/.bashrc与/etc/profile的异同

Linux知识:/root/.bashrc与/etc/profile的异同 要搞清bashrc与profile的区别,首先要弄明白什么是交互式shell和非交互式shell,什么是login shell 和non-login shell. 交互式模式就是shell等待你的输入,并且执行你提交的命令.这种模式被称作交互式是因为shell与用户进行交互.这种模式也是大多数用户非常熟悉的:登录.执行一些命令.签退.当你签退后,shell也终止了. shell也可以运行在另外一种模式:非交互式模式.在这

linux关于readlink函数获取运行路径的小程序

摘自:http://blog.csdn.net/djzhao/article/details/8178375 linux关于readlink函数获取运行路径的小程序 相关函数: stat, lstat, symlink表头文件: #include <unistd.h>定义函数:int  readlink(const  char *path,  char *buf, size_t  bufsiz);函数说明:readlink()会将参数path的符号连接内容到参数buf所指的内存空间,返回的内容

linux shell自定义函数(定义、返回值、变量作用域)介绍

http://www.jb51.net/article/33899.htm linux shell自定义函数(定义.返回值.变量作用域)介绍 linux shell 可以用户定义函数,然后在shell脚本中可以随便调用.下面说说它的定义方法,以及调用需要注意那些事项. 一.定义shell函数(define function) 语法: [ function ] funname [()] { action; [return int;] } 说明: 1.可以带function fun() 定义,也可以

【Linux知识】服务器性能测试--UnixBench

链接地址: http://blog.csdn.net/jason_asia/article/details/38309079 1.1.   服务器性能测试UnixBench 分别在DELL R720和DELL R610作为测试的服务器,因服务器配置不同,结果仅供参考. 下载: wget http://byte-unixbench.googlecode.com/files/UnixBench5.1.3.tgz 安装: tar zxf UnixBench5.1.3.tgz cd UnixBench

linux中时间函数

linux下常用时间类型有四种: time_t . struct   tm. struct  timeval .    struct   timespec 1.time_t   时间函数 time_t  类型在time.h中定义: #ifndef   __TIME__T #define  __TIME_T typedef    long  time_t #endif 可见, time_t 实际上是一个长整型,其值表示从1970年1月1日00时00分00秒(linux系统的Epoch时间)到当前时