第一百零一次闯荡江湖的无名游侠
type: channel
link: https://diyibailingyici.chuangdangjianghudewumingyouxia.cn/
description: 英雄願望 〜アルゴイゥ卜~
items: 多张图片拼接成一张长图
items: tk+python 实现的图片水印生成
items: 图片转gif、gif分解成图片小工具 使用python+tkinter实现
items: Debian12更换国内源sourcelist
items: Linux运维终极攻略：600条高频命令，助你解决99%的问题
items: Golang DES 加解密
items: sharedWorker实现网站中多页面共享一个websocket连接
items: 10 个实战的 Shell 脚本编程
items: Golang 请求限速、排队实现
items: 计算机精粹图书

多张图片拼接成一张长图
type: item
date: 2025-11-28T11:17:44+08:00
description: 多张图片拼接成一张长图介绍tk+python实现多张图片拼接到同一张长图片中地址：https://gitee.com/cx-a/splice_long_image预览图

tk+python 实现的图片水印生成
type: item
date: 2025-11-27T15:06:25+08:00
description: 图片水印生成介绍tk+python 实现的图片水印生成地址：https://gitee.com/cx-a/image-watermark-generation预览图

图片转gif、gif分解成图片小工具 使用python+tkinter实现
type: item
date: 2025-09-24T11:24:13+08:00
description: 介绍图片转gif、gif分解成图片小工具 使用python+tkinter实现地址：https://gitee.com/cx-a/image-to-gif

Debian12更换国内源sourcelist
type: item
date: 2025-07-08T11:23:37+08:00
description: 由于Debian12默认安装的源要么是光盘源，要么是国外源，速度保障都差强人意。所以安装完系统的第一步就是把源更换为国内源。nano /etc/apt/sources.list将想要的源复制黏贴其中，这里用了阿里云的源按下 Ctrl + O 保存。按下 Ctrl + X 退出。退出保存后执行：sudo apt-get update sudo apt-get upgradeDebian全球镜像站列表：https://www.debian.org/mirror/list阿里云站点deb https://mirrors.aliyun.com/debian/ bookworm main non-free non-free-firmware contrib deb-src https://mirrors.aliyun.com/debian/ bookworm main non-free non-free-firmware contrib deb https://mirrors.aliyun.com/debian-security/ bookworm-security main deb-src https://mirrors.aliyun.com/debian-security/ bookworm-security main deb https://mirrors.aliyun.com/debian/ bookworm-updates main non-free non-free-firmware contrib deb-src https://mirrors.aliyun.com/debian/ bookworm-updates main non-free non-free-firmware contrib deb https://mirrors.aliyun.com/debian/ bookworm-backports main non-free non-free-firmware contrib deb-src https://mirrors.aliyun.com/debian/ bookworm-backports main non-free non-free-firmware contrib腾讯云站点deb https://mirrors.tencent.com/debian/ bookworm main non-free non-free-firmware contrib deb-src https://mirrors.tencent.com/debian/ bookworm main non-free non-free-firmware contrib deb https://mirrors.tencent.com/debian-security/ bookworm-security main deb-src https://mirrors.tencent.com/debian-security/ bookworm-security main deb https://mirrors.tencent.com/debian/ bookworm-updates main non-free non-free-firmware contrib deb-src https://mirrors.tencent.com/debian/ bookworm-updates main non-free non-free-firmware contrib deb https://mirrors.tencent.com/debian/ bookworm-backports main non-free non-free-firmware contrib deb-src https://mirrors.tencent.com/debian/ bookworm-backports main non-free non-free-firmware contrib清华大学站点deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free non-free-firmware deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free non-free-fi…

Linux运维终极攻略：600条高频命令，助你解决99%的问题
type: item
date: 2025-06-26T14:44:00+08:00
description: 1、基本命令uname -m 显示机器的处理器架构 uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 (SMBIOS / DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性 hdparm -tT /dev/sda 在磁盘上执行测试性读取操作系统信息 arch 显示机器的处理器架构 uname -m 显示机器的处理器架构 uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS / DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性 hdparm -tT /dev/sda 在磁盘上执行测试性读取操作 cat /proc/cpuinfo 显示CPU info的信息 cat /proc/interrupts 显示中断 cat /proc/meminfo 校验内存使用 cat /proc/swaps 显示哪些swap被使用 cat /proc/version 显示内核的版本 cat /proc/net/dev 显示网络适配器及统计 cat /proc/mounts 显示已加载的文件系统 lspci -tv 罗列 PCI 设备 lsusb -tv 显示 USB 设备 date 显示系统日期 cal 2007 显示2007年的日历表 date 041217002007.00 设置日期和时间 - 月日时分年.秒 clock -w 将时间修改保存到 BIOS2、关机shutdown -h now 关闭系统(1) init 0 关闭系统(2) telinit 0 关闭系统(3) shutdown -h hours:minutes & 按预定时间关闭系统 shutdown -c 取消按预定时间关闭系统 shutdown -r now 重启(1) reboot 重启(2) logout 注销3、文件和目录cd /home 进入 '/ home' 目录' cd .. 返回上一级目录 cd ../.. 返回上两级目录 cd 进入个人的主目录 cd ~user1 进入个人的主目录 cd - 返回上次所在的目录 pwd 显示工作路径 ls 查看目录中的文件 ls -F 查看目录中的文件 ls -l 显示文件和目录的详细资料 ls -a 显示隐藏文件 ls *[0-9]* 显示包含数字的文件名和目录名 tree 显示文件和目录由根目录开始的树形结构(1) lstree 显示文件和目录由根目录开始的树形结构(2) mkdir dir1 创建一个叫做 'dir1' 的目录' mkdir dir1 dir2 同时创建两个目录 mkdir -p /tmp/dir1/dir2 创建一个目录树 rm -f file1 删除一个叫做 'file1' 的文件' rmdir dir1 删除一个叫做 'dir1' 的目录' rm -rf dir1 删除一个叫做 'dir1' 的目录并同时删除其内容 rm -rf dir1 dir2 同时删除两个目录及它们的内容 mv dir1 new_dir 重命名/移动 一个目录 cp file1 file2 复制一个文件 cp dir/* . 复制一个目录下的所有文件到当前工作目录 cp -a /tmp/dir1 . 复制一个目录到当前工作目录 cp -a dir1 dir2 复制一个目录 ln -s file1 lnk1 创建一个指向文件或目录的软链接 ln file1 lnk1 创建一个指向文件或目录的物理链接 touch -t 0712250000 file1 修改一个文件或目录的时间戳 - (YYMMDDhhmm) file file1 outputs the mime type of the file as text iconv -l 列出已知的编码 iconv -f fromEncoding -t toEncoding inputFile > outputFile creates a new from the given input file by assuming it is encoded in fromEncoding and converting it to toEncoding. find . -maxdepth 1 -name *.jpg -print -exec convert '{}' -resize 80x60 'thumbs/{}' \; batch resize files in the current directory and send them to a thumbnails directory (requires convert from Imagemagick)4、文件搜索f…

Golang DES 加解密
type: item
date: 2025-04-30T10:15:03+08:00
description: 概念理解DES是以64比特的明文为一个单位来进行加密，并生成64比特的密文。由于它每次只能处理特定长度的一块数据，所以DES属于分组密码算法。cypto/des包提供了有关des加密的功能。模式由于分组密码算法只能加密固定长度的分组，所以当加密的明文超过分组密码的长度时，就需要对分组密码算法进行迭代，而迭代的方法就称为分组密码的模式。模式主要有ECB(电子密码本)、CBC(密码分组链接模式)、CTR(计数器模式)、OFB(输出反馈模式)、CFB(密码反馈模式)五种。下面简单介绍下前两种：ECB(electronic code book)是最简单的方式，它将明文分组加密后的结果直接成为密文分组。优缺点：模式操作简单；明文中的重复内容将在密文中表现出来，特别对于图像数据和明文变化较少的数据；适于短报文的加密传递。CBC(cipher block chaining)的原理是加密算法的输入是当前的明文分组和前一密文分组的异或，第一个明文分组和一个初始向量进行异或，这样同一个明文分组重复出现时会产生不同的密文分组。特点：同一个明文分组重复出现时产生不同的密文分组；加密函数的输入是当前的明文分组和前一个密文分组的异或；每个明文分组的加密函数的输入与明文分组之间不再有固定的关系；适合加密长消息。填充方式在按8个字节对DES进行加密或解密时，如果最后一段字节不足8位，就需要对数据进行补位。即使加密或解密的数据刚好是8的倍数时，也会再补8位。举个栗子，如果末尾刚好出现1，这时你就无法判断这个1是原来数据，还是经过补位得到的1。因此，可以再补8位进行标识。填充方式主要有以下几种：pkcs7padding、pkcs5padding、zeropadding、iso10126、ansix923。pkcs7padding和pkcs5padding的填充方式相同，填充字节的值都等于填充字节的个数。例如需要填充4个字节，则填充的值为"4 4 4 4"。zeropadding填充字节的值都为0。密码DES的密钥长度是64比特，但由于每隔7个比特会设置一个用于错误检测的比特，因此其实质密钥长度为56比特。偏移量上面模式中，例如CBC，再加密第一个明文分组时，由于不存在“前一个密文分组”，因此需要事先准备一个长度为一个分组的比特序列来代替“前一个密文分组”，这个比特序列成为初始化向量，也称偏移量，通常缩写为IV。一般来说，每次加密时都会随机产生一个不同的比特序列来作为初始化向量。偏移量的长度必须和块的大小相同。输出加密后的字节在显示时可以进行hex和base64编码，hex是十六进制编码，base64是一种基于64个可打印字符来标识二进制数据的方法。下面以上面提到的几种模式和填充方式为例，进行演示如何在代码中使用。加密模式采用ECB、填充方式采用pkcs5padding、密码使用"12345678",输出时经hex编码。自己可以通过一些在线测试工具进行测试，看结果是否一致。package main import ( "crypto/des" "qiniupkg.com/x/errors.v7" "bytes" "fmt" "encoding/hex" ) func main() { data:=[]byte("hello world") key:=[]byte("12345678") result,err:=DesECBEncrypt(data,key) if err != nil { fmt.Println(err) } a:=hex.EncodeToString(result) fmt.Println(a) } func DesECBEncrypt(data, key []byte) ([]byte, error) { //NewCipher创建一个新的加密块 block, err := des.NewCipher(key) if err != nil { return nil, err } bs := block.BlockSize() data = Pkcs5Padding(data, bs) if len(data)%bs != 0 { return nil, errors.New("need a multiple of the blocksize") } out := make([]byte, len(data)) dst := out for len(data) > 0 { //Encrypt加密第一个块，将其结果保存到dst block.Encrypt(dst, data[:bs]) data = data[bs:] dst = dst[bs:] } return out, nil } func Pkcs5Padding(ciphertext []…

sharedWorker实现网站中多页面共享一个websocket连接
type: item
date: 2025-04-29T16:02:00+08:00
description: sharedWorker实现网站中多页面共享一个websocket连接之前用websocket连接时候，没开一个页面就断开了上一个页面的链接，找了一下方法html页面： WebSocket Example WebSocket Chat Example Connecting... fa worker.js// 存储所有连接的端口 const ports = []; let socket; // 当页面连接时触发 self.onconnect = (e) => { const port = e.ports[0]; ports.push(port); // 初始化 WebSocket（仅首次连接时） if (!socket) { initWebSocket(); function initWebSocket() { // WebSocket URL, replace with your server's WebSocket endpoint const wsURL = 'ws://8.137.90.97:2121/ws'; // Replace with actual URL socket = new WebSocket(wsURL); // Connection opened socket.addEventListener('open', onOpen); // Listen for messages socket.addEventListener('message', onMessage); // Listen for errors socket.addEventListener('error', onError); // Connection closed socket.addEventListener('close', onClose); } function onOpen(event) { console.log('已连接到WebSocket服务器。'); //document.getElementById('status').innerText = '已连接到WebSocket服务器。'; // Send login message or token here const loginData = { user_code: 'user', key: 'user_key', // Replace with actual user data server_password: 'myServerPassword' // Replace with actual user data or use a token instead }; socket.send(JSON.stringify(loginData)); } function onMessage(event) { console.log('来自服务器的消息 ', event.data); // 广播消息给所有页面 ports.forEach(p => p.postMessage({"type":"msg","data":event.data})); // Parse the incoming message and handle it accordingly // try { // const data = JSON.parse(event.data); // console.log(data) // if(data.message == 'Login successful'){ // document.getElementById('status').innerText = '登录成功.'; // }else{ // displayNewMessage(data); // } // } catch (e) { // console.error('解析消息失败：', e); // } } function onError(event) { //document.getElementById('status').innerText = '观察到WebSocket错误：' + event; console.error('观察到WebSocket错误：', event); } function onClose(event) { console.log('WebSocket连接已关闭。正在尝试重新连接。。。'); //document.getElementById('status').innerText = 'WebSocket连接已关闭。正在尝试重新连接。。。'; // Optionally, you can check the event.code to determine wh…

10 个实战的 Shell 脚本编程
type: item
date: 2025-04-29T10:00:00+08:00
description: 在运维日常工作中，shell 脚本堪称运维神器，本次分享 10 个使用的 shell 脚本案例，助你在工作中灵活运用，提升运维效率。1、检测两台服务器制定目录下的文件一致性#!/bin/bash ###################################### 检测两台服务器指定目录下的文件一致性 ##################################### #通过对比两台服务器上文件的md5值，达到检测一致性的目的 #!/bin/bash ###################################### 检测两台服务器指定目录下的文件一致性 ##################################### #通过对比两台服务器上文件的md5值，达到检测一致性的目的 dir=/data/web b_ip=192.168.88.10 #将指定目录下的文件全部遍历出来并作为md5sum命令的参数，进而得到所有文件的md5值，并写入到指定文件中 find $dir -type f|xargs md5sum > /tmp/ md5_a.txt ssh $b_ip "find $dir -type f|xargs md5sum > /tmp/ md5_b.txt" scp $b_ip:/tmp/ md5_b.txt /tmp #将文件名作为遍历对象进行一一比对 for f in `awk '{print 2} /tmp/ md5_a.txt' ` do #以a机器为标准，当b机器不存在遍历对象中的文件时直接输出不存在的结果 if grep -qw "$f" /tmp/ md5_b.txt then md5_a=`grep -w "$f" /tmp/ md5_a.txt|awk '{print 1}'` md5_b=`grep -w "$f" /tmp/ md5_b.txt|awk '{print 1}'` #当文件存在时，如果md5值不一致则输出文件改变的结果 if [ $md5_a != $md5_b ] then echo "$f changed." fi else echo "$f deleted." fi done2、定义一个颜色输出字符串函数#方法1： function echo_color() { if [ $1 == "green" ]; then echo -e "[32;40m$2[0m" elif [ $1 == "red" ]; then echo -e "[31;40m$2[0m" fi } #方法2： function echo_color() { case $1 in green) echo -e "[32;40m$2[0m" ;; red) echo -e "[31;40m$2[0m" ;; *) echo "Example: echo_color red string" esac } #使用方法：echo_color green "test"function 关键字定义一个函数，可加或不加。3、从 FTP 服务器下载文件#!/bin/bash if [ $# -ne 1 ]; then echo "Usage: $0 filename" fi dir=$(dirname $1) file=$(basename $1) ftp -n -v << EOF # -n 自动登录 open 192.168.1.10 # ftp服务器 user admin password binary # 设置ftp传输模式为二进制，避免MD5值不同或. tar.gz压缩包格式错误 cd $dir get "$file" EOF4、检查软件包是否安装#!/bin/bash if rpm -q sysstat &>/dev/null; then echo "sysstat is already installed." else echo "sysstat is not installed!" fi5、检查服务状态#!/bin/bash PORT_C=$(ss -anu |grep -c 123) PS_C=$(ps -ef |grep ntpd |grep -vc grep) if [ $PORT_C -eq 0 -o $PS_C -eq 0 ]; then echo "内容" | mail -s "主题" dst@ example.com fi6、检查主机存活状态方法1：将错误IP放到数组里面判断是否ping失败三次#!/bin/bash IP_LIST="192.168.18.1 192.168.1.1 192.168.18.2" for IP in $IP_LIST; do NU…

Golang 请求限速、排队实现
type: item
date: 2025-04-29T09:49:00+08:00
description: 概要在调用第三方 API 的时候, 基本都有访问限速的限制条件. 第三方的 API 有多个的时候, 就不太好控制访问速度, 常常会导致 HTTP 429(Too Many Requests) 然后就会有一段时间的禁止访问.为了应对这种限速的情况, 通过一个简单的请求队列来控制访问的速度, 之后基本没遇到过 HTTP 429 了.实现思路首先, 每个请求包装成一个 RequestParam 的 struct, 其中包含请求的地址,类型,参数以及 response 的 channel.发送请求的时候, 只要将 RequestParam 放入请求队列中即可, 请求完成后, 将 response 放入对应的 channel 中.整个代码实现很简单:package util import ( "fmt" apiclient "gitee.com/wangyubin/gutils/api_client" "gitee.com/wangyubin/gutils/logger" ) // request 包含的内容 type RequestParam struct { Api string Method string JsonReq interface{} Resp chan []byte } // 请求队列, 本质是一个channel type RequestQueue struct { Queue chan RequestParam } var queue *RequestQueue // 获取队列 func GetQueue() *RequestQueue { return queue } // 初始化队列 func InitRequestQueue(size int) { queue = &RequestQueue{ Queue: make(chan RequestParam, size), } } // 将请求放入队列 func (rq *RequestQueue) Enqueue(p RequestParam) { rq.Queue <- p } // 请求队列服务, 一直等待接受和处理请求 func (rq *RequestQueue) Run() { lg := logger.GetLogger() for p := range rq.Queue { var resp []byte var err error switch p.Method { case "GET": resp, err = apiclient.GetJson(p.Api, p.JsonReq) case "POST": resp, err = apiclient.PostJson(p.Api, p.JsonReq) default: err = fmt.Errorf("Wrong type of METHOD(%s)\n", p.Method) } if err != nil { lg.Err(err).Msg("access api error: " + p.Api) continue } if p.Resp != nil { p.Resp <- resp close(p.Resp) } } lg.Info().Msg("request queue finished!") }这里的请求是用了我自己封装的 apiclient, 可以根据实际情况替换.在我的应用场景里, 只要 api 顺序访问就不会出现 HTTP 429 了, 如果这样觉得速度太快的的话, 可以尝试在 Run() 函数中加入一些时间间隔. func (rq *RequestQueue) Run() { lg := logger.GetLogger() for p := range rq.Queue { time.Sleep(1 * time.Second) // ... 省略的代码 ... } lg.Info().Msg("request queue finished!") }使用方法使用很简单, 首先启动, 然后每个调用的地方将 RequestParam 放入队列并等待 response 即可。启动队列服务func main() { // init request queue and start queue service util.InitRequestQueue(100) queue := util.GetQueue() defer close(queue.Queue) go queue.Run() // 其他启动代码 }使用队列服务 func Request(param1 string, param2 int) error { api := "http://xxxx.com" api …

计算机精粹图书
type: item
date: 2025-04-22T11:38:04+08:00
description: 下载地址：https://ide.lanzoum.com/icCrb2u5lgqb资料来源于网络，如有侵权，请联系删除。