如何将shell script功能模块化,并且对外留出函数和参数接口
如何将shell script功能模块化,并且对外留出函数和参数接口。要写出这种高质量的模块化的东西,需要对要写的这一块的业务非常理解,知道哪些是通用的,哪些是不通用的。从而将其分离,废话不多说直接看一个我感觉很牛B的脚本。
以下脚本的作用:
我新写了一个内核device driver模块,下面的脚本是尝试将我的模块,加载模块,在/dev目录下创建结点+++删除文件,卸载模块。
参数接口部分:
#!/bin/bash
# Sample init script for the a driver module <rubini@linux.it>
DEVICE="scull"
SECTION="misc"
# The list of filenames and minor numbers: $PREFIX is prefixed to all names
PREFIX="scull"
FILES=" 0 0 1 1 2 2 3 3 priv 16
pipe0 32 pipe1 33 pipe2 34 pipe3 35
single 48 uid 64 wuid 80"
INSMOD=/sbin/insmod; # use /sbin/modprobe if you prefer
function device_specific_post_load () {
true; # fill at will
}
function device_specific_pre_unload () {
true; # fill at will
}
具体介绍:
- DEVICE是加载的模块的名字。必须和在driver代码中注册的名字相同。
- FILES是加载的模块生成的文件参数。(文件名字后缀+minor_num)。
最虎的是:
留出了2个函数接口,让我们面向接口编程。
留出的2个接口是device_specific_post_load 和 device_specific_pre_unload分别是insmod加载之后想做什么?rmmod之后想做什么?这种面向接口编程主要是对实际应用的人考虑的比较周到。
下面这个是一些不轻易被用户改变的参数:
# Everything below this line should work unchanged for any char device.
# Obviously, however, no options on the command line: either in
# /etc/${DEVICE}.conf or /etc/modules.conf (if modprobe is used)
# Optional configuration file: format is
# owner <ownername>
# group <groupname>
# mode <modename>
# options <insmod options>
CFG=/etc/${DEVICE}.conf
# kernel version, used to look for modules
KERNEL=`uname -r`
#FIXME: it looks like there is no misc section. Where should it be?
MODDIR="/lib/modules/${KERNEL}/kernel/drivers/${SECTION}"
if [ ! -d $MODDIR ]; then MODDIR="/lib/modules/${KERNEL}/${SECTION}"; fi
# Root or die
if [ "$(id -u)" != "0" ]
then
echo "You must be root to load or unload kernel modules"
exit 1
fi
# Read configuration file
if [ -r $CFG ]; then
OWNER=`awk "\\$1==\"owner\" {print \\$2}" $CFG`
GROUP=`awk "\\$1==\"group\" {print \\$2}" $CFG`
MODE=`awk "\\$1==\"mode\" {print \\$2}" $CFG`
# The options string may include extra blanks or only blanks
OPTIONS=`sed -n '/^options / s/options //p' $CFG`
fi
主要包括取得config file里面的用户权限信息,检查用户是否为root用户。
# Create device files
function create_files () {
cd /dev
local devlist=""
local file
while true; do
if [ $# -lt 2 ]; then break; fi
file="${DEVICE}$1"
mknod $file c $MAJOR $2
devlist="$devlist $file"
shift 2
done
if [ -n "$OWNER" ]; then chown $OWNER $devlist; fi
if [ -n "$GROUP" ]; then chgrp $GROUP $devlist; fi
if [ -n "$MODE" ]; then chmod $MODE $devlist; fi
}
# Remove device files
function remove_files () {
cd /dev
local devlist="" //函数里的变量尽量使用local关键字声明,代表是一个局部变量
local file
while true; do
if [ $# -lt 2 ]; then break; fi
file="${DEVICE}$1"
devlist="$devlist $file"
shift 2
done
rm -f $devlist
}
# Load and create files
function load_device () {
if [ -f $MODDIR/$DEVICE.o ]; then
devpath=$MODDIR/$DEVICE.o
else if [ -f ./$DEVICE.o ]; then
devpath=./$DEVICE.o
else
devpath=$DEVICE; # let insmod/modprobe guess
fi; fi
if [ "$devpath" != "$DEVICE" ]; then
echo -n " (loading file $devpath)"
fi
if $INSMOD $devpath $OPTIONS; then
MAJOR=`awk "\\$2==\"$DEVICE\" {print \\$1}" /proc/devices`
remove_files $FILES
create_files $FILES
device_specific_post_load
else
echo " FAILED!"
fi
}
# Unload and remove files
function unload_device () {
device_specific_pre_unload
/sbin/rmmod $DEVICE
remove_files $FILES
}
上面的4个是函数。create_files, remove_files, load_device, unload_device
下面的就是case语句进行选择运行了。
case "$1" in
start)
echo -n "Loading $DEVICE"
load_device
echo "."
;;
stop)
echo -n "Unloading $DEVICE"
unload_device
echo "."
;;
force-reload|restart)
echo -n "Reloading $DEVICE"
unload_device
load_device
echo "."
;;
*)
echo "Usage: $0 {start|stop|restart|force-reload}"
exit 1
esac
exit 0