DevOps-Jenkins

Jenkins简介

Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件项目可以进行持续集成。

什么是持续集成(CI)?

CI(Continuous integration,中文意思是持续集成)是一种软件开发实践。持续集成强调开发人员提交了新代码之后,立刻进行构建、编译、(单元)测试等这个过程,每次提交新代码都要进行此类重复操作,为了提高工作效率,避免重复工作及重复工作导致差别化问题。

什么是持续部署(CD)?

CD(Continuous Delivery, 中文意思持续交付)是在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境中,也就是说它是CI后紧跟的一个环节,当代码审核完毕打包成成品后,需要部署到真实的环境中去,这个过程也会根据代码的跟新持续的进行。

Jenkins安装

采用docker形式安装,首先安装好docker服务,然后在安装机器中对要存储Jenkins数据的目录进行赋权:

# groupadd jenkins -g 1000 && useradd jenkins -u 1000 -g jenkins
# chown -R 1000:1000 /jenkins

uid 和 gid必须是1000,和Jenkins镜像中的对应

开始安装:

# docker network create jenkins

# docker run \
--name jenkins-docker \
--detach \
--privileged \
--network jenkins \
--network-alias docker \
--env DOCKER_TLS_CERTDIR=/certs \
--volume /jenkins/certs:/certs/client \
--volume /jenkins/data:/var/jenkins_home \
--publish 8080:8080 \
--publish 50000:50000 \
jenkins/jenkins:latest ## 执行此命令获取初始密码
# docker exec -it jenkins-docker cat /var/jenkins_home/secrets/initialAdminPassword

这个时候就可以通过 serverip:8080 来访问到Jenkins。

流水线(pipeline)概括

想要更好的使用Jenkins,必须掌握其流水线(pipeline)的使用。

流水线概述

  • 默认文件名为 Jenkinsfile
  • 采用 Groovy 语法
  • 其可以实现对代码的整合、编译、质量检测或部署等一系列操作,相当于我们说的“脚本”

流水线脚本的分类包括:脚本式、声明式

  • 脚本式语法结构

    node {
    stage('Example') {
    try {
    sh 'exit 1'
    }
    catch (exc) {
    echo 'Something failed, I should sound the klaxons!'
    throw
    }
    }
    }
  • 声明式语法结构

    pipeline {
    agent any
    stages {
    stage('Example') {
    steps {
    echo 'Hello World' script {
    def browsers = ['chrome', 'firefox']
    for (int i = 0; i < browsers.size(); ++i) {
    echo "Testing the ${browsers[i]} browser"
    }
    }
    }
    }
    }
    }

我们应该用哪种方式来编写 Jenkinsfile?

推荐使用声明式语法结构来编写 Jenkinsfile,声明式语法结构的灵活性及可读性都要比脚本式语法结构要高,并且声明式结构中可以包含脚本式结构,可以说更强大一些,并且便于学习。

如何快速上手Jenkinsfile?

  1. 多看Jenkinsfile示例文件,及官方的语法介绍:Pipeline Syntax (jenkins.io),对语法有一个基础掌握。
  2. 学会使用脚本生成器

声明式常用语法介绍

  1. 最外层的pipeline,整条流水线的开始,里边定义了流水线所有内容

    pipeline{
    
    }
  2. agent,指定了流水线的执行节点,可以在pipeline的下行指定,也可以在stages的下行指定,agent有四个可选参数:

    • any:在任意节点执行pipeline
    • none:未定义,当顶层的agent none时,必须在每个stage下再单独定义agent
    • label:指定运行节点的label
    • node:自定义运行节点配置,例如指定label或customWorkspace,agent { node { label 'labelName' } } 和 agent { label 'labelName' }相同, 但 node支持其他选项 (比如customWorkspace).
    pipeline{
    agent{
    node{
    label "container"
    customWorkspace '/some/other/path' //指定自定义的工作空间,其实就是指定自定义路径
    }
    }
    }
  3. stages(阶段):包含一个或多个stage的序列,大部分执行操作都在这里,将每个离散部分串接起来,比如构建、测试和部署。

  4. stage:包含在stages中,pipeline完成的所有实际工作都需要包含到stage中,每一个阶段都要有一个名字。

  5. steps(步骤):1个stage中,一般都要运行1个steps,里边可以直接运行linux命令。相当于3-5点是一个连续的、互相关联的,例如:

    pipeline {
    agent any
    stages {
    stage('Example') {
    agent { //选择执行节点,可以在此层级指定
    label 'nginx'
    }
    steps { //执行的步骤
    echo 'Hello World'
    }
    }
    }
    }
  6. post:定义Pipeline或stage运行结束时的操作有以下多个参数可选:

    • always:无论Pipeline运行的完成状态如何都会运行

    • changed:只有当前Pipeline或steps运行的状态与先前完成的Pipeline的状态不同时,才能运行

    • failure:仅当当前Pipeline或steps处于“失败”状态时才运行

    • success:仅当当前Pipeline或steps具有“成功”状态时才运行

    • unstable:只有当前Pipeline或steps具有“不稳定”状态才能运行

    • aborted:只有当前Pipeline或steps处于“中止”状态时才能运行

    • unsuccessful:只有当前Pipeline或steps运行为“未成功”状态才能运行

    • cleanup:无论Pipeline或steps运行后为什么状态,只要前边定义的状态都没匹配到,则运行

    示例:

    pipeline {
    agent any
    stages {
    stage('Example') {
    steps {
    echo 'Hello World'
    }
    }
    }
    post {
    always {
    echo 'I will always say Hello again!'
    }
    }
    }
  7. environment:环境变量,可以定义全局变量和特定的阶段变量,取决于其在流水线的位置,该指定支持一个特殊的方法credentials(),此方法可用于在Jenkins环境中通过标识符访问预定义的凭证,其有很多种类型:

    • Secret Text:指定的环境变量将设置为密文内容
    • Secret File:指定的环境变量将设置为临时创建的文件的位置
    • Username and password:指定的环境变量将设置为username:password,并将自动定义为两个环境变量:MYVARNAME_USR和MYVARNAME_PSW
    • SSH with Private Key:指定的环境变量将设置为临时创建的SSH密钥文件的位置,并且可以自动定义为两个环境变量:MYVARNAME_USR和MYVARNAME_PSW

    示例1:

    pipeline {
    agent any
    environment {
    CC = 'clang'
    }
    stages {
    stage('Example Secret Text') {
    environment {
    // 需要提前将凭据创建好Secret Text类型的凭据
    AN_ACCESS_KEY = credentials('my-predefined-secret-text')
    }
    steps {
    sh 'printenv'
    }
    }
    }
    }

    示例2:

    pipeline {
    agent any
    stages {
    stage('Example Username/Password') {
    environment {
    // 提前创建好Username and Password类型的凭据
    SERVICE_CREDS = credentials('my-predefined-username-password')
    }
    steps {
    sh 'echo "Service user is $SERVICE_CREDS_USR"'
    sh 'echo "Service password is $SERVICE_CREDS_PSW"'
    }
    }
    stage('Example SSH Username with private key') {
    environment {
    // 提前创建好SSH Username with private key类型的凭据
    SSH_CREDS = credentials('my-predefined-ssh-creds')
    }
    steps {
    sh 'echo "SSH private key is located at $SSH_CREDS"'
    sh 'echo "SSH user is $SSH_CREDS_USR"'
    sh 'echo "SSH passphrase is $SSH_CREDS_PSW"'
    }
    }
    }
    }
  8. options:此指令允许从Pipeline本身中配置一些特定的选项。Pipeline提供了许多这样的选项,例如buildDiscarder,也可以由插件提供,例如timestamps。分享一些参数:

    • buildDiscarder:保持构建的最大个数,示例:options { buildDiscarder(logRotator(numToKeepStr: '1')) }

    • checkoutToSubdirectory:在workspace的子目录中执行源代码自动管理切换,示例:options { checkoutToSubdirectory('foo') }

    • disableConcurrentBuilds:不允许同时执行管道。可用于防止同时访问共享资源等,示例:options { disableConcurrentBuilds() }

    • disableResume:如果控制器重新启动,则不允许恢复pipeline,示例: options { disableResume() }

    • newContainerPerStage:使用docker或dockerfile agent时。每个stage将在同一节点上的新容器实例中运行,而不是在同一容器实例中运行的所有stages。

    • overrideIndexTriggers:

    • retry:失败时,按指定次数重试整个管道,可以针对Pipeline或者Stage,示例: options { retry(3) }

    • skipStagesAfterUnstable:一旦构建状态变得不稳定,就跳过各个stages。示例: options { skipStagesAfterUnstable() }

    • timeout:设置管道运行的超时时间,此参数可以针对Pipeline或者Stage,例如:options { timeout(time: 1, unit: 'HOURS') }

    • timestamps: 所有控制台输出前加上线路发出的时间,此参数可以针对Pipeline或者Stage,示例:options { timestamps() }

      pipeline {
      agent any
      options {
      timeout(time: 1, unit: 'HOURS')
      timestamps()
      buildDiscarder(logRotator(numToKeepStr: '10'))
      }
      stages {
      stage('Example') {
      options {
      timeout(time: 1200, unit: 'SECONDS')
      }
      steps {
      echo 'Hello World'
      }
      }
      }
      }
  9. parameters:为Pipeline运行前提供参数,有几种参数类型供选择:

    • string:字符串类型,示例:parameters { string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '') }
    • text:文本类型,可以包含多行,示例: parameters { text(name: 'DEPLOY_TEXT', defaultValue: 'One\nTwo\nThree\n', description: '') }
    • booleanParam:布尔类型,示例: parameters { booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '') }
    • choice:选择类型,多个选项任选其一,示例: parameters { choice(name: 'CHOICES', choices: ['one', 'two', 'three'], description: '') }
    • password:密码类型,可以提前设置密码,示例: parameters { password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'A secret password') }
    pipeline {
    agent any
    parameters {
    string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
    text(name: 'BIOGRAPHY', defaultValue: '', description: 'Enter some information about the person')
    booleanParam(name: 'TOGGLE', defaultValue: true, description: 'Toggle this value')
    choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
    password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'Enter a password')
    }
    stages {
    stage('Example') {
    steps {
    echo "Hello ${params.PERSON}"
    echo "Biography: ${params.BIOGRAPHY}"
    echo "Toggle: ${params.TOGGLE}"
    echo "Choice: ${params.CHOICE}"
    echo "Password: ${params.PASSWORD}"
    }
    }
    }
    }

    使用parameters参数有一个bug,首次构建时不会让你选择参数,第二次才可以选择。

  10. triggers:触发器,定义了Pipeline自动化触发的方式,可触发的方式有:

    • cron:计划任务定期触发,示例: triggers { cron('H */4 * * 1-5') }

    • pollSCM:与cron方式类似,但是必须发现有源码的变化,才会触发,示例: triggers { pollSCM('H */4 * * 1-5') }

      pollSCM触发器仅在Jenkins 2.22或更高版本中可用。

    • upstream:接受以逗号分隔的作业字符串和阈值。当字符串中的任何作业以最小阈值结束时,将会触发,示例:triggers { upstream(upstreamProjects: 'job1,job2', threshold: hudson.model.Result.SUCCESS) }

    pipeline {
    agent any
    triggers {
    cron('H */4 * * 1-5')
    }
    stages {
    stage('Example') {
    steps {
    echo 'Hello World'
    }
    }
    }
    }

    Jenkins cron syntax

    Jenkins cron语法遵循cron公共的语法(略有不同),每行由5个字段组成,由制表符或空格分隔。

    分钟小时
    Minutes within the hour (0–59)The hour of the day (0–23)The day of the month (1–31)The month (1–12)The day of the week (0–7) where 0 and 7 are Sunday.

    要为一个字段指定多个值,可以使用以下运算符。按优先顺序展示:

    • * 指定所有的值
    • M-N 指定值得范围
    • M-N/X or */X 在指定的范围或者整个范围内,按照 X的值为间隔步长
    • A,B,…,Z指定多个值

    为了允许定期调度的任务在系统上产生均匀负载,应尽可能使用符号H(表示“哈希”),使其执行pipeline的时间分散,更好的利用资源。

    此外,支持使用 @yearly, @annually, @monthly, @weekly, @daily, @midnight, and @hourly 作为别名,他们都等同于使用哈希自动的进行均衡,例如@hourlyH * * * *相同,表示1小时内任意时间执行即可。

    举一些cron例子:

    1. 每15分钟执行一次,可以是 at :07, :22, :37, :52:triggers{ cron('H/15 * * * *') }
    2. 在每小时的前30分钟,每10分钟执行一次:triggers{ cron('H(0-29)/10 * * * *') }
    3. 每周的周一到周五的,9点-16点之间的第45分钟每两个小时执行一次:triggers{ cron('45 9-16/2 * * 1-5') }
    4. 1-11月的每个1号和15号都要随机执行一次:triggers{ cron('H H 1,15 1-11 *') }
  11. tools:工具,目前仅支持三种工具:maven、jdk和gradle。工具的名称必须在系统设置—>全局工具配置中定义。定义好后即可开始调用:

    pipeline {
    agent any
    tools {
    maven 'apache-maven-3.0.1'
    }
    stages {
    stage('Example') {
    steps {
    sh 'mvn --version'
    }
    }
    }
    }

    第一次运行此工具时,如果没有会去下载,或者会根据你指定的获取方式去获取,比如直接从其他机器打包过来解压等方式。

  12. input:stage 的 input 指令允许你使用 input step提示输入。 在应用了 options 后,进入 stage 的 agent 或评估 when 条件前, stage 将暂停。 如果 input 被批准, stage 将会继续。 作为 input 提交的任何参数都将在环境中用于其他 stage 使用。可选配置:

    • message:必需的。 呈现给用户的信息。
    • id:可选的, 默认为 stage 名称。
    • ok:可选的,表单中 ok 按钮的描述文本。
    • submitter:可选的,以逗号分割的用户列表,只有列表用户才可以提交input内容。
    • parameters:可选参数列表,与前文介绍的相同。

    示例:

    pipeline {
    agent any
    stages {
    stage('Example') {
    input {
    message "Should we continue?"
    ok "Yes, we should."
    submitter "alice,bob"
    parameters {
    string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
    }
    }
    steps {
    echo "Hello, ${PERSON}, nice to meet you."
    }
    }
    }
    }
  13. when:逻辑判断,可以给定条件决定要不要执行此stage,when指令必须包含至少一个条件,如果when包含多个条件,则必须所有的条件都返回true,stage才会运行。内置条件有:

    • brance:分支匹配,当正在构建的分支与预设给定的分支匹配时,执行此stage,例如: when { branch 'master' },此参数仅适用于多分支流水线。
    • environment:当指定的环境变量是给定的值时,执行此stage,例如:when { environment name: 'DEPLOY_TO', value: 'production' }
    • expression:当指定的Groovy表达式评估为true时,执行此stage,例如: when { expression { return params.DEBUG_BUILD } }
    • not:当嵌套条件是错误时,执行这个stage,必须包含一个条件,例如: when { not { branch 'master' } }
    • allOf:当所有的嵌套条件都正确时(当when中有多个条件时,默认就是此策略),执行这个此stage,必须包含至少一个条件,例如: when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }
    • anyOf:当至少有一个嵌套条件为真时,执行这个阶段,必须包含至少一个条件,例如: when { anyOf { branch 'master'; branch 'staging' } }
    • beforeAgent:默认为false,默认情况下,如果在stage中包含agent,则会在执行when之前会先执行agent,如果将beforeAgent设置为true,则表示先执行when条件,when条件判断为执行stage后,才执行agent。

    示例:

    pipeline {
    agent any
    parameters {
    choice(name: 'BRANCH_NAME', choices: ['production', 'staging'], description: 'Pick something')
    string defaultValue: 'production', name: 'DEPLOY_TO', trim: true
    }
    stages {
    stage('Example Build') {
    when {
    expression { BRANCH_NAME ==~ /(production|staging)/ }
    }
    steps {
    echo "Start building ${BRANCH_NAME}"
    }
    }
    stage('Example Deploy') {
    when {
    anyOf {
    environment name: 'DEPLOY_TO', value: 'production'
    environment name: 'DEPLOY_TO', value: 'staging'
    }
    }
    steps {
    echo 'Deploying'
    }
    }
    }
    }
  14. Parallel:并行,声明式流水线的stage可以在他们内部声明多个嵌套stage, 它们将并行执行。注意,一个stage必须只有一个 stepsparallel ,嵌套的stage本身不能再进入 parallel 阶段,任何包含parallelstage不能包含agenttools,因为它们没有相关的step

    另外,可以添加 failFast true 到包含 parallelstage 中,表示当其中一个进程失败时,所有的 parallel 阶段都将被终止。

    示例:

    pipeline {
    agent any
    options {
    parallelsAlwaysFailFast() //表示后续所有的parallel阶段中都设置为failFast true
    timestamps()
    }
    stages {
    stage('Build Stage') {
    steps {
    echo 'This stage is Build.'
    }
    }
    stage('Parallel Stage --> Deploy') {
    when {
    not{
    branch 'prod'
    }
    }
    parallel {
    stage('Branch dev') {
    agent {
    label "dev"
    }
    steps {
    echo "On Branch dev deploy"
    }
    }
    stage('Branch int') {
    agent {
    label "int"
    }
    steps {
    echo "On Branch int deploy"
    }
    }
    stage('Branch test') {
    agent {
    label "test"
    }
    stages {
    stage('Nested 1') {
    steps {
    echo "In stage Nested 1 within Branch test"
    }
    }
    stage('Nested 2') {
    steps {
    echo "In stage Nested 2 within Branch test"
    }
    }
    }
    }
    }
    }
    }
    }

    此示例中:只要当branch不是prod时,则将同时在dev/int/test三个环境中deploy,test环境的deploy又分为两个stage,此两个stage并不是并行执行,而是串行执行。

  15. script:脚本式语法,可以在声明式流水线中使用,包含在step里,调用script { }块,示例如下:

    pipeline {
    agent any
    stages {
    stage('Example') {
    steps {
    echo 'Hello World' script {
    def browsers = ['chrome', 'firefox']
    for (int i = 0; i < browsers.size(); ++i) {
    echo "Testing the ${browsers[i]} browser"
    }
    }
    }
    }
    }
    }

脚本式语法

脚本式pipeline也是建立在底层流水线上的,与声明式不同的是, 脚本化流水线实际上是由 Groovy构建的通用 DSL, Groovy 语言提供的大部分功能都可以用于脚本化流水线。

  1. 脚本化流水线从 Jenkinsfile 的顶部开始向下串行执行, 就像 Groovy 或其他语言中的大多数传统脚本一样。 因此,提供流控制取决于 Groovy 表达式, 比如 if/else 条件, 例如:

    node {
    stage('Example') {
    if (env.BRANCH_NAME == 'master') {
    echo 'I only execute on the master branch'
    } else {
    echo 'I execute elsewhere'
    }
    }
    }
  2. 另一种方法是使用Groovy的异常处理支持来管理脚本化流水线流控制。当 步骤 失败 ,无论什么原因,它们都会抛出一个异常。处理错误的行为必须使用Groovy中的 try/catch/finally 块 , 例如:

    node {
    stage('Example') {
    try {
    sh 'exit 1'
    }
    catch (exc) {
    echo 'Something failed, I should sound the klaxons!'
    throw
    }
    }
    }

devops-2:Jenkins的使用及Pipeline语法讲解的更多相关文章

  1. 6.Jenkins进阶之流水线pipeline语法入门学习(1)

    目录一览: 0x00 前言简述 Pipeline 介绍 Pipeline 基础知识 Pipeline 扩展共享库 BlueOcean 介绍 0x01 Pipeline Syntax (0) Groov ...

  2. 7.Jenkins进阶之流水线pipeline语法入门学习(2)

    目录一览: (2) Declarative Pipeline Syntax 2.1) Sections - 章节 2.2) Directives - 指令 2.3) Sequential Stages ...

  3. Jenkins Pipeline 语法

    Pipeline语法 先讲Declarative Pipeline,所有声明式管道都必须包含在pipeline块中: 123 pipeline { /* insert Declarative Pipe ...

  4. jenkins pipeline语法

    目录 一.声明式 二.脚本式 基本 判断 异常处理 Steps node withEnv 一.声明式 声明式Pipeline必须包含在名为pipeline的语句块中,典型的声明式Pipeline语法如 ...

  5. Jenkins 在声明式 pipeline 中并行执行任务

    在持续集成的过程中,并行的执行那些没有依赖关系的任务可以缩短整个执行过程.Jenkins 的 pipeline 功能支持我们用代码来配置持续集成的过程.本文将介绍在 Jenkins 中使用声明式 pi ...

  6. 【07】Jenkins:流水线(Pipeline)

    写在前面的话 个人认为 Pipeline 在 Jenkins 中算是一个优化性功能,它能够将我们的构建服务的整个过程流程化,这意味着当我们在执行到某一步的时候,可以添加询问,提示我们是否继续运行下一步 ...

  7. GitLab集成Jenkins、Harborn构建pipeline流水线任务

    一.计划 在jenkins中构建流水线任务时,从GitLab当中拉取代码,通过maven打包,然后构建dokcer镜像,并将镜像推送至harbor当中.Jenkins中含开发.测试.生产视图,开发人员 ...

  8. AWS DevOps – 配合Jenkins和CodeDeploy实现代码自动化部署

    AWS DevOps – 配合Jenkins和CodeDeploy实现代码自动化部署 Amazon ElastiCache 连接至 Redis 节点 通过 AWS Command Line Inter ...

  9. pipeline语法之environment,dir(),deleteDir()方法,readJSON,writeJSON

    一 environment指令指定一系列键值对,这些对值将被定义为所有步骤的环境变量或阶段特定步骤 environment{…}, 大括号里面写一些键值对,也就是定义一些变量并赋值,这些变量就是环境变 ...

  10. DevOps系列——Jenkins/Gitlab自动打包部署

    前面只说了DevOps的两个基础组件Jenkins和GitLab,客官也不要着急,我们玩就玩的深入一点,Gitlab和Jenkins的各种配置和 插件很多,也够啃一阵子的,不要照着操作一通就感觉万事大 ...

随机推荐

  1. js 获取iframe中的元素

    今天要修改编辑器插件中的元素遇到的问题 jquery 在父窗口中获取iframe中的元素 1.Js代码 格式:$("#iframe的ID").contents().find(&qu ...

  2. XCActionBar 「Xcode 中的 Alfred」

    下载地址:https://github.com/pdcgomes/XCActionBar 基本命令: (1)「command+shift+8」或者双击「command」键可以打开「动作输入框窗口」 ( ...

  3. Android Studio 中解决.9图片报错的问题

  4. 面试题-Java基础-面向对象

    1.面向对象软件开发的优点有哪些? 代码开发模块化,更易维护和修改.代码复用.增强代码的可靠性和灵活性.增加代码的可理解性.面向对象编程有很多重要的特性,比如:封装,继承,多态和抽象.下面的章节我们会 ...

  5. cobbler自动装机服务简介与配置

    cobbler简介 Cobbler是一个Linux服务器安装的服务,可以通过网络启动(PXE)的方式来快速安装.重装物理服务器和虚拟机,同时还可以管理DHCP,DNS等. Cobbler可以使用命令行 ...

  6. Git的gc功能

    http://blog.csdn.net/lihuanshuai/article/details/37345565 Git的底层并没有采用 CVS.SVN 底层所采用的那套增量式文件系统,而是采用一套 ...

  7. [Asp.net]缓存简介

    写在前面 针对一些经常访问而很少改变的数据,使用缓存,可以提高性能.缓存是一种用空间换取时间的技术,说的直白点就是,第一次访问从数据库中读取数据,然后将这些数据存在一个地方,比如内存,硬盘中,再次访问 ...

  8. 记一次重装系统(.net开发环境重装问题汇总)

    起因: 有一天,我突然感觉到电脑的运行明显变慢,慢的可怕,启动任务资源管理器一看,不看不知道,一看吓一跳,CPU使用率,物理内存皆100%,当时的第一印象,是电脑中病毒了吧!!,进入进程一看,有几个名 ...

  9. eclipse工具maven项目打包文件不是最新修改的

    1.问题描述:maven项目,完成一些功能开发后,在进行打包更新服务器系统时,本地eclipse工具对文件打成jar包操作,更新到服务器上没有修改的效果,包括打包整个工程为一个war包,也是有同样问题 ...

  10. delphi 杀死进程

    http://blog.sina.com.cn/s/blog_554b1f1b0100aygo.html unit Tlhelp323; interface uses  Windows,SysUtil ...