使用 Shell 编写自动部署脚本的一些技巧
写了很久的 Shell 脚本,但总感觉自己写的东西各种 Low,就决定去读一读大佬写的东西。花了一周时间读了各种各样的 Shell 脚本,读完之后觉得大佬们各种牛批,就打算找个地方记一记。
传入参数处理
使用
$#
接受执行 shell 脚本时后置的参数,当传入二级参数时,依靠 shift 让参数或协议左移继续处理,直至处理完成。while [[ $# > 0 ]];do
key="$1"
case $key in
-p|--proxy)
PROXY="-x ${2}"
shift
;;
-h|--help)
HELP="1"
;;
-f|--force)
FORCE="1"
;;
-c|--check)
CHECK="1"
;;
--remove)
REMOVE="1"
;;
--version)
VERSION="$2"
shift
;;
-l|--local)
LOCAL="$2"
LOCAL_INSTALL="1"
shift
;;
--source)
DIST_SRC="$2"
shift
;;
--errifuptodate)
ERROR_IF_UPTODATE="1"
;;
*)
# unknown option
;;
esac
shift
done
定义入口函数
Shell 脚本运行时,在不同的机器有不同的效果,比如有的是从上往下执行,有的是短作业优先执行,如果没有定义函数,会造成执行的顺序错乱。
main(){
#helping information
[[ "$HELP" == "1" ]] && Help && return
[[ "$CHECK" == "1" ]] && checkUpdate && return
[[ "$REMOVE" == "1" ]] && remove && return
}
main
单个参数启动的简化写法
processName=PROCESSNAME
process=PROCESS
appDirectory=/usr/local/bin
logfile=/usr/local/bin/process.log
errfile=/usr/local/bin/process.error
start() {
echo 'Starting '${processName}'...'
cd ${appDirectory}
nohup ./$process >>$logfile 2>>$errfile &
sleep 1
}
stop() {
echo 'Stopping '${processName}'...'
pid=$(/usr/sbin/pidof ${process})
kill ${pid}
sleep 1
}
status() {
pid=$(/usr/sbin/pidof ${process})
if [[ "$pid" != "" ]]; then
echo ${processName}' is running...'
else
echo ${processName}' is not running...'
fi
}
case $1 in
start|stop|status) "$1" ;;
esac
多彩提示
Linux 自定义终端输出彩色信息非常繁琐,因此可以预定义一些色彩信息,通过函数传值简化写法。
RED="31m" # Error message
GREEN="32m" # Success message
YELLOW="33m" # Warning message
BLUE="36m" # Info message
colorEcho(){
COLOR=$1
echo -e "\033[${COLOR}${@:2}\033[0m"
}
colorEcho ${RED} "Failed to download! Please check your network or try again."
帮助信息
之前看别人写的帮助信息格式各种牛批,读了一些脚本之后发现原来全靠空格对齐…
Help(){
echo "./install-release.sh [-h] [-c] [--remove] [-p proxy] [-f] [--version vx.y.z] [-l file]"
echo " -h, --help Show help"
echo " -p, --proxy To download through a proxy server, use -p socks5://127.0.0.1:1080 or -p http://127.0.0.1:1082 etc"
echo " -f, --force Force install"
echo " --version Install a particular version, use --version v3.15"
echo " -l, --local Install from a local file"
echo " --remove Remove installed Version"
echo " -c, --check Check for update"
return 0
}
返回值定义
和 C 相反, Shell 成功返回的 True 为 0,False 为 1 ,因此约定俗成的返回值应该是这样的:
# If not specify, default meaning of return value:
# 0: Success
# 1: System error
# 2: Application error
# 3: Network error
判断系统架构
在不同的系统架构里编译出来的C++程序,性能也是千奇百怪。在需要编译操作的脚本里,判断系统架构比判断包管理重要。
sysArch(){
ARCH=$(uname -m)
if [[ "$ARCH" == "i686" ]] || [[ "$ARCH" == "i386" ]]; then
VDIS="32"
elif [[ "$ARCH" == *"armv7"* ]] || [[ "$ARCH" == "armv6l" ]]; then
VDIS="arm"
elif [[ "$ARCH" == *"armv8"* ]] || [[ "$ARCH" == "aarch64" ]]; then
VDIS="arm64"
elif [[ "$ARCH" == *"mips64le"* ]]; then
VDIS="mips64le"
elif [[ "$ARCH" == *"mips64"* ]]; then
VDIS="mips64"
elif [[ "$ARCH" == *"mipsle"* ]]; then
VDIS="mipsle"
elif [[ "$ARCH" == *"mips"* ]]; then
VDIS="mips"
elif [[ "$ARCH" == *"s390x"* ]]; then
VDIS="s390x"
elif [[ "$ARCH" == "ppc64le" ]]; then
VDIS="ppc64le"
elif [[ "$ARCH" == "ppc64" ]]; then
VDIS="ppc64"
fi
return 0
}
判断包管理系统
刚刚开始写 Shell 的时候,一直以为要先判断系统然后再决定包管理,结果每次写 Shell 判断系统的部分写了一大段,直到最近我学会了如下这种技巧。
getPMT(){
if [[ -n `command -v apt-get` ]];then
CMD_INSTALL="apt-get -y -qq install"
CMD_UPDATE="apt-get -qq update"
elif [[ -n `command -v yum` ]]; then
CMD_INSTALL="yum -y -q install"
CMD_UPDATE="yum -q makecache"
elif [[ -n `command -v zypper` ]]; then
CMD_INSTALL="zypper -y install"
CMD_UPDATE="zypper ref"
else
return 1
fi
return 0
}
判断主机 IP 地址
主要依靠
curl
命令读取一些提供 IP 地址的网站。ip addr
这个命令通常只能获取到机子的内网 IP,因此依靠其他服务器进行判断会比较靠谱。get_ip() {
ip=$(curl -s https://ipinfo.io/ip)
[[ -z $ip ]] && ip=$(curl -s https://api.ip.sb/ip)
[[ -z $ip ]] && ip=$(curl -s https://api.ipify.org)
[[ -z $ip ]] && ip=$(curl -s https://ip.seeip.org)
[[ -z $ip ]] && ip=$(curl -s https://ifconfig.co/ip)
[[ -z $ip ]] && ip=$(curl -s https://api.myip.com | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}")
[[ -z $ip ]] && ip=$(curl -s icanhazip.com)
[[ -z $ip ]] && ip=$(curl -s myip.ipip.net | grep -oE "([0-9]{1,3}\.){3}[0-9]{1,3}")
}
暂停脚本
这里主要依靠 Linux 的 read 命令暂停程序执行。
pause() {
read -rsp "$(echo -e "回车键继续或 Ctrl + C 取消.")" -d $'\n'
echo
}
评论
发表评论