1、运行脚本
脚本如下,这个脚本存在一点问题,Log4j稍微有点问题,但是对运行及日志记录没有影响,日志是通过将所有控制台数据全部写入文件的形式记录的。
#!/bin/sh
#author:wangchengwei
#date:2015-7-7
#desc:Run java application
#Java的安装目录
JAVA_HOME=/usr/lib/java-1.7.0
#运行程序所使用的用户
OWNER=root
#Java程序的目录
APP_HOME=/software/TaxiData/SocketDxpTaxi
#Main方法的类
APP_MAINCLASS=com.tiamaes.gjds.socket.server.MinaServer
#日志文件
LOG_FILE=$APP_HOME/logs/socket.log
#设置CLASSPATH
CLASSPATH=$CLASSPATH:$APP_HOME/SocketDxpTaxi.jar
#循环将lib文件夹下所有的jar添加到CLASSPATH
for i in "$APP_HOME"/lib/*.jar; do
CLASSPATH="$CLASSPATH":"$i"
done
#设置运行参数
JAVA_OPTS="-Xms512m -Xmx512m -Xmn256m -Djava.awt.headless=true -XX:MaxPermSize=128m"
#echo $CLASSPATH;
psid=0
#检查Java程序是否运行
checkpid(){
javaps=`$JAVA_HOME/bin/jps -l | grep $APP_MAINCLASS`
if [ -n "$javaps" ];then
psid=`echo $javaps | awk ‘{print $1}‘`
else
psid=0
fi
}
#运行程序
start(){
checkpid
if [ $psid -ne 0 ];then
echo "WARN:$APP_MAINCLASS already started!(pid=$psid)"
else
echo "Starting $APP_MAINCLASS..."
JAVA_CMD="nohup $JAVA_HOME/bin/java $JAVA_OPTS -classpath $CLASSPATH $APP_MAINCLASS >> $LOG_FILE 2>&1 &"
su - $OWNER -c "$JAVA_CMD"
checkpid
if [ $psid -ne 0 ];then
echo "Started $APP_MAINCLASS (pid=$psid)[OK]"
else
echo "Started $APP_MAINCLASS [FAILED]"
fi
fi
}
#停止程序
stop(){
checkpid
if [ $psid -ne 0 ];then
echo "Stoping $APP_MAINCLASS...(pid=$psid)"
su - $OWNER -c "kill $psid"
checkpid
if [ $psid -ne 0 ];then
echo "Stoping use kill -9"
su - $OWNER -c "kill -9 $psid"
fi
checkpid
if [ $psid -eq 0 ];then
echo "Stoped $APP_MAINCLASS [OK]"
else
echo "Stoped $APP_MAINCLASS [Failed]"
stop
fi
else
echo "WARN:$APP_MAINCLASS is not runing"
fi
}
#查看状态
status(){
checkpid
if [ $psid -ne 0 ];then
echo "$APP_MAINCLASS is runing (pid=$psid)"
else
echo "$APP_MAINCLASS is not runing"
fi
}
#帮助信息
info() {
echo "System Information:"
echo "****************************"
echo `head -n 1 /etc/issue`
echo `uname -a`
echo
echo "JAVA_HOME=$JAVA_HOME"
echo `$JAVA_HOME/bin/java -version`
echo
echo "APP_HOME=$APP_HOME"
echo "APP_MAINCLASS=$APP_MAINCLASS"
echo "****************************"
}
#$1表示接收第一个参数,如 ./run.sh start 。则$1就是start
case "$1" in
‘start‘)
start
;;
‘stop‘)
stop
;;
‘restart‘)
stop
start
;;
‘info‘)
info
;;
‘status‘)
status
;;
*)
echo "Usage: $0 {start|stop|restart|status|info}"
exit 1
esac
exit 0;
2、知识点解析
shell的基础知识不在赘述,自己百度学习。重点说下几个点。
2.1、运行jar
JAVA_OPTS="-Xms512m -Xmx512m -Xmn256m -Djava.awt.headless=true -XX:MaxPermSize=128m"
# java $JAVA_OPTS -classpath $CLASSPATH $APP_MAINCLASS
Java在运行jar是可以设置Java的运行参数、classpath等选项。
Java运行参数主要是内存的设置
-Xms:初始Heap大小,使用的最小内存,cpu性能高时此值应设的大一些
-Xmx:java heap最大值,使用的最大内存
-XX:PermSize:设定内存的永久保存区域
-XX:MaxPermSize:设定最大内存的永久保存区域
-Xmn:young generation的heap大小,一般设置为Xmx的3、4分之一
classpath用于设置jar运行是所依赖jar
2.2、Java中的jps命令
jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。
比较常用的参数:
-q 只显示pid,不显示class名称,jar文件名和传递给main 方法的参数
-m 输出传递给main 方法的参数,在嵌入式jvm上可能是null
-m 输出传递给main 方法的参数,在嵌入式jvm上可能是null
-l 输出应用程序main class的完整package名 或者 应用程序的jar文件完整路径名
-v 输出传递给JVM的参数
在本例中我们使用的是jps -l,使用 jps -l | grep $APP_MAINCLASS 可以根据Main方法所在的类名查看进程中是否有我们的程序。然后通过awk得到进程的pid。
2.3、su命令的使用
su - $OWNER -c "$JAVA_CMD"
上面的命令表示使用 $OWNER用户执行命令,-c后面跟命令。这样做的好处就是执行的时候是带有用户的环境变量的,而且能保证我们的应用在我们指定的用户下运行。
2.4、nohup
用途:不挂断地运行命令,说的见简单点就是让程序能够在后台运行。
语法:nohup Command [ Arg … ] [ & ]
描述:nohup 命令运行由 Command 参数和任何相关的 Arg 参数指定的命令,忽略所有挂断(SIGHUP)信号。在注销后使用 nohup 命令运行后台中的程序。要运行后台中的 nohup 命令,添加 & ( 表示”and”的符号)到命令的尾部。
无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。如果标准错误是一个终端,那么把指定的命令写给标准错误的所有输出作为标准输出重定向到相同的文件描述符
意思就是让我们的Java程序在后台运行,并且将程序产生的日志记录到$LOG_FILE中,>表示写入(先清除内容再写入内容),>>表示追加
2>&1的含义
对于& 1 更准确的说应该是文件描述符 1,而1 一般代表的就是STDOUT_FILENO,实际上这个操作就是一个dup2(2)调用.他标准输出到all_result ,然后复制标准输出到文件描述符2(STDERR_FILENO),其后果就是文件描述符1和2指向同一个文件表项,也可以说错误的输出被合并了.其中0 表示键盘输入 1表示屏幕输出 2表示错误输出.把标准出错重定向到标准输出,然后扔到/DEV/NULL下面去。通俗的说,就是把所有标准输出和标准出错都扔到垃圾桶里面。
2>&1 是将标准出错重定向到标准输出,这里的标准输出已经重定向到了$LOG_FILE文件,即将标准出错也输出到$LOG_FILE文件中