技術共有

Centos環境の起動/再起動Javaサービススクリプトの最適化

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

オフライン環境にデプロイされた複数の Java アプリケーションで構成されるシステムは、リソースの制約により、テスト段階でより頻繁にリリースする必要があるため、devops や CICD セットは存在せず、リリース用に単純に jar にパッケージ化されます。以前に起動するスクリプトを使用しました。起動する前に、受信したポートに従ってプロセスを強制終了する必要があります。そうしないと、ポートの競合が発生し、起動が失敗します。最適化ポイントの 1 つは、スクリプトの自動再起動をサポートすることです。対応するプロセスを自動的に見つけて強制終了し、再起動します。もう 1 つの点は、ログ ファイルです。再起動後、ログをクエリするときに、サービス名と現在時刻に基づいて新しいログ ファイルが生成されます。複数のプレフィックスを持つファイルがある場合、それらを手動で選択する必要があります。履歴ログ ファイルを現在のパスの下のバックアップ フォルダーにアーカイブすることを考えました。

コマンドの説明の一部

まず最初に、私はシェルの初心者であり、この領域をほとんど使用していないことを述べておきたいと思います。

ポートに基づいたクエリサービスプロセス

たとえば、ポート 8080 が占有しているプロセスをクエリするには、次のコマンドを使用します。

lsof -i:8080
  • 1

プロセスを強制終了する

これは皆さんもご存知のはずです。kill -9 を使用するのではなく、たとえば、プロセス PID 12345 のプロセスを kill するなど、単純に kill を使用しないでください。

kill -9 12345
  • 1

関数スクリプトはパラメータを受け取ります

これは比較的単純なコマンドであり、関数のパラメーターがそれに応じて使用されます。$1,$2,$3…受け取る

脚本

複数の Java サービスがあり、また再利用の考えに基づいているため、サービスを再起動する共通のメソッドを作成し、複数のサービスに対応するスクリプトを作成して、それぞれのサービス名、ポート、その他の情報を記録することを考えました。サービスのそれぞれのスクリプト内で、中間パス パラメータは、共通サービスの起動または再起動メソッドを呼び出します。

共通サービスの起動または再起動スクリプト run.sh

#!/bin/bash

start_app(){
  # 接收参数
  APP_NAME=$1;
  APP_PORT=$2;
  MEM=$3
  ACTION=$4;
  CURRENT_TIME=`date +"%Y%m%d%H%M%S"`
  
  #检查程序是否在运行
  APP_STATUS=`netstat -nlt|grep ${APP_PORT} |wc -l`;
  RUNNING_PID=$(netstat -nlp | grep :$APP_PORT | awk '{print $7}' | awk -F"/" '{ print $1 }');
  LOG_FILE=./logs/${APP_NAME}_${CURRENT_TIME}.log;
  cd ..;
  if [ "${APP_STATUS}" -eq 1 ]; then
    if [ "${ACTION}"x == "restart"x ]; then
      ## 重启前先kill原进程
      echo "kill the running app whose PID is ${RUNNING_PID} of ${APP_NAME}";
      kill -9 "${RUNNING_PID}";
      # 日志归档
      cd logs;
      for file in `ls ${APP_NAME}* -a`;
        do
          mv "${file}" backup/;
        done
      cd ..;
    else
      echo "exist running ${APP_NAME} and the PID is ${RUNNING_PID}";
      exit 0;
    fi
  fi
  echo "start ${APP_NAME} at $CURRENT_TIME";
  ## 启动程序
  nohup java -Xms${MEM}m -Xmx${MEM}m -XX:PermSize=256m -XX:MaxPermSize=512m -jar -Dfile.encoding=utf-8 -Dserver.port=${APP_PORT}  -Dspring.profiles.active=prod ${APP_NAME}  > ${LOG_FILE} 2>&1 &
  pid=`ps -ef|grep java|grep ${APP_NAME}`
  echo "${APP_NAME} has started successfully at ${CURRENT_TIME},and the pid is ${pid}"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

単一サービスの起動スクリプト

#!/bin/bash
action=$1
## 引入通用服务启动脚本
source ./run.sh
#启动方法
start(){
	# 执行通用服务脚本中的启动方法
  start_app xxx.jar 8080 4096 ${action}
}
 
#程序主入口
start

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

知らせ

再起動

パラメータを渡さずにサービス起動スクリプトを直接実行すると、サービス ポートが占有されているかどうかが判断され、占有されている場合は、サービスが終了したときに元のサービス プロセスが強制終了され、再起動されます。が開始されます。

文書の場所

jar パッケージは /opt/app ディレクトリにあり、スクリプトは /opt/app/run ディレクトリにあり、ログは /opt/app/logs ディレクトリに配置されます。 現在、このバージョンは実行のみをサポートしています。絶対パスが使用されている場合、このメソッドはエラーを報告します。これは、スクリプト内で絶対パスを使用していないメソッドがいくつかあることが原因である可能性があります。したがって、これについてはそのままにしておきます。今のところの解決策。

異常な

テスト中に遭遇したrun.sh: xxx行 $'r' 附近有语法错误エラーが発生した場合は、 sed -i 's/r$//' run.sh コマンドを使用して変換します。