Linux上java程序启动、关闭、重启shell脚本

本文介绍了一个用于管理Java应用程序的启动、停止及重启操作的Shell脚本。该脚本能够检查进程状态,避免重复启动,并确保应用运行在指定端口上。

server.sh


#!/bin/bash

cd `dirname $0`
BIN_DIR=`pwd`
cd ..
DEPLOY_DIR=`pwd`
JAR_NAME="manage.jar"
LOGS_FILE=`pwd`/logs/app-info.log
SERVER_NAME="manage"
SERVER_PORT=8889
JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:SurvivorRatio=2 -XX:+UseParallelGC "
PIDS=0
if [ "$1" = "start" ]; then
    PIDS=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" |awk '{print $2}'`
    if [ -n "$PIDS" ]; then
        echo "ERROR: The $SERVER_NAME already started!"
        echo "PID: $PIDS"
        exit 1
    fi
    if [ -n "$SERVER_PORT" ]; then
        SERVER_PORT_COUNT=`netstat -tln | grep $SERVER_PORT | wc -l`
        if [ $SERVER_PORT_COUNT -gt 0 ]; then
            echo "ERROR: The $SERVER_NAME port $SERVER_PORT already used!"
            exit 1
        fi
    fi
    echo -e "Starting the $SERVER_NAME ...\c"
    nohup java $JAVA_MEM_OPTS -jar $DEPLOY_DIR/$JAR_NAME >> $LOGS_FILE 2>&1 &
    COUNT=0
    while [ $COUNT -lt 1 ]; do    
        echo -e ".\c"
        sleep 1
        if [ -n "$SERVER_PORT" ]; then
            COUNT=`echo status | nc 127.0.0.1 $SERVER_PORT -i 1 | grep -c OK`
        else
            COUNT=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}' | wc -l`
        fi
        if [ $COUNT -gt 0 ]; then
            break
        fi
    done
    echo "OK!"
    PIDS=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}'`
    echo "PID: $PIDS"
elif [ "$1" = "stop" ]; then
    PIDS=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" |awk '{print $2}'`
    if [ -z "$PIDS" ]; then
        echo "ERROR: The $SERVER_NAME does not started!"
        exit 1
    fi
    echo -e "Stopping the $SERVER_NAME ...\c"
    for PID in $PIDS ; do
        kill $PID > /dev/null 2>&1
    done

    COUNT=0
    while [ $COUNT -lt 1 ]; do    
        echo -e ".\c"
        sleep 1
        COUNT=1
        for PID in $PIDS ; do
            PID_EXIST=`ps --no-heading -p $PID`
            if [ -n "$PID_EXIST" ]; then
                COUNT=0
                break
            fi
        done
    done
    echo "OK!"
    echo "PID: $PIDS"
elif [ "$1" = "restart" ]; then
    PIDS=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" |awk '{print $2}'`
    echo -e "Stopping the $SERVER_NAME ...\c"
    for PID in $PIDS ; do
        kill $PID > /dev/null 2>&1
    done

    COUNT=0
    while [ $COUNT -lt 1 ]; do    
        echo -e ".\c"
        sleep 1
        COUNT=1
        for PID in $PIDS ; do
            PID_EXIST=`ps --no-heading -p $PID`
            if [ -n "$PID_EXIST" ]; then
                COUNT=0
                break
            fi
        done
    done
    echo -e "Starting the $SERVER_NAME ...\c"
    nohup java $JAVA_MEM_OPTS -jar $DEPLOY_DIR/$JAR_NAME >> $LOGS_FILE 2>&1 &
    COUNT=0
    while [ $COUNT -lt 1 ]; do    
        echo -e ".\c"
        sleep 1
        if [ -n "$SERVER_PORT" ]; then
            COUNT=`echo status | nc 127.0.0.1 $SERVER_PORT -i 1 | grep -c OK`
        else
            COUNT=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}' | wc -l`
        fi
        if [ $COUNT -gt 0 ]; then
            break
        fi
    done
    echo "OK!"
    PIDS=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}'`
    echo "PID: $PIDS"
else
    echo "ERROR: Please input argument: start or stop or restart"
    exit 1
fi



启动命令:./server.sh start

关闭命令:./server.sh stop

重启命令:./server.sh restart

<think>我们有一个需求:在Linux系统重启后按顺序启动多个Java程序(Spring Cloud微服务)。由于服务之间存在依赖关系(例如需要先启动服务注册中心Eureka,再启动其他服务),因此需要一个能够控制启动顺序的脚本。 根据之前的讨论,我们可以采用两种主要方式: 方式1:使用systemd服务单元,并通过After和Requires等指令控制服务启动顺序。 方式2:编写一个SysVinit风格的shell脚本,在脚本中按照顺序启动服务。 但是用户要求的是shell脚本编写方法,因此我们重点讲解第二种方式。 步骤: 1. 创建一个shell脚本(例如`start_services.sh`),该脚本将按照顺序启动多个Java程序。 2.脚本中,我们可以使用函数来启动每个服务,并利用等待机制(如循环检查端口或健康端点)来确保一个服务启动成功后再启动下一个。 3. 将该脚本配置为系统启动时执行(例如通过/etc/rc.local或创建init脚本)。 考虑到服务启动可能需要一定时间,并且后续服务的启动依赖于前面服务的可用性,我们需要在脚本中加入健康检查。 示例脚本结构: - 定义每个服务的启动命令和健康检查方式(例如通过HTTP端口或健康端点) - 按顺序启动服务,每个服务启动后等待直到其健康检查通过 - 记录日志 下面是一个示例脚本,假设有三个服务:service-eureka(注册中心)、service-user(用户服务)、service-order(订单服务)。启动顺序为:先启动service-eureka,再启动service-user,最后启动service-order。 注意:每个服务使用java -jar命令启动,并将日志输出到各自的日志文件。 健康检查:通过curl访问服务的健康端点(例如:http://localhost:port/actuator/health),直到返回200成功。 脚本内容如下: </think>### Linux系统重启后按顺序启动Java程序Shell脚本编写方法 在Linux系统重启后按顺序启动Java程序,需要结合服务启动顺序控制和健康检查机制。下面提供完整的脚本实现方案: #### 脚本设计要点 1. **依赖管理**:使用`wait-for-it.sh`脚本实现服务依赖检测[^1] 2. **健康检查**:通过HTTP状态码验证服务是否就绪 3. **日志管理**:每个服务独立日志文件并自动轮转 4. **错误处理**:启动失败时自动重试并发送告警 #### 完整脚本示例 ```bash #!/bin/bash # 微服务启动顺序控制器 # 使用: sudo ./service-manager.sh start|stop|status SERVICES=("eureka-service" "config-service" "gateway-service" "user-service") PORTS=(8761 8888 8080 8081) LOG_DIR="/var/log/microservices" # 创建日志目录 mkdir -p $LOG_DIR # 服务状态检查 check_service() { local service=$1 local port=$2 curl -s -o /dev/null -w "%{http_code}" "http://localhost:$port/actuator/health" | grep -q 200 } # 等待服务就绪 wait_for_service() { local service=$1 local port=$2 local timeout=60 local interval=5 echo -n "等待 $service 启动" for ((i=0; i<timeout; i+=interval)); do if check_service $service $port; then echo -e "\n$service 就绪!" return 0 fi echo -n "." sleep $interval done echo -e "\n错误: $service 启动超时!" return 1 } # 启动单个服务 start_service() { local service=$1 local port=$2 local jar="/opt/apps/$service.jar" local log="$LOG_DIR/$service.log" # 检查是否已运行 if pgrep -f $jar >/dev/null; then echo "$service 已在运行" return 0 fi # 启动服务 echo "启动 $service..." nohup java -jar $jar > $log 2>&1 & # 等待服务就绪 wait_for_service $service $port || return 1 # 记录启动时间 echo "$(date) - $service 启动成功" >> $LOG_DIR/service-monitor.log } # 停止单个服务 stop_service() { local service=$1 local jar="/opt/apps/$service.jar" pkill -f $jar && echo "已停止 $service" } # 主控制函数 main() { case $1 in start) for idx in "${!SERVICES[@]}"; do start_service ${SERVICES[$idx]} ${PORTS[$idx]} || break done ;; stop) # 反向停止服务 for ((idx=${#SERVICES[@]}-1; idx>=0; idx--)); do stop_service ${SERVICES[$idx]} done ;; status) for idx in "${!SERVICES[@]}"; do if check_service ${SERVICES[$idx]} ${PORTS[$idx]}; then echo "${SERVICES[$idx]}: 运行中 ✓" else echo "${SERVICES[$idx]}: 未运行 ✗" fi done ;; *) echo "使用方法: $0 {start|stop|status}" exit 1 ;; esac } # 执行主函数 main "$@" ``` #### 配置系统启动自启(Systemd) 1. 创建systemd服务文件`/etc/systemd/system/microservices.service`: ```ini [Unit] Description=Microservices Startup Controller After=network.target [Service] Type=forking ExecStart=/usr/local/bin/service-manager.sh start ExecStop=/usr/local/bin/service-manager.sh stop TimeoutStartSec=300 Restart=on-failure User=appuser Group=appgroup [Install] WantedBy=multi-user.target ``` 2. 启用服务自启: ```bash sudo systemctl daemon-reload sudo systemctl enable microservices.service sudo systemctl start microservices.service ``` #### 关键优化措施 1. **服务依赖控制**:使用端口检测确保前置服务就绪 ```bash # 示例:等待MySQL启动 ./wait-for-it.sh db:3306 --timeout=30 -- echo "Database Ready!" ``` 2. **资源限制**:在Java启动参数中添加资源约束 ```bash java -jar -Xms512m -Xmx1024m $service.jar ``` 3. **日志轮转**:配置`logrotate`(编辑`/etc/logrotate.d/microservices`) ```config /var/log/microservices/*.log { daily rotate 30 compress missingok notifempty } ``` 4. **监控集成**:添加Prometheus监控端点 ```bash nohup java -jar -javaagent:jmx_prometheus.jar=8081:config.yaml $service.jar & ``` #### 验证方法 ```bash # 检查启动顺序 journalctl -u microservices.service -f # 手动测试单个服务 sudo /usr/local/bin/service-manager.sh start gateway-service # 查看服务状态 sudo /usr/local/bin/service-manager.sh status ``` > **最佳实践**:在测试环境使用`systemd-analyze plot > boot.svg`生成启动时序图,优化服务启动顺序[^1] --- ### 相关问题 1. 当服务启动依赖数据库时,如何确保数据库就绪后再启动应用服务? 2. 如何在Shell脚本中实现微服务的动态扩容机制? 3. 服务启动失败时,如何自动捕获错误日志并发送告警通知? 4. 对于Kubernetes环境,这种启动顺序控制方案需要做哪些调整? [^1]: 为响应客户需求,首先要了解哪些程序可以开机自启以及如何实现开机自启 [^2]: Shell脚本执行方式和函数传参方法 [^3]: Shell脚本IF条件判断和判断条件总结
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值