导读: 笔者编写了一个用于控制 Java JAR 在 Linux 服务器上启动、停止、查询当前状态的 bash 简单脚本,分享出来希望对各位在熟悉 bash 命令时有所帮助。本文分为以下三个部分
- 脚本概述
- 脚本代码
- 部分 shell 命令解析
脚本概述
admin.sh 脚本中定义了以下四个方法:
- usage() 操作提示
- start() 启动
- stop() 停止
- status() 状态查询
// 在使用 脚本 前需先授权,这里赋予最高权限
chmod 777 脚本名
// 启动脚本
./admin.sh start
脚本会根据传入的 $1 参数判断要执行的操作。例如传入 start 后会执行启动逻辑:读取 boot.pid 文件获取旧的 pid 并查看相应进程是否在运行中,无运行则执行启动命令并将新的 pid 写入到 boot.pid 文件中。stop 逻辑则是先判断对应 pid 的进程是否存在,存在则 kill 掉。
脚本代码
#!/bin/bash
# 获取脚本所在的路径,jar 包与执行脚本在同一个路径下,即等于获取到了 jar 包所在路径
BOOTPATH=$(cd `dirname $0`; pwd)
BOOTPID=${BOOTPATH}/boot.pid
BOOTLOG=${BOOTPATH}/boot.log
APPNAME="spider-0.0.1-SNAPSHOT"
JAR_FILE=${APPNAME}".jar"
# 输出操作提示
function usage() {
echo - e "n Usage: $0 (start|stop|status)n"
exit -1
}
# 启动方法
function start
{
oldpid="`cat $BOOTPID`"
# 通过 pid 查看程序是否在运行中
if test `ps aux | grep -v grep | grep $oldpid | grep $APPNAME | wc -l` -gt 0
then
echo "Failed to start $APPNAME ($APPNAME already running)"
else
ulimit -n 262140
# 执行启动命令(配置文件托管在 apollo 中的启动方式)
nohup java -Denv=pro -jar $JAR_FILE &
# 判断是否启动成功
if [ $? -ne 0 ]
then
echo "Failed to start $APPNAME"
echo "Failed to start $APPNAME" >>${BOOTLOG}
else
# $! 获取 Shell 最后运行的后台Process 的 PID,
pid="$!";
# 将新的 pid 重定向输出到 boot.pid 文件中覆盖旧的 pid 进行持久化存储
echo "$pid" > $BOOTPID
# 日志追加输出
echo "start ... ">>${BOOTLOG}
echo "pid is $pid">>${BOOTLOG}
echo "status is $?">>${BOOTLOG}
fi
fi
}
# 停止方法
function stop
{
oldpid="`cat $BOOTPID`"
echo "oldpid is $oldpid">>${BOOTLOG}
if test `ps aux | grep -v grep | grep $oldpid | grep $APPNAME | wc -l` -gt 0
then
kill $oldpid
sleep 5
fi
# 判断是否停止成功
if [ $? -ne 0 ]
then
echo "Failed to stop $APPNAME"
fi
}
# 查看运行状态
function status
{
pid="`cat $BOOTPID`"
ps aux | grep $pid | grep $APPNAME | grep -v grep >>${BOOTLOG} 2>&1
if [ $? -eq 0 ]
then
echo "$APPNAME is running"
else
echo "$APPNAME is not running"
fi
}
# 如果输出的参数小于 1 则输出提示
if [ $# -lt 1 ]; then
usage
fi
# 进入到 jar 包所在路径
cd $BOOTPATH
# 根据输入的参数执行对应的操作
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
exit 0
;;
*)
usage
;;
esac
# 打印当前状态
status
部分 shell 命令解析
1、 #!/ bin/bash
脚本开头使用 #!/bin/bash,用于指定此脚本使用/bin/bash来解释执行。shell 是一个命令语言解释器,我们在提示符下输入的每个命令都由 shell 先解释然后传给Linux内核, bash 是大多数 Linux 系统的缺省 shell。
2、$() 和 ` `
$() 和 ` ` 反引号都是 用来做命令替换。会先完成它们里面的命令行,然后将其结果输出
[ root @localhost ~]# echo today is $(date "+%Y-%m-%d")
today is 2021-10-19
3、bash 脚本中的 $X
在 bash 脚本中 $ 后跟随着不同的 X 有不同的含义:
- $$ :Shell本身的PID(ProcessID)
- $! :Shell最后运行的后台Process的PID
- $? :最后运行的命令的结束代码(返回值,退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败返回 1)
- $- :使用Set命令设定的Flag一览
- $* :所有参数列表。如”$*”用「”」括起来的情况、以”$1 $2 … $n”的形式输出所有参数。
- $@ :所有参数列表。如”$@”用「”」括起来的情况、以”$1″ “$2” … “$n” 的形式输出所有参数。
- $# :添加到Shell的参数个数
- $0 :Shell本身的文件名
- $1~$n :添加到Shell的各参数值。$1是第1参数、$2是第2参数
注: 这里就是我们实现 $1 入参,指定选择什么操作的具体实现方式
// 脚本中编写
echo $1
// 执行脚本时传入参数
./test.sh start
// 这样脚本中输出 $1 会被替换为 start
4、echo 用法
- -e:处理特殊参数
- -n:不换行输出
echo hello // 输出到屏幕
echo hello > tmp.txt // 输出重定向,如果 tmp .txt 存在则覆盖,不存在则创建
echo hello >> tmp.txt // 输出追加重定向,如果 tmp.txt 存在则进行内容追加,不存在则创建
5、$(cd `dirname $0`; pwd)
这句比较有意思。其单独在命令行输出是毫无意义的,在脚本文件中才有作用,它返回的是这个脚本文件所在的目录。这里我们可以把脚本和我们的 jar 包放在同一目录下,这样就可以用这句获取到 jar 包所在的目录了。
- dirname $0 取得当前执行的脚本文件的父目录
- cd `dirname $0` 进入这个目录
- pwd 显示当前的工作目录
7、逻辑表达式在 bash 中的对应表示(通过理解英文名比较容易记住)
- 大于 -gt (greater than)
- 小于 -lt (less than)
- 大于或等于 -ge (greater than or equal)
- 小于或等于 -le (less than or equal)
- 不相等 -ne (not equal)
8、ll 查看权限
首列中 10 个字符用于表示不同用户能对文件干什么,三四列为用户与用户所在的组
- 第一个字符代表文件(-)、目录(d),链接(l)
- 其余字符每3个一组(rwx),读(r)、写(w)、执行(x)
- 第一组rwx:文件所有者的权限是读、写和执行
- 第二组rw-:与文件所有者同一组的用户的权限是读、写但不能执行
- 第三组r–:不与文件所有者同组的其他用户的权限是读不能写和执行
9、chmod 权限控制
如要执行 admin.sh 脚本,我们需先通过 chmod 进行授权。
chmod 777 脚本名 // 赋予最高权限
- -rw——- (600) — 只有读写权限
- -rw-r–r– (644) — 只有有读写权限;而属组用户和其他用户只有读权限
- -rwx—— (700) — 只有读、写、执行权限
- -rwxr-xr-x (755) — 有读、写、执行权限;而属组用户和其他用户只有读、执行权限
- -rwx–x–x (711) — 有读、写、执行权限;而属组用户和其他用户只有执行权限。
10、 grep 管道用法
- |grep firefox 过滤关键字
- |grep firefox |wc -l 关键字统计
- |grep firefox |grep firefox test 多重过滤
- |grep -v grep 去除包含 grep 的进程行 ,使结果更为准确
最后
感谢您的阅读,如果喜欢本文欢迎关注和转发,转载需注明出处,本头条号将持续分享IT技术知识。对于文章内容有其他想法或意见建议等,欢迎提出共同讨论共同进步。