首页
留言
友链
关于
Search
1
思源笔记docker私有化部署及使用体验分享
1,193 阅读
2
windows11 远程提示:为安全考虑,已锁定该用户帐户,原因是登录尝试或密码更改尝试过多。
619 阅读
3
Pointer-Focus:一款功能强大的教学、录屏辅助软件
389 阅读
4
在vue-cli3使用sass(scss)定义的全局样式及变量
323 阅读
5
使用cspell对项目做拼写规范检查
264 阅读
Web前端
CSS
JavaScript
交互
Vue
小程序
后端
运维
生活
其他
转载
软件
登录
Search
标签搜索
docker
DevOps
magic-boot
Linux
酷壳
RabbitMQ
Node
git
工具
Vue
MybatisPlus
clickhouse
规范
前端
产品
markdown
axios
H5
经纬度
vue-cli
朱治龙
累计撰写
118
篇文章
累计收到
0
条评论
首页
栏目
Web前端
CSS
JavaScript
交互
Vue
小程序
后端
运维
生活
其他
转载
软件
页面
留言
友链
关于
搜索到
39
篇与
运维
的结果
2024-04-07
基于 Magic-api + Clickhouse 实现业务数据更新的项目记录
背景介绍项目有用到 Clickhouse 作为数仓,存储一些用户日常业务产生的大数据,下面先简单介绍一下我们这个任务的需求背景:我们的每个用户都会归属于某个用户组,并基于用户所在的计费组织实现产品使用过程中的消费等情况。而按照系统的设定用户初始注册时是没有归属用户组的,计费组织的主账号可以在控制台将用户绑定到该计费组下,也可以解绑,解绑后也可以绑定到其他用户组。为了更好的这个变更情况,我们在 Clickhouse 添加了一张名为 user_type 的表,每次该数据变更都会新增一条记录,该表的结构如下:CREATE TABLE user_type ( `user_id` Nullable(String), `present_type` Nullable(String), `pay_type` Nullable(String), `group_type` Nullable(String), `start_date` Nullable(Date), `end_date` Nullable(Date), `uni_key` Nullable(String) ) ENGINE = Log;实现方案本项目初期由使用 dbt + Clickhouse 的方式来实现,但是经实践运行一段时间后发现 dbt 做数据同步很方便,但是要添加一些业务逻辑就显得很棘手。为了解决 dbt 的问题,我们使用已搭建的 magic-api 来实现这个数据的更新,由于相关数据仅需一天一更新即可,所以我们可以直接利用 magic-api 自带的定时任务机制来实现更新。技术细节为便于相关业务逻辑在接口和定时任务中复用,我们将核心代码写在函数模块中:相关步骤核心代码如下步骤:1、从计费系统获取最新的userType信息var statSQL = `select e.*, CONCAT(e.user_id,'-',e.present_type,'-',e.pay_type,'-',e.group_type,'-',date_format(e.start_date,'%Y-%m-%d')) as uni_key FROM( SELECT a.user_id, CASE WHEN EXISTS ( SELECT 1 FROM ( SELECT t1.user_id user_id from b_contract t1 LEFT JOIN b_contract_item t2 ON t1.id = t2.contract_id WHERE t2.is_present = 0 and t2.received_payments > 0 GROUP BY t1.user_id UNION SELECT u2.user_id user_id from b_user as u1, b_user as u2 where u1.group_id=u2.group_id AND u1.user_id != u2.user_id AND EXISTS( SELECT 1 FROM (SELECT t1.user_id from b_contract t1 LEFT JOIN b_contract_item t2 ON t1.id = t2.contract_id WHERE t2.is_present = 0 and t2.received_payments > 0 GROUP BY t1.user_id) c WHERE c.user_id = u1.user_id ) ) d WHERE a.user_id = d.user_id ) then 'pay' else 'no pay' END as present_type, CASE WHEN EXISTS( SELECT 1 FROM( SELECT t1.user_id FROM b_user t1 , b_group t2 WHERE t1.user_id=t2.pay_user_id AND t2.pay_user_id IS NOT NULL )b WHERE a.user_id = b.user_id ) THEN 'master' ELSE 'slave' END as pay_type, CASE WHEN EXISTS(SELECT 1 FROM(SELECT t1.user_id FROM b_user t1 WHERE t1.group_id IS NOT NULL)b WHERE a.user_id = b.user_id) THEN 'group' ELSE 'no group' END as group_type, CURRENT_DATE as start_date, DATE(null) as end_date FROM b_user a )e` return db['NB'].select(statSQL)2、将上一步获取到的信息存储到Clickhouse 的一张临时表import log; import cn.hutool.core.date.DateUtil; import '@/statForProduction/userTypeStat/getLatestUserTypeData' as getLatestUserType; // ------------------- 一、创建临时表 ------------------- const TEMP_TABLE_NAME = 'user_type_temp' var checkExistRes = db['CH'].select(`SELECT 1 FROM system.tables WHERE database = 'dw' AND name = '${TEMP_TABLE_NAME}'`) log.info(checkExistRes.size() + '') // 不存在表的话就基于 user_type 表创建一张临时表 if (checkExistRes.size() === 0) { var initTemporaryTableSQL = `CREATE TABLE ${TEMP_TABLE_NAME} as user_type` db['CH'].update(initTemporaryTableSQL) } else { // 临时表存在则先清空临时表的数据,便于下一步将输入存入临时表 var truncateTemporaryTableSQL = `truncate table ${TEMP_TABLE_NAME}` db['CH'].update(truncateTemporaryTableSQL) } // ------------------- 二、获取最新的用户类型数据 ------------------- log.info(`============ 开始从计费系统获取最新的用户类型数据,该操作耗时较长,请耐心等待 ============`) var timer = DateUtil.timer() const userTypeList = getLatestUserType() log.info(`getLatestUserType cost time: ${timer.intervalPretty()}.`) // ------------------- 三、将数据存入临时表 ------------------- const BATCH_INSERT_COUNT = 1000 // 分批次入临时表,一次插入记录条数 var timer = DateUtil.timer() const allDataCount = userTypeList.size() if (allDataCount > 0) { log.info(`开始导入数据到临时表,待导入的总记录数为:${allDataCount},预计分${Math.ceil(allDataCount/BATCH_INSERT_COUNT)::int}批导入。`) const willInsertArr = [] var insertSQL = `insert into ${TEMP_TABLE_NAME}(user_id,present_type,pay_type,group_type,start_date,end_date,uni_key)` // 分批次插入临时表 for (index,userTypeItem in userTypeList) { willInsertArr.push(`('${userTypeItem.userId}','${userTypeItem.presentType}','${userTypeItem.payType}','${userTypeItem.groupType}','${userTypeItem.startDate}', null,'${userTypeItem.uniKey}')`) if (willInsertArr.size() === BATCH_INSERT_COUNT) { db['CH'].update(`${insertSQL} values${willInsertArr.join(',')}`) // 清空数据 willInsertArr.clear() log.info('Batch insert:' + index) } } // 不满整批次数据单独处理 if (willInsertArr.size() > 0) { db['CH'].update(`${insertSQL} values${willInsertArr.join(',')}`) // 清空数据 willInsertArr.clear() } } log.info(`insert latest user type to Temporary Table cost time: ${timer.intervalPretty()}.`) return true3、将临时表数据跟前一次最新的用户数据对比后,将有变更和新增的数据写入user_type表import log; import cn.hutool.core.date.DateUtil; const LATEST_TABLE_NAME = 'user_type_latest' // 用户最新类型数据表 const TEMP_TABLE_NAME = 'user_type_temp' // 该表存储从计费表获取到用户当前的用户类型数据,已在上一步获取数据完毕 // 一、从user_type表获取所有用户最新的用户类型数据并插入到用于计算的临时表 // 1.1 新建临时表,用于存储每个用户user_type 表中最新的用户类型数据 var checkExistRes = db['CH'].select(`SELECT 1 FROM system.tables WHERE database = 'dw' AND name = '${LATEST_TABLE_NAME}'`) log.info(checkExistRes.size() + '') // 不存在表的话就基于 user_type 表创建一张临时表 if (checkExistRes.size() === 0) { var initTemporaryTableSQL = `CREATE TABLE ${LATEST_TABLE_NAME} as user_type` db['CH'].update(initTemporaryTableSQL) } else { // 临时表存在则先清空临时表的数据,便于下一步将输入存入临时表 var truncateTemporaryTableSQL = `truncate table ${LATEST_TABLE_NAME}` db['CH'].update(truncateTemporaryTableSQL) } // 1.2 将最新数据写入临时表 // 该方式在数据量较大的情况下极有可能导致内存溢出,拟采取其他方案:在user_type 数据初始化的时候,将最新的用户类型数据存储到user_type_latest表,对比更新完成后将临时表的数据更新到user_type_latest便于下次对比 // const insertLatestDataSQL = `insert into ${LATEST_TABLE_NAME} SELECT user_type.user_id uid,user_type.present_type ,user_type.pay_type ,user_type.group_type,user_type.start_date,user_type.end_date,user_type.uni_key // FROM user_type, (SELECT user_type.user_id uid2,max(user_type.start_date) AS latestDate FROM user_type GROUP BY user_type.user_id) AS temp // WHERE user_type.start_date = temp.latestDate and uid = temp.uid2` // db['CH'].update(insertLatestDataSQL) // 二、两个临时表的数据做对比,并将最新数据更新到 user_type var timer = DateUtil.timer() // 2.1 更新有变更的数据 const changedInsertSQL = `insert into user_type select tuts.* from ${LATEST_TABLE_NAME} tutl left join ${TEMP_TABLE_NAME} tuts on tutl.user_id =tuts.user_id where tutl.present_type != tuts.present_type or tutl.pay_type != tuts.pay_type or tutl.group_type != tuts.group_type` timer.start("insertChangeData") db['CH'].update(changedInsertSQL) // 2.2 新增用户数据直接插入 timer.start("insertNewData") const insertNewUserSQL = `insert into user_type select * from ${TEMP_TABLE_NAME} tuts where tuts.user_id not in (select tutl.user_id from ${LATEST_TABLE_NAME} tutl) ` db['CH'].update(insertNewUserSQL) // 三、如果有数据更新,则将临时表的数据替换latest表 // 3.1 清理已有的数据 const truncateLatestTableSQL = `truncate table ${LATEST_TABLE_NAME}` db['CH'].update(truncateLatestTableSQL) // 3.2 从临时表导入最新的数据 const initialLatestTableDataSQL = `insert into ${LATEST_TABLE_NAME} select * from ${TEMP_TABLE_NAME}` db['CH'].update(initialLatestTableDataSQL) log.info(`insertChangeData cost time: ${timer.intervalPretty('insertChangeData')}`) log.info(`insertNewUser cost time: ${timer.intervalPretty('insertNewData')}`) // 四、清理临时表 const dropTempTableSQL = `drop table ${TEMP_TABLE_NAME}` db['CH'].update(dropTempTableSQL) return true 定义好相关函数后,我们可以直接在接口中用起来了,为此我定义了两个接口,一个接口用于数据初始化,一个接口用于手动更新数据:接口定义01数据初始化import log; import '@/statForProduction/userTypeStat/maintenance/clearUserTypeData' as clearUserTypeData import '@/statForProduction/userTypeStat/saveToTemporaryTable' as saveToTemporaryTable const LATEST_TABLE_NAME = 'user_type_latest' // 用户最新类型数据表 const TEMP_TABLE_NAME = 'user_type_temp' // 该表存储从计费表获取到用户当前的用户类型数据 // 一、清空所有user_type表的数据 clearUserTypeData() // 二、一次性写入所有 saveToTemporaryTable() // 三、将临时表的所有数据一次性写入user_type 表作为初始数据 const initialUserTypeDataSQL = `insert into user_type select * from ${TEMP_TABLE_NAME}` db['CH'].update(initialUserTypeDataSQL) // 四、将数据写入最新用户类型表,便于下一次做数据比对 // 4.1 基于 user_type 表 创建 user_type_latest 表 var checkExistRes = db['CH'].select(`SELECT 1 FROM system.tables WHERE database = 'dw' AND name = '${LATEST_TABLE_NAME}'`) log.info(checkExistRes.size() + '') // 不存在表的话就基于 user_type 表创建一张 if (checkExistRes.size() === 0) { var createLatestTableSQL = `CREATE TABLE ${LATEST_TABLE_NAME} as user_type` db['CH'].update(createLatestTableSQL) } else { // 表存在则先清空表的数据,便于下一步将最新的用户类型数据存入该表 var truncateLatestTableSQL = `truncate table ${LATEST_TABLE_NAME}` db['CH'].update(truncateLatestTableSQL) } // 4.2 插入该表的初始数据 const initialLatestTableDataSQL = `insert into ${LATEST_TABLE_NAME} select * from ${TEMP_TABLE_NAME}` db['CH'].update(initialLatestTableDataSQL) // 五、清理临时表 const dropTempTableSQL = `drop table ${TEMP_TABLE_NAME}` db['CH'].update(dropTempTableSQL) 02手工同步用户类型数据/** * 本接口用于手工临时同步数据用,日常使用定时任务自动同步操作即可 */ import '@/statForProduction/userTypeStat/saveToTemporaryTable' as saveToTemporaryTable import '@/statForProduction/userTypeStat/updateUserTypeData' as updateUserTypeData saveToTemporaryTable() updateUserTypeData()添加定时任务本任务用到的部分 Clickhouse SQL-- 判断数据表是否存在 SELECT 1 FROM system.tables WHERE database = 'dw' AND name = 'temp_user_type_session' -- 根据user_type 表创建一张名为 temp_user_type_session 的临时表 CREATE TABLE temp_user_type_session as user_type; -- 清空某数据表中的所有内容 truncate table temp_user_type_session; -- 查询所有用户最新的用户类型数据 SELECT user_type.user_id uid,user_type.present_type ,user_type.pay_type ,user_type.group_type,user_type.start_date,user_type.end_date,user_type.uni_key FROM user_type, (SELECT user_type.user_id uid2,max(user_type.start_date) AS latestDate FROM user_type GROUP BY user_type.user_id) AS temp WHERE user_type.start_date = temp.latestDate and uid = temp.uid2; -- 获取有差异的数据 select tutl.*,tuts.user_id user_id2, tuts.present_type present_type2, tuts.pay_type pay_type2, tuts.group_type group_type2, tuts.start_date start_date2,tuts.uni_key uni_key2 from temp_user_type_latest tutl left join temp_user_type_session tuts on tutl.user_id =tuts.user_id where tutl.present_type != tuts.present_type or tutl.pay_type != tuts.pay_type or tutl.group_type != tuts.group_type;
2024年04月07日
5 阅读
0 评论
0 点赞
2023-12-13
Jeepay开源版使用过程中踩过的坑
1、商户系统登录问题添加商户的时候有设置登录名,但是没有设置账号密码的位置,好不容易找到对商户重置密码的地方,但是那个勾选重置密码的复选框又超级容易被理解为用户下次登录需重置密码的配置项。勾选后有提示重置为默认密码,但是又没有说明默认密码是什么,然后非得要查看源码才知道是通过常量设置的默认密码为:jeepay6662、证书文件不存在问题好不容易登录商户系统了,进行支付测试的功能验证,提示证书文件不存在:整个应用部署过程完全是基于官方提供的 docker-compose.yml 文件,最后发现默认配置的 /home/jeepay/upload 目录根本就没有挂载到宿主机,修改 docker-compose.yml ,payment、manager、merchant 应用的 volumes 应用均挂载 /home/jeepay 目录,如: volumes: - ./jeepayData:/home/jeepay3、支付测试不显示二维码的问题支付测试时不显示支付二维码,发现HTTP请求中有个 404 请求:检查代码,确定应用存在对应的接口路径:查看docker 日志复现如下 error 信息:基于该信息可得知,nginx在接收到二维码图片请求时根本就没有请求到 jeepay-payment 这个后端服务,而是直接请求了root 目录中的文件,由此我们调整一下 代理的api接口的优先级,修改 jeepay-ui 根目录下的 default.conf.template 文件,在/api/ 前添加 ^~ ,nginx的路径匹配规则如下:/:通用匹配,任何请求都可以匹配=:用于不含正则表达式的uri前,要求请求字符串与uri严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。~:用于表示uri包含正则表达式,并且区分大小写。~*:用于表示uri包含正则表达式,并且不区分大小写。^~:用于不包含正则表达式的uri前,要求nginx服务器找到标识uri和请求字符串匹配度最高的location后,立即使用此location处理请求,而不再使用location块中的正则uri与请求字符串做匹配。!~和!~*:分别表示区分大小写不匹配和不区分大小写不匹配的正则优先级:= --> ^~ --> /* #当有多个包含/进行正则匹配时,选择正则表达式最长的location配置执行。多个location配置的情况下匹配顺序为: 首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 /通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。注意:如果uri包含正则表达式,则必须要有 ~ 或者 ~ 标识。修改后的 default.conf.template 文件如下所示:server { listen 80; listen [::]:80; server_name localhost; root /workspace/; try_files $uri $uri/ /index.html; location ^~ /api/ { proxy_next_upstream http_502 http_504 error timeout invalid_header; proxy_pass http://$BACKEND_HOST; 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_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # favicon.ico location = /favicon.ico { log_not_found off; access_log off; } # robots.txt location = /robots.txt { log_not_found off; access_log off; } # assets, media location ~* \.(?:css(\.map)?|js(\.map)?|jpe?g|png|gif|ico|cur|heic|webp|tiff?|mp3|m4a|aac|ogg|midi?|wav|mp4|mov|webm|mpe?g|avi|ogv|flv|wmv)$ { expires 7d; access_log off; } # svg, fonts location ~* \.(?:svgz?|ttf|ttc|otf|eot|woff2?)$ { add_header Access-Control-Allow-Origin "*"; expires 7d; access_log off; } # gzip gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml; } 4、公众号/小程序支付的URL多了一级/cashier应用部署完毕,进行支付测试时,采用「微信支付二维码」的方式已支付成功,但是采用「公众号/小程序」的支付方式,在扫码后,发现扫码后的页面显示空白,进一步排查,发现是由于页面的css和js资源文件404导致的,进一步排查,是由于请求的资源多了一级path,一下是问题排查过程:系统配置中的支付网关地址填写的是 https://jeepay-cashier.work.zhuzhilong.com:但是在使用支付测试功能,支付方式采用「公众号/小程序」进行支付测试时,生成的二维码如下:二维码识别后的地址为:https://jeepay-cashier.work.zhuzhilong.com/cashier/index.html#/hub/78d439f3140fe4047c7f8f6cda1048313636890021b83c0c167270dbce4fc2ff根据应用部署情况,比预期的访问路径多了 /cashier,查看源代码后,发现这个路径是写死在 com.jeequan.jeepay.core.model.DBApplicationConfig.java中的:去掉相关方法中的 /cashier 后,根据 docker-compose.yml 重新构建镜像及重启服务后,可正常支付。
2023年12月13日
15 阅读
0 评论
0 点赞
2023-10-30
docker compose 部署Umami
很长一段时间是用的cnzz做的网站访问统计,功能强大,分析结果对于小白用户也超级友好,自从被阿里收购后,整合成Umeng的一部分勉强还能用,但是自从开启收费(收割用户)模式后,高昂的价格,无疑把我们这种小白个人用户完全隔离在外了。然后用了一段时间的百度统计,感觉也是不尽如人意,然后就只好另辟蹊径,调研了市面主流的流量统计工具(也就调研了Matomo 和Umami)后,选择了Umami 作为个人流量统计工具,主要是Matomo不少明细数据是存储的Binary数据,不便于通过SQL直观的查看,相对于Matomo而言,Umami 算是轻量级别的,UI 界面也更现代化。Umami 支持 PostgreSQL 和 MySQL 两种数据库,分别对应不同的Docker 镜像。ProstgreSQL:docker pull ghcr.io/umami-software/umami:postgresql-latestMySQL:docker pull ghcr.io/umami-software/umami:mysql-latest由于我的服务器上面已安装 MySQL 客户端,就直接采用 MySQL 的镜像。ghcr.io 是 GitHub 的 Docker 镜像仓库,国内环境可能在pull 时会碰到些网络方面的问题,我是通过一台境外的服务器pull 后,然后 push 到本人的 Docker 私服进行下载的,也可以采用导出备份后在导入的方式。如果你在pull过程中也存在这方面网络的问题的话,也推荐使用这个方式。docker-compose.ymlversion: "3.8" services: umami: image: ghcr.io/umami-software/umami:mysql-latest # image: hub.work.zhuzhilong.com/apps/umami:mysql container_name: umami restart: unless-stopped volumes: - ../hosts:/etc/hosts environment: - DATABASE_URL=mysql://DB_USERNAME:DB_PASSWORD@DB_HOST:DB_PORT/umami - DATABASE_TYPE=mysql - APP_SECRET=umami2023 - TZ=Asia/Shanghai networks: - net-zzl ports: - 8202:3000 networks: net-zzl: name: bridge_zzl external: true 使用 docker compose up -d 启动后,可使用默认的管理员账号登录:用户名:admin密码:umami登录后即可修改密码及添加站点了。以下是整合后的部分界面截图:顺便说下,umami的表结构比较简单,访问用户的IP信息都没有存表,如果有复杂运营场景的话,还是推荐使用 Matomo 之类的功能更强大的工具。当前版本(2.8.0)只有11张表:{mtitle title="2023-12-18更新"/}应用升级近日登录umami时提示最新发布了2.9.0 版本,而根据更新日志中的内容有提到可以查看访客的城市信息了,便及时更新了下,使用docker compose 的方式更新超级简单,主要执行如下命令:docker compose pull docker compose up --force-recreate提示数据库更新成功:然后重启应用即可
2023年10月30日
43 阅读
0 评论
0 点赞
2023-10-30
docker compose 部署 中微子代理(NeutrinoProxy)
近期在开源中国有看到 Neutrino-proxy 的一些介绍,了解到 NeutrinoProxy 是一款基于 Netty 的内网穿透工具,官方的介绍信息如下:基本介绍中微子代理 (neutrino-proxy) 是一款基于 netty 的内网穿透神器。该项目采用最为宽松的 MIT 协议,因此您可以对它进行复制、修改、传播并用于任何个人或商业行为。Gitee 地址:https://gitee.com/dromara/neutrino-proxy官网地址:http://neutrino-proxy.dromara.org服务端管理后台截图:主要特点:1、流量监控:首页图表、报表管理多维度流量监控。全方位掌握实时、历史代理数据。2、用户 / License:支持多用户、多客户端使用。后台禁用实时生效。3、端口池:对外端口统一管理,支持用户、License 独占端口。4、端口映射:新增、编辑、删除、禁用实时生效。5、Docker:服务端支持 Docker 一键部署。6、SSL 证书:支持 SSL,保护您的信息安全。7、域名映射:支持绑定子域名,方便本地调试三方回调8、采用最为宽松的 MIT 协议,免去你的后顾之忧之前一直有在用 FRP 作为内网穿透工具,用了很多年也确实非常好用,不过 FRP 在可视化管理方面比较欠缺,虽然提供了dashboard,但是只提供了代理端口查看及浏览统计方面的功能,不能提供多用户方面的管控。而 Neutrino 正好弥补了这方面的不足。以下是使用 docker compose 部署相关的代码,仅作为记录。服务端:docker-compose.ymlversion: '3.8' services: app: image: registry.cn-hangzhou.aliyuncs.com/asgc/neutrino-proxy:latest container_name: neutrino-proxy restart: always networks: - net-zzl ports: - 9000-9200:9000-9200/tcp - 9201:8888 volumes: - ./config:/root/neutrino-proxy/config networks: net-zzl: name: bridge_zzl external: true ./config/app.ymlneutrino: data: db: type: mysql # 自己的数据库实例,创建一个空的名为'neutrino-proxy'的数据库即可,首次启动服务端会自动初始化 url: jdbc:mysql://DB_HOST:3306/neutrino-proxy?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useAffectedRows=true&useSSL=false driver-class: com.mysql.jdbc.Driver # 数据库帐号 username: DB_USERNAME # 数据库密码 password: DB_PASSWORD客户端官网文档不推荐使用docker的方式部署,但是考虑到要部署Java 环境之类的,对宿主机而言是挺麻烦的,还是试着通过docker 的方式部署的客户端,经过验证也是 OK 的。docker-composeversion: '3.8' services: app: image: aoshiguchen/neutrino-proxy-client:latest container_name: neutrino-proxy-client restart: always network_mode: host volumes: - ./config:/root/neutrino-proxy/config./config/app.ymlneutrino: proxy: logger: # 日志级别 level: ${LOG_LEVEL:info} tunnel: # 线程池相关配置,用于技术调优,可忽略 thread-count: 50 # 隧道SSL证书配置 key-store-password: ${STORE_PASS:123456} jks-path: ${JKS_PATH:classpath:/test.jks} # 服务端IP,这里替换成主机IP或域名 server-ip: ${SERVER_IP:proxy.xxx.com} # 服务端端口(对应服务端app.yml中的tunnel.port、tunnel.ssl-port) server-port: ${SERVER_PORT:9002} # 是否启用SSL(注意:该配置必须和server-port对应上) ssl-enable: ${SSL_ENABLE:true} # 客户端连接唯一凭证,这里替换成key license-key: ${LICENSE_KEY:ec7e9906cXXXXXX6430895c37fec75cd4e11} # 客户端唯一身份标识(可忽略,若不设置首次启动会自动生成) client-id: ${CLIENT_ID:workServer} # 是否开启隧道传输报文日志(日志级别为debug时开启才有效) transfer-log-enable: ${CLIENT_LOG:false} # 重连设置 reconnection: # 重连间隔(秒) interval-seconds: 10 # 是否开启无限重连(未开启时,客户端license不合法会自动停止应用,开启了则不会,请谨慎开启) unlimited: false client: udp: # 线程池相关配置,用于技术调优,可忽略 boss-thread-count: 5 work-thread-count: 20 # udp傀儡端口范围 puppet-port-range: 10000-10500 # 是否开启隧道传输报文日志(日志级别为debug时开启才有效) transfer-log-enable: ${CLIENT_LOG:false}实现后的效果截图:
2023年10月30日
29 阅读
0 评论
0 点赞
2023-08-27
修改gitlab账号密码
由于本人的gitlab为个人所用,隔久了未用,之前设置的密码不能登录了,便试着在数据库层面重置密码,本文主要对重置gitlab管理员密码的过程进行记录
2023年08月27日
6 阅读
0 评论
0 点赞
2023-08-17
自定义 docker 网络
docker 容器如果没有指定网络,在启动时会默认生成一个桥接的网络,如下图所示:启动的 docker 容器多了,再启动其他容器的时候,就会出现Error response from daemon: Pool overlaps with other one on this address space 的提示。为解决这个问题,可以采用手工创建桥接网络,然后在 docker-compose.yml 中指定网络的方式解决。{card-describe title="本地 docker 环境信息"}jiuzilong@jiuzilong:/data/dockerRoot/apps/chat2db$ docker -v Docker version 24.0.4, build 3713ee1 jiuzilong@jiuzilong:/data/dockerRoot/apps/chat2db$ docker compose version Docker Compose version v2.19.1 jiuzilong@jiuzilong:/data/dockerRoot/apps/chat2db$ {/card-describe}一、创建桥接网络:docker network create --subnet=192.168.100.0/16 --gateway=192.168.100.1 --opt "com.docker.network.bridge.name"="bridge_zzl" bridge_zzl如果创建失败,极有可能是网络数量超标了,可以停掉一些容器再创建。失败截图如下:如果创建成功,会响应创建成功的 NETWORK ID,如下图所示:二、docker-compose.yml 配置网络配置示例:version: '3' services: app: # image: 'jc21/nginx-proxy-manager:2.9.22' # image: 'chishin/nginx-proxy-manager-zh:latest' image: 'zhuzl/nginx-proxy-manager:ssl' restart: unless-stopped container_name: nginxProxyManager ports: - '80:80' - '81:81' - '443:443' networks: - net-zzl volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt networks: net-zzl: name: bridge_zzl external: true 核心是networks: net-zzl: name: bridge_zzl external: true然后在 docker 应用中通过 networks 指定 networks: - net-zzl{alert type="warning"}特别注意:在拷贝上面代码到 docker-compose.yml 文件时,需要特别留意缩进问题{/alert}
2023年08月17日
74 阅读
0 评论
0 点赞
2023-08-11
ubuntu环境安装Harbor记录
Harbor 是一款优秀的开源企业容器镜像仓库。包括了基于web界面的权限管理(RBAC)、LDAP、审计、安全漏洞扫描、镜像验真、管理界面、自我注册、HA 等企业必需的功能,同时针对中国用户的特点,设计镜像复制和中文支持等功能。官网链接:https://goharbor.io/为方便应用开发部署,想要自己搭建Docker 镜像仓库,以下是部署过程。{card-describe title="Ubuntu版本情况"}zhuzl@zhuzl-M9-PRO:/data/software/harbor$ uname -a Linux zhuzl-M9-PRO 6.2.0-26-generic #26~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Jul 13 16:27:29 UTC 2 x86_64 x86_64 x86_64 GNU/Linux{/card-describe}一、下载安装包根据Harbor官网的引导,可通过github的发布页面下载离线安装包:https://github.com/goharbor/harbor/releases由于国内网络下载速度堪忧,本次下载使用 ghproxy.com 进行代理加速下载,也就是在下载地址前添加 https://ghproxy.com/。下载记录如下:zhuzl@zhuzl-M9-PRO:/data/software$ wget https://ghproxy.com/https://github.com/goharbor/harbor/releases/download/v2.8.4/harbor-offline-installer-v2.8.4.tgz --2023-08-18 08:48:42-- https://ghproxy.com/https://github.com/goharbor/harbor/releases/download/v2.8.4/harbor-offline-installer-v2.8.4.tgz 正在解析主机 ghproxy.com (ghproxy.com)... 192.9.132.155 正在连接 ghproxy.com (ghproxy.com)|192.9.132.155|:443... 已连接。 已发出 HTTP 请求,正在等待回应... 200 OK 长度: 608175520 (580M) [application/octet-stream] 正在保存至: ‘harbor-offline-installer-v2.8.4.tgz’ harbor-offline-installer-v2.8.4.tgz 100%[==============================================================================================>] 580.00M 4.40MB/s 用时 2m 9s 2023-08-18 08:50:52 (4.49 MB/s) - 已保存 ‘harbor-offline-installer-v2.8.4.tgz’ [608175520/608175520]) zhuzl@zhuzl-M9-PRO:/data/software$ 二、解压安装包文件下载下来是一个以 .tgz 格式结尾的压缩文件,我们可以直接使用 tar 解压,解压命令为(需替换X.Y.Z为下载对应的版本):tar -zxvf harbor-offline-installer-vX.Y.Z.tgz解压记录如下:zhuzl@zhuzl-M9-PRO:/data/software$ tar -zxvf harbor-offline-installer-v2.8.4.tgz harbor/harbor.v2.8.4.tar.gz harbor/prepare harbor/LICENSE harbor/install.sh harbor/common.sh harbor/harbor.yml.tmpl zhuzl@zhuzl-M9-PRO:/data/software$ 三、配置及安装搜了下网上的课程,大多都是从配置证书开始的,我部署应用时一般都是应用开启http服务,使用nginx代理的时候再使用SSL证书对外提供https的访问。3.1 配置拷贝解压出来的 harbor.yml.tmpl 文件为 harbor.yml。修改这个配置文件。主要有如下信息需要修改的地方:hostname: 修改为域名https: 根据需要配置,我本处是直接注释掉了harbor_admin_password:管理员密码data_volume: harbor数据目录,这是宿主机的文件目录修改后执行初始化:./prepare初始化日志记录日下:zhuzl@zhuzl-M9-PRO:/data/dockerRoot/apps/harbor$ ./prepareprepare base dir is set to /data/dockerRoot/apps/harborWARNING:root:WARNING: HTTP protocol is insecure. Harbor will deprecate http protocol in the future. Please make sure to upgrade to httpsGenerated configuration file: /config/portal/nginx.confGenerated configuration file: /config/log/logrotate.confGenerated configuration file: /config/log/rsyslog_docker.confGenerated configuration file: /config/nginx/nginx.confGenerated configuration file: /config/core/envGenerated configuration file: /config/core/app.confGenerated configuration file: /config/registry/config.ymlGenerated configuration file: /config/registryctl/envGenerated configuration file: /config/registryctl/config.ymlGenerated configuration file: /config/db/envGenerated configuration file: /config/jobservice/envGenerated configuration file: /config/jobservice/config.ymlGenerated and saved secret to file: /data/secret/keys/secretkeySuccessfully called func: create_root_certGenerated configuration file: /compose_location/docker-compose.ymlClean up the input dirzhuzl@zhuzl-M9-PRO:/data/dockerRoot/apps/harbor$初始化完成后,会在当前目录生成 `docker-compose.yml`文件,此时,我们可以使用 `docker compose` 启动docker 服务啦,日志记录如下:zhuzl@zhuzl-M9-PRO:/data/dockerRoot/apps/harbor$ sudo docker compose up -d[+] Running 9/9 ✔ Container harbor-log Started 0.3s ✔ Container redis Started 0.7s ✔ Container registry Started 1.1s ✔ Container registryctl Started 0.9s ✔ Container harbor-portal Started 0.8s ✔ Container harbor-db Started 1.1s ✔ Container harbor-core Started 1.5s ✔ Container nginx Started 2.0s ✔ Container harbor-jobservice Started 2.1szhuzl@zhuzl-M9-PRO:/data/dockerRoot/apps/harbor$ 对了,执行`docker compose`的时候一定要用`sudo`,否则会出现文件权限相关的报错。 启动完成后,可以通过 `nginx` 配置代理的方式对外提供服务,配置好后,访问出现如下图所示的登录界面: ![harbor 登录界面](https://blog.zhuzhilong.cn/usr/uploads/2023/08/2381568293.png) 在登录界面可以使用管理员账号 admin,进行登录,密码为在`harbor.yml` 文件中`harbor_admin_password` 配置的默认密码。 登录成功后,主界面如下图所示: ![Harbor主界面](https://blog.zhuzhilong.cn/usr/uploads/2023/08/3334557343.png)
2023年08月11日
39 阅读
0 评论
0 点赞
2023-07-13
通过Docker Compose安装Jira
由于数据库在服务器上已提前安装好,本处省略MySQL的安装流程。环境说明Jira 相关的文件统一放到 /data/dockerRoot/jira 目录。docker-compose.yml 文件内容如下:version: '3.9' services: jira: container_name: jira image: atlassian/jira-software:latest restart: "no" ports: - 18080:8080 environment: CATALINA_OPTS: -javaagent:/opt/atlassian/jira/atlassian-agent.jar volumes: - ./jira_data:/var/atlassian/application-data/jira - ./libs/atlassian-agent.jar:/opt/atlassian/jira/atlassian-agent.jar - ./libs/mysql-connector-java-8.0.30.jar:/opt/atlassian/jira/lib/mysql-connector-java.jar - ../hosts:/etc/hosts - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:rolibs 目录的文件打包如下:libs.zip启动服务sudo docker compose up -d设置JiraJira 容器启动完毕后,可通过 http://localhost:18080 访问,会自动调整到如下图所示的初始化向导页面:1、设置为中文单击 右上角的「Language」2、我将设置它自己在第二步选择「我将设置它自己」3、数据库连接配置连接数据库选择「其他数据库」,数据库类型根据本地环境进行选择,选择对应的数据库,要提前引入对应数据库的驱动 jar 包。4、设置应用程序属性5、设置许可证如果本地有Java 环境,可以在本地生成许可证,没有的话进入Jira 容器生成也可以执行如下命令,替换对应的服务器ID:java -jar atlassian-agent.jar -d -m test@test.com -n BAT -p jira -o lewis2951 -s B87T-QH0H-UBTM-IU5Q以上命令相关说明如下:java -jar atlassian-agent.jar \ -m zh_season@163.com # Licence Emali \ -n atlassian # Licence Name \ -o atlassian # Licence organization \ -p crowd # Licence product, support: crowd, conf, jira, bitbucket \ -s <copy from website> # License server id以上通过本地环境生成,复制许可证内容到输入框。6、设置管理员根据自己需求设置,Email 可以是一个不存在的,但是建议使用真实Email。7、设置电子邮件通知8、完成部署到此,Jira 就部署完成了。进入欢迎页面,可以创建一个示例项目,9、查看许可证在管理 → 应用程序下可查看许可证信息
2023年07月13日
13 阅读
0 评论
0 点赞
2023-07-01
常用docker 命令
该文档内容主要用于日常记录,会逐步添加重启 docker 服务sudo systemctl daemon-reload sudo systemctl restart docker将当前用户添加到docker用户组,那样就不用每次执行docker命令都加sudosudo usermod -aG docker $USER复制容器中的目录到本地:sudo docker cp <CONTAINER_ID>:/usr/local/tomcat/webapps/ROOT ./temp进入容器sudo docker exec -it mongodb /bin/bash创建网络docker network create --driver=bridge --subnet=192.168.0.0/16 bridge_zzl构建镜像docker build -f ./Dockerfile.devIstio -t console-mobile-ui:0.0.1 .将其他仓库的 docker 镜像推送到本地私服一般用于本地下载外网镜像超级慢的情况,可找台外网的机器 pull,然后 push 到 Docker 私服docker pull ghcr.io/huolalatech/page-spy-web:release docker tag ghcr.io/huolalatech/page-spy-web:release xxx.yyy.zhuzhilong.com/apps/page-spy-web:release docker push xxx.yyy.zhuzhilong.com/apps/page-spy-web:release
2023年07月01日
28 阅读
0 评论
0 点赞
2023-06-29
处理360路由器不能通过代理在外网访问的问题
缘起2020年的时候,感觉家里的路由实在是太慢了,正好360新出的360WiFi6全屋路由 天穹 V6 路由感觉还蛮不错,就入手了。 使用至今整体还算稳定,功能也能满足大部分使用场景,而且系统自带「自定义hosts」功能,在内网想要使用域名访问部署的服务也就方便多了,虽说不支持泛域名解析,一个一个配有些繁琐,但好歹也省去另外部署DNS的繁琐操作了。只是官方自带的 app 在功能上有不少阉割,像「功能扩展」下的大部分功能就只能通过PC 网页端访问。今年618屯了台配置还不错的迷你主机,准备放在家里长期开机做内网开发服务器用。当然作为一个程序员长期开机的机器,内网穿透肯定是要部署的。上下求索所有准备工作就绪后,想着方便随时配置路由,便把路由通过内网穿透在外网可以随时远程访问。配置好FRP和nginx代理后,登录页面可以正常访问,但是登录后,跳转到主界面,闪一下便又回到登录界面了。问题既然出了,先看看有没有碰到同样问题的小伙伴。便通过360路由官方的社区链接,看看有没有用户反馈相同的问题,于是找到下面这几个反馈同类问题的帖子:360路由P2还是不能通过外网 wan口登录管理?外网怎么访问路由器后台如何在外网下访问路由器的登录界面P1好像不能在外网登录管理页面嘛!!看了一圈,始终没有一个能解决问题的答复,而且看一些标注为「产品答疑师」的回复都不能解决实际反馈的问题,看来是时候施展混迹IT圈多年所学的三脚猫功夫啦。毕竟原理上都是HTTP访问,浏览器发起的HTTP请求只要跟内网请求头信息一致,理论上都是可行的。开始折腾于是通过nginx 代理的地址,真发现如下问题:登录后,发起了「GET /router/get_router_device_capability.cgi」ajax 请求,但是,该接口响应的是302,又重定向到/login.htm登录页面。初步以为是后端对 Host 或 Referer这些头信息做了校验,遂配置nginx相关头信息: proxy_set_header Host http://192.168.0.1; proxy_set_header Referer http://192.168.0.1/login_pc.htm;重启 nginx 再次访问,发现问题依旧。进一步发现请求头中有一个token_id的头信息,值为 undefined,根据 token_id 字符串搜了下网页代码,发现从url获取参数存在问题:该导致了请求的时候根本没获取到用户认证所需的 token_id,导致请求失败。进一步深挖,发现头信息中的 Cookie 是存在 token_id 的:这样的话,是不是可以考虑nginx代理的时候,从Cookie中获取token_id然后设置一个 名为token_id的头请求后端呢?说干就干,一翻摸索后,在nginx配置信息中加入如下信息:set $TOKEN_ID ""; if ($http_cookie ~* "token_id=(.+?)(?=;|$)") { set $TOKEN_ID "$1"; } proxy_set_header token_id "$TOKEN_ID";完整nginx虚拟主机配置信息如下:server { listen 80; server_name router.home.zhuzhilong.cn; location / { proxy_set_header Referer http://192.168.0.1/login_pc.htm; proxy_pass http://192.168.0.1; set $TOKEN_ID ""; if ($http_cookie ~* "token_id=(.+?)(?=;|$)") { set $TOKEN_ID "$1"; } proxy_set_header token_id "$TOKEN_ID"; } }重启路由器,验证成功!!圆满收场最终实现后的效果录屏如下:{dplayer src="/usr/uploads/2023/06/4228503511.mp4"/}
2023年06月29日
163 阅读
0 评论
0 点赞
2023-06-06
Ubuntu 添加FRP客户端自启动
背景介绍今年618 的时候购置了一台迷你主机,主要用于家庭内部服务器使用,主要基于Docker 部署其他应用,而 Ubuntu 作为 docker 原生支持最好的操作系统,而且还有漂亮的桌面,当然也就成了本迷你主机的操作系统首选。装完系统后,部署的很多应用只能内部使用,为了方便,当然不能只局限于家庭内部环境使用。结合之前不熟的FRP服务端,完全可以对外提供WEB服务,于是便有了本期的教程。下载 FRPFRP 是服务端和客户端打包在一个压缩包文件里的,可以直接从github下载就好。FRP 发布地址:https://github.com/fatedier/frp/releases本处直接下载最新的0.49.0 版本,根据操作系统,本处选择frp_0.49.0_linux_amd64.tar.gz 进行下载:wget https://github.com/fatedier/frp/releases/download/v0.49.0/frp_0.49.0_linux_amd64.tar.gz下载后 解压文件tar -zxvf frp_0.49.0_linux_amd64.tar.gz将解压的文件移动到当前用户有权限的目录,本案例中移动到 /data/apps/frp目录编辑 frpc.ini 文件本处结合实际情况,修改内容如下,部分涉密数据做了调整:[common] server_addr = SERVER_IP server_port = 7000 # for authentication token = TOKEN log_file = /data/apps/frp/frpc.log log_level = info log_max_days = 30 [home_ssh] type = tcp local_ip = 127.0.0.1 local_port = 22 remote_port = 4000 [home_web_pan] type = http local_ip = 127.0.0.1 local_port = 80 http_user = zhuzl http_pwd = PASSWORD subdomain = pan [home_web_kod] type = http local_ip = 127.0.0.1 local_port = 80 http_user = zhuzl http_pwd = PASSWORD subdomain = kod 配置完成后,可直接运行frpc 验证是否OK../frpc若有问题,可检查frpc.ini相关配置信息是否正确配置frpc自启动配置自启动过程中,为避免权限相关问题,本处直接切换为 root 账号添加 frpc.servicevi /etc/systemd/system/frpc.service输入如下服务配置内容[Unit] Description=Frp Client Service After=network.target [Service] Type=simple User=jiuzilong Restart=on-failure RestartSec=5s ExecStart=/data/apps/frp/frpc -c /data/apps/frp/frpc.ini [Install] WantedBy=multi-user.target 启用服务# 启用服务 systemctl enable frpc.service # 禁用服务 systemctl disable frpc.service重启服务systemctl daemon-reload systemctl start frpc验证服务启动状态systemctl status frpc参考链接FRP官方文档: https://gofrp.org/docs/overview/FRP服务端安装并设置开机自启动: https://blog.zhuzhilong.cn/software/install-frps-as-service.html推荐另一种docker compose 的启动方式:version: '3.3' services: frpc: restart: always network_mode: host volumes: - './frpc.ini:/etc/frp/frpc.ini' container_name: frpc image: snowdreamtech/frpc
2023年06月06日
16 阅读
0 评论
0 点赞
2023-06-05
部署Cloudreve
参考链接:https://docs.cloudreve.org/getting-started/install#docker-composedocker-compose.ymlversion: "3.8" services: cloudreve: container_name: cloudreve image: cloudreve/cloudreve:latest restart: unless-stopped ports: - "8004:5212" volumes: - temp_data:/data - ./cloudreve/uploads:/cloudreve/uploads - ./cloudreve/conf.ini:/cloudreve/conf.ini - ./cloudreve/cloudreve.db:/cloudreve/cloudreve.db - ./avatar:/cloudreve/avatar depends_on: - aria2 aria2: container_name: aria2 image: ddsderek/aria2-pro restart: unless-stopped environment: - RPC_SECRET=your_aria_rpc_token - RPC_PORT=6800 - DOWNLOAD_DIR=/data - PUID=1000 - PGID=1000 - UMASK_SET=022 - TZ=Asia/Shanghai volumes: - ./aria2/config:/config - temp_data:/data volumes: temp_data: driver: local driver_opts: type: none device: ./data o: bind 在当前目录创建相关目录及文件mkdir -vp cloudreve/{uploads,avatar} \ && touch cloudreve/conf.ini \ && touch cloudreve/cloudreve.db \ && mkdir -p aria2/config \ && mkdir -p data/aria2 \ && chmod -R 777 data/aria2启动容器docker compose up -d启动后从日志中查看登录账号信息:
2023年06月05日
3 阅读
0 评论
0 点赞
2023-06-05
部署spug
参考: https://www.spug.cc/docs/install-docker创建 docker-compose.ymlversion: '3.9' services: spug: image: openspug/spug-service container_name: spug privileged: true restart: always volumes: - ./service:/data/spug - ./repos:/data/repos ports: - 8002:80 environment: - MYSQL_DATABASE=spug - MYSQL_USER=spug - MYSQL_PASSWORD=Passw0rd - MYSQL_HOST=192.168.1.200 - MYSQL_PORT=3306启动容器docker compose up -d初始化以下操作会创建一个用户名为 zhuzl 密码为 Passw0rd 的管理员账户,可自行替换管理员账户/密码。docker exec spug init_spug zhuzl Passw0rd
2023年06月05日
2 阅读
0 评论
0 点赞
2023-05-14
FRP服务端安装并设置开机自启动
背景介绍之前一直有使用FRP做内网穿透,一般主要用于远程桌面和对外提供http服务进行测试,由于域名备案信息被撤销,原有解析过去的二级域名被拦截了,所以考虑将FRP 服务端部署到一台墙外的服务器上去,搜了一圈没找到之前的部署记录,本次也就只好将安装过程记录备忘了。安装时间:2023-05-14 15:51安装下载最新版本的frpfrp 在GitHub的地址是,# 进入用户目录 cd /usr/local # 下载frp 最新版, wget https://github.com/fatedier/frp/releases/download/v0.48.0/frp_0.48.0_linux_amd64.tar.gz # 解压 tar -zxvf frp_0.48.0_linux_amd64.tar.gz配置打开服务端配置文件vi /usr/local/frp/frps.ini 参考frps_full.ini,将服务端配置文件(frps.ini)修改为如下内容[common] bind_addr = 0.0.0.0 bind_port = 7000 token = TOKEN_INFO # udp port to help make udp hole to penetrate nat bind_udp_port = 7001 # if you want to support virtual host, you must set the http port for listening (optional) # Note: http port and https port can be same with bind_port vhost_http_port = 80 vhost_https_port = 443 # console or real logFile path like ./frps.log log_file = ./frps.log # set dashboard_addr and dashboard_port to view dashboard of frps # dashboard_addr's default value is same with bind_addr # dashboard is available only if dashboard_port is set dashboard_addr = 0.0.0.0 dashboard_port = 7500 # dashboard user and passwd for basic auth protect dashboard_user = admin dashboard_pwd = admin # dashboard TLS mode dashboard_tls_mode = false # authentication_method specifies what authentication method to use authenticate frpc with frps. # If "token" is specified - token will be read into login message. # If "oidc" is specified - OIDC (Open ID Connect) token will be issued using OIDC settings. By default, this value is "token". authentication_method = token # if subdomain_host is not empty, you can set subdomain when type is http or https in frpc's configure file # when subdomain is test, the host used by routing is test.frps.com subdomain_host = lan.dev.trswcm.com自启动添加自启动文件vi /etc/systemd/system/frps.service输入如下内容:[Unit] Description=Frp Server Service After=network.target [Service] Type=simple User=root Restart=on-failure RestartSec=5s ExecStart=/usr/local/frp/frps -c /usr/local/frp/frps.ini [Install] WantedBy=multi-user.target添加可执行权限chmod +x /etc/systemd/system/frps.service注册服务systemctl enable frps.service当出现如下提示信息后表示注册成功 [root@VM-0-9-centos systemd]# systemctl enable frps.service Created symlink from /etc/systemd/system/multi-user.target.wants/frps.service to /etc/systemd/system/frps.service.启动服务systemctl daemon-reload systemctl start frps启动过程有可能会报错,报错的话,请根据错误提示进行相应调整查看服务状态systemctl status frps出现如下截图所示信息则表示已启动成功:推荐另一种简单的docker-compose 的方式:‵‵‵ yamlversion: '3.3'services:frps: restart: always network_mode: host volumes: - './frps.ini:/etc/frp/frps.ini' container_name: frps image: snowdreamtech/frps
2023年05月14日
20 阅读
0 评论
0 点赞
2023-03-20
windows11 远程提示:为安全考虑,已锁定该用户帐户,原因是登录尝试或密码更改尝试过多。
现象使用windows 自带的远程桌面工具 mstsc 远程另一台主机时提示用户把账号信息已锁定:完整错误信息如下:[Window Title] 远程桌面连接 [Content] 为安全考虑,已锁定该用户帐户,原因是登录尝试或密码更改尝试过多。请稍候片刻再重试,或与系统管理员或技术支持联系。 [^] 隐藏详细信息(D) [确定] [Expanded Information] 错误代码: 0xd07 扩展错误代码: 0x0 时间戳 (UTC): 03/20/23 06:37:34 AM 按Ctrl+C进行复制。解决一、进入组策略命令行输入 gpedit.msc,在打开的 本地组策略编辑器中打开如下路径:计算机配置 —>Windows设置 —> 安全设置 —> 账户策略 —> 账户锁定策略,如下图所示:修改限制双击「帐户锁定阈值」策略,在打开的对话框中将值修改为 0,如下图所示:修改后,单击「确定」按钮保存即可。
2023年03月20日
619 阅读
0 评论
0 点赞
2022-11-04
CentOS安装LibreOffice记录
LibreOffice安装下载地址:https://zh-cn.libreoffice.org/download/libreoffice/下载最新的Windows版本,目前最新文档版本是7.3.7。下载后正常安装即可。下载LibreOffice:# 下载主安装程序 wget https://mirrors.ustc.edu.cn/tdf/libreoffice/stable/7.3.7/rpm/x86_64/LibreOffice_7.3.7_Linux_x86-64_rpm.tar.gz # 下载中文字体支持包 wget https://mirrors.ustc.edu.cn/tdf/libreoffice/stable/7.3.7/rpm/x86_64/LibreOffice_7.3.7_Linux_x86-64_rpm_langpack_zh-CN.tar.gz解压tar -zxvf LibreOffice_7.3.7_Linux_x86-64_rpm.tar.gz安装# 进入安装目录 cd LibreOffice_7.3.7_Linux_x86-64_rpm/RPMS/ # 安装 yum localinstall -y *.rpm程序路径:/opt/libreoffice7.3/program/soffice启动nohup /opt/libreoffice7.3/program/soffice --headless --accept="socket,host=127.0.0.1,port=8100;urp;" --nofirststartwizard &
2022年11月04日
25 阅读
0 评论
0 点赞
2022-11-04
CentOS 安装 OpenOffice记录
项目有需要用到OpenOffice进行word文档解析,需在服务器部署OpenOffice,以下为安装记录。下载地址:https://www.openoffice.org/download/index.html当前最新版本是4.1.13。下载后正常安装即可。下载wget http://jaist.dl.sourceforge.net/project/openofficeorg.mirror/4.1.13/binaries/zh-CN/Apache_OpenOffice_4.1.13_Linux_x86-64_install-rpm_zh-CN.tar.gz解压tar -zxvf Apache_OpenOffice_4.1.13_Linux_x86-64_install-rpm_zh-CN.tar.gz安装cd zh-CN/RPMS/ rpm -ivh *.rpm 启动服务nohup /opt/openoffice4/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard >/dev/null 2>&1 & 若启动过程中提示如下信息:no suitable windowing system found, exiting.。可执行如下代码安装缺失的依赖。yum groupinstall "X Window System"自启动将以上启动服务的代码添加到 /etc/rc.d/rc.local最底部,或自行参考Linux添加服务的方式实现自启动。
2022年11月04日
15 阅读
0 评论
0 点赞
2022-09-15
思源笔记docker私有化部署及使用体验分享
说明考虑到网络问题、数据隐私和安全性,很多人都无法放心将所有笔记保存在 Notion、Wolai 这类纯在线服务上,一旦服务变卦 (比如收费、倒闭等) 都会很被动。所以,如果有一款既拥有各种先进特性,还能自建服务器的开源笔记软件,那就非常完美了!而它就是思源笔记以下是思源笔记官网的介绍,着实让人心动:部署官网提供 Docker 方式,让私有化部署便捷了不少。只需要两条命令即可:# 拉取镜像 docker pull b3log/siyuan # docker 运行 docker run --name siyuan -it -d --restart=always -v /data/siyuan/workspace:/siyuan/workspace -p 6806:6806 -u $(id -u):$(id -g) b3log/siyuan --workspace=/siyuan/workspace配置 nginx 对外提供服务我使用的腾讯云的服务器,将思源笔记使用docker 运行后,通常使用 nginx 代理对外提供应用服务。nginx 代理配置信息如下server { listen 80; server_name siyuannote.dev.wljy.xyz; index index.html index.htm default.htm default.html; root /www/wwwroot/siyuannote.dev.wljy.xyz; location / { proxy_pass http://10.0.12.15:6806; 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_set_header REMOTE-HOST $remote_addr; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; add_header X-Cache $upstream_cache_status; #Set Nginx Cache add_header Cache-Control no-cache; } access_log /www/wwwlogs/siyuannote.dev.wljy.xyz.log; error_log /www/wwwlogs/siyuannote.dev.wljy.xyz.error.log; }配制好后,重启 nginx 服务即可使用我们nginx配置的域名(siyuannote.dev.wljy.xyz)访问了。初体验国际化初次访问的时候,默认是英文版的,可以按Alt + P,在打开的对话框中,选择 Appearance -> Language 中选择 简体中文:使用体验Block编辑思源笔记在使用体验上,较常规markdown编辑器,一大特色就是Block编辑模式,按下 /后可快速使用内置 20+ 种类型的块元素和 10+ 种行级元素。表格排版对于一些结构化的数据,难免会使用表格进行布局,而常规的markdown 在使用表格时异常难使用,思源笔记提供右键方式操作表格,也还算灵活:粘贴Markdown初次使用的时候,直接把 markdown 内容在编辑器中Ctrl + V 粘贴,发现直接变成代码块了。感觉有些不习惯,这一点语雀做得最好。在快捷键中查看了下 粘贴为纯文本方式 ,可以使用 Ctrl + Shift + V。从快捷键配置界面可以看出思源笔记的快捷键还是很丰富的,而且可以自定义。粘贴剪贴板中的图片经验证可直接粘贴剪贴板中的截图图片上传到服务器中,图片上传后持久化存储在服务器思源笔记工作目录的assets目录中。没有看到可以配置图床的地方。安全配置思源笔记部署后默认是不需要密码即可访问的,我们私有化部署更多的是要控制只有我们自己能访问。可在配置界面的 关于 -> 访问授权码 中 设置授权码:配置后将只能输入授权码解锁后才可访问:功能扩展思源笔记提供「集市」模块,可在线下载主题、模板、图表、挂件,初步使用感觉还是蛮方便的。尾声Typora 开启强制收费模式后,有短暂的使用过Mark Text,但是发现Mark Text 在打开较大 markdown 文件时比较卡顿。偶然在公众号中看到推荐的思源笔记,通过官网了解后,便有了试用的冲动。使用下来,感觉可以作为后续的主markdown编辑器使用。Links官网:https://b3log.org/siyuan/思源笔记Docker镜像:https://hub.docker.com/r/b3log/siyuan
2022年09月15日
1,193 阅读
0 评论
0 点赞
2022-07-02
使用 Syncthing 同步文件
下载syncthingwget https://github.com/syncthing/syncthing/releases/download/v1.20.2/syncthing-linux-amd64-v1.20.2.tar.gz tar -zxvf syncthing-linux-amd64-v1.20.2.tar.gz本应用解压的路径为 /opt/syncthing-linux-amd64-v1.20.2。下面配置syncthing 自启动。配置自启动根据官方提供的说明(https://docs.syncthing.net/users/autostart.html)有两种方式.第1种为 Using Supervisord,这种还要安装 supervisor,并启动服务,稍显麻烦,这里我们直接采用系统服务的方式。1、拷贝自启动文件到服务目录cp /opt/syncthing-linux-amd64-v1.20.2/etc/linux-systemd/system/syncthing@.service /etc/systemd/system/syncthing@root.service2、修改自启动文件主要修改内容为ExecStart 的内容,修改后的内容示例如下:/opt/syncthing-linux-amd64-v1.20.2/syncthing serve --gui-address=172.17.0.11:8384 --no-restart --logflags=0 3、启用并启动服务systemctl enable syncthing@root.service systemctl start syncthing@root.service
2022年07月02日
44 阅读
0 评论
0 点赞
2022-05-19
快速下载github文件
将github.com修改为 hub.fastgit.xyz下载文件时可以在下载链接前加如下前缀:https://github.91chi.fun//如:https://github.91chi.fun//https://github.com/git-for-windows/git/releases/download/v2.36.1.windows.1/Git-2.36.1-64-bit.exe另一种方案,使用FastGithub:https://github.com/dotnetcore/FastGithub
2022年05月19日
5 阅读
0 评论
0 点赞
1
2