当前位置: 首页 > news >正文

linux 脚本解释

if [ $? -ne 0 ]; then

echo "错误: 无法关闭现有 Tomcat 实例,终止启动流程!" >&2

exit 1

fi

  1. $? 是shell中的特殊变量,表示上一个命令的退出状态码
  2. -ne 0 表示"不等于0"(在Unix/Linux中,0通常表示成功,非0表示错误)
  3. 如果前一个命令执行失败(返回非0),则执行花括号内的内容:
    • 输出错误信息到标准错误输出(stderr)
    • 使用exit 1终止脚本执行并返回错误状态码1

--------------------------------------------------------------------------------------------------

if [ -z "$1" ]; then
echo "用法: $0 <TOMCAT_DIRECTORY>"
exit 1
fi

具体解释如下:

  1. if [ -z "$1" ] 检查第一个参数($1)是否为空字符串

    • -z 测试字符串长度是否为0
    • $1 表示脚本的第一个参数
  2. 如果参数为空(即用户没有提供参数),则:

    • 输出用法提示:echo "用法: $0 <TOMCAT_DIRECTORY>"
      • $0 表示当前脚本的名称
    • 以状态码1退出脚本:exit 1 (1通常表示错误退出)

---------------------------------------------------------------------------------------------------

TOMCAT_DIR="$1"
TIMEOUT=10
TOMCAT=$(basename "${TOMCAT_DIR}")
CURRENT_USER=$(whoami)

以下是详细解释:

  1. TOMCAT_DIR="$1"

    • 将脚本的第一个参数($1)赋值给变量TOMCAT_DIR
    • 这个参数应该是Tomcat的安装目录路径
  2. TIMEOUT=10

    • 设置超时时间为10秒
    • 用于后续等待Tomcat关闭的时间控制
  3. TOMCAT=$(basename "${TOMCAT_DIR}")

    • 使用basename命令从目录路径中提取最后一级目录名
    • 例如:如果TOMCAT_DIR/opt/apache-tomcat-9.0.45,则TOMCAT值为apache-tomcat-9.0.45
  4. CURRENT_USER=$(whoami)

    • 获取当前执行脚本的用户名
    • 用于后续的权限检查和日志记录

-------------------------------------------------------------------------------------------------------------

# 检查目录和脚本存在性
[ ! -d "${TOMCAT_DIR}" ] && echo "错误: 目录不存在" && exit 1
[ ! -x "${TOMCAT_DIR}/bin/shutdown.sh" ] && echo "错误: shutdown.sh 不可执行" && exit 1

# 获取 Tomcat 主进程 PID(精确匹配)
get_pids() {
ps -ef | grep "${TOMCAT}" | grep "org.apache.catalina.startup.Bootstrap" | grep -v grep | awk '{print $2}'
}

详细解释它们的功能和实现原理:

  1. 目录和脚本存在性检查部分:

    • [ ! -d "${TOMCAT_DIR}" ]:检查指定的Tomcat目录是否存在
      • -d测试目录是否存在
      • !表示逻辑非
    • [ ! -x "${TOMCAT_DIR}/bin/shutdown.sh" ]:检查shutdown.sh脚本是否存在且可执行
      • -x测试文件是否存在且可执行
    • 如果任一检查失败,会输出错误信息并以状态码1退出
  2. 获取Tomcat进程PID的函数:

    • ps -ef:列出所有进程的完整信息
    • grep "${TOMCAT}":过滤包含Tomcat目录名的进程
    • grep "org.apache.catalina.startup.Bootstrap":精确匹配Tomcat主类
    • grep -v grep:排除grep命令自身的进程
    • awk '{print $2}':提取第二列(即PID)
    • 这个函数通过多级过滤确保只获取真正的Tomcat主进程PID

----------------------------------------------------------------------------------------------------------------

# 初始检查进程
PIDS=$(get_pids)
if [ -z "${PIDS}" ]; then
echo "Tomcat 未运行,无需关闭"
exit 0
fi

echo "检测到 Tomcat 进程 (PID: ${PIDS})"

# 步骤1:尝试优雅关闭(忽略非关键错误,但记录)
echo "尝试优雅关闭..."
if ! ${TOMCAT_DIR}/bin/shutdown.sh; then
echo "警告: shutdown.sh 执行失败(可能权限不足)"
fi

# 等待优雅关闭
echo "等待 ${TIMEOUT} 秒..."
sleep ${TIMEOUT}

详细解析:

  1. 初始进程检查:

    • 调用get_pids函数获取Tomcat进程PID
    • 如果PID为空(-z测试),输出提示并正常退出(exit 0)
    • 否则显示检测到的进程PID
  2. 优雅关闭流程:

    • 首先尝试执行Tomcat的shutdown.sh脚本
    • 使用if ! command结构捕获执行失败情况
    • 即使失败也仅输出警告而不终止(因为后续还有强制关闭逻辑)
  3. 等待处理:

    • 使用sleep命令等待预设的TIMEOUT时间(之前定义为10秒)
    • 这是给Tomcat完成正常关闭流程的时间窗口

----------------------------------------------------------------------------------------------------------

# 步骤2:检查是否仍有进程
PIDS=$(get_pids)
if [ -n "${PIDS}" ]; then
echo "尝试正常终止进程 (PID: ${PIDS})"
# 逐个检查并终止进程,记录失败
for pid in ${PIDS}; do
# 检查进程所有者
PROCESS_OWNER=$(ps -o user= -p "${pid}" 2>/dev/null || echo "unknown")
echo "进程 ${pid} 所有者: ${PROCESS_OWNER}"

# 尝试终止进程
if ! kill "${pid}" 2>/dev/null; then
echo "错误: 无法终止进程 ${pid}(权限不足,当前用户 ${CURRENT_USER} 无法操作 ${PROCESS_OWNER} 的进程)"
exit 1  # 权限不足时立即报错退出
fi
done

    # 等待后再次检查
sleep 5
PIDS=$(get_pids)
if [ -n "${PIDS}" ]; then
echo "尝试强制终止进程 (PID: ${PIDS})"
for pid in ${PIDS}; do
if ! kill -9 "${pid}" 2>/dev/null; then
echo "错误: 无法强制终止进程 ${pid}(权限不足)"
exit 1  # 权限不足时立即报错退出
fi
done
fi
fi

# 最终检查
PIDS=$(get_pids)
if [ -z "${PIDS}" ]; then
echo "Tomcat 已成功关闭"
else
echo "错误: 仍有进程未关闭 (PID: ${PIDS})"
exit 1
fi

echo "========== 关闭完成 =========="
exit 0

详细解析:

  1. 进程二次检查:

    • 使用-n测试检查是否仍有存活的Tomcat进程
    • 如果有则进入强制终止流程
  2. 分级终止策略:

    • 先尝试普通kill命令(SIGTERM信号)
    • 检查每个进程的所有者(使用ps -o user= -p PID)
    • 对kill失败的情况立即报错退出(权限问题)
  3. 强制终止阶段:

    • 等待5秒后再次检查
    • 对仍然存活的进程使用kill -9(SIGKILL信号)
    • 同样处理权限错误情况
  4. 最终状态确认:

    • 最后一次检查进程状态
    • 根据结果输出成功/失败信息
    • 返回相应的退出状态码(0成功/1失败)

这个设计体现了完善的进程管理策略:

  • 分级处理(先优雅后强制)
  • 完善的错误检查和权限验证
  • 明确的进程状态跟踪
  • 清晰的执行反馈

代码中几个关键Shell技巧:

  • 2>/dev/null屏蔽错误输出
  • ps -o user=只输出用户名列
  • || echo "unknown"错误处理
  • 多级if [ -n/-z ]条件测试
http://www.dtcms.com/a/286130.html

相关文章:

  • 数据库防止数组字符串序列化
  • 后端参数校验
  • 20250718-FDU-HDUOJ钉耙编程一
  • 商汤将发布日日新6.5大模型及具身智能平台该咋看?
  • 五大开源OCR开源框架评估01-Tesseract:OCR 领域的远古巨神
  • 前端权限控制:深入理解与实现RBAC模型
  • Maven 配置文件核心配置:本地仓库、镜像与 JDK 版本
  • python学智能算法(二十四)|SVM-最优化几何距离的理解
  • Java并发编程痛点解析:从底层原理到实战解决方案
  • [3-02-03].第03章:编程模式 - 阻塞式编程与响应式编程对比
  • Python爬虫入门到实战(3)-对网页进行操作
  • 用AME获取免费SSL证书
  • 免费PDF文件格式转换工具
  • LeafletJS 与 React:构建现代地图应用
  • leetcode2_135.分发糖果
  • 信息安全性测试:渗透测试、漏洞扫描与代码审计全解析
  • 基于ECDH的隐私求交(PSI)技术发展历程
  • 进阶向:智能图像增强系统
  • 项目优化之开机自启动
  • kubernetes pod 深度解析
  • 持续同调文章阅读(四)
  • Selenium 攻略:从元素操作到 WebDriver 实战
  • 基于Spring Boot的农村农产品销售系统设计与实现
  • SGLang 推理框架深度解析:请求的调度与生命周期
  • 客户知识共享门户的核心价值:提升效率与客户体验
  • 网页的性能优化,以及具体的应用场景
  • 安卓页面卡顿测试方案详解
  • FLTK UI窗口关闭时延时卡顿问题全流程分析与优化实战
  • pip用国内的源 + Hugging Face 官方国内镜像
  • 基于华为openEuler系统安装DailyNotes个人笔记管理工具