代码之家  ›  专栏  ›  技术社区  ›  mglauche

如何有效地处理maven-3时间戳快照?

  •  83
  • mglauche  · 技术社区  · 14 年前

    现在maven-3做到了 drop support 对于快照工艺品,<uniqueVersion>false<uniqueVersion>您似乎真的需要使用带时间戳的快照。尤其是m2eclipse,它在内部使用maven 3似乎受到了影响,更新快照在快照不唯一时不起作用。

    似乎是最好的 practice before 将所有快照设置为uniqueVersion=false

    现在,切换到带时间戳的版本似乎没什么大问题,毕竟它们是由一个中央nexus存储库管理的,该存储库能够定期删除旧快照。

    问题是本地开发人员工作站。他们的本地存储库很快就会增长 非常 带有独特快照的大型。

    如何处理这个问题?

    现在我看到以下可能的解决方案:

    • 要求开发人员定期清除存储库(这会导致大量的fustration,因为删除需要很长时间,下载所需的所有内容需要更长时间)
    • 设置一些脚本来删除所有 快照 本地存储库中的目录,并要求开发人员不时运行该脚本(比第一个更好,但运行和下载当前快照仍需要相当长的时间)
    • 使用dependency:purge local repository插件(从eclipse运行时确实有问题,因为打开的文件需要从每个项目运行)
    • 在每个工作站上设置nexus,并设置一个任务来清理旧快照(最好的结果,但我不想维护50多个nexus服务器,另外开发人员工作站上的内存总是很紧张)
    • 完全停止使用快照

    防止本地存储库填满硬盘空间的最佳方法是什么?

    更新:

    为了验证beaviour并提供更多信息,我安装了一个小型nexus服务器,构建了两个项目(a和b)并尝试:

    答:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>de.glauche</groupId>
      <artifactId>a</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <distributionManagement>
        <snapshotRepository>
            <id>nexus</id>
            <name>nexus</name>
            <url>http://server:8081/nexus/content/repositories/snapshots</url>
        </snapshotRepository>
      </distributionManagement>
    
    </project>
    

    乙:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>de.glauche</groupId>
      <artifactId>b</artifactId>
      <version>0.0.1-SNAPSHOT</version>
        <distributionManagement>
        <snapshotRepository>
            <id>nexus</id>
            <name>nexus</name>
            <url>http://server:8081/nexus/content/repositories/snapshots/</url>
        </snapshotRepository>
      </distributionManagement>
     <repositories>
        <repository>
            <id>nexus</id>
            <name>nexus</name>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <url>http://server:8081/nexus/content/repositories/snapshots/</url>
        </repository>
     </repositories>
      <dependencies>
        <dependency>
            <groupId>de.glauche</groupId>
            <artifactId>a</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
      </dependencies>
    </project>
    

    现在,当我使用maven并在“a”上运行“deploy”时

    a-0.0.1-SNAPSHOT.jar
    a-0.0.1-20101204.150527-6.jar
    a-0.0.1-SNAPSHOT.pom
    a-0.0.1-20101204.150527-6.pom
    

    在本地存储库中。每次运行deploy目标时使用新的时间戳版本。当我尝试从nexus服务器更新快照时也会发生同样的情况(关闭“a”项目,从本地存储库中删除它,构建“b”)

    在一个构建了大量快照的环境中(比如hudson服务器…),本地的repositoy充满了旧版本 快速的

    更新2:

    为了测试失败的原因和方式,我做了更多的测试。每个测试都是针对clean everything运行的(de/glauche从machines和nexus中都被删除)

    • mvn与maven 2.2.1一起部署:

    机器A上的本地存储库包含snapshot.jar+snapshot-timestamp.jar

    但是:nexus中只有一个带时间戳的jar,元数据读取:

    <?xml version="1.0" encoding="UTF-8"?>
    <metadata>
      <groupId>de.glauche</groupId>
      <artifactId>a</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <versioning>
        <snapshot>
          <timestamp>20101206.200039</timestamp>
    
          <buildNumber>1</buildNumber>
        </snapshot>
        <lastUpdated>20101206200039</lastUpdated>
      </versioning>
    </metadata>
    
    • 在m2eclipse(embedded m3 final)中运行update dependencies(在机器B上)->本地存储库有snapshot.jar+snapshot-timestamp.jar:(
    • 使用外部maven 2.2.1运行包目标->本地存储库具有snapshot.jar+snapshot-timestamp.jar:(

    好的,下一次尝试使用maven 3.0.1(在删除项目a的所有痕迹之后)

    • 机器A上的本地存储库看起来更好,只有一个没有时间戳的jar

    • nexus中只有一个带时间戳的jar,元数据读取:

      德格拉切 一 0.0.1-快照

      <snapshot>
        <timestamp>20101206.201808</timestamp>
        <buildNumber>3</buildNumber>
      </snapshot>
      <lastUpdated>20101206201808</lastUpdated>
      <snapshotVersions>
        <snapshotVersion>
          <extension>jar</extension>
          <value>0.0.1-20101206.201808-3</value>
          <updated>20101206201808</updated>
        </snapshotVersion>
        <snapshotVersion>
          <extension>pom</extension>
          <value>0.0.1-20101206.201808-3</value>
          <updated>20101206201808</updated>
        </snapshotVersion>
      </snapshotVersions>
      

    • 在m2eclipse(embedded m3 final)中运行update dependencies(在机器B上)->本地存储库有snapshot.jar+snapshot-timestamp.jar:(

    • 使用外部maven 2.2.1运行包目标->本地存储库具有snapshot.jar+snapshot-timestamp.jar:(

    所以,概括一下:maven3中的“deploy”目标比2.2.1中的更好,创建机器上的本地存储库看起来很好。 但是,接收器总是有很多时间限制的版本。。。

    我做错什么了?

    更新3

    我还测试了各种其他配置,首先将nexus替换为artifactory->相同的行为。然后使用linux maven 3客户端从存储库管理器下载快照->本地存储库仍有带时间戳的快照:(

    6 回复  |  直到 7 年前
        1
  •  34
  •   Stefan Falk    8 年前

    这个 <uniqueVersion> 应用于(通过mvn deploy)部署到Maven存储库(如Nexus)的构件的配置。

    要从Nexus中删除这些内容,您可以轻松创建一个自动作业,每天清除快照存储库。它可以配置为保留一定数量的shapshot或将其保留一段时间。它非常简单,而且效果很好。

    开发人员机器上本地存储库中的工件从“安装”目标到达那里,并且不使用这些时间戳…它们只是继续替换唯一的快照版本,除非您也在增加修订号(例如1.0.0-SNAPSHOT到1.0.1-SNAPSHOT)。

        2
  •  13
  •   Shadow Wizard    13 年前

    此插件从本地存储库中删除项目的工件。只保留一个大型本地快照副本很有用。

    <plugin>         
        <groupId>org.codehaus.mojo</groupId>         
        <artifactId>build-helper-maven-plugin</artifactId>         
        <version>1.7</version>         
        <executions>           
            <execution>             
                <id>remove-old-artifacts</id>             
                <phase>package</phase>             
                <goals>               
                    <goal>remove-project-artifact</goal>             
                </goals>            
                <configuration>  
                    <removeAll>true</removeAll><!-- When true, remove all built artifacts including all versions. When false, remove all built artifacts of this project version -->             
                </configuration>          
            </execution>         
        </executions>       
    </plugin>
    
        3
  •  7
  •   yurinadestin    11 年前

    我不喜欢任何提议的解决方案。删除maven缓存通常会显著增加网络流量并减慢构建过程。build helper maven插件只对一个工件有帮助,我想要一个解决方案,可以在一个简单的命令中从本地缓存中清除所有过时的时间戳快照工件。经过几天的搜索,我放弃了,决定写一个小程序。最后的程序似乎在我们的环境中运行得很好。所以我决定和其他可能需要这种工具的人分享。可以从github中提取源: https://github.com/nadestin/tools/tree/master/MavenCacheCleanup

        4
  •  2
  •   cwash    14 年前

    至于其中的远程存储库部分,我认为前面讨论定期清除快照的答案将起作用。但没有人解决过您的问题中的本地开发人员工作站同步部分。

    我们还没有开始使用Maven3,所以我们还没有看到快照开始在本地机器上构建。

    但是m2eclipse有不同的问题。当我们启用了“工作区解决方案”并且项目存在于工作区内时,源更新通常会使我们处于出血边缘。但是我们发现让m2eclipse用Nexus中最近发布的工件更新自己是非常困难的。我们的团队中也遇到了类似的问题,尤其是因为我们有一个非常大的项目图。。。有很多依赖项不在您的工作区中,但会经常发布快照。

    我敢肯定,这可以追溯到m2eclipse中的一个问题,即它不能完全按照应有的方式处理快照。您可以在eclipse中的Maven控制台中看到,m2eclipse告诉您它正在跳过最近发布的快照的更新,因为它有一个缓存版本。如果从运行配置或命令行执行-U操作, 马文 将获取元数据更改。但是一个“更新快照…”选项应该告诉m2eclipse让Maven终止这个缓存。它似乎没有被传下去。如果你有兴趣投票的话,似乎有一个bug被归档了: https://issues.sonatype.org/browse/MNGECLIPSE-2608

    你在某个地方的评论中提到过这个。

    解决这个问题的最好办法似乎是让开发人员在m2eclipse内部出现故障时清除本地工作站。对另一个问题的类似解决方案。。。其他人报告了Maven 2.2.1和3支持m2eclipse的问题,我也看到了同样的情况。

    我希望如果您使用的是Maven3,您可以将其配置为只提取最新的快照,并将其缓存到存储库所说的时间(或者直到您手动使其过期)。希望这样您就不需要在本地存储库中放置一堆快照。

    除非你说的是一个构建服务器,它正在手动执行 mvn install 在他们身上。至于如何防止快照在构建服务器这样的环境中生成,我们已经通过让每个构建使用自己的工作区和本地存储库(尽管在Maven 2.2.1中,某些东西(如POM)似乎总是从~/.m2/repository中产生)来避开了这一问题,额外的快照实际上只在单个构建之后,它们就会被丢弃(然后从头下载)。因此,我们已经看到这种方法最终会占用更多的空间,但它往往比在单个存储库中解决所有问题更稳定。这个选项(在Hudson上)被称为“使用私有Maven存储库”,当您选择使用Maven构建时,它位于项目配置构建部分的高级按钮下。以下是该选项的帮助说明:

    通常,哈德逊使用本地的Maven 由Maven确定的存储库 确切的过程似乎是 没有证件,但是 ~/.m2/存储库,可以重写 年 ~/.m2/settings.xml(请参阅参考 这通常意味着 执行的所有作业 同一个节点共享一个Maven 储存库。好处是 您可以节省磁盘空间,但是 缺点是有时 这些构建可能会干扰 其他。例如,你可能会 错误地构建成功, 就因为你拥有所有 本地存储库中的依赖项, 尽管事实上 POM中的存储库可能有它们。

    也有一些报告的问题 关于有并发Maven 尝试使用同一本地的进程 储存库。

    当这个选项被选中时,哈德逊 会告诉Maven使用 $WORKSPACE/.repository作为本地 Maven存储库。这意味着每个工作 会有自己独立的小牛 存储库仅用于自身。它修复了 以上问题,代价是 额外的磁盘空间消耗。

    使用此选项时,请考虑 设置Maven工件管理器以便 你不用打遥控器 Maven存储库太频繁了。

    如果您想激活此模式 在执行的所有Maven作业中 哈德逊,参考技术 在这里描述。

    希望这有帮助-如果它不能解决你的问题,请让我知道我错过了什么。

        5
  •  1
  •   vnov    10 年前

    在groovy中 ,删除带时间戳的文件,如 artifact-0.0.1-20101204.150527-6.jar 很简单:

    root = 'path to your repository'
    
    new File(root).eachFileRecurse {
      if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
        println 'Deleting ' + it.name
        it.delete()
      }
    }
    

    安装 Groovy ,将脚本保存到一个文件中,并计划每周执行、开始、登录,以及任何适合您的操作。

    或者,您甚至可以使用 gmavenplus-plugin . 注意,maven如何将存储库位置设置到属性中 settings.localRepository 然后通过配置绑定到变量中 repository :

      <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>1.3</version>
        <executions>
          <execution>
            <phase>install</phase>
            <goals>
              <goal>execute</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <properties>
            <property>
              <name>repository</name>
              <value>${settings.localRepository}</value>
            </property>
          </properties>
          <scripts>
            <script><![CDATA[
              new File(repository).eachFileRecurse {
                if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
                  println 'Deleting snapshot ' + it.getAbsolutePath()
                  it.delete()
                }
              }
            ]]></script>
          </scripts>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.3.7</version>
            <scope>runtime</scope>
          </dependency>
        </dependencies>
      </plugin>  
    
        6
  •  0
  •   vaquar khan    8 年前

    在POM文件中添加以下参数

    聚甲醛

    <configuration>
    <outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
    </configuration>
    

    https://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html

    POM示例

    <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.10</version>
            <executions>
              <execution>
                <id>copy</id>
                <phase>package</phase>
                <goals>
                  <goal>copy</goal>
                </goals>
                <configuration>
                  <artifactItems>
                    <artifactItem>
                      <groupId>junit</groupId>
                      <artifactId>junit</artifactId>
                      <version>3.8.1</version>
                      <type>jar</type>
                      <overWrite>false</overWrite>
                      <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                      <destFileName>optional-new-name.jar</destFileName>
                    </artifactItem>
                  </artifactItems>
                  **<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>**
                  <outputDirectory>${project.build.directory}/wars</outputDirectory>
                  <overWriteReleases>false</overWriteReleases>
                  <overWriteSnapshots>true</overWriteSnapshots>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    

    在Jenkins中配置:

    // copy artifact 
    copyMavenArtifact(artifact: "commons-collections:commons-collections:3.2.2:jar", outputAbsoluteArtifactFilename: "${pwd()}/target/my-folder/commons-collections.jar")