tomcat 的启动文件 start.sh shell脚本详解
前些天,花了一些时间整理linux shell编程。看了一些简单的语法后,觉得还是不够深刻。想着,是不是可以直接查看一些开源软件的启动脚本快速提升shell编写能力。
下面来看看tomcat bin目录下的 start.sh 文件到底在做什么呢?
源码解析
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -----------------------------------------------------------------------------
# Start Script for the CATALINA Server
# -----------------------------------------------------------------------------
# Better OS/400 detection: see Bugzilla 31132
os400=false
case "`uname`" in
OS400*) os400=true;;
esac
# resolve links - $0 may be a softlink
PRG="$0"
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
上述为第一段代码块:默认设置变量os400=false
,接着判断系统是不是属于OS400
,如果uname
的结果为OS400
开头的字符串,那么会匹配上 OS400*
,并且 赋值os400=true
。
第二段代码块:设定执行的脚本名称为PRG
,比如执行start.sh
脚本的时候,如果执行的命令是/tomcat/bin/start.sh
,那么PRG=/tomcat/bin/start.sh
;如果执行命令为:./bin/start.sh
,那么PRG=bin/start.sh
;
第三段代码块: 通过一个while
循环判断"$PRG"
的路径是不是一个链接,如果是一个链接,那么找到其链接源,直到"$PRG"
不是一个链接时,循环结束;代码中while
循环条件-h
是判断"$PRG"
是否为链接,如果是链接进入循环,否则跳出循环;循环内ls -ld "$PRG"
是获取"$PRG"
脚本路径的目录。通过正则expr
来匹配'.*-> \(.*\)$'
,若匹配上,则是链接,否则为非链接。匹配结果重定向至/dev/null
,这个文件可以理解为一个大窟窿,多大的文件都能吃掉。若匹配上,匹配结果重新赋值给PRG
,PRG="$link"
。若没有匹配上,那么赋值执行文件的完整路径给PRG
。正常的链接文件,会有下面的特殊格式:
[root@test-cdh bin]# ll /usr/bin/python3
lrwxrwxrwx 1 root root 38 10月 25 2017 /usr/bin/python3 -> /usr/local/python3/install/bin/python3
PRGDIR=`dirname "$PRG"`
EXECUTABLE=catalina.sh
# Check that target executable exists
if $os400; then
# -x will Only work on the os400 if the files are:
# 1. owned by the user
# 2. owned by the PRIMARY group of the user
# this will not work if the user belongs in secondary groups
eval
else
if [ ! -x "$PRGDIR"/"$EXECUTABLE" ]; then
echo "Cannot find $PRGDIR/$EXECUTABLE"
echo "The file is absent or does not have execute permission"
echo "This file is needed to run this program"
exit 1
fi
fi
exec "$PRGDIR"/"$EXECUTABLE" start "$@"
上述代码块,第一段代码块:获取本脚本的真实执行目录赋值给PRGDIR
,定义变量EXECUTABLE
。当$os400
为真时,执行eval
命令;为假时,判断"$PRGDIR"/"$EXECUTABLE"
文件是否为可执行/存在的文件,若不是可执行/存在文件,给出echo
提示;若是存在的可执行文件,那么执行命令:"$PRGDIR"/"$EXECUTABLE" start "$@"
。比如我执行的start.sh
的脚本的完整路径(非链接)为:/tomcat/bin/start.sh
,并且命令后传参为arg1 arg2 arg3
,那么上述命令实际为:/tomcat/bin/start.sh catalina.sh arg1 arg2 arg3
。 $@
同$*
都是表示列表中的所有参数。
注:eval
后的接一个命令参数,如果后面的参数是一个变量,那么会将变量转换成其真实命令。如下:
[root@host2 ~]# f="head -n 10 install.log"
[root@host2 ~]# echo $f
head -n 10 install.log
[root@host2 ~]# eval $f
Installing libgcc-4.4.7-4.el6.x86_64
warning: libgcc-4.4.7-4.el6.x86_64: Header V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY
Installing fontpackages-filesystem-1.41-1.1.el6.noarch
Installing m17n-db-1.5.5-1.1.el6.noarch
Installing setup-2.8.14-20.el6_4.1.noarch
Installing xml-common-0.6.3-32.el6.noarch
Installing filesystem-2.4.30-3.el6.x86_64
Installing kernel-headers-2.6.32-431.el6.x86_64
Installing iso-codes-3.16-2.el6.noarch
Installing xkeyboard-config-2.6-6.el6.noarch
上述echo $f
能将变量替换成真实命令,而eval $f
先将变量翻译成命令head -n 10 install.log
,而后执行该命令结果。eval
对其后的命令进行了二次扫描。
上述最后一行代码exec "$PRGDIR"/"$EXECUTABLE" start "$@"
的exec
命令也有讲究。exec
执行其后的命令时,会关闭当前进程,建立一个新进程。此进程比较特殊,此进程的pid与被关闭的进程pid是同一个pi,所以看上去并不会产生新的进程。同时,若exec后的命令执行后,则退出当前进程。如下:
[root@host2 ~]# cat demo.sh
#!/bin/bash
f="head -n 10 install.log"
exec echo "execute illegal command:"
exec ls_nocommand
exec eval $f
[root@host2 ~]# ./demo.sh
execute illegal command:
exec
执行命令成功后,后续的命令并未执行
[root@host2 ~]# cat demo.sh
#!/bin/bash
f="head -n 10 install.log"
echo "execute illegal command:"
exec ls_nocommand
exec eval $f
[root@host2 ~]# ./demo.sh
execute illegal command:
./demo.sh: line 5: exec: ls_nocommand: not found
exec
执行命令成功后,后续的命令并未执行
更多推荐
所有评论(0)