#!/bin/sh echo " =====关闭Java应用======" #######修改下面的 jar包 名######### PID=`lsof -i:6002| grep LISTEN |awk '{print $2}'` if [ $PID >> 0 ];then kill -9 $PID nohup java $JAVA_OPTS -jar -Xms1024m -Xmx2048m ./*.jar -Duser.timezone=Asia/Shanghai 2>&1 | rotatelogs /wasoft/logs/fmapp-%Y-%m-%d.out 43200 480 & else nohup java $JAVA_OPTS -jar -Xms1024m -Xmx2048m ./*.jar -Duser.timezone=Asia/Shanghai 2>&1 | rotatelogs /wasoft/logs/fmapp-%Y-%m-%d.out 43200 480 & fi tail -f log/basesc-by1.log
时间: 2024-04-18 19:26:34 浏览: 186
这段 Shell 脚本的作用是关闭一个 Java 应用,并重新启动它。具体步骤如下:
1. 首先,通过 lsof 命令找到监听在端口 6002 上的 Java 进程,并获取其进程 ID(PID)。
2. 如果 PID 大于 0,说明进程存在,使用 kill 命令强制终止该进程。
3. 然后,使用 nohup 命令启动一个新的 Java 进程,执行指定的 jar 文件,并设置 JVM 的内存参数(-Xms 和 -Xmx)以及时区参数(-Duser.timezone)。
4. 将 Java 进程的输出重定向到指定的日志文件,并使用 rotatelogs 工具按照一定时间间隔和文件大小进行日志切割。
5. 如果 PID 为 0,说明进程不存在,直接启动一个新的 Java 进程。
最后,使用 tail 命令实时查看日志文件 `log/basesc-by1.log` 的内容。
请注意,这是一段示例代码,具体使用时需要根据实际情况修改相关配置和文件路径。
相关问题
#!/bin/sh ## java env #export JAVA_HOME=/data/jdk1.8.0_121 #export JRE_HOME=$JAVA_HOME/jre ## service name #当前目录 NOW_PATH=$(cd `dirname $0`; pwd) #jar包路径 JAR_DIR=`ls -ltr $NOW_PATH/*.jar| tail -1` #jar包名字 JAR_NAME=${JAR_DIR##*/} #日志名字 LOG_NAME=${JAR_NAME%%.*} PID=$LOG_NAME\.pid #PS3="Select you will exec Menu:" #select i in start stop restart #do case $1 in start) nohup java -Xms256m -Xmx1024m -jar $JAR_NAME > logs/$LOG_NAME.log 2>&1 & echo $! > $NOW_PATH/$PID echo "=== start $JAR_NAME" tail -1000f logs/$LOG_NAME.log ;; stop) echo "=== stop $JAR_NAME" ps -ef|grep $JAR_NAME |grep -v grep |awk '{print $2}'|xargs kill -9 ;; restart) $0 stop sleep 2 $0 start echo "=== restart $LOG_NAME" ;; *) echo "Usage:$0 {start|stop|restart|help}" ;; esac exit 0 #done
<think>嗯,用户想了解如何通过shell脚本管理Java应用程序的启动、停止和重启。我需要结合提供的引用内容,整理出一个清晰的步骤说明。
首先,启动部分。根据引用[3],使用nohup命令在后台运行Java程序,指定JVM参数和配置文件,输出重定向到日志文件。需要确定jar包的位置和名称,可能还需要处理找到最新jar的问题,如引用[1]提到的自动查找最新jar。这部分可能需要用到ls命令按时间排序,取第一个结果。
然后是停止功能。需要先获取应用的进程ID,可以用ps和grep组合命令找到对应的Java进程,再用kill命令终止。要注意避免误杀其他进程,可能需要更精确的匹配,比如jar包名称。
重启的话,其实就是先执行停止,再启动。但要确保停止完成后再启动,可能需要添加等待时间,或者检查进程是否真的终止。
另外,脚本需要接受参数,比如start、stop、restart,可以用case语句处理不同的命令。引用[2]的示例中使用了这种方法,应该参考这个结构。
还要考虑日志文件的处理,比如输出到指定位置,或者使用nohup防止终端关闭后进程终止。引用[3]中的nohup用法是正确的,需要包含进去。
可能还需要设置JVM内存参数,如-Xms和-Xmx,用户的应用可能有不同的需求,所以脚本中应该留出变量位置,方便修改。
安全问题也要注意,比如确保脚本有执行权限,使用绝对路径避免依赖当前目录。引用[1]提到自动查找当前目录的最新jar,但用户可能需要指定固定路径,或者根据实际情况调整。
最后,测试脚本的各种情况,比如重复启动是否处理正确,停止时没有进程是否存在错误,重启是否平滑等。可能需要添加错误处理,比如进程不存在时给出提示。
总结下来,脚本的大致结构是:定义变量(如JAVA_HOME, JAR_NAME, JVM_OPTS),根据参数执行不同操作,启动时找jar包并后台运行,停止时杀进程,重启组合两者。同时给出使用示例和注意事项,如权限、日志管理等。</think>### 如何通过Shell脚本管理Java应用程序
#### 一、脚本核心功能设计
1. **启动应用**
- 使用`nohup`命令在后台运行Java进程,避免终端关闭导致服务中断
- 自动定位JAR文件(支持指定固定路径或动态获取最新文件)
- 设置JVM参数(如内存分配:`-Xms256m -Xmx3024m`)
- 指定Spring配置文件(如`--spring.profiles.active=prod`)
- 日志重定向到文件(如`> app.log 2>&1`)[^3]
2. **停止应用**
- 通过`ps -ef | grep java`查找进程ID(PID)
- 使用`kill -9`强制终止进程(需精确匹配JAR名称避免误杀)[^2]
3. **重启应用**
- 先执行停止逻辑,等待1秒后启动新进程
- 添加进程状态检查确保操作完整性
#### 二、完整脚本示例
```bash
#!/bin/bash
APP_NAME="projectname.jar" # 指定JAR包名称
JAVA_HOME="/app/jdk1.8.0_92/bin/java" # JDK路径
JVM_OPTS="-Xms256m -Xmx3024m" # JVM参数
SPRING_PROFILE="--spring.profiles.active=prod" # 环境配置
case $1 in
start)
nohup $JAVA_HOME -jar $JVM_OPTS $APP_NAME $SPRING_PROFILE > app.log 2>&1 &
echo "Application started"
;;
stop)
PID=$(ps -ef | grep $APP_NAME | grep -v grep | awk '{print $2}')
if [ -n "$PID" ]; then
kill -9 $PID
echo "Application stopped"
else
echo "Application not running"
fi
;;
restart)
$0 stop
sleep 1
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
```
#### 三、关键操作说明
1. **自动查找最新JAR(扩展功能)**
在引用[1]的基础上添加动态查找逻辑:
```bash
# 获取当前目录最新JAR文件
LATEST_JAR=$(ls -t *.jar | head -1)
nohup java -jar $LATEST_JAR > output.log &
```
2. **进程管理强化**
- 精确过滤进程:`grep '[p]attern'`避免误匹配
- 添加状态检查命令:
```bash
status)
PID=$(pgrep -f $APP_NAME)
[ -n "$PID" ] && echo "Running (PID: $PID)" || echo "Not running"
;;
```
#### 四、使用示例
```bash
# 赋予执行权限
chmod +x app_manager.sh
# 启动应用
./app_manager.sh start
# 停止应用
./app_manager.sh stop
# 重启应用
./app_manager.sh restart
```
#### 五、注意事项
1. 确保脚本与JAR文件路径一致(或配置绝对路径)
2. 生产环境建议添加日志轮转机制(如`logrotate`)
3. 内存参数需根据服务器配置调整,避免OOM错误[^3]
4. 复杂场景可增加启动超时检测和健康检查
#!/bin/sh #LANG=zh_CN.UTF-8 #export LANG DEPLOY_DIR=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd); CONF_DIR=$DEPLOY_DIR/config LIB_DIR=$DEPLOY_DIR/lib LOGS_DIR=$DEPLOY_DIR/logs JAVA_OPTS=" -server -Xms8G -Xmx8G -Xss256K -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:+DisableExplicitGC -XX:+PrintGCDetails -Xloggc:$LOGS_DIR/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$LOGS_DIR/trade.dump -Djava.net.preferIPv4Stack=true" LIB_JARS=`ls $LIB_DIR | grep .jar | awk '{print "'$LIB_DIR'/"$0}' | tr "\n" ":"` # 不同配置文件放到 config 目录后,指定 spring.config.name 为文件名即可,不要配置文件后缀 nohup java $JAVA_OPTS -Dlog4j.configurationFile=config/logback-spring.xml -Dspring.config.name=application -classpath $CONF_DIR:$LIB_JARS com.camelgames.ssh.Application >/dev/null 2>&1 & echo $! >pid为什么通过sh start.sh执行没有反应
<think>嗯,用户遇到了一个问题,执行sh start.sh后没有反应,需要分析可能的原因。首先,我需要仔细看看用户提供的脚本内容,找出可能的问题所在。用户之前的问题是关于修改目录权限的,现在这个脚本是一个启动Java应用的shell脚本,可能涉及环境变量、路径设置、Java配置等问题。
首先,脚本的开头是#!/bin/sh,但里面用了${BASH_SOURCE[0]},而sh通常是指向dash或者其他更基本的shell,可能不支持BASH_SOURCE变量,这会导致DEPLOY_DIR获取不正确。比如,在/bin/sh环境下,BASH_SOURCE可能未定义,导致路径错误,进而影响后续的目录设置,如CONF_DIR、LIB_DIR等,导致java命令找不到必要的jar包或配置文件,从而启动失败。
然后,检查LANG的设置,用户注释掉了LANG=zh_CN.UTF-8和export LANG,这可能导致脚本在执行过程中出现编码问题,尤其是当路径或文件名包含非ASCII字符时,但可能不是主要问题,但需要留意。
接下来,JAVA_OPTS设置了一大堆参数,包括内存设置、GC参数、日志路径等。需要确认这些参数是否正确,特别是日志目录LOGS_DIR是否存在,是否有写入权限。如果LOGS_DIR不存在,java命令可能会因为无法创建日志文件而启动失败,但错误输出被重定向到/dev/null,导致用户看不到错误信息。
LIB_JARS的生成部分,使用了ls和awk来拼接所有jar文件的路径,用冒号分隔。这里如果LIB_DIR路径不正确,或者目录中没有jar文件,会导致类路径为空,java无法找到主类,从而启动失败。另外,tr命令用来替换换行符为冒号,是否正确处理了所有jar文件需要确认。
nohup命令将输出重定向到/dev/null,并且后台执行,最后将进程ID写入pid文件。用户执行sh start.sh后,脚本会立即返回,但可能Java进程在启动过程中遇到错误而退出,但用户看不到任何输出,因为stdout和stderr都被丢弃了。此外,使用sh而不是bash可能导致脚本中的某些语法不被支持,比如BASH_SOURCE。
可能的解决方案包括:将脚本的shebang改为#!/bin/bash,确保使用bash来执行;检查DEPLOY_DIR是否正确获取;确认所有目录是否存在,是否有权限;检查Java命令是否存在,版本是否合适;查看nohup.out文件是否有错误信息;或者去掉输出重定向,暂时保留输出以便调试。此外,检查是否有重复的配置,比如log4j和logback的配置是否有冲突,或者Spring的配置文件是否正确。
另外,用户可能没有执行权限,需要chmod +x start.sh,或者使用bash start.sh来执行。还有,检查是否已经有一个进程在运行,端口被占用,导致应用无法启动。或者查看生成的pid文件中的进程ID是否有效,是否还在运行。
总结可能的原因:1. shebang使用了sh导致BASH_SOURCE不可用;2. 路径变量错误导致找不到jar或配置文件;3. 日志目录无法写入;4. Java参数错误;5. 类路径生成错误;6. 输出被重定向导致看不到错误信息。</think>以下是对该启动脚本问题的详细分析及解决方案:
**一、基础诊断步骤**
```bash
# 检查脚本执行权限
ls -l start.sh # 确认有x权限(若无则执行 chmod +x start.sh)
# 查看实时输出(临时移除重定向)
nohup java ... 2>&1 | tee nohup.out # 替换原nohup行
```
**二、关键问题定位**
1. **Shell解释器不兼容**
```bash
#!/bin/sh → #!/bin/bash # 必须修改!原脚本使用Bash特有语法
```
- ${BASH_SOURCE[0]} 在标准sh中不可用,会导致`DEPLOY_DIR`路径获取错误
2. **路径设置隐患**
```bash
# 增加路径验证
echo "DEPLOY_DIR: $DEPLOY_DIR" # 插入调试语句
test -d "$LIB_DIR" || echo "LIB目录不存在!" # 目录存在性检查
```
3. **类路径生成缺陷**
```bash
# 改进的类路径生成方式
LIB_JARS=$(find "$LIB_DIR" -name '*.jar' -printf '%p:' | sed 's/:$//')
```
- 原`ls+grep+awk`组合对含空格文件名处理不安全
**三、增强型启动脚本修正**
```bash
#!/bin/bash # 关键修改点!
DEPLOY_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# 增加目录初始化
mkdir -p "$LOGS_DIR" # 自动创建日志目录
# 增加环境检查
command -v java >/dev/null 2>&1 || { echo "Java未安装!"; exit 1; }
# 改进的启动命令
nohup java $JAVA_OPTS \
-Dspring.config.location=file:"$CONF_DIR/application.properties" \
-cp "$CONF_DIR:$LIB_JARS" \
com.camelgames.ssh.Application > "$LOGS_DIR/console.out" 2>&1 &
# 增加启动状态检测
sleep 3
if ps -p $! >/dev/null; then
echo $! > pid
echo "启动成功,PID: $!"
else
echo "启动失败!查看日志:$LOGS_DIR/console.out"
exit 1
fi
```
**四、补充检查清单**
1. **Java环境验证**
```bash
java -version # 确认版本符合要求
ulimit -n # 检查文件句柄数(建议>4096)
```
2. **配置文件验证**
```bash
ls -l "$CONF_DIR" # 检查application.properties是否存在
cat "$CONF_DIR/logback-spring.xml" # 检查日志配置有效性
```
3. **内存分配检查**
```bash
free -h # 确认8G内存分配合理
# 物理内存不足会导致OOM Killer终止进程
```
**五、高级调试技巧**
```bash
# 使用远程调试模式(临时添加参数)
JAVA_OPTS+=" -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
# 生成线程Dump
kill -3 <PID> # 输出到日志文件
```
建议按照以下顺序排查:
1. 修正shebang为`#!/bin/bash`
2. 执行`bash -x start.sh`查看详细执行流程
3. 检查`logs/console.out`中的错误信息
4. 验证Java进程是否存活`ps -ef | grep com.camelgames.ssh.Application`
阅读全文
相关推荐

















