数以百万计的开发人员编写 shell 脚本来解决各种类型的任务。我使用 shell 脚本来简化部署、生命周期管理、安装或简单地用作胶水语言。
我注意到没有人真正关心 shell 脚本的样式和质量。许多团队花费大量时间来修复 Java、C++、... 样式问题,但完全忽略了他们的 shell 脚本中的问题。顺便说一句,通常没有标准的方法来在特定项目中实现 shell 脚本,因此人们可能会发现许多不同的、丑陋的和有缺陷的脚本,散布在代码库中。
为了在我的项目中克服这个问题,我决定创建一个通用且足够好的 shell 脚本模板。我将按原样提供我的模板,以使这个问题更有用。开箱即用的这些模板提供:
- 命令行参数处理
- 同步
- 一些基本的帮助
参数处理:getopts(最新版本:shell-script-template@github)
#!/bin/bash
# ------------------------------------------------------------------
# [Author] Title
# Description
# ------------------------------------------------------------------
VERSION=0.1.0
SUBJECT=some-unique-id
USAGE="Usage: command -ihv args"
# --- Options processing -------------------------------------------
if [ $# == 0 ] ; then
echo $USAGE
exit 1;
fi
while getopts ":i:vh" optname
do
case "$optname" in
"v")
echo "Version $VERSION"
exit 0;
;;
"i")
echo "-i argument: $OPTARG"
;;
"h")
echo $USAGE
exit 0;
;;
"?")
echo "Unknown option $OPTARG"
exit 0;
;;
":")
echo "No argument value for option $OPTARG"
exit 0;
;;
*)
echo "Unknown error while processing options"
exit 0;
;;
esac
done
shift $(($OPTIND - 1))
param1=$1
param2=$2
# --- Locks -------------------------------------------------------
LOCK_FILE=/tmp/$SUBJECT.lock
if [ -f "$LOCK_FILE" ]; then
echo "Script is already running"
exit
fi
trap "rm -f $LOCK_FILE" EXIT
touch $LOCK_FILE
# --- Body --------------------------------------------------------
# SCRIPT LOGIC GOES HERE
echo $param1
echo $param2
# -----------------------------------------------------------------
Shell Flags (shFlags) 允许大量简化命令行参数的处理,所以在某个时刻我决定不忽略这种可能性。
参数处理:shflags(最新版本:shell-script-template@github)
#!/bin/bash
# ------------------------------------------------------------------
# [Author] Title
# Description
#
# This script uses shFlags -- Advanced command-line flag
# library for Unix shell scripts.
# http://code.google.com/p/shflags/
#
# Dependency:
# http://shflags.googlecode.com/svn/trunk/source/1.0/src/shflags
# ------------------------------------------------------------------
VERSION=0.1.0
SUBJECT=some-unique-id
USAGE="Usage: command -hv args"
# --- Option processing --------------------------------------------
if [ $# == 0 ] ; then
echo $USAGE
exit 1;
fi
. ./shflags
DEFINE_string 'aparam' 'adefault' 'First parameter'
DEFINE_string 'bparam' 'bdefault' 'Second parameter'
# parse command line
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"
shift $(($OPTIND - 1))
param1=$1
param2=$2
# --- Locks -------------------------------------------------------
LOCK_FILE=/tmp/${SUBJECT}.lock
if [ -f "$LOCK_FILE" ]; then
echo "Script is already running"
exit
fi
trap "rm -f $LOCK_FILE" EXIT
touch $LOCK_FILE
# -- Body ---------------------------------------------------------
# SCRIPT LOGIC GOES HERE
echo "Param A: $FLAGS_aparam"
echo "Param B: $FLAGS_bparam"
echo $param1
echo $param2
# -----------------------------------------------------------------
我确实认为可以改进这些模板以进一步简化开发人员的生活。
所以问题是如何改进它们以具有以下特性:
- 内置日志记录
- 更好的错误处理
- 更好的便携性
- 占地面积更小
- 内置执行时间跟踪