Mr. Kin's Blog

计算机知识分享/软件应用讲解

1   数组和字符串

1.1   数组

  • 集合的定义:由一个或多个确定的元素所构成的整体。
  • 集合的特性:
    • 集合里的元素类型不一定相同
    • 集合里的元素没有顺序
  • 列表(又称线性列表)的定义:是一种数据项构成的有限序列,即按照一定的线性顺序,排列而成的数据项的集合。
    • 列表的概念是在集合的特征上形成的,它具有顺序,且长度是可变的。
    • 列表最常见的表现形式:数组和链表
      • C++和Java中,数组中的元素类型必须保持一致。
      • Python数组叫list,元素类型可以不同,具有更多高级功能。
    • 特殊类型的列表:栈和队列
  • 列表和数组的区别
    • 数组
      • 数组有索引,用来标识每项数据在数组中的位置,且在大多数编程语言中,索引是从 0 算起的。
      • 数组中的元素在内存中是连续存储,且每个元素占用的相同大小内存。
    • 列表
      • 列表没有索引
      • 列表中的元素在内存中可能彼此相邻,也可能不相邻。例如链表。

1.2   数组的操作

对于数组,计算机会在内存中为其申请一段连续的空间,并且会记下索引为 0 处的内存地址

  • 读取元素:读取数组中的元素,是通过访问索引的方式来读取的,索引一般从 0 开始。寻找索引为2的元素,实际就是在索引为0的元素内存地址上偏移+2得到新地址的元素。
    • 时间复杂度:O(1)
  • 查找元素:由于只保存了索引为 0 处的内存地址,因此需要从数组开头逐步向后查找。
    • 时间复杂度:O(N)
  • 插入元素
    • 末尾插入:只需要一步(根据数组的长度和位置计算出需插入元素的内存地址插入即可)。
    • 中间插入:需要在数组中腾出空间,才能继续操作插入(这种操作,更推荐使用链表)。
  • 删除元素:与插入元素类似
    • 末尾删除:只需要一步
    • 中间删除:删除中间元素后,后面的元素需要对该位置进行操作
    • 时间复杂度:O(N)。数组长度N,例如删除第一个元素,总步骤数:1+(N-1)=N。(1为删除操作,N-1为移动操作)

1.3   字符串

字符串是由字符串数组形成的。

2   参考文献

[1] 数组和字符串[EB/OL]. https://leetcode.cn/leetbook/detail/array-and-string/.

“程序设计类教学辅助教学平台”(Programming Teaching Assistant,亦简称 PTA)(依稀记得以前这玩意叫PAT),面向高校和社会的程序自动评测、开放式的教学辅助平台。

练习代码文件的仓库链接:点击跳转

难点题解主要参考PAT(tiny656)和[PAT(枝桠)]

基础编程题目集PTA平台

函数题

6-1 简单输出整数PTA平台

简单的for循环运用

6-2 多项式求值PTA平台

先罗列多项式值,分析构成规律,再去考虑如何编写逻辑。(当年我是傻乎乎分开两个for循环处理,因此导致会导致部份用例运行超时)

6-3 简单求和PTA平台

for循环中应为i<N,注意main函数最后赋值的下标,即需要保持和main函数中for循环的条件一致。(当年是挺傻乎乎的)

6-4 求自定类型元素的平均PTA平台

for循环中应为i<N,注意main函数最后赋值的下标,即需要保持和main函数中for循环的条件一致。

6-5 求自定类型元素的最大值PTA平台

for循环中应为i<N,注意main函数最后赋值的下标,即需要保持和main函数中for循环的条件一致。

第一个MaxNum应该设为数组里的元素。如果设为0的话,当元素全为负数时,没法输出最大值。(也不知道我当年是怎么想出这种傻乎乎的逻辑)

1   docker的基础命令操作

命令功能注释
docker ps列出当前正在运行的容器
docker ps -a列出所有容器(包括已停止的容器)
docker logs container_name查看指定容器的日志
docker inspect container_name/image获取指定容器或镜像的详细信息
docker exec -it container_name /bin/bash进入指定容器的交互式终端-i: 交互式操作
-t: 终端
-it:以交互式终端运行容器,例如 docker exec -it container_name bash
docker stop container_name停止一个或多个容器
docker rm container_name删除一个或多个容器
docker rmi image-name:tag删除一个或多个镜像不加tag则会删除所有
docker run image-name --name container_name -d启动一个新的容器并运行命令
docker start container_name启动已停止的容器
docker restart container_name重启一个容器
docker version显示 Docker 客户端和守护进程的版本信息
docker network ls列出所有 Docker 网络
docker volume ls列出所有 Docker 卷
docker images ls列出本地存储的所有镜像
docker compose -f docker-compose.yml up -d启动多容器应用(从 docker-compose.yml 文件)-d:后台运行容器,例如 docker run -d ubuntu
docker compose -f docker-compose.yml down停止并删除由 docker-compose 启动的容器、网络等
docker compose logs -f docker-compose.yml查看指定compose的运行日志
docker info显示 Docker 系统的详细信息
docker stats显示容器的实时资源使用情况
docker builder prune删除所有未被使用的构建缓存
docker builder prune --filter 'until=240h'删除所有未被使用的构建缓存,并保留最近10天的缓存
docker system prune清理磁盘,删除关闭的容器、无用的数据卷和网络,以及dangling镜像(即无tag的镜像)
docker system prune -a比上面命令清理得更加彻底,没有容器使用Docker镜像都会被删掉

2   使用apt仓库为Debian安装docker

2.1   添加Docker的官方GPG密钥

1
2
3
4
5
6
apt update
apt install ca-certificates -y
install -m 0755 -d /etc/apt/keyrings
# 可能下载会出现ssl验证错误,多重复执行几次wget下载就能成功下载
wget https://download.docker.com/linux/debian/gpg -O /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc

2.2   添加Docker的官方仓库

1
2
3
4
5
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update

2.3   安装Docker

1
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

2.4   验证Docker版本

1
2
docker -v
docker version

2.5   修改Docker镜像源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<EOF
{
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.mybacc.com",
"https://dytt.online",
"https://lispy.org",
"https://docker.xiaogenban1993.com",
"https://docker.yomansunter.com",
"https://aicarbon.xyz",
"https://666860.xyz",
"https://docker.zhai.cm",
"https://a.ussh.net",
"https://hub.littlediary.cn",
"https://hub.rat.dev",
"https://docker.m.daocloud.io"
]
}
EOF

2.6   重启相关服务

1
2
systemctl daemon-reload
systemctl restart docker

3   Docker部署Dockge(docker compose可视化管理)

  • dockge容器运行是UTC世界时,指定环境变量或者同步宿主机的时区都是无法生效,容器日志纪录的时间戳就是UTC时间——Mr. Kin,2025-05-22
  • docker实现的终端功能只有简单shell命令,因此终端更多是使用docker相关命令,其余复杂的操作,还是推荐ssh连接到服务器进行操作。

/opt/stacks路径下任意文件夹的名称都是作为堆栈stack名称,显示在dockge网页管理后台上。其中,在文件夹内,docker-compose.yml或者compose.yml文件名称是必需,其他自定义文件名称,dockge将无法识别。

例如,/opt/stacks/dockge文件夹,在dockge网页管理后台上显示为dockge

  1. 创建stacks文件夹:
1
mkdir -p /opt/stacks/dockge
  1. 创建dockgedocker-compose.yml文件:nano /opt/stacks/dockge/docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
services:
dockge:
image: louislam/dockge:latest
container_name: dockge
restart: unless-stopped
ports:
- 5001:5001
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /root/dockge_data:/app/data
# Stacks Directory
# ⚠️ READ IT CAREFULLY. If you did it wrong, your data could end up writing into a WRONG PATH.
# ⚠️ 1. FULL path only. No relative path (MUST)
# ⚠️ 2. Left Stacks Path === Right Stacks Path (MUST)
- /opt/stacks:/opt/stacks
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
# Tell Dockge where to find the stacks
- DOCKGE_STACKS_DIR=/opt/stacks
- DOCKGE_ENABLE_CONSOLE=true
  1. 访问dockge网页管理后台:http://10.10.10.10:5001。初次访问会提示创建用户和密码。

4   Docker搭建Gitea

4.1   创建Gitea的mysql数据库数据文件夹

root账户路径下,创建mysql文件夹和子目录:mkdir -p /root/mysql/conf.d

创建my.ininano /root/mysql/conf.d/my.ini

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
###### [client]配置模块 ######
[client]
default-character-set=utf8mb4
socket=/var/lib/mysql/mysql.sock

###### [mysql]配置模块 ######
[mysql]
# 设置MySQL客户端默认字符集
default-character-set=utf8mb4
socket=/var/lib/mysql/mysql.sock

###### [mysqld]配置模块 ######
[mysqld]
port=3306
user=mysql
# 设置sql模式 sql_mode模式引起的分组查询出现*this is incompatible with sql_mode=only_full_group_by,这里最好剔除ONLY_FULL_GROUP_BY
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
server-id= 1

# MySQL8 的密码认证插件 如果不设置低版本navicat无法连接
#default_authentication_plugin=mysql_native_password

# 禁用符号链接以防止各种安全风险
symbolic-links=0

# 允许最大连接数
max_connections=1000

# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8mb4

# 数据库字符集对应一些排序等规则,注意要和 character-set-server 对应
collation-server = utf8mb4_unicode_ci

# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB

# 0: 表名将按指定方式存储,并且比较区分大小写;
# 1: 表名以小写形式存储在磁盘上,比较不区分大小写;
lower_case_table_names=1

max_allowed_packet=16M

# 设置时区
default-time_zone='+8:00'

4.2   创建Gitea数据文件夹和配置文件

root账户路径下,创建gitea文件夹和子目录:mkdir -p /root/gitea/gitea/conf

创建app.ini文件:nano /root/gitea/gitea/conf/app.ini

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
APP_NAME = Gitea: Git with a cup of tea
RUN_MODE = prod
WORK_PATH = /data/gitea

[repository]
ROOT = /data/git/repositories

[repository.local]
LOCAL_COPY_PATH = /data/gitea/tmp/local-repo

[repository.upload]
TEMP_PATH = /data/gitea/uploads

[server]
APP_DATA_PATH = /data/gitea
DOMAIN = localhost
SSH_DOMAIN = localhost
HTTP_PORT = 3000
ROOT_URL = http://192.168.1.10:3000/
DISABLE_SSH = false
SSH_PORT = 22
SSH_LISTEN_PORT = 22
LFS_START_SERVER = true
LFS_JWT_SECRET =
OFFLINE_MODE = true

[database]
PATH = /data/gitea/gitea.db
DB_TYPE = mysql
HOST = database:3306
NAME = gitea
USER = gitea
PASSWD = normalpdxxx
LOG_SQL = false
SSL_MODE = disable

[mailer]
ENABLED = false

[openid]
ENABLE_OPENID_SIGNIN = true
ENABLE_OPENID_SIGNUP = true

[cron.update_checker]
ENABLED = false

[indexer]
ISSUE_INDEXER_PATH = /data/gitea/indexers/issues.bleve

[session]
PROVIDER_CONFIG = /data/gitea/sessions

[picture]
AVATAR_UPLOAD_PATH = /data/gitea/avatars
REPOSITORY_AVATAR_UPLOAD_PATH = /data/gitea/repo-avatars

[attachment]
PATH = /data/gitea/attachments

[log]
MODE = console
LEVEL = info
ROOT_PATH = /data/gitea/log

[security]
INSTALL_LOCK = true
INTERNAL_TOKEN =
PASSWORD_HASH_ALGO = pbkdf2
SECRET_KEY =
REVERSE_PROXY_LIMIT = 1
REVERSE_PROXY_TRUSTED_PROXIES = *

[service]
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
DISABLE_REGISTRATION = false
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
ENABLE_CAPTCHA = false
REQUIRE_SIGNIN_VIEW = false
DEFAULT_KEEP_EMAIL_PRIVATE = false
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
DEFAULT_ENABLE_TIMETRACKING = true
NO_REPLY_ADDRESS = noreply.localhost

[lfs]
PATH = /data/git/lfs

[repository.pull-request]
DEFAULT_MERGE_STYLE = merge

[repository.signing]
DEFAULT_TRUST_MODEL = committer

[oauth2]
JWT_SECRET =

4.3   创建actions_runner配置文件

如果是本地搭建并只在本地使用,配件文件的host设置为127.0.0.1就能访问到gitea实例了。

1
nano /root/actions_runner_config.yaml

actions_runner_config.yaml内容:

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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# Example configuration file, it's safe to copy this as the default config file without any modification.

# You don't have to copy this file to your instance,
# just run `./act_runner generate-config > config.yaml` to generate a config file.

log:
# The level of logging, can be trace, debug, info, warn, error, fatal
level: info

runner:
# Where to store the registration result.
file: .runner
# Execute how many tasks concurrently at the same time.
capacity: 2
# Extra environment variables to run jobs.
envs:
A_TEST_ENV_NAME_1: a_test_env_value_1
A_TEST_ENV_NAME_2: a_test_env_value_2
# Extra environment variables to run jobs from a file.
# It will be ignored if it's empty or the file doesn't exist.
env_file: .env
# The timeout for a job to be finished.
# Please note that the Gitea instance also has a timeout (3h by default) for the job.
# So the job could be stopped by the Gitea instance if it's timeout is shorter than this.
timeout: 3h
# Whether skip verifying the TLS certificate of the Gitea instance.
insecure: false
# The timeout for fetching the job from the Gitea instance.
fetch_timeout: 5s
# The interval for fetching the job from the Gitea instance.
fetch_interval: 2s
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
# Like: "macos-arm64:host" or "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"
# Find more images provided by Gitea at https://gitea.com/gitea/runner-images .
# If it's empty when registering, it will ask for inputting labels.
# If it's empty when execute `daemon`, will use labels in `.runner` file.
labels:
- "ubuntu-latest:docker://gitea/runner-images:ubuntu-latest"
- "ubuntu-22.04:docker://gitea/runner-images:ubuntu-22.04"
- "ubuntu-20.04:docker://gitea/runner-images:ubuntu-20.04"

cache:
# Enable cache server to use actions/cache.
enabled: true
# The directory to store the cache data.
# If it's empty, the cache data will be stored in $HOME/.cache/actcache.
dir: ""
# The host of the cache server.
# It's not for the address to listen, but the address to connect from job containers.
# So 0.0.0.0 is a bad choice, leave it empty to detect automatically.
host: "10.10.10.10"
# The port of the cache server.
# 0 means to use a random available port.
port: 18088
# The external cache server URL. Valid only when enable is true.
# If it's specified, act_runner will use this URL as the ACTIONS_CACHE_URL rather than start a server by itself.
# The URL should generally end with "/".
external_server: ""

container:
# Specifies the network to which the container will connect.
# Could be host, bridge or the name of a custom network.
# If it's empty, act_runner will create a network automatically.
network: ""
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
privileged: false
# And other options to be used when the container is started (eg, --add-host=my.gitea.url:host-gateway).
options:
# The parent directory of a job's working directory.
# NOTE: There is no need to add the first '/' of the path as act_runner will add it automatically.
# If the path starts with '/', the '/' will be trimmed.
# For example, if the parent directory is /path/to/my/dir, workdir_parent should be path/to/my/dir
# If it's empty, /workspace will be used.
workdir_parent:
# Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob
# You can specify multiple volumes. If the sequence is empty, no volumes can be mounted.
# For example, if you only allow containers to mount the `data` volume and all the json files in `/src`, you should change the config to:
# valid_volumes:
# - data
# - /src/*.json
# If you want to allow any volume, please use the following configuration:
# valid_volumes:
# - '**'
valid_volumes: []
# overrides the docker client host with the specified one.
# If it's empty, act_runner will find an available docker host automatically.
# If it's "-", act_runner will find an available docker host automatically, but the docker host won't be mounted to the job containers and service containers.
# If it's not empty or "-", the specified docker host will be used. An error will be returned if it doesn't work.
docker_host: ""
# Pull docker image(s) even if already present
force_pull: true
# Rebuild docker image(s) even if already present
force_rebuild: false

host:
# The parent directory of a job's working directory.
# If it's empty, $HOME/.cache/act/ will be used.
workdir_parent:

4.4   启动Docker-Compose

runner容器的环境变量environment的Gitea实例地址GITEA_INSTANCE_URL参数这里,不能用http://server直接作为参数。虽然docker compose容器之间可以识别这个写法,但action runner运行时无法识别该参数,使用checkout脚本甚至都拉取不了源码到runner容器内。

但参数设置错误也会导致如下错误:

1
2
3
level=error msg="Cannot ping the Gitea instance server" error="unknown: 500 Internal Server Error"
# or
level=error msg="Cannot ping the Gitea instance server" error="unavailable: dial tcp: lookup server on 127.0.0.11:53: server misbehaving"

runner容器的环境变量environment的runner注册令牌GITEA_RUNNER_REGISTRATION_TOKEN参数步骤:在Gitea管理后台->Actions->Runners->创建Runner->创建新的令牌或者查看已有的令牌。

1
2
nano /root/docker-compose.yml
docker compose -f docker-compose.yml up -d

docker-compose.yml内容:

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
66
67
68
69
70
71
72
73
74
networks:
gitea:
external: false

services:
server:
image: docker.gitea.com/gitea:nightly
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=mysql
- GITEA__database__HOST=database:3306
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=normalpdxxx
restart: always
networks:
- gitea
volumes:
- /root/gitea:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
depends_on:
- database

database:
image: docker.io/library/mysql:latest
container_name: mysql
restart: always
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=rootpdxxx
- MYSQL_DATABASE=gitea
- MYSQL_USER=gitea
- MYSQL_PASSWORD=normalpdxxx
networks:
- gitea
volumes:
# 映射数据目录,宿主机:容器
- /root/mysql/data:/var/lib/mysql
# 映射配置目录,宿主机:容器
- /root/mysql/conf.d:/etc/mysql/conf.d
# 映射日志目录,宿主机:容器
- /root/mysql/log:/var/log/mysql
# 让容器的时钟与宿主机时钟同步,避免时间的问题,ro是read only的意思,就是只读。
- /etc/localtime:/etc/localtime:ro

runner:
image: gitea/act_runner:nightly
container_name: runner
restart: always
ports:
- "18088:18088"
environment:
- CONFIG_FILE=/config.yaml
- GITEA_INSTANCE_URL=http://10.10.10.10:3000
- GITEA_RUNNER_REGISTRATION_TOKEN=xxx_token
- GITEA_RUNNER_NAME=${RUNNER_NAME}
- GITEA_RUNNER_LABELS=${RUNNER_LABELS}
networks:
- gitea
volumes:
- /root/actions_runner_config.yaml:/config.yaml
- /root/actions_runner:/data
- /root/actions_runner_cache:/root/.cache
- /var/run/docker.sock:/var/run/docker.sock
- /etc/localtime:/etc/localtime:ro
depends_on:
- server

4.5   迁移Gitea的mysql数据库和git仓库数据

  1. 备份其他服务器上的Gitea的mysql数据库、git仓库数据和gitea其他资产数据。
  2. 进入mysql容器,并使用备份sql文件恢复mysql数据库。
  3. 停止docker-compose
  4. 迁移Gitea的git仓库数据和其他资产数据(例如avatars,actions_logs等),
    • Git仓库数据路径:/root/gitea/git/repositories
    • Git仓库lfs数据路径:/root/gitea/git/lfs
    • Gitea资产数据路径:
      • /root/gitea/gitea/attachments
      • /root/gitea/gitea/repo-archive
      • /root/gitea/gitea/actions_logs
      • /root/gitea/gitea/conf
      • /root/gitea/gitea/actions_artifacts
      • /root/gitea/gitea/jwt
      • /root/gitea/gitea/indexers
      • /root/gitea/gitea/tmp
      • /root/gitea/gitea/repo-avatars
      • /root/gitea/gitea/queues
      • /root/gitea/gitea/packages
      • /root/gitea/gitea/home
      • /root/gitea/gitea/avatars
      • /root/gitea/gitea/log
  5. 重新运行docker-compose

4.6   Gitea搭建和使用的踩坑

4.6.1   actions_runner容器无法正常启动,日志提示未注册runner

问题现象:docker logs runner查看日志提示如下,同时,gitea管理后台查看runner也无法看到有正常在线的runner。

1
2
level=error msg="fail to invoke Declare" error="unknown: rpc error: code = Unauthenticated desc = unregistered runner"
Error: Unknown: rpc error: code = Unauthenticated desc = unregistered runner

问题原因:/root/actions_runner路径下有一个隐藏文件夹.runner,该文件夹存储runner配置数据,但该数据是旧的,gitea实例无法识别,因此runner容器无法成功注册。

解决方法:

  1. 停止docker-compose
  2. 删除.runner文件夹:rm -rf /root/actions_runner/.runner
  3. 重新运行docker-compose
  4. 之后在gitea管理后台就能看到正常在线的新runner了

4.6.2   “版本发布”下,自己上传的文件url错误

背景说明:Gitea构建在子局域网IP10.10.10.10,然后外部网络访问该Gitea服务是通过IP192.168.1.10(宿主机IP192.168.1.10已设置路由表转发3000端口到IP10.10.10.10,即192.168.1.10:3000->10.10.10.10:3000

问题现象:在版本发布内容中,上传的资产文件assets下载路径链接指向http://10.10.10.10:3000/xxx.zip

问题原因:Gitea的配置文件app.ini中的ROOT_URL未设置参数,导致下载路径链接自动指向http://10.10.10.10:3000/xxx

解决方法:编辑app.ini文件,将[server]小节中的ROOT_URL参数设置为http://192.168.1.10:3000即可。

4.6.3   Gitea管理后台提示当前访问的url和app.ini配置url不同

问题现象:Gitea管理后台提示警告,你的app.iniROOT_URLhttp://10.10.10.10:3000,但当前访问的url是http://192.168.1.10:3000。你应该正确设置ROOT_URL,否则网络服务可能无法正常运行。

问题原因:Gitea的配置文件app.ini中的ROOT_URL未设置参数或者设置错误的url,导致下载路径链接自动指向http://10.10.10.10:3000/xxx

解决方法:编辑app.ini文件,将[server]小节中的ROOT_URL参数设置为当前访问URL即可,例如http://192.168.1.10:3000

5   Docker搭建Redis

5.1   Redis容器清理缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 通过可交互终端进入redis容器
docker exec -it redis /bin/bash
# 登录容器的redis服务
redis-cli -h 127.0.0.1 -p 6379
# 若Redis设置有密码使用该命令,否则执行 keys *会报错:(error) NOAUTH Authentication required。
redis-cli -h 127.0.0.1 -p 6379 -a redis

# 查看所有key值
keys *
# 删除指定索引的值
del key
# 清除当前数据库缓存
flushdb
# 清除整个redis所有缓存
flushall

6   Docker搭建DataEase

请提前为宿主机安装好Docker以及配置好镜像源,这里不作介绍。

6.1   下载DataEase部署脚本。

最新的DataEase V1.x部署脚本并解压(本文示例为v1.18.27版本)。

dataease-release-v1.18.27.tar.gzdataease-v1.18.27-online.tar.gz这两个文件数据完全一致,随意下载,本人解压并比对过文件哈希值。

v2.x开源社区版不支持创建用户,代码层面写死只有一个admin账户,若有用户管理的需求,可以不用考虑v2.x版本或者考虑商业版的v2.x。

6.2   修改配置文件install.conf

安装模式模式修改为local,端口这些自行根据需求改,如下配置文件是修改为8100。

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
# 基础配置
## 安装目录
DE_BASE=/opt
## Service 端口
DE_PORT=8100
## 部署及运行模式,可选值有 local、simple、cluster,分别对应 本地模式、精简模式、集群模式
DE_ENGINE_MODE=local
## docker 网段设置
DE_DOCKER_SUBNET=172.19.0.0/16
## docker 网关 IP
DE_DOCKER_GATEWAY=172.19.0.1
## Apache Doris FE IP (外部 Doris 此参数无效)
DE_DORIS_FE_IP=172.19.0.198
## Apache Doris BE IP (外部 Doris 此参数无效)
DE_DORIS_BE_IP=172.19.0.199
## 登录超时时间,单位min。如果不设置则默认8小时,也就是480
DE_LOGIN_TIMEOUT=480
## 新建用户初始密码
DE_INIT_PASSWORD=DataEase123456

# 数据库配置
## 是否使用外部数据库
DE_EXTERNAL_MYSQL=false
## 数据库地址
DE_MYSQL_HOST=mysql
## 数据库端口
DE_MYSQL_PORT=3306
## DataEase 数据库库名
DE_MYSQL_DB=dataease
## 数据库用户名
DE_MYSQL_USER=root
## 数据库密码
DE_MYSQL_PASSWORD=Password123@mysql
## 数据库参数
DE_MYSQL_PARAMS="autoReconnect=false&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true"

# Apache Doris 配置
## 是否使用外部 Apache Doris
DE_EXTERNAL_DORIS=false
## Doris 地址
DE_DORIS_HOST=doris-fe
## Doris 查询连接端口
DE_DORIS_PORT=9030
## Doris http端口
DE_DORIS_HTTPPORT=8030
## Doris 数据库名称
DE_DORIS_DB=dataease
## Doris 用户名
DE_DORIS_USER=root
## Doris 密码
DE_DORIS_PASSWORD=Password123@doris

# Kettle 配置
## 是否使用外部 Kettle - (目前还不支持外部Kettle,除非不需运行Kettle,否则请不要修改此参数)
DE_EXTERNAL_KETTLE=false
## Kettle 服务器地址
DE_CARTE_HOST=kettle
## Kettle 访问端口
DE_CARTE_PORT=18080
## Kettle 用户名
DE_CARTE_USER=cluster
## Kettle 密码
DE_CARTE_PASSWORD=cluster

6.2.1   不同安装模式的区别

DE_ENGINE_MODE=local
使用本地模式安装,DataEase 会自带 Doris 与 Kettle 组件,无需再做额外配置,但各组件均为单点,不具备高可用特性。
在此模式下,Excel 数据集、API 数据集以及定时同步的数据默认保存在自带的 Doris 组件中。

DE_ENGINE_MODE=simple
使用精简模式安装,系统不会额外安装 Doris 与 Kettle 组件,提供用户轻量级的应用系统,尤其是对接数据量较小的情况。
在此模式下,Excel 数据集或 API 数据集的相关数据存储在数据引擎中(默认配置自带的 MySQL 组件,用户可在系统管理界面配置数据引擎,数据引擎目前仅支持 MySQL 类型)。
注意:由于精简模式未配置 Kettle 与 Doris,故精简模式不提供定时同步模式。

DE_ENGINE_MODE=cluster
使用集群模式安装,系统不会额外安装 Doris 与 Kettle 组件,但会在系统管理模块提供 Doris 与 Kettle 的链接配置界面(请参考【系统管理】的【系统参数】说明),用户可独立安装 Doris 集群及 Kettle 并配置在 DataEase 中。集群模式下 Excel 数据集,API 数据集以及定时同步的数据通过 Kettle 抽取到 Doris 集群中。
Doris 安装部署可参考:http://doris.incubator.apache.org/zh-CN/
Kettle 安装部署可参考:http://www.kettle.org.cn/

6.3   安装DataEase

运行命令安装DataEase,并查看对应docker容器是否正常运行。

1
2
bash ./install.sh
docker ps -a

6.4   创建DataEase的踩坑记录

6.4.1   doris-be容器状态一直为unhealthy

问题:doris-be容器状态一直为unhealthy,一直在尝试反复启动。docker logs doris-be查看到如下日志输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
doris_role:be
DEBUG >>>>>> FE_SERVERS=[fe1:172.19.0.198:9010]
DEBUG >>>>>> BE_ADDR=[172.19.0.199:9050]
DEBUG >>>>>> feIpArray = 172.19.0.198
DEBUG >>>>>> feEditLogPortArray = 9010
DEBUG >>>>>> masterFe = 172.19.0.198:9010
DEBUG >>>>>> be_addr = 172.19.0.199:9050
DEBUG >>>>>> Append the configuration [priority_networks = 172.19.0.0/24] to /opt/apache-doris/be/conf/fe.conf
DEBUG >>>>>> registerMySQL = mysql -uroot -P9030 -h172.19.0.198 -e "alter system add backend '172.19.0.199:9050'"
DEBUG >>>>>> registerShell = /opt/apache-doris/be/bin/start_be.sh &
mysql -uroot -P9030 -h172.19.0.198 -e "show backends" | grep " 172.19.0.199 " | grep " 9050 "
10003 default_cluster 172.19.0.199 9050 -1 -1 -1 NULL NULL false false false 0 0.000 1.000 B 0.000 0.00 % 0.00 % 0.000 {"location" : "default"} java.net.NoRouteToHostException: No route to host (Host unreachable) {"lastStreamLoadTime":-1,"isQueryDisabled":false,"isLoadDisabled":false} 1
DEBUG >>>>>> The 0 time to register BE node, be_join_status=0
DEBUG >>>>>> run command /opt/apache-doris/be/bin/start_be.sh &
DEBUG >>>>>> registered : 1
Please set vm.max_map_count to be 2000000 under root using 'sysctl -w vm.max_map_count=2000000'.
ERROR 1105 (HY000) at line 1: errCode = 2, detailMessage = There is no scanNode Backend available.[10003: not alive]
DEBUG >>>>>> The 1 time to check is_alive >>>>>> 1
ERROR 1105 (HY000) at line 1: errCode = 2, detailMessage = There is no scanNode Backend available.[10003: not alive]

可以查看上述日志输出提示Please set vm.max_map_count to be 2000000 under root using 'sysctl -w vm.max_map_count=2000000'.

原因:Doris作为分布式数据库,对于内存映射数量有要求,Linux系统默认参数值无法满足,例如PVE系统默认的vm.max_map_count=262144

  • 解决方法1:请在运行doris容器的宿主机上,运行sysctl -w vm.max_map_count=2000000命令设置vm.max_map_count内核参数。若宿主机本身也是容器化的虚拟机,例如PVE的LXC容器,可以直接在PVE上运行命令修改参数。
    • 查看参数值:sysctl vm.max_map_count
    • 宿主机PVE重启后,vm.max_map_count参数可能会被重置为默认值,若查看日志仍提示报错,请尝试重设参数。
  • 解决方法2:换DataEase v2版本,v2系列不需要部署Doris。

6.4.2   在DataEase添加Excel数据集后,预览数据界面无法加载,并一直提示Access denied for user 'root@172.19.0.4'

原因:修改过install.conf的MySQL和Doris的密码都会导致出现该故障。据5939的issue反馈该问题在1.18.23已修复,但本人使用1.18.27版本部署,修改密码仍会出现该问题。

解决方法:不修改install.conf的MySQL和Doris的密码,直接使用模板预设的默认密码完成部署。

6.5   DataEase使用踩坑纪录

  • 变更/删除数据集,均会导致丢失仪表盘的过滤器参数
  • 仪表盘的视图在超过1000条数据时则无法全部导出excel表格(比如实际导出的excel表格行数为1001,有一行是表头)
    • 建议导出操作,使用数据集的导出功能。
  • excel数据源若有几万行,则无法成功导入dataease作为数据集,在数据同步阶段会失效(可能是内存溢出的问题,有待排查验证)
  • V2社区开源版不支持创建多用户

7   Docker Desktop(Windows)

7.1   Docker Unexpected error

问题:无法启用Docker Desktop,提示报错Docker Unexpected error

原因:之前有安装并卸载过Docker Desktop。重新安装Docker Desktop有可能触发此问题。

解决方法:

1
2
3
wsl --unregister docker-desktop
wsl --unregister docker-desktop-data
# 运行上面两条命令,然后重新启动Docker Desktop

8   参考文献

[1] Docker Unexpected error[EB/OL]. https://github.com/docker/for-win/issues/14034.
[2] Install Docker Engine on Debian[EB/OL]. https://docs.docker.com/engine/install/debian/#install-using-the-repository.
[3] DockerHub 国内加速镜像列表[EB/OL]. https://github.com/dongyubin/DockerHub.
[4] Docker 容器使用[EB/OL]. https://www.runoob.com/docker/docker-container-usage.html.
[5] [Question]配置doris数据源提示错误:Access denied for user 'root@172.19.0.4' (using password: YES)[EB/OL]. https://github.com/dataease/dataease/issues/5939.
[6] 安装模式[EB/OL]. https://dataease.io/docs/v1/installation/installation_mode/#11.
[7] Docker Build Cache 缓存清理[EB/OL]. https://blog.csdn.net/catoop/article/details/128002962.
[8] docker下redis容器清理缓存[EB/OL]. https://blog.csdn.net/weixin_44662304/article/details/114694451.
[9] “版本发布”下,自己上传的文件url错误[EB/OL]. https://forum.gitea.com/t/url/8030/1.
[10] 反向代理[EB/OL]. https://docs.gitea.com/zh-cn/administration/reverse-proxies.
[11] 使用 Docker 安装[EB/OL]. https://docs.gitea.com/zh-cn/next/installation/install-with-docker.
[12] Act Runner[EB/OL]. https://docs.gitea.com/zh-cn/next/usage/actions/act-runner.
[13] 备份与恢复[EB/OL]. https://docs.gitea.com/zh-cn/next/administration/backup-and-restore.
[14] 求助:Docker-compose部署act_runner出现错误[EB/OL]. https://forum.gitea.com/t/docker-compose-act-runner/8525.
[15] Runner Will Not Register via Docker Compose[EB/OL]. https://gitea.com/gitea/act_runner/issues/550.
[16] runner: level=error msg="Cannot ping the Gitea instance server" error="unknown: 500 Internal Server Error"[EB/OL]. https://gitea.com/gitea/act_runner/issues/400.
[17] 使用docker-compose 部署 MySQL(所有版本通用)[EB/OL]. https://blog.csdn.net/weixin_44606481/article/details/132840940.

1   数学计算

  • 对于指数函数来说底数不能为负数,而对于代数运算来说却可以为负数。因为n总是表示正整数,底数为负数是可以的,这个式子仍然是有限次代数运算的极限
  • 乘除法的计算本质:计算过程中的错位相加是为了保证各行的小数点位置相同,实际就是保证各个数字的权重相同。

2   生活琐事

当花费大量时间却无法解决一个问题时,若非紧急状态,建议先将该问题放一边。等到放松或者忙完另外一件事情甚至于明天再重新去思考解决这个问题。

3   生活记录

  • 灭蟑螂:洗衣服+饭+白糖。
  • 盖章:公章盖签字位置,以及骑缝章(盖边缘,确保完整章都出现在边缘)。
  • 去打印店,一定得输出PDF再打印。
  • 不要买大豆油,加热有腥臭味。买花生油。
  • 湖南人fh不分,弗兰银/湖兰人/胡建人。
  • 出门在外吃饭,看大货车司机。
  • 学生票要取纸票,得刷磁条才能享受优惠,否则检票时会面临补票的问题。
  • 四六级口语分两天,笔试一天(上午四,下午六)。
  • 2021花呗弹窗说需上报征信。
  • 京东白条的注销,需要下载京东金融白条>设置>账户安全>注销白条用户>继续注销,或者直接在京东金融客服,输入注销白条,可以直接跳转。
  • 信用卡(透支信用贷款),小额消费贷款(多笔记录不利于征信)

4   医学

  • 睡眠一定要规律,否则生物钟不好调整适应,会造成人体免疫力下降。
  • 关于外伤伤口的处理:生理盐水清洗伤口即可,剩下等身体自动修复。消毒可以用碘伏。P.S.切忌使用紫药水,不仅致癌,还会形成结痂无法观察伤口。
  • 烫伤疼痛明显:冷水冲洗30分钟。

4.1   药品清单

  • 蚬壳胃散-海螵蛸
  • 小柴胡冲剂
  • 复方黄芩片-肇庆新湖制药
  • 复方穿心莲-广州白云山和记黄埔中药
  • 氯芬黄敏片-广州白云山明兴制药
  • 复方氨酚烷胺片(感冒)
  • 维C银翘片-国药集团德众(佛山)药业有限公司
  • 腹可安片-广州白云山一药业
  • 正露丸(喇叭丸)-大幸药品
  • 桂林西瓜霜-桂林三金药业
  • 冰硼散(微毒性)
  • 维C片
  • 维B片
  • 盐酸小襞碱片
  • 枸地氯雷他定片-扬子江药业集团
  • 脾氨肽口服冻干粉
  • 攻肤之王-广州泽上堂生物科技有限公司

1   基础

ffmpeg -i input.avi -metadata key=value -codec copy output.avi
ffprobe "file" #查看metadata

1.1   查询命令

1
2
3
4
5
ffmpeg.exe -h -> help.txt # 打印帮助文件
ffmpeg -h encoder=libx264
ffmpeg -hwaccels # 查看支持的硬件加速选项
ffmpeg -codecs | grep cuvid # 查看cuvid提供的GPU编解码器(grep为Linux命令)
ffmpeg -f lavfi -i nullsrc -c:v nvenc -gpu list -f null none_output (-hwaccel_device N 和 -gpu N)

1.2   硬件编码

1
2
3
4
5
6
-c:v h264_nvenc -rc:v vbr_hq -cq:v 19 -b:v 2500k -maxrate:v 5000k -profile:v high
ffmpeg -hwaccel cuvid -c:v h264_cuvid -i <input> -c:v h264_nvenc -b:v 2048k -vf scale_npp=1280:-1 -y <output>
ffmpeg -vsync 0 -hwaccel cuvid -c:v h264_cuvid -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4
-hwaccel cuda -hwaccel_output_format cuda
ffmpeg -vsync 0 –hwaccel cuvid -c:v h264_cuvid –resize 1280x720 -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4
ffmpeg -r 30 -f image2 -i %4d.jpg -r 30 -c:v h264_nvenc -profile:v high -level 5.1 -preset slow -rc:v vbr_hq -cq:v 19 -b:v 2500k -maxrate:v 5000k ../output.mp4

2   实战案例

2.1   合并多个视频文件

1
2
3
4
5
6
ffmpeg -f concat -i filelist.txt -c copy output.mp4
# filelist.txt
# file '1.flv'
# file '2.flv'
# file '3.flv'
# file '4.flv'

3   常见知识点

  • yuv420p的p代表planar
  • k和K都是表示$10^3/2^{10}$,K之后的只有大写,比如M表示$10^6/2^{20}$(详见Expression Evaluation
  • bufsize配合maxrate参数使用可控制编码时的码率波动,例如264的cbr恒定码率编码中,同时设置b:v maxrate minrate bufsize(前三个都是设置为1M,bufsize设置为50k,最后编码出来的码率波动最小996kbit/s,1001kbit/s)。bufsize is the "rate control buffer",即码率控制缓存。作用是每次达到bufsize大小,都是计算并调整到average平均码率。
  • filter chain之间的filter用分号,普通的filter之间用逗号
  • aac编码:网络视频128k;高质量192k

4   常见错误/警告

4.1   时间戳问题

常见于 Non-monotonous DTS in output stream

完美的解决方式暂未找到,网上的解决方法基本为:先转为 mts 文件,后转为 mp4。(本质是重新编码,确实可以解决时间戳错误,但也会劣化音质和画质。)

4.2   deprecated pixel format used, make sure you did set range correctly

This is just a warning, not an error. You can safely ignore it when using ffmpeg from the command-line, and you don't have to fix anything.

The warning occurs when converting from a yuv420p source to JPEG, which makes ffmpeg choose yuvj420p as output format. That format is required for writing files with the mjpeg encoder.

These two pixel formats have different color ranges: the former is from 16–235, which is "limited range" (also called "MPEG" range), the latter defaults to 0–255, which is "full range". The warning is meant for using FFmpeg as a library in your own code (like here). See also the comments on this question.

R.I.P