Podman安装最新的JFrog Artifactory制品仓库

1、前言

JFrog Artifactory 是目前全球唯一的支持所有开发语言,功能最强大的二进制制品仓库。

2、系统平台

操作系统 : Ubuntu 22.04.4 LTS (GNU/Linux 6.5.0-26-generic x86_64)

3、安装依赖&拉取镜像

使用 OSS 社区版本,官方有详细说明介绍

完整的执行指令如下图所示

# 安装 podman
$ sudo apt install podman

# 创建一个低权限用户,尽量不要使用root用户,身份操作podman,降低安全风险
$ sudo adduser podman
 
# 允许用户下的容器在系统启动的时候启动服务
$ sudo loginctl enable-linger podman

$ export JFROG_HOME=/home/podman/.dockers/jfrogoss
 
# 准备本地目录映射 
$ sudo mkdir -p $JFROG_HOME/var/etc/

$ cd $JFROG_HOME/var/etc/

$ sudo touch ./system.yaml

$ sudo chown -R podman $JFROG_HOME

$ sudo chown -R 1030:1030 $JFROG_HOME/var

$ sudo chmod -R 777 $JFROG_HOME/var

# 手工拉去部分镜像,或者可以在 /etc/containers/registries.conf 配置下载服务器,可省略前面的服务器 releases-docker.jfrog.io 
$ podman pull releases-docker.jfrog.io/jfrog/artifactory-oss

执行上面的指令后,可以看到 releases-docker.jfrog.io/jfrog/artifactory-oss 镜像下载进度。

4、启动配置

首先要创建本地的数据目录,然后启动的时候挂载本地创建的数据目录即可。

执行启动指令: 

# 为 Docker 容器分配内存资源。可以使用 --memory 参数设置容器可以使用的内存量,使用 --memory-swap 参数限制交换空间的大小

$ podman run --name jfrogoss --cpus=2 --memory=2g --memory-swap=4g -d -v /home/podman/.dockers/jfrogoss/var:/var/opt/jfrog/artifactory -p 18081:8081 -p 18082:8082 releases-docker.jfrog.io/jfrog/artifactory-oss

# 查看该容器
$ podman ps

# 如果需要进入容器查看执行情况,参考如下命令
# podman exec -it jfrogoss bash

# 每次都启动新容器方式创建servcie //--new参数,每次启动都删除旧容器,启动一个新容器 
$ podman generate systemd --restart-policy=always -n --new -f jfrogoss

查看进程及IP跟端口号,启动一切正常了,打开浏览器访问系统看看效果。

查看启动文件:

$ cat container-jfrogoss.service

内容如下:

# container-jfrogoss.service
# autogenerated by Podman 3.4.4
# Sat Mar 30 19:04:05 CST 2024

[Unit]
Description=Podman container-jfrogoss.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers

[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --cgroups=no-conmon --rm --sdnotify=conmon --replace --name jfrogoss --cpus=2 --memory=2g --memory-swap=4g -d -v /home/podman/.dockers/jfrogoss/var:/var/opt/jfrog/artifactory -p 18081:8081 -p 18082:8082 releases-docker.jfrog.io/jfrog/artifactory-oss
ExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all

[Install]
WantedBy=default.target

需要额外注意的一个地方是,给出的路径必须是完整路径 “/home/podman/.dockers/jfrogoss”,不能是 “~/.dockers/jfrogoss”,Systemd不能正确展开 “~” ,导致路径找不到,从而在启动的时候失败,报告错误代码 125 。

Systemd 配置,开机/重启自动启动服务:

# 切换到刚刚创建的低权限用户 ,注意,必须使用 su - user 的方式切换
# 如果使用 su user 切换会导致环境变量被带到新用户,导致执行报错
# ERRO[0000] XDG_RUNTIME_DIR directory "/run/user/1000" is not owned by the current user 
 
$ su - podman

# 保存到 ~/.config/systemd/user/
$ mkdir .config

$ mkdir .config/systemd

$ mkdir .config/systemd/user

$ mv container-jfrogoss.service ~/.config/systemd/user/


# 以当前用户身份刷新配置文件,让其生效
$ systemctl --user daemon-reload

# 设置容器开机自启,并且现在启动
$ systemctl --user enable --now ~/.config/systemd/user/container-jfrogoss.service

# 如果需要进入容器查看执行情况,参考如下命令
# podman exec -it jfrogoss bash

# 测试,重启系统,观察是否能开机自动启动
$ sudo reboot

# 启动或重启服务
# systemctl --user start container-jfrogoss.service
# systemctl --user restart container-jfrogoss.service

# 如果启动失败,观察服务日志
# sudo journalctl -f

5、访问、登录

Access Artifactory from your browser at: 

http://SERVER_HOSTNAME:18082/ui/

For example, on your local machine: 

http://localhost:18082/ui/

默认用户名:admin, 密码: password

启用匿名访问:

Maven服务器配置

客户端配置 http://SERVER_HOSTNAME:18082/artifactory/maven-remote/

参考链接


macOS Catalina(10.15.4)/IntelliJ IDEA 2018.3/Tomcat 9.0.33/Maven项目调试报错"Caused by: java.util.zip.ZipException: zip file is empty"

macOS Catalina(10.15.4)/IntelliJ IDEA 2018.3/Tomcat 9.0.33/Maven项目调试时报错,这个项目以前是可以正常调试的,一段时间之后,就不能正常调试之下了

继续阅读macOS Catalina(10.15.4)/IntelliJ IDEA 2018.3/Tomcat 9.0.33/Maven项目调试报错"Caused by: java.util.zip.ZipException: zip file is empty"

struts2升级之后报错“java.lang.NoSuchMethodError: org.apache.commons.lang3.reflect.MethodUtils.getAnnotation”

struts2 从如下版本:

<struts2.version>2.5.10.1</struts2.version>
<apache.commons.version>3.5</apache.commons.version>

升级到

<struts2.version>2.5.20</struts2.version>

之后报错如下:

四月 13, 2019 10:07:59 上午 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet [default] in context with path [] threw exception [Filter execution threw an exception] with root cause
java.lang.NoSuchMethodError: org.apache.commons.lang3.reflect.MethodUtils.getAnnotation(Ljava/lang/reflect/Method;Ljava/lang/Class;ZZ)Ljava/lang/annotation/Annotation;
	at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:44)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.doIntercept(ConversionErrorInterceptor.java:142)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:137)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:137)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:201)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:67)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:133)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:89)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:101)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:142)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:160)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:175)
	at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at org.apache.struts2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:121)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:167)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:203)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:196)
	at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
	at org.apache.struts2.factory.StrutsActionProxy.execute(StrutsActionProxy.java:48)
	at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:574)
	at org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:79)
	at org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:141)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:1025)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1137)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:317)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:745)

解决方法为升级

<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-lang3</artifactId>
	<version>${apache.commons.version}</version>
</dependency>

到更高的版本,如下:

<struts2.version>2.5.20</struts2.version>
<apache.commons.version>3.8.1</apache.commons.version>

参考链接


java.lang.NoSuchMethodError: org.apache.commons.lang3.math.NumberUtils.isCreatable(Ljava/lang/String

Maven 打包时丢失".properties"文件

今天在打包项目war文件的时候,突然发现居然每个action包里面的properties文件都没打进来,在网上看了半天终于找到解决方法。

问题:maven执行package命令打包时,src/main/java路径下的properties文件全部丢失。

继续阅读Maven 打包时丢失".properties"文件

解决Apache Archiva下载文件超时的问题

注意: Apache Archiva 2024-02 开始已经停止维护 建议使用 JFrog Artifactory 替代。

最近使用自己搭建的Apache Archiva来代理Maven仓库,经常发生失败的情况,观察Archiva的日志(logs/archiva.log),看到如下的内容:

2016-11-22 19:52:02,773 [ajp-bio-127.0.0.1-8009-exec-74] WARN  org.apache.archiva.proxy.DefaultRepositoryProxyConnectors [] - Transfer error from repository central for artifact org.mockito:mockito-core:2.2.22::jar , continuing to next repository. Error message: Download failure on resource [https://repo.maven.apache.org/maven2/org/mockito/mockito-core/2.2.22/mockito-core-2.2.22.jar]:GET request of: org/mockito/mockito-core/2.2.22/mockito-core-2.2.22.jar from central failed (cause: java.net.SocketTimeoutException: Read timed out)
2016-11-22 19:52:02,773 [ajp-bio-127.0.0.1-8009-exec-74] ERROR org.apache.archiva.webdav.ArchivaDavResourceFactory [] - Failures occurred downloading from some remote repositories:
        central: Download failure on resource [https://repo.maven.apache.org/maven2/org/mockito/mockito-core/2.2.22/mockito-core-2.2.22.jar]:GET request of: org/mockito/mockito-core/2.2.22/mockito-core-2.2.22.jar from central failed (cause: java.net.SocketTimeoutException: Read timed out)
org.apache.archiva.policies.ProxyDownloadException: Failures occurred downloading from some remote repositories:
        central: Download failure on resource [https://repo.maven.apache.org/maven2/org/mockito/mockito-core/2.2.22/mockito-core-2.2.22.jar]:GET request of: org/mockito/mockito-core/2.2.22/mockito-core-2.2.22.jar from central failed (cause: java.net.SocketTimeoutException: Read timed out)
        at org.apache.archiva.proxy.DefaultRepositoryProxyConnectors.fetchFromProxies(DefaultRepositoryProxyConnectors.java:366) ~[archiva-proxy-2.2.1.jar:?]
        at org.apache.archiva.webdav.ArchivaDavResourceFactory.fetchContentFromProxies(ArchivaDavResourceFactory.java:820) [archiva-webdav-2.2.1.jar:?]
        at org.apache.archiva.webdav.ArchivaDavResourceFactory.processRepository(ArchivaDavResourceFactory.java:629) [archiva-webdav-2.2.1.jar:?]
        at org.apache.archiva.webdav.ArchivaDavResourceFactory.createResource(ArchivaDavResourceFactory.java:325) [archiva-webdav-2.2.1.jar:?]
        at org.apache.archiva.webdav.RepositoryServlet.service(RepositoryServlet.java:126) [archiva-webdav-2.2.1.jar:?]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api-3.0.jar:?]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [tomcat-catalina-7.0.52.jar:7.0.52]
        at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:193) [tomcat-coyote-7.0.52.jar:7.0.52]
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) [tomcat-coyote-7.0.52.jar:7.0.52]
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313) [tomcat-coyote-7.0.52.jar:7.0.52]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [?:1.7.0_111]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [?:1.7.0_111]
        at java.lang.Thread.run(Thread.java:745) [?:1.7.0_111]

明显是从https://repo.maven.apache.org/maven2这个地址下载数据的时候发生了异常。这个仓库的地址是Apache Archiva中的默认仓库地址。从目前的测试来看,这个地址在国内访问,经常出现问题。对于国内用户来说https://repo1.maven.org/maven2这个中央仓库的地址是相对来说更加稳定。因此只要在Remote Repositories中增加这个中央仓库地址即可。
如下图操作:

repositorylist

add_repository

另外,在添加完成后,顺便在属性中修改一下Download Timeout,从默认的60秒修改到600秒,减少超时的发生即可。

如上操作只能部分解决问题,在现实过程中,依旧会发生失败,失败主要集中在下载https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.gz这个索引文件的时候,这个索引文件有300-400MB的样子,一次完整的下载基本上是都会失败,要命的是Apache Archiva在处理这个文件的时候,基本上没有进行任何容错处理。这个时候我们要么修改源代码来修正,要么需要辅助Apache Archiva完成这个文件的下载。

下面,我们实验通过Linux定时任务,nginxaria2来实现对Apache Archiva下载的辅助处理。

1.首先安装必须的软件

$ sudo apt-get install nginx

$ sudo apt-get install aria2

2.接下来,配置nginx

$ sudo vim /etc/nginx/sites-enabled/default

整个配置文件的原文如下:

##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# http://wiki.nginx.org/Pitfalls
# http://wiki.nginx.org/QuickStart
# http://wiki.nginx.org/Configuration
#
# Generally, you will want to move this file somewhere, and start with a clean
# file but keep this around for reference. Or just disable in sites-enabled.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
	listen 80 default_server;
	listen [::]:80 default_server;

	# SSL configuration
	#
	# listen 443 ssl default_server;
	# listen [::]:443 ssl default_server;
	#
	# Note: You should disable gzip for SSL traffic.
	# See: https://bugs.debian.org/773332
	#
	# Read up on ssl_ciphers to ensure a secure configuration.
	# See: https://bugs.debian.org/765782
	#
	# Self signed certs generated by the ssl-cert package
	# Don't use them in a production server!
	#
	# include snippets/snakeoil.conf;

	root /var/www/html;

	# Add index.php to the list if you are using PHP
	index index.html index.htm index.nginx-debian.html;

	server_name _;

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		try_files $uri $uri/ =404;
	}

	# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
	#
	#location ~ \.php$ {
	#	include snippets/fastcgi-php.conf;
	#
	#	# With php7.0-cgi alone:
	#	fastcgi_pass 127.0.0.1:9000;
	#	# With php7.0-fpm:
	#	fastcgi_pass unix:/run/php/php7.0-fpm.sock;
	#}

	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	#location ~ /\.ht {
	#	deny all;
	#}
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#	listen 80;
#	listen [::]:80;
#
#	server_name example.com;
#
#	root /var/www/example.com;
#	index index.html;
#
#	location / {
#		try_files $uri $uri/ =404;
#	}
#}

修改后的结果如下:

##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# http://wiki.nginx.org/Pitfalls
# http://wiki.nginx.org/QuickStart
# http://wiki.nginx.org/Configuration
#
# Generally, you will want to move this file somewhere, and start with a clean
# file but keep this around for reference. Or just disable in sites-enabled.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
	#listen 80 default_server;
	#listen [::]:80 default_server;
	listen 127.0.0.1:8090 default_server;
	# SSL configuration
	#
	# listen 443 ssl default_server;
	# listen [::]:443 ssl default_server;
	#
	# Note: You should disable gzip for SSL traffic.
	# See: https://bugs.debian.org/773332
	#
	# Read up on ssl_ciphers to ensure a secure configuration.
	# See: https://bugs.debian.org/765782
	#
	# Self signed certs generated by the ssl-cert package
	# Don't use them in a production server!
	#
	# include snippets/snakeoil.conf;

	root /data/nginx/maven_index;

	# Add index.php to the list if you are using PHP
	index index.html index.htm index.nginx-debian.html;

	server_name _;

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		try_files $uri $uri/ =404;
		resolver 114.114.114.114 218.85.152.99;
		resolver_timeout 30s;
		
		#nginx 不支持if嵌套也不支持多条件判断,因此只能用下面的方式来模拟
		#留意判断语句与括号之间的空格,缺失空格会导致语法错误		
		#if ( ( $host ~* "repo1\.maven\.org" ) && ( $request_uri ~* "maven2/\.index" ) ) {
		set $flag 0;
		if ( $host ~* "repo1\.maven\.org" ) {
			set $flag "${flag}1";
		}
		if ( $request_uri ~* "maven2/\.index" ) {
			set $flag "${flag}2";
		}
		if ($flag = "012") {
			proxy_pass http://127.0.0.1:8090$request_uri;
		}
		#避免循环重定向问题
 		if ( $host != "127.0.0.1" ) {
			proxy_pass http://$host$request_uri;
		}		
	}

	# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
	#
	#location ~ \.php$ {
	#	include snippets/fastcgi-php.conf;
	#
	#	# With php7.0-cgi alone:
	#	fastcgi_pass 127.0.0.1:9000;
	#	# With php7.0-fpm:
	#	fastcgi_pass unix:/run/php/php7.0-fpm.sock;
	#}

	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	#location ~ /\.ht {
	#	deny all;
	#}
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#	listen 80;
#	listen [::]:80;
#
#	server_name example.com;
#
#	root /var/www/example.com;
#	index index.html;
#
#	location / {
#		try_files $uri $uri/ =404;
#	}
#}

接下来,重启nginx服务。

3.设置定时任务,定时检查远端服务器上的数据是否有更新

任务脚本内容如下:

nginx_dir="/data/nginx"
mvn_idx_dir="$nginx_dir/maven2/.index"
mvn_idx_dl_dir="$nginx_dir/maven2/.CacheIndex"
mvn_idx_name="nexus-maven-repository-index"
mvn_idx_path_name="$mvn_idx_dir/$mvn_idx_name"
mvn_idx_gz_name="$mvn_idx_dir/$mvn_idx_name.gz"
mvn_idx_prop_name="$mvn_idx_dir/$mvn_idx_name.properties"
mvn_idx_dl_gz_name="$mvn_idx_dl_dir/$mvn_idx_name.gz"
mvn_idx_dl_prop_name="$mvn_idx_dl_dir/$mvn_idx_name.properties"
log_file="/data/nginx/maven_index_log.txt"
dt_fmt="`date "+%Y-%m-%d %H:%M:%S"`"



if [ ! -d $mvn_idx_dl_dir ]; then
	mkdir -p $mvn_idx_dl_dir
fi

if [ ! -d $mvn_idx_dir ]; then
	mkdir -p $mvn_idx_dir
fi

if [ ! -d $mvn_idx_dl_dir ]; then
	echo "$dt_fmt	mkdir $mvn_idx_dl_dir failed !" >> $log_file
	exit -1 
fi

if [ ! -d $mvn_idx_dir ]; then
	echo "$dt_fmt	mkdir $mvn_idx_dir failed !" >> $log_file
	exit -1 
fi

cd $mvn_idx_dl_dir

dl_idx="true"
dl_prop="true"

#echo mvn_idx_gz_name="$mvn_idx_gz_name"
#先检查是不是需要下载文件,然后再下载文件,减少不必要的网络请求数据
if [ -f "$mvn_idx_gz_name" ]; then
	remote_idx_md5=$(curl -s https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.gz.md5)
	 
	if [ "${#remote_idx_md5}" != "32" ] ; then
		echo "$dt_fmt	download $mvn_idx_gz_name.md5 failed !" >> $log_file
		exit -1
	fi
	local_idx_md5=$(md5sum $mvn_idx_gz_name | cut -b 1-32)
	
	#echo remote_idx_md5="$remote_idx_md5" local_idx_md5="$local_idx_md5"
	if [ "$remote_idx_md5" = "$local_idx_md5" ] ; then
		dl_idx="false"
		if [ -f "$mvn_idx_prop_name" ]; then
			remote_prop_md5=$(curl -s https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.properties.md5)
			if [ "${#remote_prop_md5}" != "32" ] ; then
				echo "$dt_fmt	download $mvn_idx_prop_name failed !" >> $log_file
				exit -1
			fi
			local_prop_md5=$(md5sum $mvn_idx_prop_name | cut -b 1-32)
			if [ "$remote_prop_md5" = "$local_prop_md5" ] ; then
				dl_prop="false"
				echo "$dt_fmt	check file success ,no need to update !" >> $log_file
				exit 0
			fi
		fi
	fi
fi

if [ "$dl_idx" = "true" ] ; then
	aria2c -c https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.gz
	aria2c -c https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.gz.md5
	aria2c -c https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.gz.sha1
fi

if [ "$dl_prop" = "true" ] ; then
	aria2c -c https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.properties
	aria2c -c https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.properties.md5
	aria2c -c https://repo1.maven.org/maven2/.index/nexus-maven-repository-index.properties.sha1
fi

#校验下载到的文件
if [ "$dl_idx" = "true" ] ; then
	dl_idx_md5=$(md5sum $mvn_idx_dl_gz_name | cut -b 1-32)
	dl_idx_f_md5=$(cat $mvn_idx_dl_gz_name.md5)
	if [ "$dl_idx_md5" = "$dl_idx_f_md5" ] ; then
		rm -rf $mvn_idx_gz_name
		mv $mvn_idx_dl_gz_name $mvn_idx_gz_name
		rm -rf $mvn_idx_gz_name.md5 
		mv $mvn_idx_dl_gz_name.md5 $mvn_idx_gz_name.md5
		rm -rf $mvn_idx_gz_name.sha1
		mv $mvn_idx_dl_gz_name.sha1 $mvn_idx_gz_name.sha1
	else
		echo "$dt_fmt	check downloaded index file failed !" >> $log_file
		cd  $nginx_dir
		rm -rf $mvn_idx_dl_dir
	fi
fi

if [ "$dl_prop" = "true" ] ; then
	dl_prop_md5=$(md5sum $mvn_idx_dl_prop_name | cut -b 1-32)
	dl_prop_f_md5=$(cat $mvn_idx_dl_prop_name.md5)
	if [ "$dl_prop_md5" = "$dl_prop_f_md5" ] ; then
		rm -rf $mvn_idx_prop_name
		mv $mvn_idx_dl_prop_name $mvn_idx_prop_name
		rm -rf $mvn_idx_prop_name.md5 
		mv $mvn_idx_dl_prop_name.md5 $mvn_idx_prop_name.md5
		rm -rf $mvn_idx_prop_name.sha1
		mv $mvn_idx_dl_prop_name.sha1 $mvn_idx_prop_name.sha1
	else
		echo "$dt_fmt	check downloaded properties file failed !" >> $log_file
		cd  $nginx_dir
		rm -rf $mvn_idx_dl_dir
	fi
fi

默认我们把脚本执行路径为/data/nginx/mvn_index_corn.sh

设置定时任务的脚本如下:

chmod +x /data/nginx/mvn_index_corn.sh
#write out current crontab
crontab -l > addcron
#echo new cron into cron file ,每隔30分钟我们调度一次任务,前面是文件锁,防止并发冲突
echo "30 * * * * flock -x -w 10 /dev/shm/mvn_index_corn.lock -c \"sh /data/nginx/mvn_index_corn.sh\"" >> addcron
#install new cron file
crontab addcron
rm addcron

执行上面的脚本。

4.设置Apache Archiva的代理服务器配置

使用junit测试IntelliJ IDEA 2016.2建立的maven项目

maven project项目中引入junit插件并不困难,只需要在pom.xml中配置好依赖包即可(IDE环境下,依赖项会自动生成)。另外,test类文件需要按照/src/main/java/的文件结构(main改为test)。
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>com.test</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <!--junit 的版本-->
        <junit.version>4.12</junit.version>
    </properties>

    <dependencies>
        <!-- 单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

如下图:

mavenjunitpath

在Ubuntu 14.04 系统中的Apache Tomcat上部署Apache Archiva 2.2.1

注意: Apache Archiva 2024-02 开始已经停止维护 建议使用 JFrog Artifactory 替代。

简介


Apache Archiva是一套可扩展的Artifact Repository管理系统。它能够与MavenContinuumANT等构建工具完美结合。Archiva提供的功能包括:远程Repository代理,基于角色的安全访问管理,Artifact分发、维护、查询,生成使用报告,提供基于Web的管理界面等。 本来是Sonatype Nexus更加方便的,但是可惜最新的版本不支持在Tomcat中使用了,因此只能转而使用Apache Archiva

操作步骤


1.下载Apache Archiva

Apache官方网站下载,下载其中的War包。如下图: DownloadArchivaHtml 也可以在本站下载. 具体的命令如下:

$ wget https://www.mobibrw.com/wp-content/uploads/2016/07/apache-archiva-2.2.1.war_.zip

$ unzip apache-archiva-2.2.1.war_.zip

$ sudo mv apache-archiva-2.2.1.war /var/lib/tomcat7/webapps/archiva.war

 

2.下载Apache Archiva依赖的Jar包

Apache Archiva需要依赖derby-10.10.1.1.jar(或更高版本)(org.apache.derby:derby:10.10.1.1), activation-1.1.jar(javax.activation:activation:1.1),mail-1.4.jar(javax.mail:mail:1.4.7).可以在MVN Repository官网下载。也可以在本站打包下载。 下载完成后,需要放到Tomcat的安装目录下面的lib目录下。 具体的命令如下:

$ wget https://www.mobibrw.com/wp-content/uploads/2016/07/ArchivaArchiveJars.zip

$ unzip ArchivaArchiveJars.zip

$ sudo mv activation-1.1.jar /usr/share/tomcat7/lib

$ sudo mv derby-10.10.1.1.jar /usr/share/tomcat7/lib

$ sudo mv mail-1.4.7.jar /usr/share/tomcat7/lib

 

3.配置Apache Archiva

(1)停止Tomcat,后续的操作是先关闭Tomcat为前提的。

$ sudo service tomcat7 stop

(2)把下载到的apache-archiva-2.2.1.war重命名成archiva.war然后放到Tomcat安装目录下的webapps目录下面。

$ wget https://www.mobibrw.com/wp-content/uploads/2016/07/apache-archiva-2.2.1.war_.zip

$ unzip apache-archiva-2.2.1.war_.zip

$ sudo mv apache-archiva-2.2.1.war /var/lib/tomcat7/webapps/archiva.war

(3)在Tomcat的配置文件中增加两项appserver.homeappserver.base,两者都指向相同的目录即可,本例中,都指向了/data/Archiva这个目录。

$ mkdir /data/Archiva

$ sudo vim /usr/share/tomcat7/bin/setenv.sh

在脚本的第一行执行代码中增加如下内容:

export CATALINA_OPTS="-Dappserver.home=/data/Archiva -Dappserver.base=/data/Archiva"

注意:不要直接修改catalina.sh这个文件,原因在于这个文件每次更新都可能会被替换掉,环境变量的设置都应该在setenv.sh中设置。
注意catalina.sh这个文件中的如下注释

#   Do not set the variables in this script. Instead put them into a script
#   setenv.sh in CATALINA_BASE/bin to keep your customizations separate.

(4)由于Apache Archiva 2.2.1BUG,他没有自动创建必须的目录,导致如果这个目录不存在会初始化失败。因此我们需要手动创建这些目录。

$ mkdir /data/Archiva/conf

$ mkdir /data/Archiva/derby

$ mkdir /data/Archiva/logs

$ chown -R tomcat7:tomcat7 /data/Archiva/

(5)在Tomcat的配置目录下的Catalina\localhost目录下面创建一个名为archiva.xml的配置文件.

$ sudo vim /etc/tomcat7/Catalina/localhost/archiva.xml

里面的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/data/Archiva/derby" 
	docBase="${catalina.base}/webapps/archiva.war">
	<Resource name="jdbc/users" auth="Container" type="javax.sql.DataSource"
		username="sa"
		password=""
		driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
		url="jdbc:derby:/data/Archiva/derby/db;create=true" />

	<Resource name="mail/Session" auth="Container"
		type="javax.mail.Session"
		mail.smtp.host="localhost"/>
</Context>

注意其中的Context path为数据库相关配置文件所在的路径,包含配置,数据库等等很多文件,url为数据库的具体存储目录,仅仅包含数据库数据。 注意:Ubuntu系统下面CATALINA_HOME指向/usr/share/tomcat7,而CATALINA_BASE指向/var/lib/tomcat7

(6)启动或者重启Tomcat,等待几分钟之后,即可成功配置完成。

$ sudo service tomcat7 start

如下图: ApacheArchivaIndexPage 注意,如果在最后一步发生失败,那么我们需要删除/data/Archiva这个目录,以及Tomcat安装目录下面的webapps\archiva这两个目录,原因是在配置过程中修改了部分文件,如果不删除这几个文件,会导致各种异常。

注意,上图中的"Create Admin User"按钮,当创建用户的时候,貌似用户名是可以不用"admin"的,但是,实际上,管理员的用户名是不变的,不管你输入什么,最后登陆的时候填写的用户名,永远必须是"admin",否则会一直提示用户名或密码不正确。

注意,如果使用Apache Httpd(Apache 2.x)作为前端代理Tomcat的情况下部署Apache Archiva,并且使用AJPApache JServ Protocol)的方式进行通信,那么在配置Apache Httpd(Apache 2.x)的配置文件的时候,里面写入的名字必须严格跟Tomcat中部署的名字一致,比如,如果Tomcat配置的时候是archiva,那么在Apache Httpd(Apache 2.x)的配置文件中,也必须使用archiva,不能像其他简单项目一样进行命名重定向。如下:

$ sudo vim /etc/apache2/sites-available/000-default.conf

里面增加的AJP代理信息如下:

#for Apache Archiva
#此处的名字不可改变,对于Apache Archiva,由于他会进行304重定向,因此
#如果这里的名字跟Tomcat中部署的如果不同名,那么会出现登陆后无法进入控制
#页面的问题
ProxyPass /archiva/ ajp://127.0.0.1:8009/archiva/
ProxyPassReverse /archiva/ ajp://127.0.0.1:8009/archiva/

更详细的配置说明,参考 Ubuntu 13.10 Apache 2.2 通过 AJP 整合 Tomcat 7

客户端配置


在客户机上找到.m2所在的目录,找到settings.xml这个配置文件,如果不存在,则手工创建,里面的默认内容如下:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
            http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <localRepository/>
    <interactiveMode/>
    <usePluginRegistry/>
    <offline/>
    <pluginGroups/>
    <servers/>
    <mirrors/>
    <proxies/>
    <profiles/>
    <activeProfiles/>
</settings>

在其中的mirrors中间增加如下内容:

<mirror>
	<id>internal</id>
	<name>Archiva Managed Internal Repository</name>
	<url>http://www.mobibrw.com/archiva/repository/internal</url>
	<mirrorOf>*</mirrorOf>
</mirror>

修改后的内容变成如下样子:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
            http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <localRepository/>
    <interactiveMode/>
    <usePluginRegistry/>
    <offline/>
    <pluginGroups/>
    <servers/>
    <mirrors>
		<mirror>
			<id>internal</id>
			<name>Archiva Managed Internal Repository</name>
			<url>http://www.mobibrw.com/archiva/repository/internal</url>
			<mirrorOf>*</mirrorOf>
		</mirror>
	</mirrors>
    <proxies/>
    <profiles/>
    <activeProfiles/>
</settings>

目前使用的时候,发现,在Apache Archiva刚刚配置完成后,是没办法进行访问的,这个时候一切都返回404,等服务器启动几个小时之后,从中央服务器同步完成数据了,就可以进行访问了,这个问题纠结了好久,最后发现只要等待就可以了,不知道是不是一个通病。
另外就是,在Apache Archiva的搜索页面中使用Search,如果是第一次使用,会发现搜索任何包都提示找不到,原因是因为在设计的时候,只搜索本地已经下载过的包,而在中央仓库中的包是不搜索的,因此会一直提示找不到任何包,只要有任何的客户端调用过,那么就可以在搜索页中找到了,这个问题不必纠结。

引用链接


mvn报错:No goals have been specified for this build

选择【Run As】-【Maven build】的时候,报:

[INFO] Scanning for projects…[INFO]
[INFO] BUILD FAILURE[INFO]
[INFO] Total time: 0.109s[INFO] Finished at: Wed Apr 13 11:04:20 CST 2011[INFO] Final Memory: 1M/4M[INFO]
ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal> or <plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. Available lifecycle phases are: validate, initialize, generate-sources, process-sources, generate-resources,
process-resources, compile, process-classes, generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-
test-classes, test, prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy, pre-site, site, post-site, site-deploy,
pre-clean, clean, post-clean. -> [Help 1][ERROR] [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.[ERROR] Re-run Maven using the -X switch to enable full debug logging.[ERROR] [ERROR] For more information about the errors and possible solutions, please read the following articles:[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoGoalSpecifiedException

eclipse安装的maven插件是m2eclipse,在控制台使用命令mvn compile并未报错。后在pom.xml文件<build>标签后面加上

<defaultGoal>compile</defaultGoal>

即可。

其实使用命令行时就已经指定了phase,而使用m2eclipse的【Run As】-【Maven build】时并未为其指定goal或phase,所以才报这个错误。