/etc/systemd/system/my-application.service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[Unit]
Description=ApplicationName

[Service]
StartLimitInterval=5
StartLimitBurst=10
Restart=always
RestartSec=120
StandardOutput=append:/data/project/logs/stdout.log
StandardError=append:/data/project/logs/stderr.log
WorkingDirectory=/opt/project
ExecStart=/usr/local/java/jdk-21.0.3+9-jre/bin/java \
-XX:+ExitOnOutOfMemoryError \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/data/project/dumps/oom.bin \
-Dspring.profiles.active= \
-Dspring.config.location=classpath:application.yml,/opt/project/application.yml \
-Dlogging.config=/opt/project/logback.xml \
-jar /opt/project/project.jar

[Install]
WantedBy=multi-user.target
1
2
3
4
5
systemctl daemon-reload

systemctl status my-application.service
# 开机自启动
systemctl enable my-application.service

build.gradle

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
plugins {
id 'java'
id 'maven-publish'
id 'org.springframework.boot' version '3.3.1'
id 'io.spring.dependency-management' version '1.1.5'
id 'org.springframework.boot.experimental.thin-launcher' version '1.0.31.RELEASE'
}

bootJar {
archiveFileName = "${project.name}.jar"
}

thinJar {
archiveFileName = "${project.name}-thin.jar"
}

thinResolvePrepare {
delete file('thin')
into file('thin')
}

publishing {
publications {
maven(MavenPublication) {
from components.java
}
}
}

generatePomFileForMavenPublication {
destination = file('pom.xml')
}

生成 pom.xml

1
./gradlew generatePomFileForMavenPublication

编译生成 thin jar 包

1
./gradlew clean thinResolvePrepare

缓存 maven 依赖

1
./mvnw dependency:resolve

生成 thin jar 依赖结构

1
java -Dthin.dryrun=true -Dthin.root=thin -Dthin.repo=https://maven.aliyun.com/repository/public -jar thin/${project.name}-thin.jar

可能需要的命令

1
2
3
rsync -avzh thin/repository/ server:/opt/project/repository/

scp thin/${project.name}-thin.jar server:/opt/project/${project.name}.jar

~/.m2/settings.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="UTF-8"?>
<settings
xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<mirrors>
<mirror>
<id>aliyun</id>
<mirrorOf>*</mirrorOf>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public/</url>
</mirror>
</mirrors>
</settings>

~/.gradle/init.gradle

1
2
3
4
5
6
7
8
9
10
11
12
13
allprojects {
buildscript {
repositories {
maven { url 'https://maven.aliyun.com/repository/gradle-plugin/' }
mavenLocal()
}
}
repositories {
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/spring/' }
mavenLocal()
}
}

build.gradle

1
2
3
4
5
6
7
8
9
10
11
12
buildscript {
repositories {
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
mavenLocal()
}
}

repositories {
maven { url 'https://maven.aliyun.com/repository/public' }
maven { url 'https://maven.aliyun.com/repository/spring' }
mavenLocal()
}

在根目录创建文件夹 scripts,在文件夹中创建文件 gitalk-init.js,内容如下:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
const axios = require("axios")
const md5 = require("md5")

const options = {
owner: "starudream",
repo: "blog-page",
accessToken: "<<placeholder>>",
labels: "Gitalk,",
}

const axiosGithub = axios.create({
baseURL: "https://api.github.com",
headers: {
"Accept": "application/json",
},
})

const getIssueByLabels = (id) => {
return axiosGithub.get(`/repos/${options.owner}/${options.repo}/issues`, {
headers: {
Authorization: `token ${options.accessToken}`,
},
params: {
labels: options.labels.concat(id),
t: Date.now(),
},
}).then(res => {
if (res && res.data && res.data.length) {
return res.data[0]
}
return null
})
}

const createIssue = (title, body, id) => {
return axiosGithub.post(`/repos/${options.owner}/${options.repo}/issues`, {
title,
labels: options.labels.concat(id).split(","),
body: body,
}, {
headers: {
Authorization: `token ${options.accessToken}`,
},
}).then(res => {
return res.data
})
}

hexo.extend.generator.register("gitalk-init", locals => {
locals.posts.each(post => {
if (post.layout !== "post" || !post.published || !post.comments) return
const title = post.title + " | " + hexo.config.title
const path = "/" + post.path
const hash = md5(path)
getIssueByLabels(hash).then(res => {
if (res) {
console.log(`【${title}】has existed`)
return
}
createIssue(title, post.permalink, hash).then(res => {
console.log(`【${title}】has created`)
})
})
})
})

然后运行 hexo generate --force 即会自动执行 scripts 内脚本文件。