乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

使用frp进行内网穿透实现外网访问局域网中的服务器

发表于 2022-09-20

前言

之前给大家介绍过使用内网云实现内网穿透的方案, 一行指令搞定, 详见《使用内网云进行内网穿透实现外网访问局域网中的服务器》

今天给大家介绍如何使用frp实现内网穿透

frp是一个免费开源的内网穿透工具, 包含服务端(frps)和客户端( frpc)

Github

假如你自己有云服务器, 那么将服务端安装到具有公网ip的服务器中, 将客户端安装到内网的机器上, 即可实现内网穿透功能

当然 如果你没有云服务也没有关系 网上有些热心肠的大佬们给我们提供了中转服务器 比如: freefrp:

image-20220920172928529

而我们要做的仅仅就是在内网的机器上安装用于连接的客户端即可

接下来我以本地的Mac电脑为例 充当内网机器 介绍使用方法

使用方法

http穿透

  1. 首先下载客户端程序

    点击下载

    image-20220920173201984

    由于是Mac系统 因此我们选择Darwin_amd64, 下载后解压:

    image-20220920174602538

    客户端只用frpc开头的文件, 其他的可以移除,

  2. 修改配置文件

    打开配置文件frpc.ini, 然后修改成以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [common]
    server_addr = frp.freefrp.net
    server_port = 7000
    token = freefrp.net

    [mac_http]
    type = http
    local_ip = 127.0.0.1
    local_port = 13000
    custom_domains = git.newban.cn

    image-20220921101048772

    参数详解:

    • 中括号中的名称可以自定义 但不能重复

    • type: 表示连接类型, 支持http/https udp tcp 等协议

    • server_addr:服务器 IP 地址或者域名地址

    • *server_port *:服务端口号

    • token:服务端访问密码

    • local_ip: 需要进行穿透的内网ip, 通常为127.0.0.1 如果使用虚拟机或者docker 建议改成局域网ip

    • local_port: 需要进行穿透的内网端口号

    • custom_domains: 自定义域名 需要将域名解析到服务器地址 这样使用域名就能直接访问到内网程序了

  1. 域名解析

    将配置文件中的自定义域名以CNAME的方式解析到frp.freefrp.net

  2. 启动frpc客户端程序

    1
    ./frpc
  3. 浏览器访问

    此时 我们通过域名就能直接在任意浏览器上访问到127.0.0.1:3000

  4. 多域名解析

    假如我们需要将多个不同域名同时解析到同一个内网程序, 那么只需增加一个新模块, 配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    [common]
    server_addr = frp.freefrp.net
    server_port = 7000
    token = freefrp.net

    [mac_http]
    type = http
    local_ip = 127.0.0.1
    local_port = 13000
    custom_domains = git.newban.cn


    [mac_http2]
    type = http
    local_ip = 127.0.0.1
    local_port = 13000
    custom_domains = git.insoan.com
  1. 实现以Web的形式可视化配置客户端

    只需在common的节点下配置admin参数即可, 如下:

    1
    2
    3
    4
    5
    6
    7
    8
    [common]
    server_addr = frp.freefrp.net
    server_port = 7000
    token = freefrp.net
    admin_addr = 127.0.0.1 #客户端Web管理地址
    admin_port = 7122 #客户端Web管理端口
    admin_user = admin #客户端Web管理用户名
    admin_pwd = 123456 #客户端Web管理密码

    配置完后重启frp, 然后在浏览器输入http://127.0.0.1:7122, 即可以Web的形式监控当前正在穿透的程序:

    image-20220922115156138

ssh穿透

  1. 配置TCP连接

    如果我们需要进行ssh访问, 那么我们需要在客户端配置tcp协议, 配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [common]
    server_addr = frp.freefrp.net
    server_port = 7000
    token = freefrp.net

    [mac_http]
    type = http
    local_ip = 127.0.0.1
    local_port = 13000
    custom_domains = git.newban.cn

    [mac_ssh]
    type = tcp
    local_ip = 127.0.0.1
    local_port = 22
    remote_port = 12323

    参数解析:

    • remote_port: 服务器端口映射 意思就是将服务器的12323端口映射到内网的22端口
  2. ssh访问

    此时 我们在命令窗口执行以下指令就可以进行ssh连接了

    1
    ssh -p 12323 root@frp.freefrp.net

    由于我们之前将自定义域名以CNAME形式解析到了frp.freefrp.net, 所以 我们也可以用自定义域名进行连接, 如下:

    1
    ssh -p 12323 root@git.newban.cn

总结

至此 我们的内网穿透客户端配置就ok了, 相比内网云 使用frpc+freefrp.net中转服务器的模式进行内网穿透可以实现完全免费且稳定的服务

下一章 给大家介绍《如何使用supervisor实现内网穿透持久化》

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用内网云进行内网穿透实现外网访问局域网中的服务器

发表于 2022-09-20

前言

有时候我可能会借助家里的电脑临时充当服务器供外网访问, 此时需要进行内网穿透才能实现

网上偶然发现一个提供内网穿透服务的网站, 名为内网云:

image-20220920162143938

如果是临时使用 那么完全免费, 付费的话5块钱一个月

接下来给大家介绍 如何使用

使用指南

http映射

假设我的电脑上开了一个Web服务, 地址为:http://localhost:3000, 我们想实现外网访问到这个地址的内容, 此时我们可以在电脑的命令窗口中输入以下指令:

1
ssh -R 80:127.0.0.1:3000 sh@sh3.neiwangyun.net

指令解析:

  • ssh:ssh远程命令
  • -R:远程端口绑定
  • 80:固定端口
  • 127.0.0.1:固定的本机网络
  • 3000:你需要转发的网络端口,自行更改
  • sh:默认匿名账号,不需要密码验证
  • sh3.neiwangyun.net:内网云服务器节点的地址,固定值

简而言之 这句指令的意思就是将sh3.neiwangyun.net服务器的80端口转发到本地的3000

执行完毕后出现以下内容:

image-20220920162759901

结果解析:

  • username:sh账号名称
  • type:anonymous账号类型
  • subdomain: xxxxxxxxxx.neiwangyun.net 子域名
  • bandwidth: random 网络带宽
  • expire_time: random过期时间
  • unid: 唯一识别码
  • http:http链接
  • https:https链接
  • ipport:直连用的ip和端口
  • remote_ip:客户端ip,服务器看到的连接者IP

此时 我们在浏览器中输入http/https的地址则可以访问到http://localhost:3000的内容

ssh映射

假如我们需要在外网中对家里的电脑进行ssh连接, 那么我们需要更改指令端口,如下:

1
ssh -R 80:127.0.0.1:22 sh@sh3.neiwangyun.net

image-20220920164300687

执行完毕后 我们需要用ipport的值进行ssh访问, 如下:

1
ssh hostname@olveddnzffdhshsh3.neiwangyun.net:31258

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

本地nginx反向代理localhost端口转发失败的解决方案

发表于 2022-09-20

问题

有时候为了方便 懒得开虚拟机直接将nginx部署在了本地, 在进行端口映射测试时可能会出现访问502 Bad Getway的问题

我们先来分析一下nginx的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http{

upstream gitea{
server 127.0.0.1:13000;
}
server{
listen 80;
server_name localhost;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://gitea;
break;
}
}

}

这里我们将127.0.0.1:13000映射给了localhost:80, 如果我们在浏览器中输入localhost显然是无法访问的

解决方案

如果想要正常访问 需要将127.0.0.1改成局域网ip地址, 修改后的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
http{

upstream gitea{
server 192.168.13.155:13000;
}
server{
listen 80;
server_name localhost;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://gitea;
break;
}
}

}

重启nginx使配置生效, 此时即可正常转发访问了

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

关于使用ssh进行仓库clone端口号非22的解决办法

发表于 2022-09-19

问题

我们在使用docker搭建私有git仓库时, 会将容器的22端口映射到宿主的其他端口上, 此时如果我们使用ssh地址进行仓库clone, 则会报错 提示ssh: connect to host localhost port 22: Connection refused:

image-20220920121534132

假设映射到宿主的端口号为10022, 那么解决方案如下:

解决方案

  1. 第一种 clone时指定端口号:

    1
    git clone ssh://git@localhost:10022/songjian/ggg.git

    注意: 需要带上ssh://这个协议头

  2. 第二种 在.ssh目录下的config文件中增加port字段指定端口访问:

    1
    2
    3
    4
    5
    Host localhost
    HostName localhost
    Port 10022
    PreferredAuthentications publickey
    IdentityFile ~/.ssh/id_rsa

    由于git默认port是22, 此时我们修改后则可以按照正常的形式进行仓库的克隆:

    1
    git clone git@localhost/songjian/ggg.git
  3. 第三种 使用nginx反向代理

    在nginx.conf文件中配置如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    stream {
    upstream ssh-proxy {
    server 服务器ip:10022;
    }
    server {
    listen 22;
    proxy_pass ssh-proxy;
    }
    }

    配置好后, 直接正常形式clone:

    1
    git clone git@localhost/songjian/ggg.git

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Docker搭建基于gitea的私有git仓库

发表于 2022-09-19

前言

最近打算将一些私有仓库转移到自己服务器上, 以备不时之需, 目前免费开源的Git仓库框架有Gitlab和Gitea, 考虑到资源消耗问题, 果断选择了Gitea

Gitea的Github地址

接下来分享我个人使用Docker快速搭建Gitea的过程

步骤如下

安装gitea

  1. 搜索gitea镜像

    1
    docker search gitea
  2. 拉取gitea镜像

    1
    docker pull gitea/gitea
  3. 创建并运行容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    docker run -id \
    --privileged=true \
    --restart=always \
    --name=c_gitea \
    -p 10022:22 \
    -p 13000:3000 \
    -v /root/app/gitea:/data \
    -h c_gitea \
    gitea/gitea:latest

    参数详解:

    • privileged: 是否授予容器root权限
    • restart : docker启动是是否自动启动容器
    • name: 表示容器别名
    • -p 10022:22: 容器暴露了22和3000端口
    • -v /root/app/gitea:/data: 容器的data目录挂载到/root/app/gitea
  4. 浏览器访问gitea配置页面

    1
    http://服务器ip:13000

    image-20220919172350179

    这里主要需要配置数据库以及域名 其他的保持默认即可

    首先数据库的话 这里有多种数据库可选, 考虑到资源消耗和移植方便 我选择sqlite3

    那么在进行配置之前 我们需要先安装sqlite3来创建数据库文件

    依然使用docker快速安装:

安装sqlite3

  1. 拉取镜像

    1
    docker pull nouchka/sqlite3
  2. 创建并运行容器

    1
    2
    3
    4
    5
    6
    7
    docker run -id \
    --restart=always \
    --name=c_sqlite \
    -p 1433:1433 \
    -v /root/app/gitea/sqlite:/root/db \
    -h c_sqlite \
    nouchka/sqlite3:latest
  3. 进入容器

    1
    docker exec -it c_sqlite bash
  1. 进入容器后运行指令创建数据库

    1
    sqlite3 数据库名.db

    运行创建数据库指令时 sqlite3默认会在当前目录生成db文件, 所以执行前要确保当前目录为挂载目录,也就是/root/db

    image-20220919182016029

    执行`sqlite3`进入`SQL`状态, 此时我们输入`.database`可以查看并刷新已经创建的数据库文件 这一步关键 否则宿主挂载目录文件不更新
  2. 退出数据库

    1
    .quit

    image-20220919182305343

    此时我们在宿主的`/root/app/gitea/sqlite`可以查看到刚刚生成的数据库

数据库关联

我们需要明白的是, 在docker中gitea容器是个独立的系统, 在配置页面中填写的路径皆为gitea容器内部路径, 而非宿主路径

由于gitea容器的/data目录映射到了宿主的/root/app/gitea目录, 因此 我们需要将生成的sqlite数据库文件放置在宿主的/root/app/gitea目录下, 这样gitea容器才能访问到数据库文件

这一点 我在sqlite容器创建时已经考虑到了, 所以将sqlite挂载目录设为了/root/app/gitea/sqlite, 从而免去了数据库文件的迁移

此时 我只需在配置页面数据库路径一项填入/data/sqlite/gitea.db即可:

image-20220920101539648

如果后期需要修改配置可以进入/root/app/gitea/gitea/conf/app.ini 进行修改, 每次修改后记得需要重启gitea容器才能生效

配置完毕后 点击安装

紧接着自动跳转到登录页面, 此时我们注册一个新账号然后登录:

image-20220920102423120

至此 我们的私有仓库就搭建完毕了, 如果需要节省资源, 可以将sqlite容器停止, 它的存在只是为了创建数据库 以及必要的时候进行数据自定义处理, 暂时不需要它保持运行状态

外部仓库同步

gitea支持从外部仓库导入 支持以下常见厂商:

image-20220920103201263

如果从github 导入 首先需要去github中申请一个access token

image-20220920104007824

当然我们也可以直接使用clone的形式进行迁移 无需token:

image-20220920115211964

后面的就不多介绍了

自定义域名

正常情况下我们可以通过地址http://服务器公网IP:13000来访问服务器, 如果需要配置自定义域名, 那么需要修改一些配置:

首先域名端, 也就是域名解析需要指向服务器IP, 这点不做过多介绍 大家都明白

另外就是服务端

由于我使用了Nginx进行反向代理, 并且给docker配置了桥接网络, 所以在nginx.conf文件中配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
http{
upstream gitea{
server c_gitea:3000;
}
server{
listen 80;
server_name git.newban.cn;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://gitea;
break;
}
}

}

通过桥接网络 我们可以直接使用容器别名实现容器间的相互通信, 减少端口暴露的风险

gitea目录结构

数据库主要用于存放用户和仓库相关的配置数据

image-20220920112051764

而我们的代码主要是放在了本地磁盘的/root/app/gitea/git目录下:

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
.
├── git
│   ├── lfs
│   └── repositories
├── gitea
│   ├── attachments
│   ├── avatars
│   ├── conf
│   ├── home
│   ├── indexers
│   ├── jwt
│   ├── log
│   ├── packages
│   ├── queues
│   ├── repo-archive
│   ├── repo-avatars
│   ├── sessions
│   └── tmp
├── sqlite
│   └── gitea.db
└── ssh
├── ssh_host_dsa_key
├── ssh_host_dsa_key.pub
├── ssh_host_ecdsa_key
├── ssh_host_ecdsa_key.pub
├── ssh_host_ed25519_key
├── ssh_host_ed25519_key.pub
├── ssh_host_rsa_key
└── ssh_host_rsa_key.pub

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

Android Studio关于插件市场Marketplace无法搜索的问题解决

发表于 2022-09-17

问题

有的小伙伴在进行插件搜索时可能会出现搜索空白的情况, 界面显示Not Found

此时 只需要设置一下国内代理即可:

image-20220916162230660

进入代理设置, 勾选自动代理 并输入以下地址:

1
http://mirrors.neusoft.edu.cn:80

重新搜索 OK

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

自建 Git 服务器:Gitea 与 Gitlab 部署踩坑经历与对比总结

发表于 2022-09-17

前言

这一周我都在折腾在自己的内网服务器中部署私有 Git 服务器,对于目前用的最广泛的 Gitea 与 GitLab 都进行了实际部署,并邀请了多人进行试用。

对于这两个被广泛使用的可自托管的 Git 托管方案,网上似乎都是几张清单式的功能对比表,所以我想在这篇文章中对比两者在我实践中感受到的的差别,以及说说这几天我趟过的坑,为准备自建 Git 托管网站的用户提供参考与建议。

在正文开始前,我先提醒一件事情:不推荐在非自己托管的 Gitea 上使用 GitHub TOKEN 等个人敏感信息,目前(v1.16.4) Gitea 的隐私管理缺陷可能会向站点管理员泄露你的隐私。这个问题可以说是我遇到的最大的坑,也是让我转向 GitLab 的主因,我会在正文中详细说明这个问题。

更新:Gitea v1.16.6 已经修复了泄露 TOKEN 的问题,但对于切记注意第三方 Gitea 托管站点的版本。

在本文发布后,Gitea 作者已经看到了部分对 Gitea 缺失功能的吐槽,并开始在新版本中实现它们,所以部分内容可能有所过时。

概述

作为可以自己部署的 Git 托管服务器方案,Gitea 与 GitLab 有很多相似之处:有着和 GitHub 相似的仓库界面,一样有着基本的 Git Server 功能,一样同时支持 http(s) 与 ssh,一样支持 Issue 和 Pull requests……

Gitea 是完全开源免费的项目,而 GitLab 有着开源并免费的版本 GitLab CE,也有付费并有闭源功能的 GitLab EE。它们也都提供了由各自的官方托管版网站,你可以前往 gitea.com 与 gitlab.com 体验它们的用法。

这些最基础的东西双方都很相似,只看双方提供的功能对比表很难感受出它们有多大差别,但在实际部署它们后,你可以很直观地感受到它们骨子里就是不同的,它们之间的区别就和 com.sun.net.httpserver 和 Spring 全家桶一样,是单一功能的库与一个生态的区别。

Gitea 是一个功能较为单一的 Git 托管服务器,所有功能都围绕着 Git 托管而来,而且给出了较高的可定制性。在部署 Gitea 的时候,我很明确自己的目的是实现 Git 托管功能,部署后我再根据自己的需求去组合其他工具来满足我的工作流。

GitLab 则是一个大而全的解决方案整合,将 Git 托管、持续集成/部署等功能做在了一起,试图解决你的所有需求。在我部署它之后,我需要探索它的功能,学习它的工作流,适应它来完成我的工作。

资源占用

作为 Git 托管服务器使用时,Gitea 资源占用明显要低得多。

静态硬盘占用上,Gitea 核心是一个 100 MiB 上下的可执行文件,外加上作为必要依赖的 Git(如果内置 SQLite 不够的话也需要单独部署一个 MySQL 或者 PostgreSQL 做数据库),而 GitLab 光 Docker image 大小就 GiB 级了……不用我多说,截一下 GitLab 的日志文件夹就知道这玩意有多重量级了:

1
2
3
4
$ ls ./gitlab/logs
alertmanager gitlab-kas gitlab-workhorse nginx prometheus redis sshd
gitaly gitlab-rails grafana postgres-exporter puma redis-exporter
gitlab-exporter gitlab-shell logrotate postgresql reconfigure sidekiq

我断断续续跑了两天,这日志就快 200MiB 了……

内存方面,我这里 Gitea 日常占用内存通常在几百 MiB 浮动,而 GitLab 的 Docker 容器目前内存占用是 14GiB。

GitLab CPU 占用率(相对于一个核心计算)日常待机在 35% 上下,而 Gitea 通常是 0.2% 左右。(这些都是日常无负载状态下的情况,如果有机会的话我试试进一步比较,现在正在停用 GItea,懒得折腾了。)

网站配置

Gitea 大部分配置都要通过修改 app.ini 并重启 Gitea 服务器来应用,后台管理面板基本没有可修改的配置,不能进行配置热修改。

GitLab 部分网络相关的配置(域名,端口,代理,邮箱等)需要修改 gitlab.rb 并重启 GitLab,剩下的大多选项都是在管理员面板里通过 Web UI 进行热修改并及时生效。

对于要稳定运行的 Git 托管服务器来说,Gitea 每次修改配置后想要生效都要离线一段时间,好在 Gitea 启动很快,我这里从启动到能正常访问大概只要 10 秒钟(数据库跑在另一个容器里,没有计算它的启动时间),而 GitLab 启动一次要一分多钟,但由于 GitLab 大部分配置都是热修改,除了最开始部署时需要修改配置,运行中基本没有重启的需求。

想要自定义页面布局在 GitLab 上非常困难,除了首页内容可以通过管理面板修改外,剩下的地方似乎都无法用常规手段修改。Gitea 放开了很多 tmpl 文件可配置,我想要给站点每个页面底部添加一条链接,自己提供一个 extra_links_footer.tmpl 就能完成,但在 GitLab 我是没有找到什么好办法去实现。(似乎能改 /var/opt/gitlab 里的东西来修改布局,但我改了这个文件夹里的一些配置后再重启后,我修改的地方都被还原了,有空再做进一步的探索。)

另外有一点就是,Gitea 内几乎所有链接都在使用基于 ROOT_URL 的绝对链接,所以基本绑死在这个 ROOT_URL 上,配置好后基本没办法用多个域名访问同一个 Gitea。准备使用内网穿透的用户要注意一下这个问题,很多内网穿透服务分配给用户的都是非标准端口,如果想在内外网都能良好访问自己的 Gitea 服务器,最好让 Gitea 内网的端口与公网端口一致,不然很多麻烦事情。

GitLab 会检测你用来访问 GitHub 所用的域名,而且很多地方都会根据这个更改显示,不会因为用不同于 external_url 的地址访问而出现问题,这方面问题会比 Gitea 少很多。 (注意一下,如果你在 external_url 中写了带端口号的地址,GitLab 的侦听端口也会跟着变更。不想改侦听端口的话记着覆盖 nginx['listen_port'] 设置)

隐私保护

隐私保护方面我觉得是 Gitea 最值得诟病的问题,也是我转而投向 GitLab 的主因。

Gitea 的一些功能需要 GitHub TOKEN 实现(譬如从 GitHub 导入私有项目等),GitHub TOKEN 作为用户隐私,本身应该受到良好保护,但我在实际使用过程中发现,目前版本(v1.16.4)的 Gitea 有严重的安全问题:

当用户正在进行使用 GitHub TOKEN 访问 GitHub 仓库的任务时,包含了 GitHub TOKEN 的 URL 直接明文出现在管理后台中,管理员可以轻松的从后台看到这些隐私信息:

img

这应该开发者考虑不周造成的问题,相对而言能明显感受到 GitLab 要更关心用户的隐私保护问题,涉及到隐私信息时都高度敏感,在不修改服务器本身的情况下,管理员也无法触及它们。(当然在管理员能接触到 GitLab 服务器的情况下,依然可以通过篡改服务器来窃取用户隐私,所以对第三方托管的服务器并不能无保留的信任。)

imgGitLab 中带有用户 TOKEN 的 URL 显示

功能

消息通知

GitLab 与 Gitea 都能配置邮件消息通知。

GitLab 每个用户都能设置自己接受的通知,或者完全拒绝邮件通知,设置的粒度可以细分到组/项目级别,管理员还能通过管理后台对用户手动群发邮件通知。

Gitea 的用户无法控制自己接受的通知,只能由管理员配置通知的类型,而且也只能进行全局范围的配置,无法细分到用户身上,而且所有通知都是 Gitea 的自动通知,管理员无法发送自定义通知。

对于 Gitea 这个邮件通知,不能说不能用,但对于多用户的服务器来说,我觉得难用到很难接受的程度,我在配好邮箱后尝试了一会就关掉了。

存储库导入与镜像

Gitea 和 GitLab 也都支持导入第三方 Git 仓库,特别是提供了原生的迁移 GitHub 仓库的办法,可以连带着 Issue、PR 等其他数据一同导入进来。

此项功能需要 GitHub TOKEN 来完成,Gitea 有泄露 TOKEN 的问题,这点在前面已经说过了,所以不建议在第三方托管的 Gitea 上进行此操作。

但如果在你自己的 Gitea 上执行,不需要担心隐私问题的话,我尝试下来的体验非常好,仓库内容基本都能原模原样地导入过来。

imgGitea 导入的 Issue

而 GitLab 的迁移功能个人体验就比较差了。Issue 虽然也能搬过来,但是无法做到 Gitea 这样保持创建者信息,所有的 Issue 创建者都会变成进行导入的用户,然后在内容中添加一条 Created by 信息来标识原创建者。

问题更大的是,GitLab 的 Issue Markdown 语法和 GitHub 有一定差别。最典型的问题是,GitHub Issue 中单个换行符就能换行,GitLab 则是保持了标准的 Markdown 语法,需要连续两个换行才可以,这导致导入的 Issue 格式全都乱成一团,根本没法看:

imgGitLab 导入后的样子

除此之外,Gitea 和 GitLab 还支持存储库镜像功能,能够让一个 Gitea/GitLab 存储库与一个外部的存储库(譬如 GitHub 上的存储库)保持关联。它们都支持这两种镜像模式:

  • Push 镜像:以当前仓库为主要仓库,在当前仓库发生修改后自动将修改推送到外部仓库中。
  • Pull 镜像:以外部仓库为主要仓库,在固定间隔后或者手动触发时从外部仓库拉取内容更新当前仓库中。

在镜像功能上,GitLab 很离谱的把 Pull 镜像归属到了 EE 功能中,也就是要付费才能使用,这一点我是完全没有想到的,因为这个功能怎么看都应该属于 CE 的范畴,这也是我对 GitLab CE 意见最大的地方。我自己部署的是 GitLab CE,所以无法尝试 Pull 镜像了。

GitLab 的 Push 镜像功能会在每次用户修改仓库或者手动触发时进行推送,我使用下来体验良好。

Gitea 的 Pull 镜像当然是完全能免费使用的,基本的定时与手动更新仓库功能都可用,就是可惜无法同时同步 wiki、Issue 和 PR。

而 Gitea 的 Push 镜像,我自己没有尝试过,但看文档的描述,Gitea 的 Push 镜像同步是定时触发的,我觉得这就挺迷惑的,还是 GitLab 的策略更好用。

而且特别要注意,Gitea 同步时唯一的认证方式是账号密码认证,但 GitHub 现在禁止账密认证,导致无法正常进行认证,唯一的解决方案是把 GitHub TOKEN 写在 URL 里,但除非是你自部署的 Gitea 并且其他人无法访问这个仓库,否则就会导致你的 GitHub TOKEN 泄露。

GitLab 原生就支持使用 GitHub TOKEN 或者通过 SSH 进行认证。SSH 不知道为什么我这里配好公钥也无法通过认证,但用 GitHub TOKEN 认证的方式工作一切正常,而且对 TOKEN 也有应有的保护,作为主要仓库使用并用它同步到 GitHub 上是没问题的。(SSH 地址必须是 ssh://git@github.com/<group name>/<repo name>.git 的形式,GitHub 的 Code 按钮里那个地址不能直接用,前面要补上 ssh://,中间的冒号也要改成正斜杠)

CI/CD

谈 Gitea 与 GitLab 的区别,那肯定少不了 CI/CD 这个重头戏。

Gitea 没有提供内置的 CI/CD 支持,但是可以用 Gitea 提供的 API 与其他 CI 集成,目前推荐的比较多的似乎是是自部署 Drone CI,但也可以与 Travis CI 这类现成的 CI 集成。

imgGitea 与 Drone CI 的集成

Gitea 与 CI 的集成我没有亲自尝试过,但可以参考上面 gitea.com 里现成的例子。我本来想尝试部署 JetBrains TeamCity,但 Gitea 目前的 API 并不足以与 TeamCity 集成,这在后续版本中可能会改进。

而 GitLab 原生就集成了一套强大的 CI 功能,而且就像 GitHub Action 与 GitHub 那样,它与 GitLab 有着极为紧密的结合。

GitLab 用于执行 GitLab CI 的程序叫做 GitLab Runner。在刚开始看文档的时候,我一直很疑惑为什么 GitLab Runner 的介绍在用户指南里,而非管理员的配置指南中,在配置好后我才豁然开朗,因为 GitLab 不止允许管理员注册全局可用的共享 GitLab Runner,它还允许一般用户为自己或者组注册自托管的 GitLab Runner 实例,让 CI 仅跑在自己的机器上。

目前我只是简单的配置并跑了一些简单的样例,尝试后我觉得很喜欢这样一套高度集成而且灵活易配置的 CI 方案,我认为这方面 GitLab 要比 Gitea强很多。

总结

根据到目前为止我自己的实际体验,对于仅个人或者小型团队内部的 Git 服务器来说,我更推荐 Gitea,它更轻量,更容易定制化,GitLab 相对来说太吃资源了,而且很多高级功能一般用户可能永远用不上。

如果是中大型团队/企业,或者是要搭建公开服务的站点,那么我只推荐 GitLab。Gitea 对于隐私的保护实在有很多欠缺,而且用起来的时候经常能感受到很多设计并不适合向大量用户提供稳定的服务。GitLab 虽然重,但是整体考虑更加完善,更适合作为商业化的产品使用。

目前我还没有来得及尝试更多功能,所以暂时也给不了更多建议,以后或许会继续更新踩坑经历,希望能帮到更多用户。

本文转载自: 知乎

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

国内代码托管厂商汇总

发表于 2022-09-17

汇总如下

  1. Gitee

    点击进入

    开源中国旗下的产品, 算是国内老牌厂商了

  2. Coding.net

    点击进入

    目前属于腾讯旗下的产品

  3. CodeUp

    点击进入

    阿里云旗下的产品

  4. GitCode

    点击进入

    CSDN旗下的产品

  5. 小程序代码托管

    点击进入

    也是腾讯旗下的 主要用于微信小程序代码托管

  6. 极狐 JihuLab

    点击进入

    基于Gitlab搭建的托管平台

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

MAC下使用Tree指令打印目录结构树

发表于 2022-09-17

前言

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
.
├── app
│   ├── build
│   │   ├── exe
│   │   │   └── main
│   │   │   └── main
│   │   ├── objs
│   │   │   └── main
│   │   │   └── mainCpp
│   │   │   └── c8slc3rovxgcr2csa5t8w6tth
│   │   │   └── HH.o
│   │   └── tmp
│   │   ├── compileMainExecutableMainCpp
│   │   │   ├── options.txt
│   │   │   └── output.txt
│   │   └── linkMainExecutable
│   │   ├── options.txt
│   │   └── output.txt
│   ├── build.gradle
│   ├── libs
│   ├── proguard-rules.pro
│   └── src
│   ├── androidTest
│   │   └── java
│   │   └── com
│   │   └── example
│   │   └── myapplication
│   │   └── ExampleInstrumentedTest.kt
│   ├── main
│   │   ├── c
│   │   │   ├── Hello.c
│   │   │   └── Hello.h
│   │   └── cpp
│   │   └── HH.cpp
│   └── test
│   └── java
│   └── com
│   └── example
│   └── myapplication
│   └── ExampleUnitTest.kt
├── build.gradle
├── gradle
│   └── wrapper
│   ├── gradle-wrapper.jar
│   └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle

如果你也想要打印类似于上面的目录结构树, 那么我们可以安装一个tree程序,

如果是Mac平台 那么直接使用brew工具进行安装:

1
brew install tree

安装完毕后 在你只需要打印结构树的目录下输入tree即可

Tree的常用技巧

  1. 如果想将目录树输出到文本, 我们可以:

    1
    tree >README.md
  2. 如果我们指定打印层级数, 那么可以:

    1
    tree -L 层级数量
  3. 如果我们只想打印文件夹

    1
    tree -d
  4. 如果我们想滤除掉某个文件夹

    1
    tree -I 文件夹名称

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

使用Android Studio进行C/C++的开发

发表于 2022-09-17

前言

作为一名专业Android开发者, 当我们遇到需要C/C++的开发时, 完全可以直接使用Android Studio, 而不用另外下载诸如CLion AppCode等收费IDE

使用Android Studio的好处有:

  • 免费: JetBrains的软件大部分都是收费的 唯独Android Studio 完全免费使用
  • Gradle天然支持C语言的编译: Gradle不仅可以编译Groovy Java和Kotlin, 还可以编译C/C++ 、Scala和Swift, 未来还会支持更多语言, 潜力无限
  • 节省电脑资源: 无需装多个IDE, 一个Android Studio就可以搞定Android Web和C的开发 你说爽不爽

说了这么多好处, 接来了咱们来聊聊如何实现Android Studio的C/C++开发

实现步骤

  1. 创建一个空工程, 默认选择Android空Activity工程即可, 然后将一些用不上的文件都清除, 最后目录结构如下:

    1
    2
    3
    4
    5
    6
    .
    |-- build.gradle
    `-- src
    `-- main
    `-- c
    `-- hello.c

    如果是C++开发, 那么目录名改成cpp, 其结构如下:

    1
    2
    3
    4
    5
    6
    .
    |-- build.gradle
    `-- src
    `-- main
    `-- cpp
    `-- hello.cpp
  2. 在App目录下的build.gradle中的内容全部清除 然后填入以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    apply plugin: 'c'

    model {
    components {
    main(NativeExecutableSpec) {
    }
    }
    }

    dependencies {

    }

    同样的 如果是C++, 则将plugin改成cpp, 如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    apply plugin: 'cpp'

    model {
    components {
    main(NativeExecutableSpec) {
    }
    }
    }

    dependencies {

    }
  3. gradle同步之后, 右侧gradle task面板中会生成三个task:

    image-20220916122044974

  4. 此时我们尝试编写C代码

    1
    2
    3
    4
    5
    6
    #include <stdio.h>

    int main(int argc, char** argv){
    printf("Hello World!\n");
    return 0;
    }
  5. 编写完后 运行gradle task中的build, 就会自动对源码进行编译并生成可执行文件, 该文件我们可以在build目录中找到

    image-20220916122359799

  6. 打开文件 双击运行, 此时控台输出Hello World

    image-20220916122515283

构建执行流程优化

  1. 编译结束后自动执行程序

    修改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
    apply plugin: 'c'

    model {
    components {
    main(NativeExecutableSpec) {
    println("开始编译...")

    }
    }
    }
    task execProgram(){
    doLast {
    println("开始执行...")
    exec {
    commandLine("./build/exe/main/main")
    }
    }

    }

    build.finalizedBy(execProgram)

    dependencies {

    }

    这样, 点击build任务之后就会自动执行程序了, 如果只想重复执行程序 不进行重新编译, 那么单独执行execProgram任务即可:

    image-20220916181048724

增加代码错误提示功能

虽然c/c++程序可以正常编译执行了, 但是代码在编写过程中并没有语法错误提示, 在这种环境下写代码的体验会比较差

接下来 我们把该功能实现, 这里需要配合android插件以及cmake构建工具:

  1. 下载NDK和cmake工具

    image-20220928141059262

    image-20220928141148055

  2. 配置build.gradle

    增加如下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    apply plugin: 'com.android.application'
    android{
    compileSdkVersion 30
    externalNativeBuild {
    cmake {
    path "CMakeLists.txt"
    }
    }
    defaultConfig {
    //需要限制最小库版本不能太低 不然有些c库可能缺失
    minSdkVersion 21
    targetSdkVersion 30

    }
    }
  3. 在build.gradle同级目录下创建CMakeLists.txt文件

    并添加以下内容:

    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
    # 限定cmake最小版本号 当前使用的版本必须在这个之上
    cmake_minimum_required(VERSION 3.10.2)

    # 描述工程名称
    project("cproject")

    # 自定义变量 使用${变量名}进行引用
    set(BINARY_NAME "android-lib")
    set(EXEC_NAME "androidexc")


    #获取指定目录下源文件列表,保存到 `DIR_SRCS` 变量中
    aux_source_directory(${PROJECT_SOURCE_DIR}/src/main/c DIR_SRCS)

    # 生成可执行文件
    add_executable(${EXEC_NAME} ${DIR_SRCS})

    # 生成动态链接库
    add_library( # 动态库名称
    ${BINARY_NAME}

    # 生成动态库
    SHARED

    # 被编译进入库中的源码文件
    ${DIR_SRCS})
  4. 在main目录下创建AndroidManifest.xml文件

    并添加以下内容, 包名自定义:

    1
    2
    3
    4
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="自定义包名">
    </manifest>
  5. 同步工程

    同步刷新gradle工程后, 此时我们发现c目录下的源码可以语法错误提示了, 并且代码自动补全功能也有了

    image-20220928170120305

实现交叉编译

经过上面如此一番配置之后, 相当于结合了gradle和cmake两大构建工具,可以说是强大无比

我们既可以使用gradle执行execProgram任务生成本地平台的可执行文件, 同时还可以使用cmake交叉编译生成android平台的执行文件和动态库文件

我们只需编译工程或者执行build任务, 即可自动生成执行文件和动态库, 同时动态库会被gradle工具自动打包进apk文件中

image-20220928171158748

image-20220928171103061

本文为作者原创转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

1…101112…48

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

479 日志
139 标签
RSS
© 2024 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%