diff --git a/maven/06 maven命令插件Plugins.md b/maven/06 maven命令插件Plugins.md index 70d17b3c..8a25a96d 100644 --- a/maven/06 maven命令插件Plugins.md +++ b/maven/06 maven命令插件Plugins.md @@ -56,7 +56,7 @@ mvn compiler:compile ``` -## 2 常用插件 +### 常用插件 分为两类 @@ -73,50 +73,6 @@ mvn compiler:compile * javadoc 为工程生成 Javadoc。 * antrun 从构建过程的任意一个阶段中运行一个 ant 任务的集合。 -### help插件:分析依赖 -![](image/2022-11-05-23-03-56.png) - - -### archetype插件:创建工程 - -``` -mvn archetype:generate -DgroupId=com.ykl -DartifactId=project04-maven-import -DarchetypeArtifactId=maven-archetype-quickstart -Dversion=0.0.1-snapshot -``` - - - -### dependcy:依赖管理和分析 - - -* 查看依赖列表 - -``` -mvn dependcy:list -mvn dependcy:tree -``` -### spring-boot-maven-plugin - -spring-boot-maven-plugin是spring boot提供的maven打包插件。可打直接可运行的jar包或war包。 - -```xml - - - - org.springframework.boot - spring-boot-maven-plugin - - - -``` -插件提供了6个maven goal - -* build-info:生成项目的构建信息文件 build-info.properties -* help:用于展示spring-boot-maven-plugin的帮助信息。使用命令行mvn spring-boot:help -Ddetail=true -Dgoal=可展示goal的参数描述信息。 -* repackage:可生成可执行的jar包或war包。插件的核心goal。 -* run:运行 Spring Boot 应用 -* start:在集成测试阶段,控制生命周期 -* stop:在集成测试阶段,控制生命周期 - ## 2 自定义插件 ### 创建工程 @@ -272,3 +228,117 @@ mvn hello:sayHello + +## 3 help插件:分析依赖 +![](image/2022-11-05-23-03-56.png) + + +## 4 archetype插件:创建工程 + +``` +mvn archetype:generate -DgroupId=com.ykl -DartifactId=project04-maven-import -DarchetypeArtifactId=maven-archetype-quickstart -Dversion=0.0.1-snapshot +``` + + + +## 5 dependcy:依赖管理和分析 + + +* 查看依赖列表 + +``` +mvn dependcy:list +mvn dependcy:tree +``` +## 6 spring-boot-maven-plugin + +spring-boot-maven-plugin是spring boot提供的maven打包插件。可打直接可运行的jar包或war包。 + +```xml + + + + org.springframework.boot + spring-boot-maven-plugin + + + +``` +插件提供了6个maven goal + +* build-info:生成项目的构建信息文件 build-info.properties +* help:用于展示spring-boot-maven-plugin的帮助信息。使用命令行mvn spring-boot:help -Ddetail=true -Dgoal=可展示goal的参数描述信息。 +* repackage:可生成可执行的jar包或war包。插件的核心goal。 +* run:运行 Spring Boot 应用 +* start:在集成测试阶段,控制生命周期 +* stop:在集成测试阶段,控制生命周期 + + +## 7 surefire插件 + +### 简介 + +如果你执行过mvn test或者执行其他maven命令时跑了测试用例,你就已经用过maven-surefire-plugin了。 maven-surefire-plugin是maven里执行测试用例的插件,不显示配置就会用默认配置。 这个插件的surefire:test命令会默认绑定maven执行的test阶段。 + +如果你自己声明了,那么可以指定自己的版本,并且可以配置自定义的参数。 + +### 导入 + +```xml + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + + +``` + +运行命令mvn test即可使用此插件。 + +### 源码详解 +前面通过学习知道Mojo是运行的核心类,而SurefirePlugin就是Mojo的子类。 由此可知,如果要学习这个 maven-surefire-plugin,入口就是在SurefirePlugin类。 + +![](image/2022-12-05-19-38-40.png) + +![](image/2022-12-05-19-38-23.png) + + +![](image/2022-12-05-19-38-13.png) + + +### 常用参数 + +| 是否常用 | 参数名 | 使用方法 | 解释 | +|---|---|---|---| +| 常用 | skipTests | -D,或者xml配置标签 | 用于跳过单测 | +| 常用 | maven.test.skip.exec | -D,或者xml配置标签 | 用于跳过单测 | +| 常用 | maven.test.skip | -D,或者xml配置标签 | 用于跳过单测 | +| 不常用 | testClassesDirectory | xml配置标签 | 指定测试模块目录编译后目录 | +| 不常用 | maven.test.dependency.excludes | -D,或者xml配置标签 | 要排除的依赖,格式:groupId:artifactId | +| 不常用 | maven.test.additionalClasspath | -D,或者xml配置标签 | 追加classpath | +| 不常用 | project.build.testSourceDirectory | xml配置标签 | 指定测试模块目录源码目录 | +| 不常用 | excludes | xml配置 | 指定规则的类不需要被单测,eg: **/*Test.java | +| 不常用 | surefire.reportNameSuffix | -D,或者xml配置标签 | test报表后缀 | +| 不常用 | maven.test.redirectTestOutputToFile | -D,或者xml配置标签 | 运行的单侧输出重定向到report目录中 | +| 不常用 | failIfNoTests | -D,或者xml配置标签 | 如果没有单测就报错 | +| 不常用 | forkMode | -D,或者xml配置标签 | 运行模式 | +| 不常用 | jvm | -D,或者xml配置标签 | 指定jvm目录,如果不指定会读取系统 | +| 不常用 | argLine | -D,或者xml配置标签 | Jvm运行参数 | +| 不常用 | threadCount | -D,或者xml配置标签 | 线程数 | +| 不常用 | forkCount | -D,或者xml配置标签 | 指定启用多少个vm,1.5C 以数字结尾,数字乘以cpu核心数 | +| 不常用 | reuseForks | -D,或者xml配置标签 | 是否可重新使用forks进程 | +| 不常用 | disableXmlReport | -D,或者xml配置标签 | 禁用xml报告 | +| 不常用 | enableassertions | -D,或者xml配置标签 | 启用断言assert语句 | + + +forkMode 可设置值有 “never”, “once”, “always” 和 “pertest”。 + +* pretest: 每一个测试创建一个新进程,为每个测试创建新的JVM是单独测试的最彻底方式,但也是最慢的,不适合hudson上持续回归。 +* once:在一个进程中进行所有测试。once为默认设置,在Hudson上持续回归时建议使用默认设置。 +* always:在一个进程中并行的运行脚本,Junit4.7以上版本才可以使用,surefire的版本要在2.6以上提供这个功能, \ No newline at end of file diff --git a/maven/image/2022-12-05-19-38-13.png b/maven/image/2022-12-05-19-38-13.png new file mode 100644 index 00000000..4a2d3178 Binary files /dev/null and b/maven/image/2022-12-05-19-38-13.png differ diff --git a/maven/image/2022-12-05-19-38-23.png b/maven/image/2022-12-05-19-38-23.png new file mode 100644 index 00000000..19ef0642 Binary files /dev/null and b/maven/image/2022-12-05-19-38-23.png differ diff --git a/maven/image/2022-12-05-19-38-40.png b/maven/image/2022-12-05-19-38-40.png new file mode 100644 index 00000000..36131cb0 Binary files /dev/null and b/maven/image/2022-12-05-19-38-40.png differ diff --git a/test.sh b/test.sh new file mode 100644 index 00000000..826934ff --- /dev/null +++ b/test.sh @@ -0,0 +1,571 @@ +# cat zclean.sh +#!/bin/bash +# version: 0.9.2 +export LANG=C +export PATH=/sbin:/bin:/usr/local/sbin:/usr/sbin:/usr/local/bin:/usr/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/admin/bin + + +readonly LOGS_DIR=/home/admin/logs/ +readonly CONF_FILE=/home/admin/conf/zclean.conf + +# 兼容逻辑,部分老应用通过云游部署会带上 app.env 等前缀,这里为了处理这种情况用 grep 来过滤 +RESERVE=`([[ -f /opt/antcloud/conf/env.file ]] && cat /opt/antcloud/conf/env.file || env) |grep ZCLEAN_RESERVE_DAYS | awk -F= '{print $2}'` +RESERVE=${RESERVE:-14} +MAX_LOG_DIR_SIZE=`([[ -f /opt/antcloud/conf/env.file ]] && cat /opt/antcloud/conf/env.file || env) |grep ZCLEAN_MAX_LOG_DIR_SIZE | awk -F= '{print $2}'` +MAX_LOG_DIR_SIZE=${MAX_LOG_DIR_SIZE:-100} # unit is G + +DELETE_FLAG='-delete' +DEBUG='' +CHUNK_SIZE='' +INTERACTIVE=0 +ZCLEAN_DIGEST="${LOGS_DIR}/zclean.log.$(date +%F)" + + +{ + readonly ZCLEAN_OK=1 + readonly ZCLEAN_CRUSH=2 + readonly ZCLEAN_ERROR=3 + readonly ZCLEAN_IGNORE=4 +} + +[[ ! -d $LOGS_DIR ]] && exit + +CMD_PREFIX='' +if $(which ionice >& /dev/null); then + CMD_PREFIX="ionice -c3 " +fi +if $(which nice >& /dev/null); then + CMD_PREFIX="nice -n 19 $CMD_PREFIX" +fi +FIND_CMD="${CMD_PREFIX}find" +RM_CMD="${CMD_PREFIX}rm" + +TRUNCATE_CMD='' +if $(which truncate >& /dev/null); then + TRUNCATE_CMD="${CMD_PREFIX}truncate" +fi + +LSOF_CMD='' +if $(which lsof >& /dev/null); then + LSOF_CMD="lsof" +fi + +LSOF_FILE=/tmp/zclean_lsof.out +if [[ -d /dev/shm ]]; then + shm_mode=$(stat -c "%A" /dev/shm) + if [[ $shm_mode == drwxrwxrwt ]]; then + LSOF_FILE=/dev/shm/zclean_lsof.out + fi +fi + +prepare_lsof() { + # walkaroud for Alios7 kenrel bug + if [[ $HOSTNAME =~ paycorecloud-30- ]]; then + FIND_CMD $LOGS_DIR -name '*.log' > $LSOF_FILE + return + fi + if [[ $HOSTNAME =~ paycorecloud-31- ]]; then + FIND_CMD $LOGS_DIR -name '*.log' > $LSOF_FILE + return + fi + if [[ -n $LSOF_CMD ]]; then + ulimit -n 1024 + $LSOF_CMD +D $LOGS_DIR 2> /dev/null > $LSOF_FILE + fi +} + +delete_lsof() { + $RM_CMD -rf $LSOF_FILE +} + +# only return true when all ready +file_in_lsof() { + local fpath=$1 + if [[ -n $LSOF_CMD && -f $LSOF_FILE ]]; then + grep -q $fpath $LSOF_FILE + return $? + else + return 1 + fi + +} + +log_error() { + echo $(date +"%F %T") [ERROR] $@ >> $ZCLEAN_DIGEST +} + +log_info() { + echo $(date +"%F %T") [INFO] $@ >> $ZCLEAN_DIGEST +} + +log_warn() { + echo $(date +"%F %T") [WARN] $@ >> $ZCLEAN_DIGEST +} + +log_debug() { + [[ $DEBUG != '-debug' ]] && return + echo $(date +"%F %T") [DEBUG] $@ >> $ZCLEAN_DIGEST +} + +delete_files() { + [[ $DELETE_FLAG != '-delete' ]] && return + $RM_CMD -rf "$@" >& /dev/null +} + +crush_files() { + [[ $DELETE_FLAG != '-delete' ]] && return + for f in "$@"; do + > $f + done +} + +clean_file() { + # eliminates file in a low-speed way (default: 20MB/S) + local fpath=$1 + local fsize=$2 + local chunksize=${CHUNK_SIZE:-20} + + if [[ $DELETE_FLAG != '-delete' || ! -f $fpath ]]; then + return $ZCLEAN_ERROR + fi + + local is_open=0 + if file_in_lsof $fpath >& /dev/null; then + is_open=1 + fi + + if [[ $is_open -eq 1 && $fsize -eq 0 ]]; then + log_debug "ignore $fpath(+) size $fsize" + return $ZCLEAN_IGNORE + fi + + if [[ $chunksize -eq 0 || -z $TRUNCATE_CMD ]]; then + # fast delete + if [[ $is_open -eq 1 ]]; then + crush_files $fpath + log_debug "removed $fpath(+) size $fsize directly" + else + delete_files $fpath + log_debug "removed $fpath size $fsize directly" + fi + else + # slow delete + local tstart=$SECONDS + local tstake=$((1+tstart)) + local loop=$((fsize/(1048576*chunksize)+1)) + local tdiff + if [[ $fsize -eq 0 ]]; then + loop=0 + fi + for ((i=0; i $expired ]]; then + continue + else + clean_file $fpath $fsize + ret_code=$? + if [[ $ret_code -eq $ZCLEAN_OK || $ret_code -eq $ZCLEAN_CRUSH ]]; then + log_info "deleted expired file $fpath size $fsize" + fi + fi + done +} + +clean_huge() { + local blocks big_size fpath fsize + blocks=$(df /home -k|awk 'END {print $2}') + if [[ ! $? ]]; then + log_error "can't get home partition total size" + exit 1 + fi + + if [[ $blocks -ge ${MAX_LOG_DIR_SIZE}*1024*1024 ]]; then + blocks=$(( MAX_LOG_DIR_SIZE*1024*1024 )) + fi + + # 120G + if [[ $blocks -ge 125829120 ]]; then + big_size=50G + else + big_size=30G + fi + $FIND_CMD $LOGS_DIR \ + -type f \ + -name '*log*' \ + -size +$big_size \ + -printf '%p %s\n' | \ + while read fpath fsize; do + crush_files "$fpath" + log_warn "deleted huge file $fpath size $fsize" + done +} + +clean_by_day() { + local how_long=$1 + local ret_code=$ZCLEAN_OK + $FIND_CMD $LOGS_DIR \ + -type f \ + -name '*log*' \ + -mtime "+${how_long}" \ + -printf '%p %s\n' | \ + while read fpath fsize; do + clean_file $fpath $fsize + ret_code=$? + if [[ $ret_code -eq $ZCLEAN_OK || $ret_code -eq $ZCLEAN_CRUSH ]]; then + log_info "deleted $((how_long+1)) days ago file $fpath size $fsize" + fi + done +} + +clean_by_hour() { + local how_long=$1 + local ret_code=$ZCLEAN_OK + $FIND_CMD $LOGS_DIR \ + -type f \ + -name '*log*' \ + -mmin "+$((how_long*60))" \ + -printf '%p %s\n' | \ + while read fpath fsize; do + clean_file $fpath $fsize + ret_code=$? + if [[ $ret_code -eq $ZCLEAN_OK || $ret_code -eq $ZCLEAN_CRUSH ]]; then + log_info "deleted $how_long hours ago file $fpath size $fsize" + fi + done +} + +clean_largest() { + local fsize fpath fblock + local ret_code=$ZCLEAN_OK + + $FIND_CMD $LOGS_DIR \ + -type f \ + -printf '%b %s %p\n' | \ + sort -nr | head -1 | \ + while read fblock fsize fpath ; do + # 10G + if [[ $fsize -gt 10737418240 ]]; then + crush_files $fpath + else + clean_file $fpath $fsize + fi + ret_code=$? + if [[ $ret_code -eq $ZCLEAN_OK || $ret_code -eq $ZCLEAN_CRUSH ]]; then + log_info "deleted largest file $fpath size $fsize" + fi + done +} + +in_low_traffic() { + local now=$(date '+%R') + if [[ "$now" > "04:00" && "$now" < "04:30" ]]; then + return 0 + else + return 1 + fi +} + + +clean_until() { + local from_rate to_rate cur_usage old_usage how_long count force + how_long=$((RESERVE-1)) + from_rate=$1 + to_rate=$2 + force=$3 + count=0 + + cur_usage=$(get_home_usage) + + # should exist some huge files + if [[ $cur_usage -ge 97 ]]; then + clean_huge + old_usage=$cur_usage + cur_usage=$(get_home_usage) + if [[ $cur_usage -ne $old_usage ]]; then + log_info "usage from $old_usage to $cur_usage" + fi + fi + + if ! in_low_traffic; then + [[ $cur_usage -lt $from_rate ]] && return + fi + + prepare_lsof + + clean_expired + old_usage=$cur_usage + cur_usage=$(get_home_usage) + if [[ $cur_usage -ne $old_usage ]]; then + log_info "usage from $old_usage to $cur_usage" + fi + + # now we have to remove recent logs by date + while [[ $cur_usage -gt $to_rate ]]; do + if [[ $how_long -lt 1 ]]; then + break + else + how_long=$((how_long-1)) + fi + clean_by_day $how_long + old_usage=$cur_usage + cur_usage=$(get_home_usage) + if [[ $cur_usage -ne $old_usage ]]; then + log_info "usage from $old_usage to $cur_usage" + fi + done + + # in hours + how_long=24 + while [[ $cur_usage -gt $to_rate ]]; do + if [[ $how_long -lt 2 ]]; then + break + else + how_long=$((how_long-1)) + fi + clean_by_hour $how_long + old_usage=$cur_usage + cur_usage=$(get_home_usage) + if [[ $cur_usage -ne $old_usage ]]; then + log_info "usage from $old_usage to $cur_usage" + fi + done + + [[ $force -ne 1 ]] && return + # last resort, find top size logs to deleted + + if [[ $CHUNK_SIZE -ne 0 ]]; then + CHUNK_SIZE=100 + fi + while [[ $cur_usage -gt $to_rate ]]; do + if [[ $count -gt 5 ]]; then + log_error "give up deleting largest files" + break + fi + count=$((count+1)) + clean_largest + old_usage=$cur_usage + cur_usage=$(get_home_usage) + if [[ $cur_usage -ne $old_usage ]]; then + log_info "usage from $old_usage to $cur_usage" + fi + done + + delete_lsof +} + +ensure_unique() { + local pgid=$(ps -p $$ -o pgid=) + local pids=$(ps -e -o pid,pgid,cmd | \ + grep [z]clean | grep bash | \ + awk "\$2 != $pgid {print \$1}") + if [[ -n $pids ]]; then + if [[ $INTERACTIVE -eq 1 ]]; then + kill $pids + else + log_info "$0 is running, wait for another round of dispatch" + exit 0 + fi + fi +} + +_main() { + local to_rate=90 + local from_rate=$to_rate + local do_sleep=0 + local force=0 + + # load config + if [[ -f $CONF_FILE && ! "$*" =~ --noconf ]]; then + while read -r line; do + key=$(echo $line|cut -d= -f1) + value=$(echo $line|cut -d= -f2) + case $key in + to) + to_rate=$value;; + block) + CHUNK_SIZE=$value;; + fast) + CHUNK_SIZE=0;; + from) + from_rate=$value;; + max_size) + MAX_LOG_DIR_SIZE=$value;; + sleep) + do_sleep=1;; + debug) + DEBUG='-debug';; + force) + force=1;; + *) + ;; + esac + done < $CONF_FILE + fi + + # option help + # -r clean to this ratio + # -b wipe this blocksize each time + # -t start cleaning when above this ratio + # -m max size of log dir,unit is G + # -n fast delete (use rm -rf) + # -s random sleep awhile in a app clusters + # -d extra debug logging + # -f force delete largest file + while getopts ":r:b:t:nsdfi" opt; do + case $opt in + r) + if [[ ! $OPTARG =~ ^[0-9]+$ ]]; then + echo "$0: rate $OPTARG is an invalid number" >&2 + exit 1; + fi + if [[ $OPTARG -le 1 || $OPTARG -ge 99 ]]; then + echo "$0: rate $OPTARG out of range (1, 99)" >&2 + exit 1; + fi + to_rate=$OPTARG ;; + b) + if [[ ! $OPTARG =~ ^[0-9]+[mMgG]?$ ]]; then + echo "$0: block size $OPTARG is invalid" >&2 + exit 1; + fi + if [[ $OPTARG =~ [gG]$ ]]; then + CHUNK_SIZE=$(echo $OPTARG|tr -d 'gG') + CHUNK_SIZE=$((CHUNK_SIZE*1024)) + else + CHUNK_SIZE=$(echo $OPTARG|tr -d 'mM') + fi ;; + t) + if [[ ! $OPTARG =~ ^[0-9]+$ ]]; then + echo "$0: rate $OPTARG is an invalid number" >&2 + exit 1; + fi + if [[ $OPTARG -le 1 || $OPTARG -ge 99 ]]; then + echo "$0: rate $OPTARG out of range (1, 99)" >&2 + exit 1; + fi + from_rate=$OPTARG ;; + m) + if [[ ! $OPTARG =~ ^[0-9]+$ ]]; then + echo "$0: max size $OPTARG is invalid" >&2 + exit 1; + fi + MAX_LOG_DIR_SIZE=$OPTARG ;; + n) + CHUNK_SIZE=0 ;; + s) + do_sleep=1 ;; + d) + DEBUG='-debug' ;; + f) + force=1 ;; + i) + INTERACTIVE=1 ;; + + \?) + echo "$0: invalid option: -$OPTARG" >&2 + exit 1;; + :) + echo "$0: option -$OPTARG requires an argument" >&2 + exit 1 ;; + esac + done + + if [[ $to_rate -ge $from_rate ]]; then + to_rate=$from_rate + fi + + ensure_unique + [[ $do_sleep -eq 1 ]] && sleep_dif + clean_until $from_rate $to_rate $force +} + +# TODO make a decision whether /home/admin is innocent +# TODO deamonize + +_main "$@" \ No newline at end of file