标准化您的 UNIX 命令行工具( 四 )


 --comment|-c) OPT_COMMENT=$2;shift 2;;
 esac
done
OPTS=""
if [ -n "$OPT_$HOMEDIR" ]
then
OPTS="$OPTS -d $OPT_HOMEDIR"
fi
if [ -n "$GROUP" ]
then
OPTS="$OPTS -g $OPT_GROUP"
fi
if [ -n "$OPT_GROUPS" ]
then
OPTS="$OPTS -G $OPT_GROUPS"
fi
if [ -n "$OPT_SHELL" ]
then
OPTS="$OPTS -s $OPT_SHELL"
fi
if [ -n "$OPT_UID" ]
then
OPTS="$OPTS -u $OPT_UID"
fi
if [ -n "$OPT_COMMENT" ]
then
OPTS="$OPTS -c "$OPT_COMMENT""
fi
if [ -n "$OPT_NOUNIQUE" ]
then
OPTS="$OPTS -o"
fi
CMD=adduser
UNAME=`uname`
case $UNAME in
Solaris) CMD=useradd;break;;
esac
$CMD $OPTS $*
该脚本的关键是 foreach 循环,它遍历所提供的命令行参数(在 $* 中提供) 。对于每个选项,case 语句会尝试识别该选项——使用短格式或长格式并设置一个变量 。命令行开关为 $1 。如果该选项后面正常地跟着一个值(例如,用户 ID),您可以将 $2 当作该值来进行访问,并使用它将该值赋于某个变量 。
识别出某个选项后,shift 语句从 $* 变量列表中移动一个位置(若指定了数字,则移动指定数目的位置),以便已经识别出的命令行参数在循环的下一次迭代中不再在 $* 变量中 。
识别并提取出可能的参数以后,您所需做的就是构建新的选项来提供给最终要使用的命令 。由于 useradd/adduser 都支持短格式的参数,所以可在此基础上构建新的命令选项字符串 。这是通过检查对应的变量是否已设置并将该选项添加到命令行来实现的 。请注意双引号的使用,它确保了原始命令中引用的参数被保留并得到正确识别 。
将该脚本安装在支持任一种原始命令的平台上以后,您现在可以添加用户并指定所要的选项,包括对参数进行混合和匹配(请参见清单 9) 。
清单 9. 添加用户
$ adduser.sh --homedir /etc -g wheel --shell /bin/bash -c "New user" mcbrown
同样的基本原理也可以用于构建其他命令的包装,甚至更改参数名称和选项,或者提供等效的表达式 。
如果希望用原始名称安装该脚本——例如,adduser——并将其放在某个目录中(例如,/usr/local/compat),您必须确保该目录在 PATH 中出现在实际命令的目录之前 。下面是假设将兼容性脚本放在 /usr/local/compat 目录中的一个例子:$ PATH=/usr/local/compat:$PATH 。
使用单个源
无论您是使用多个脚本还是单个配置脚本/别名来支持统一的环境,您也许都希望使用单独一组脚本来支持系统 。因此,设置新系统以使用标准化脚本(无论它们是独立脚本还是安装外壳函数和别名)非常简单,只需将它们复制到新系统即可 。
通过使用命令行工具和外壳流控制(如 if 或 case)的组合,您可以使用单个源来选择各种要使用的选项 。有两个工具在这种情况下很有用:一个工具识别主机(如 hostname 或 uname),另一个工具识别平台 (uname) 。
uname 产生的缺省输出是基本操作系统名称,如 Linux 或 Solaris 。例如,可以按照前一部分中的 ps 示例,将该命令与 case 语句结合使用以选择正确的别名,如清单 10 所示 。
清单 10. uname 的输出
UNAME='uname'
case "$UNAME" in
FreeBSD|NetBSD|Darwin)
alias ps='ps -o pid,ppid,command'
break
;;
Solaris|Linux)
alias ps='ps -o pid,ppid,cmd'
break
;;
esac
也可以在脚本中使用同样的基本过程来选择特定的序列 。
在使用内联外壳函数时,与在每次使用函数时才做出决定相比,使用类似如此的包装来选择正确的函数定义通常更容易,因为这样做会更加高效 。

推荐阅读