普通视图

发现新文章,点击刷新页面。
今天 — 2025年5月9日首页

使用 Python 脚本实现图片相似度匹配

2025年5月9日 00:00

随着相机像素越来越大,图片体积也变大了。在图片处理中,较大的文件体积会影响性能,因此杜老师会先生成缩略图,筛选完成后再通过 Python 脚本实现图片相似度匹配。这里是一个简单的示例,供需要的小伙伴们参考。

脚本说明

以下是个基于 Python 的脚本,使用 PIL 以及 imagehash 库来实现。

遍历目录 A 中所有图片。

在目录 B 中查找相似的图片「通过感知哈希算法判断」

如找到匹配项,则将图片复制到目录 C,并以目录 A 图片的名字命名。

脚本代码

在运行脚本前,需安装所需的 Python 库:

1
pip install pillow imagehash

dir_a, dir_bdir_c 替换为实际路径;threshold 控制图像相似度阈值,可以根据需要调整;支持多种常见格式图片文件;使用 imagehash.phash 进行感知哈希的比较,适合用于识别视觉上接近的图片:

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
import os
import shutil
from PIL import Image
import imagehash

# 定义目录路径
dir_a = 'path/to/dirA'
dir_b = 'path/to/dirB'
dir_c = 'path/to/dirC'

# 设置相似度阈值(越小越严格)
threshold = 5

# 获取图片的感知哈希值
def get_image_hash(filepath):
try:
return imagehash.phash(Image.open(filepath))
except Exception as e:
print(f"无法处理文件 {filepath}: {e}")
return None

# 判断两个哈希值是否相似
def is_similar(hash1, hash2):
return hash1 - hash2 <= threshold

# 确保目标目录存在
os.makedirs(dir_c, exist_ok=True)

# 遍历目录 A
for filename in os.listdir(dir_a):
file_a_path = os.path.join(dir_a, filename)

# 检查是否为图片
if not filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp')):
continue

hash_a = get_image_hash(file_a_path)
if hash_a is None:
continue

# 遍历目录 B 寻找相似图片
for b_filename in os.listdir(dir_b):
file_b_path = os.path.join(dir_b, b_filename)

# 检查是否为图片
if not b_filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp')):
continue

hash_b = get_image_hash(file_b_path)
if hash_b is None:
continue

if is_similar(hash_a, hash_b):
# 构建目标路径
file_c_path = os.path.join(dir_c, filename)
# 复制并重命名文件
shutil.copy(file_b_path, file_c_path)
print(f"已找到匹配: {filename} -> {b_filename}, 已复制到 {file_c_path}")
昨天以前首页

使用 Python 脚本下载指定网页的图片文件

2025年3月31日 00:00

有小伙伴反馈说侧边栏随机图出现了重复,有些审美疲劳,要求杜老师再更新一些图片,正好聊天广场有小伙伴分享了一个美图的网址。本文分享如何使用 Python 脚本下载指定网页的图片文件,需要的小伙伴可以参考文中代码。

代码需求

使用 Python 的语言编写一个脚本,下载指定网址中包含的多种格式图片文件,如 JPG 和 PNG 格式图片。

将图片保存至指定的目录中,可以指定绝对路径,或者相对路径。

并用随机数重命名,防止同名图片触发覆盖事件。

尽可能使用 Python 的标准库,尽量避免使用第三方库。

变更解释

  1. 导入必要的库:包括 os/requests/re 以及 random

  2. 定义函数:download_images 函数可用于下载图片;

  3. 获取图片链接:使用正则表达式从网页内容中提取图片 URL;

  4. 下载保存图片:使用 requests 库下载图片,并且使用 random 库生成随机数作为文件名;

  5. 指定目录:确保保存目录存在,如果不存在则创建;

  6. 获取内容:使用 requests 库获取网页内容。

功能代码

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
import os
import requests
import re
import random

def download_images(url, save_folder):
# 确保保存目录存在
if not os.path.exists(save_folder):
os.makedirs(save_folder)

# 发送HTTP请求获取网页内容
response = requests.get(url)
if response.status_code != 200:
print(f"Failed to retrieve the webpage. Status code: {response.status_code}")
return

# 使用正则表达式查找所有的图片URL
image_urls = re.findall(r'<img[^>]+src=["\'](.*?)["\']', response.text)

for img_url in image_urls:
# 处理相对路径的URL
if not img_url.startswith(('http://', 'https://')):
img_url = os.path.join(url, img_url)

# 下载图片
img_response = requests.get(img_url)
if img_response.status_code == 200:
# 生成随机文件名
random_filename = f"{random.randint(10000, 99999)}.jpg"
save_path = os.path.join(save_folder, random_filename)

# 保存图片
with open(save_path, 'wb') as f:
f.write(img_response.content)
print(f"Downloaded and saved {img_url} as {save_path}")
else:
print(f"Failed to download {img_url}. Status code: {img_response.status_code}")

# 读取网址列表文件
def read_urls_from_file(file_path):
with open(file_path, 'r') as file:
urls = file.readlines()
return [url.strip() for url in urls]

# 示例调用
if __name__ == "__main__":
urls_file = 'f:\\代码\\urls.txt' # 包含网址的文件路径
save_folder = 'f:\\代码\\images' # 保存图片的目录路径

urls = read_urls_from_file(urls_file)
for url in urls:
download_images(url, save_folder)

注意:本示例代码仅适用于 Python 3.x 版本,运行于 Windows 系统。如使用 Linux 系统,可能需要进行相应修改。

使用说明

将上述的代码保存为 download_images.py 文件。

在运行脚本时,传入目标网页的 URL 和保存图片的目录路径。

脚本会自动下载网页中所有图片,并且以随机数命名保存到指定目录中。

打开的网址保存在一个文件,每行一个网址。

如何使用 GDB 或 LLDB 调试器重复运行程序直到错误

2025年3月21日 04:35

gdb-debugger 如何使用 GDB 或 LLDB 调试器重复运行程序直到错误 gdb / lldb 小技巧 程序员 编程 计算机 计算机 调试

GDB Debugger 调试器

如何使用 GDB 或 LLDB 调试器重复运行程序直到发生错误

在调试程序时,有时候我们希望一直运行程序直到遇到错误。GDB(GNU 调试器)和 LLDB(LLVM 调试器)都提供了自动化此过程的方法。

这在调试一些不稳定的程序非常有用,例如有时候写的一些单元测试可能随机崩溃SegFault。最近我在调试一个测试每跑1000次就有一次崩溃的时候就发现gdb/lldb调试器非常有用。

简介:GDB vs LLDB

GDB(GNU 调试器)和 LLDB(LLVM 调试器)是用于低级别应用程序调试的强大工具。GDB 传统上用于由 GCC 编译的程序,而 LLDB 是 LLVM 项目的一部分,与 Clang 无缝配合。两者都提供强大的功能,但 GDB 在 Linux 环境中更常见,而 LLDB 在 macOS 上以及处理 Swift 时更受青睐。

自动化执行直到发生错误

调试重复性任务可能很乏味。通过自动化这些任务,直到发生错误,可以节省大量时间和精力。以下是如何在 GDB 和 LLDB 中设置重复执行直到遇到错误的步骤。

GDB 脚本

下面是一个 GDB 脚本,它会重复执行,直到发生错误:

repeat_until_error.gdb

while 1
  run
  if $_exitcode != 0
    echo "发生错误,退出码:$_exitcode\n"
    break
  end
end

要运行此脚本,将其保存为 repeat_until_error.gdb,然后使用以下命令执行 GDB:

gdb -q -x repeat_until_error.gdb ./your_program

或者,当你处于 gdb 提示符时,运行:

source repeat_until_error.gdb

“run” 命令用于启动程序,你可以为它添加参数,例如:

run param1 param2 ...

你也可以使用 “r” 作为 “run” 的简写。

LLDB 脚本

类似地,在 LLDB 中,你可以使用以下脚本实现相同的效果:

repeat_until_error.lldb

while (1)
  run
  process launch
  if (process status != 0)
    script print("发生错误,退出码:", lldb.process.GetExitStatus())
    break
  end
end

要运行此脚本,将其保存为 repeat_until_error.lldb,然后运行:

lldb --source repeat_until_error.lldb ./your_program

或者,在 lldb 提示符处运行:

source repeat_until_error.lldb

在 “run” 命令之后,你还可以通过附加参数来启动程序,例如:

run param1 param2

总结

GDB 和 LLDB 都提供了方便的方法来自动化调试任务,选择使用哪种工具通常取决于你所使用的平台和工具链。GDB 与 GCC 的集成使其成为 Linux 开发者的首选,而 LLDB 在与 Clang 和 macOS 的无缝配合方面同样强大。

自动化重复的调试命令可以为你节省大量时间和精力 —— 无论你使用 GDB 还是 LLDB,这些脚本都能帮助你简化工作流程。

gdb / lldb 调试

英文:How to Repeat Until Errors using GDB or LLDB Debugger?

本文一共 603 个汉字, 你数一下对不对.
如何使用 GDB 或 LLDB 调试器重复运行程序直到错误. (AMP 移动加速版本)

扫描二维码,分享本文到微信朋友圈
75a5a60b9cac61e5c8c71a96e17f2d9c 如何使用 GDB 或 LLDB 调试器重复运行程序直到错误 gdb / lldb 小技巧 程序员 编程 计算机 计算机 调试
The post 如何使用 GDB 或 LLDB 调试器重复运行程序直到错误 first appeared on 小赖子的英国生活和资讯.

相关文章:

  1. 按揭贷款(房贷,车贷) 每月还贷计算器 去年给银行借了17万英镑 买了20万7500英镑的房子, 25年还清. 前2年是定率 Fix Rate 的合同 (年利率2.49%). 每个月大概是还 700多英镑. 有很多种还贷的计算方式, 定率/每月固定 是比较常用的. 简单来说就是 每个月交的钱是...
  2. 智能手机 HTC One M9 使用测评 虽然我对手机要求不高, 远远没有像追求VPS服务器一样, 但是怎么算来两年内换了四个手机, 先是三星 S4 用了一年多, 然后 Nokia Lumia 635 Windows Phone, 后来又是 BLU, 半年多前换了...
  3. 同一台服务器上多个WORDPRESS站点的一些设置可以移出去 我自从把所有网站都挪到一处VPS服务器上 就发现很多事情省事很多 可以同时管理多个网站 包括 WORDPRESS博客. 比如我有四个WORDPRESS博客 然后我就把通用的一些资料给移出去 移到 HTTP或者HTTPS都不能直接访问的文件夹里这样就更安全许多. 文件 wp-conn.php 存储了 相同的数据库资料. 1 2...
  4. 比特币最近波动有点大: 一天牛市一天熊 比特币10万美金以内都是最后上车的机会! 比特币近期的价格波动可以归因于多个关键因素,包括地缘政治动态、监管变化以及加密行业内的重大安全事件。其中一个主要影响因素是美国前总统唐纳德·特朗普对乌克兰和加密货币监管的立场变化。据报道,特朗普再次当选,他可能会推动减少美国对乌克兰的支持,这可能会影响全球金融市场和风险偏好。同时,特朗普正在将自己塑造为亲加密货币的候选人,表示有意让美国成为一个更加友好的加密货币环境。这一立场引发了市场对监管政策可能发生变化的猜测,导致市场情绪在乐观和不确定性之间波动。 特朗普对俄乌战争的态度 美国第43届总统唐纳德·特朗普已经在2025年1月当选并正式上任(第二次),那么他的政策可能会对比特币价格的波动产生更加直接和显著的影响。他政府对乌克兰和加密货币监管的立场已经不再是猜测,而是正在实际塑造市场的关键力量。 特朗普(Donald Trump)减少美国对乌克兰的支持,全球投资者可能会预期地缘政治稳定性发生变化,从而增加对比特币作为避险资产的需求。同时,他的亲加密货币立场可能正在推动市场的乐观情绪。如果他的政府推出有利于加密行业的监管政策,例如明确的合规指南或减少监管审查,可能会吸引更多机构投资者进入市场,并促进更广泛的加密货币采用。然而,政策的快速变化也可能导致短期市场剧烈波动,因为市场需要时间来消化新的政策动向。 朝鲜黑客盗取Bybit交易所15亿美元的ETH 另一个显著影响比特币价格的事件是近期涉及朝鲜黑客组织“Lazarus”的15亿美元以太坊被盗案件。据报道,Bybit交易所(全球第二)这些被盗的ETH已经被清洗,此次大规模黑客攻击引发了人们对加密行业安全性的担忧。此类安全事件不仅会削弱投资者信心,还可能引发更严格的监管审查,导致短期市场动荡。此外,被盗资金的大规模流动和出售可能对市场流动性造成冲击,进一步加大价格波动。随着这些事件的持续发酵,比特币价格正受到政治决策、监管预期以及安全挑战等多重因素的影响。 与此同时,与朝鲜黑客组织 Lazarus 相关的 15 亿美元以太坊被盗事件仍在影响加密市场。由于这些被盗 ETH 已被清洗,人们对加密行业安全漏洞的担忧持续存在,同时也可能引发更严格的监管审查。政治、监管和安全等多重因素交织在一起,共同导致了比特币近期的剧烈价格波动。...
  5. 公司给配了台高配DELL笔记本 早上例会结束的时候我顺便说了一句 我的笔记本有点慢, 当时我并不知道我的经理远程用电话也参加会议了(他全程在听), senior staff SE 对着电话说, “peter, you hear that? btw, my disks are...
  6. 5美元的 Raspberry PI – Zero 树莓PI Raspberry PI 来自于英国, 从第一代模型 A, 到后来的 B, B+ 甚至 是2代, 休积都很小 价钱也一直在 30美元左右. 当然在英国会贵一点 大概在...
  7. 英国硬盘数据恢复失败的经验和教训 上一周, 不小心触碰了机箱后面的电源线, 接触不良, 结果机器再也开不起来了. 显示 Invalid Disk, Replace. 大概就是主硬盘MBR区坏了. 我以为是接触不良, 于是反复插把硬盘卡槽好几次, 机器认不出, 硬盘也没声音, 于是便网上搜索了一个剑桥评价最高的 硬盘数据恢复公司...
  8. 优化设计 个人主页 并且 PageSpeed Insights 双项 100分 坛子的个人主页 www.tanzhijun.com 不错 很适合个人主页的模板. 而且是手机友好. 于是我照着把 我的主页改了改. https://steakovercooked.com 并且做了几点修改: 0. 使用 google mod_pagespeed 把 JS,...

使用 Python 脚本验证指定目录的图片文件

2025年2月26日 00:00

有小伙伴说杜老师说侧边栏随机图片素材太少,翻来覆去只有那么几张。为了充实随机图片,杜老师采集了一个图片网站。奈何能力有限,某些图片采集失败,保存为空文件,所以需要编写一个脚本,来验证图片是否为正常。

代码需求

使用 Python 语言编写一个小项目,需要遍历指定目录下所有子目录「子目录名称为中文」

验证子目录下的图片文件是否能正常打开,如果能则跳过,如果无法正常打开则返回其路径。

变更解释

  1. 使用 os 模块来遍历目录和子目录;

  2. 使用 PIL 库来验证图片文件是否能正常打开。

注意事项

请确保安装了 Pillow 库,可以使用下面的命令来安装:

1
pip install pillow

root_directory 变量设置为需要遍历的目录路径:

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
import os
from PIL import Image

def validate_images_in_directory(root_dir):
invalid_image_paths = []

for dirpath, dirnames, filenames in os.walk(root_dir):
for filename in filenames:
if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp')):
file_path = os.path.join(dirpath, filename)
try:
with Image.open(file_path) as img:
img.verify() # 尝试验证图片文件
except (IOError, SyntaxError) as e:
invalid_image_paths.append(file_path)

return invalid_image_paths

if __name__ == "__main__":
root_directory = '指定目录路径' # 替换为实际的目录路径
invalid_images = validate_images_in_directory(root_directory)

if invalid_images:
print("无法打开的图片文件路径:")
for path in invalid_images:
print(path)
else:
print("所有图片文件都能正常打开。")

执行代码

1
python3 images.py

注意:将上面的代码保存为 images.py 文件,然后在命令行中执行上面的命令。

如何快速清空七牛的存储空间中的所有文件,并删除存储空间

2025年1月25日 14:45

如果你和我一样,有很多历史的文件存储在七牛上,但如今已经不再需要使用,那么就可以考虑删除七牛的存储空间,来节省费用。

但七牛为了保证安全,所以要求必须删除所有的文件后才能删除空间,以避免误删除,所以需要一个个删除所有的文件。为了快速删除七牛存储空间的文件,我写了个简单的脚本,帮助你快速删除七牛空间下的所有文件。

具体操作可参考如下脚本,你只需要

  1. 在本地安装七牛 SDK :pip install qiniu
  2. 创建一个新文件 run.py 并复制下方的代码,修改其中的访问密钥和存储空间名称
  3. 执行 python run.py 就可以了。
# -*- coding: utf-8 -*-
# 导入七牛云 SDK 所需的模块
from qiniu import Auth
from qiniu import BucketManager, build_batch_delete
# 七牛云账号的访问密钥
access_key = '你的 ACCESS Key'
secret_key = '你的 Secret Key'
# 要清理的存储空间名称
bucket_name = '你要清空的空间名称'


# 使用 AK、SK 初始化授权对象
q = Auth(access_key, secret_key)
# 初始化存储空间管理器
bucket = BucketManager(q)

# 设置每次列举的最大条目数
limit = 1000

# 循环列举并删除存储空间中的文件
while True:
    # 列举存储空间中的文件
    # ret: 包含文件信息的字典
    # eof: 是否已列举完所有文件
    # info: 请求的状态信息
    ret, eof, info = bucket.list(bucket=bucket_name)
    # 从返回结果中提取文件名列表
    keys = [item['key'] for item in ret['items']]
    # 构建批量删除操作
    ops = build_batch_delete(bucket_name, keys)
    # 执行批量删除操作
    ret, info = bucket.batch(ops)
    # 检查删除操作是否成功
    if info.status_code == 200:
        print(f"success delete {len(keys)} files!")
    
    # 判断是否已经列举完所有文件
    if eof:
        break
    else:
        continue
# 输出清理完成的提示信息
print(f"delete all files in {bucket_name}")

执行成功后,你会看到如下面这样的命令,接下来等他自动执行即可,你就不用做任何事情了。

image

当工具提示你 delete all files in 你的 kodo 名时,你就可以回到七牛控制台,删除掉空的 kodo 了。

image

MySQL参数一键配置脚本: 有效提升数据库性能

2024年12月23日 03:15

我一直是自己租用VPS服务器,然后搭建各种服务,比如博客就是Apache2+MySQL数据库。一般来说就是默认参数,没有去管,不过最近发现MySQL的性能参数都很保守,不能发挥整个服务器的性能。

然后我就网上搜索了一下,根据参数配置建议,用ChatGPT写了以下Python和BASH脚本。只需要在需要优化的服务器上,跑一下该脚本,然后就会显示参数配置,然后直接把参数添加到MySQL数据库配置参数文件上: /etc/mysql/mysql.conf.d/mysqld.cnf

然后运行: service mysql restart 重启MySQL服务器。

运行了几周,发现效果很好,博客反应速度也快了很多,这很大原因是根据了内存增加了MySQL缓存大小。

Python脚本优化MySQL数据库参数

把下面的Python脚本存成 mysql_config.py 然后运行 python3 mysql_config.py

def get_total_ram():
    with open('/proc/meminfo', 'r') as f:
        for line in f:
            if line.startswith("MemTotal:"):
                total_ram_kb = int(line.split()[1])
                return total_ram_kb * 1024  # 转换为字节(bytes)
    return 0  # 如果未找到 MemTotal,则返回 0

def calculate_mysql_settings():
    # 获取总内存(以字节为单位)
    total_ram = get_total_ram()

    # 根据总内存(以字节为单位)计算 MySQL 配置
    innodb_buffer_pool_size = int(total_ram * 0.3)  # 使用内存的 30%
    key_buffer_size = min(total_ram * 20 // 100, 512 * 1024 * 1024)  # 使用内存的 20%,最大限制为 512MB
    sort_buffer_size = min(total_ram * 25 // 1000, 4 * 1024 * 1024)  # 使用内存的 0.25%,最大限制为 4MB
    read_rnd_buffer_size = min(total_ram * 625 // 100000, 512 * 1024)  # 使用内存的 0.0625%,最大限制为 512KB
    tmp_table_size = max_heap_table_size = min(total_ram * 5 // 100, 64 * 1024 * 1024)  # 使用内存的 5%,最大限制为 64MB
    join_buffer_size = min(total_ram * 2 // 1000, 4 * 1024 * 1024)  # 使用内存的 0.2%,最大限制为 4MB
    table_open_cache = min(400 + (total_ram // 64), 2000)  # 根据内存动态计算,最大限制为 2000
    thread_cache_size = min(total_ram * 15 // 1000, 100)  # 使用内存的 1.5%,最大限制为 100
    innodb_log_buffer_size = min(total_ram * 5 // 100, 16 * 1024 * 1024)  # 使用内存的 5%,最大限制为 16MB

    # 以字节为单位打印配置
    print(f"MySQL 配置(基于总内存 {total_ram / (1024 * 1024):.2f} MB):")
    print("将以下内容添加到 /etc/mysql/mysql.conf.d/mysqld.cnf 的末尾\n")
    
    print(f"innodb_buffer_pool_size = {innodb_buffer_pool_size}")
    print(f"key_buffer_size = {key_buffer_size}")
    print(f"sort_buffer_size = {sort_buffer_size}")
    print(f"read_rnd_buffer_size = {read_rnd_buffer_size}")
    print(f"tmp_table_size = {tmp_table_size}")
    print(f"max_heap_table_size = {max_heap_table_size}")
    print(f"join_buffer_size = {join_buffer_size}")
    print(f"table_open_cache = {table_open_cache}")
    print(f"thread_cache_size = {thread_cache_size}")
    print(f"innodb_log_buffer_size = {innodb_log_buffer_size}")

    # 打印自定义设置
    print("expire_logs_days = 3")
    print("max_binlog_size = 100M")

if __name__ == "__main__":
    calculate_mysql_settings()

会打印出类似以下的配置:

innodb_buffer_pool_size = 626468044
key_buffer_size = 417645363
sort_buffer_size = 4194304
read_rnd_buffer_size = 524288
tmp_table_size = 67108864
max_heap_table_size = 67108864
join_buffer_size = 4176453
table_open_cache = 2000
thread_cache_size = 100
innodb_log_buffer_size = 16777216
expire_logs_days = 3
max_binlog_size = 100M

添加到MySQL的配置文件:/etc/mysql/mysql.conf.d/mysqld.cnf 然后重启数据库即可:service mysql restart

BASH脚本优化MySQL数据库参数

以下是完成同样功能的BASH脚本。

#!/bin/bash

# 获取总内存大小(以字节为单位)
get_total_ram() {
    # 从 /proc/meminfo 中提取总内存(以 kB 为单位)
    total_ram_kb=$(awk '/^MemTotal:/ {print $2}' /proc/meminfo)
    if [[ -z "$total_ram_kb" ]]; then
        echo 0  # 如果未找到 MemTotal,则返回 0
    else
        echo $((total_ram_kb * 1024))  # 将 kB 转换为字节
    fi
}

# 根据总内存大小计算 MySQL 配置
calculate_mysql_settings() {
    # 获取总内存(以字节为单位)
    total_ram=$(get_total_ram)

    # 计算 MySQL 配置参数
    innodb_buffer_pool_size=$((total_ram * 30 / 100))  # 使用内存的 30%
    key_buffer_size=$(($((total_ram * 20 / 100)) < $((512 * 1024 * 1024)) ? $((total_ram * 20 / 100)) : $((512 * 1024 * 1024))))  # 使用内存的 20%,最大限制为 512MB
    sort_buffer_size=$(($((total_ram * 25 / 1000)) < $((4 * 1024 * 1024)) ? $((total_ram * 25 / 1000)) : $((4 * 1024 * 1024))))  # 使用内存的 0.25%,最大限制为 4MB
    read_rnd_buffer_size=$(($((total_ram * 625 / 100000)) < $((512 * 1024)) ? $((total_ram * 625 / 100000)) : $((512 * 1024))))  # 使用内存的 0.0625%,最大限制为 512KB
    tmp_table_size=$((total_ram * 5 / 100 < 64 * 1024 * 1024 ? total_ram * 5 / 100 : 64 * 1024 * 1024))  # 使用内存的 5%,最大限制为 64MB
    max_heap_table_size=$tmp_table_size  # 临时表大小等于最大堆表大小
    join_buffer_size=$(($((total_ram * 2 / 1000)) < $((4 * 1024 * 1024)) ? $((total_ram * 2 / 1000)) : $((4 * 1024 * 1024))))  # 使用内存的 0.2%,最大限制为 4MB
    table_open_cache=$(($((400 + total_ram / 64)) < 2000 ? $((400 + total_ram / 64)) : 2000))  # 根据内存动态计算,最大限制为 2000
    thread_cache_size=$(($((total_ram * 15 / 1000)) < 100 ? $((total_ram * 15 / 1000)) : 100))  # 使用内存的 1.5%,最大限制为 100
    innodb_log_buffer_size=$(($((total_ram * 5 / 100)) < $((16 * 1024 * 1024)) ? $((total_ram * 5 / 100)) : $((16 * 1024 * 1024))))  # 使用内存的 5%,最大限制为 16MB

    # 打印配置(以字节为单位)
    echo "MySQL 配置(基于总内存 $((total_ram / (1024 * 1024))) MB):"
    echo "将以下内容添加到 /etc/mysql/mysql.conf.d/mysqld.cnf 的末尾"
    echo
    echo "innodb_buffer_pool_size = $innodb_buffer_pool_size"
    echo "key_buffer_size = $key_buffer_size"
    echo "sort_buffer_size = $sort_buffer_size"
    echo "read_rnd_buffer_size = $read_rnd_buffer_size"
    echo "tmp_table_size = $tmp_table_size"
    echo "max_heap_table_size = $max_heap_table_size"
    echo "join_buffer_size = $join_buffer_size"
    echo "table_open_cache = $table_open_cache"
    echo "thread_cache_size = $thread_cache_size"
    echo "innodb_log_buffer_size = $innodb_log_buffer_size"
    echo
    echo "expire_logs_days = 3"  # 日志过期天数设置为 3 天
    echo "max_binlog_size = 100M"  # 最大二进制日志大小设置为 100M
}

# 主函数调用
calculate_mysql_settings

需要注意的是,我在脚本后面加入了一些我自定义的配置,根据需求自行修改即可。在配置文件里,后面定义的会覆盖前面的,这就是为什么要添加到文件尾的原因。

其中最关键的配置 innodb_buffer_pool_size 我设置为使用当前内存的30%,如果服务器只有数据库/博客这个功能,可以适当的提高比例,比如60%-80%。

英文:Python/Bash Script to Print the Optimized Parameters for MySQL Servers

运维/DevOps

本文一共 812 个汉字, 你数一下对不对.
MySQL参数一键配置脚本: 有效提升数据库性能. (AMP 移动加速版本)

扫描二维码,分享本文到微信朋友圈
75a5a60b9cac61e5c8c71a96e17f2d9c MySQL参数一键配置脚本: 有效提升数据库性能 MySQL 学习笔记 数据库 计算机 计算机 运维 运维 DevOps
The post MySQL参数一键配置脚本: 有效提升数据库性能 first appeared on 小赖子的英国生活和资讯.

相关文章:

  1. 步步高学生电脑上 Basic 编程语言 peek 用法示例 步步高学生电脑 是8位FC机的经典之作.它上面的BASIC有三个版本 1.0, 2.0 和 2.1 2.1 版本有个在线帮助,实际上是 help.cmd 1.0 是用 Esc 键退回到 DOS 的,...
  2. 一张图告诉你北京的雾霾有多严重 一北京的朋友朋友圈发的: 左上为全新口罩;右上为全新口罩本周一到周五每天室外戴20分钟左右;左下为全新口罩今早室外+公交车戴一个半小时;右下为全新口罩今早开车戴一小时左右. 还有这图 空气污染 – 红色的是严重的.中国,尤其是华北地区,是全球最红的地区,没有”之一”. 本文一共 113 个汉字, 你数一下对不对. 一张图告诉你北京的雾霾有多严重. (AMP 移动加速版本) 赞赏我的几个理由. ¥...
  3. 你给SteemIt中文微信群拖后腿了么? 这年头不缺算法, 就缺数据. 这两天花了很多时间在整API上, 整完之后自己用了一下还觉得真是挺方便的. 今天就突然想看一看自己是否给大家拖后腿了, 于是调用每日中文区微信群排行榜单的API, 刷刷拿着 NodeJs 练手: 1 2 3 4 5 6...
  4. 穷举算法的应用 – 去除EXCEL文件中的保护 EXCEL 是可以用密码来保护的. 比如 这个EXCEL 就用了密码保护. 打开EXCEL文件 你会注意到 无法编辑 无法查看宏(VBA)的代码. 去除保护很简单 第一步先编辑宏 VBA 把下面的VBA代码拷贝到VBA编辑器里 并按下F5运行 1...
  5. 谈谈 Utopian 成立公司 就在刚刚 Utopian 的老板 @elear 在 帖子和 discord 上宣布在 意大利成立 Utopian 公司. 可喜可贺! 这开始只是 Steem 上的一个小项目,...
  6. 步步高多媒体学生电脑 汇编程序设计 – 1 英文同步 90年代后期步步高生产的软驱一号(又称步步高多媒体学生电脑)和98型学生电脑都带了软驱,一按电源件, 都从软盘启动(98型可以从内置的电子盘启动) 步步高提供了直接在学习机上写汇编开发的工具 BASM. BASM 可以用来写 6502 汇编,并可以编译成 CMD 小型可执行程序 不支持 EXC 程序. CMD...
  7. 按揭贷款(房贷,车贷) 每月还贷计算器 去年给银行借了17万英镑 买了20万7500英镑的房子, 25年还清. 前2年是定率 Fix Rate 的合同 (年利率2.49%). 每个月大概是还 700多英镑. 有很多种还贷的计算方式, 定率/每月固定 是比较常用的. 简单来说就是 每个月交的钱是...
  8. 舍得给员工培训的公司是好公司 最近出差比较多, 很多人问我都干嘛去. 各种开会, 各种培训. 公司从剑桥一个软件公司请了一个专业的软件专家来做软件工程上的顾问. 我是 R&D 研发经理, 所以很自然的就要和他经常讨论, 然后目标是把当前公司的软件开发流程给完善, 提高, 把以前做的不对的得整对了. 培训的内容很多, 让我觉得以前公司完全就是在瞎搞, 什么...

GitHub 库自动同步脚本分享

2024年4月15日 00:00

杜老师复刻了 70 多个库,每次源库更新后都需要一一手动同步,太过麻烦。今天分享一个自动同步脚本,有需要的小伙伴可以试一下。注意如对本地库有修改,建议使用 PR 来同步,避免代码覆盖。

代码同步

不太清楚小伙伴们同步代码方式,有人习惯用 PR,有人喜欢用下图同步的方式。不管哪种方式,都需要手动操作的。如有仓库过多,每个都要同步一遍,想想是多大工作量。杜老师分享了 GitHub 库自动同步脚本,供有需要的小伙伴参考:

脚本分享

进入要同步的库中,切换至 Actions,点击 New workflow 项:

打开新页面后,点击篮字的 set up a workflow yourself:

设置文件名 sync.yml「可自定义,不与其它脚本同名即可」

将下面的脚本填到输入框中,点击右上方 Commit changes 即可:

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
name: Upstream Sync

permissions:
contents: write

on:
schedule:
- cron: "0 0 * * *" # every day
workflow_dispatch:

jobs:
sync_latest_from_upstream:
name: Sync latest commits from upstream repo
runs-on: ubuntu-latest
if: ${{ github.event.repository.fork }}

steps:
# Step 1: run a standard checkout action
- name: Checkout target repo
uses: actions/checkout@v4

# Step 2: run the sync action
- name: Sync upstream changes
id: sync
uses: aormsby/Fork-Sync-With-Upstream-action@v3.4
with:
upstream_sync_repo: arnidan/nsfw-api
upstream_sync_branch: main
target_sync_branch: main
target_repo_token: ${{ secrets.GITHUB_TOKEN }} # automatically generated, no need to set

# Set test_mode true to run tests instead of the true action!!
test_mode: false

- name: Sync check
if: failure()
run: |
echo "[Error] 由于上游仓库的 workflow 文件变更,导致 GitHub 自动暂停了本次自动更新,您需要手动 Sync Fork 一次。"
echo "[Error] Due to a change in the workflow file of the upstream repository, GitHub has automatically suspended the scheduled automatic update. You need to manually sync your fork."
exit 1

9 个实用的 Shell 脚本

2024年2月12日 00:00

好久没更新了,实在不知道写点什么好,就在网上找了一些资源。正文是杜老师整理的 9 个实用 Shell 脚本,供有需要的小伙伴参考。需要注意的是,这些脚本为杜老师收集,并没有测试过,小伙伴们使用之前要先测试。

写在最前

常来的小伙伴应该发现杜老师说近两周没有更新了,过年期间确实有太多的事情需要处理,各种亲戚走动等等。目前已经处理差不多了,工作上的节奏也已慢慢稳定,近期开始补上之前拖更文章。开头也祝愿来访的小伙伴们龙年大吉,博客访问蒸蒸日上,身体和服务器健健康康,心想和收入皆遂意!

DoS 攻击防范自动屏蔽攻击 IP

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
LOG_FILE=/usr/local/nginx/logs/demo2.access.log
ABNORMAL_IP=$(tail -n5000 $LOG_FILE | grep $DATE | awk '{a[$1]++}END{for(i in a)if(a[i]>10)print i}')
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL | grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
echo "$(date +'%F_%T') $IP" >>/tmp/drop_ip.log
fi
done

Linux 系统发送告警邮件的脚本

1
2
3
4
5
# yum install mailx
# vi /etc/mail.rc
set from=baojingtongzhi@163.com smtp=smtp.163.com
set smtp-auth-user=baojingtongzhi@163.com smtp-auth-password=123456
set smtp-auth=login

MySQL 数据库的单循环备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=localhost
USER=backup
PASS=123.com
BACKUP_DIR=/data/db_backup
DB_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "show databases;" 2>/dev/null | egrep -v "Database|information_schema|mysql|performance_schema|sys")

for DB in $DB_LIST; do
BACKUP_NAME=$BACKUP_DIR/${DB}_${DATE}.sql
if ! mysqldump -h$HOST -u$USER -p$PASS -B $DB >$BACKUP_NAME 2>/dev/null; then
echo "$BACKUP_NAME 备份失败!"
fi
done

MySQL 数据库的多循环备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=localhost
USER=backup
PASS=123.com
BACKUP_DIR=/data/db_backup
DB_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "show databases;" 2>/dev/null | egrep -v "Database|information_schema|mysql|performance_schema|sys")

for DB in $DB_LIST; do
BACKUP_DB_DIR=$BACKUP_DIR/${DB}_${DATE}
[ ! -d $BACKUP_DB_DIR ] && mkdir -p $BACKUP_DB_DIR &>/dev/null
TABLE_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "use $DB;show tables;" 2>/dev/null)
for TABLE in $TABLE_LIST; do
BACKUP_NAME=$BACKUP_DB_DIR/${TABLE}.sql
if ! mysqldump -h$HOST -u$USER -p$PASS $DB $TABLE >$BACKUP_NAME 2>/dev/null; then
echo "$BACKUP_NAME 备份失败!"
fi
done
done

Nginx 的访问日志按天切割

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
LOG_DIR=/usr/local/nginx/logs
YESTERDAY_TIME=$(date -d "yesterday" +%F)
LOG_MONTH_DIR=$LOG_DIR/$(date +"%Y-%m")
LOG_FILE_LIST="default.access.log"

for LOG_FILE in $LOG_FILE_LIST; do
[ ! -d $LOG_MONTH_DIR ] && mkdir -p $LOG_MONTH_DIR
mv $LOG_DIR/$LOG_FILE $LOG_MONTH_DIR/${LOG_FILE}_${YESTERDAY_TIME}
done

kill -USR1 $(cat /var/run/nginx.pid)

Nginx 访问日志的分析脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/bin/bash
#日志格式: $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"
LOG_FILE=$1
echo "统计访问最多的 10 个 IP"
awk '{a[$1]++}END{print "UV:",length(a);for(v in a)print v,a[v]}' $LOG_FILE | sort -k2 -nr | head -10
echo "----------------------"

echo "统计时间段访问最多 IP"
awk '$4>="[01/Dec/2018:13:20:25" && $4<="[27/Nov/2018:16:20:49"{a[$1]++}END{for(v in a)print v,a[v]}' $LOG_FILE | sort -k2 -nr | head -10
echo "----------------------"

echo "统计访问最多 10 个页面"
awk '{a[$7]++}END{print "PV:",length(a);for(v in a){if(a[v]>10)print v,a[v]}}' $LOG_FILE | sort -k2 -nr
echo "----------------------"

echo "统计访问页面状态码的数量"
awk '{a[$7" "$9]++}END{for(v in a){if(a[v]>5)print v,a[v]}}'

查看网卡实时流量脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
NIC=$1
echo -e " In ------ Out"
while true; do
OLD_IN=$(awk '$0~"'$NIC'"{print $2}' /proc/net/dev)
OLD_OUT=$(awk '$0~"'$NIC'"{print $10}' /proc/net/dev)
sleep 1
NEW_IN=$(awk '$0~"'$NIC'"{print $2}' /proc/net/dev)
NEW_OUT=$(awk '$0~"'$NIC'"{print $10}' /proc/net/dev)
IN=$(printf "%.1f%s" "$((($NEW_IN - $OLD_IN) / 1024))" "KB/s")
OUT=$(printf "%.1f%s" "$((($NEW_OUT - $OLD_OUT) / 1024))" "KB/s")
echo "$IN $OUT"
sleep 1
done

服务器系统配置初始化脚本

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
#/bin/bash
#设置时区同步时间
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
if ! crontab -l | grep ntpdate &>/dev/null; then
(
echo "* 1 * * * ntpdate time.windows.com >/dev/null 2>&1"
crontab -l
) | crontab
fi

#禁用 SELinux 防火墙
sed -i '/SELINUX/{s/permissive/disabled/}' /etc/selinux/config

#关闭各版本防火墙
if egrep "7.[0-9]" /etc/redhat-release &>/dev/null; then
systemctl stop firewalld
systemctl disable firewalld
elif egrep "6.[0-9]" /etc/redhat-release &>/dev/null; then
service iptables stop
chkconfig iptables off
fi

#历史命令显示操作时间
if ! grep HISTTIMEFORMAT /etc/bashrc; then
echo 'export HISTTIMEFORMAT="%F %T `whoami` "' >>/etc/bashrc
fi

#SSH 的超时时间
if ! grep "TMOUT=600" /etc/profile &>/dev/null; then
echo "export TMOUT=600" >>/etc/profile
fi

#禁止 root 的远程登录
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config

#禁止定时任务发送邮件
sed -i 's/^MAILTO=root/MAILTO=""/' /etc/crontab

#设置最大打开的文件数
if ! grep "* soft nofile 65535" /etc/security/limits.conf &>/dev/null; then
cat >>/etc/security/limits.conf <<EOF
* soft nofile 65535
* hard nofile 65535
EOF
fi

#系统内核优化
cat >>/etc/sysctl.conf <<EOF
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 20480
net.ipv4.tcp_max_syn_backlog = 20480
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_fin_timeout = 20
EOF

#减少 Swap 的使用
echo "0" >/proc/sys/vm/swappiness

#安装系统性能分析工具
yum install gcc make autoconf vim sysstat net-tools iostat if

监控 100 台服务器磁盘利用率脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
HOST_INFO=host.info
for IP in $(awk '/^[^#]/{print $1}' $HOST_INFO); do
USER=$(awk -v ip=$IP 'ip==$1{print $2}' $HOST_INFO)
PORT=$(awk -v ip=$IP 'ip==$1{print $3}' $HOST_INFO)
TMP_FILE=/tmp/disk.tmp
ssh -p $PORT $USER@$IP 'df -h' >$TMP_FILE
USE_RATE_LIST=$(awk 'BEGIN{OFS="="}/^\/dev/{print $NF,int($5)}' $TMP_FILE)
for USE_RATE in $USE_RATE_LIST; do
PART_NAME=${USE_RATE%=*}
USE_RATE=${USE_RATE#*=}
if [ $USE_RATE -ge 80 ]; then
echo "Warning: $PART_NAME Partition usage $USE_RATE%!"
fi
done
done

MySQL 数据库备份脚本参考分享

2024年1月25日 00:00

在之前的文件中杜老师推荐了两款云主机面板,有小伙伴留言说因服务器配置比较低,未使用云主机面板,一直为数据库备份问题困扰。杜老师之前工作的环境也是没有面板,编写过相关的备份脚本,在此文中分享给需要的小伙伴们~

设置环境变量

1
2
3
4
5
6
#!/bin/bash
# Setup environment variables
export MYSQL_HOST=localhost
export MYSQL_PORT=3306
export MYSQL_USER=root
export MYSQL_PASSWORD=your_password

注意:需要设置环境变量,以便脚本可以找到 MySQL 数据库。在脚本中,添加以上内容。

创建备份目录

1
2
3
4
5
6
# Create backup directory
BACKUP_DIR=/path/to/backup/directory
# Check if backup directory exists
if [ ! -d "$BACKUP_DIR" ]; then
mkdir -p "$BACKUP_DIR"
fi

注意:创建一个目录,以存储备份的文件。在脚本中,添加以上内容。

备份 MySQL 数据库

1
2
3
4
# Backup database
DATABASE_NAME=your_database_name
BACKUP_FILE="$BACKUP_DIR/$DATABASE_NAME-$(date +"%Y-%m-%d_%H-%M-%S").sql"
mysqldump -u $MYSQL_USER -p$MYSQL_PASSWORD --host=$MYSQL_HOST --port=$MYSQL_PORT $DATABASE_NAME > "$BACKUP_FILE"

注意:使用 mysqldump 命令备份数据库。在脚本中,添加以上内容。

检查备份是否成功

1
2
3
4
5
6
7
# Check if backup file exists
if [ -f "$BACKUP_FILE" ]; then
echo "Backup completed successfully!"
else
echo "Backup failed!"
exit 1
fi

注意:检查备份文件是否创建。在脚本中,添加以上内容。

压缩备份文件

1
2
3
4
5
# Compress backup file
COMPRESSED_BACKUP_FILE="$BACKUP_FILE".gz
gzip "$BACKUP_FILE"
# Remove original backup file
rm "$BACKUP_FILE"

注意:为了节省空间,可使用 gzip 命令压缩备份文件。在脚本中,添加以上内容。

删除 MySQL 旧备份

1
2
3
4
5
# Remove old backups
OLD_BACKUPS=$(ls -t "$BACKUP_DIR" | tail -n +7)
if [ ! -z "$OLD_BACKUPS" ]; then
rm "$BACKUP_DIR/$OLD_BACKUPS"
fi

注意:删除旧备份文件以节省空间。在脚本中,添加以上内容。

设置定时任务

最后,可使用 crontab 命令设置定时任务,以便脚本定期运行。在终端中输入以下命令:

1
crontab -e

在打开的编辑器中,添加以下行的内容,比如以每天凌晨的一点运行脚本。保存并退出编辑器:

1
0 1 * * * /path/to/your/backup_script.sh

还有哪些开源工具

除上面脚本外,还有一些开源「有商业版」工具也可实现 MySQL 数据库备份,供需要的小伙伴们参考选择:

名称描述
mysqldumpmysqldump 是 MySQL 官方提供的备份工具,可将 MySQL 数据库的数据和结构导出为 SQL 文件。
XtraBackupXtraBackup 是一个 Percona 提供的备份工具,可在线备份 MySQL 数据,提供增量备份、压缩功能。
Zmanda Recovery ManagerZmanda Recovery Manager 是一款商业的备份和恢复解决方案,可支持 MySQL 和其它数据库。提供完整备份、增量备份、多种存储介质、自动化备份和恢复等功能。
mydumpermydumper 是一个 MySQL 官方派生的高性能 MySQL 备份工具,支持并行备份,可更快地备份大型 MySQL 数据库。

接收 GitHub Webhook 并自动执行脚本

2022年5月17日 00:00

本博客的模板是 Volantis,开发者们非常勤劳,经常更新些新玩意。每次收到更新通知时杜老师都会第一时间同步代码,不过还要登录服务器部署才可以生效。本文分享如何配置接收 GitHub Webhook 后自动执行脚本。

工具下载

下载地址:

下载地址

解压配置

下载后可先本地解压再传到服务器上的/opt 目录,或在服务器运行 unzip linux-webhook.zip。如提示 command not found,请执行下面的命令:

1
2
yum -y install unzip # CentOS
apt -y install unzip # Ubuntu

然后编写服务配置文件,将下面代码写入/lib/systemd/system/webhook.service,其中的 SECRET 可自定义:

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=linux-webhook
After=network.target

[Service]
Type=simple
ExecStart=/opt/linux-webhook --bash /opt/github.sh --secret SECRET
Restart=on-failure
RestartSec=30s

[Install]
WantedBy=multi-user.target

编写脚本

将需执行的脚本写入/opt/github.sh,例如:

1
2
3
#!/bin/bash
echo "Hello Webhook"
exit 0

脚本末尾一定要加入 exit 0。最后赋予文件执行权限:

1
2
chmod +x /opt/linux-webhook
chmod +x /opt/github.sh

服务相关命令:

1
2
3
4
systemctl daemon-reload # 重载配置
systemctl start webhook # 启动服务
systemctl status webhook # 状态查询
systemctl enable webhook # 开机启动

服务默认端口为 2020,更换请将 ExecStart 项改为:

1
ExecStart=/opt/linux-webhook --port PORT --bash /opt/github.sh --secret SECRET

其它配置

Settings->Webhooks:

Add webhook:

Payload URL 填写 http://IP:PORT/web-hook,Content type 选择 application/json,Secret 填写之前设置的,最后点击 Add webhook 就行了:

Recent Deliveries 会显示回调状态,绿色对勾即为成功:

Shell 脚本练习题

2020年11月11日 00:00

作为一枚十分贴心的杜老师,在此给大家准备了六道 Shell 脚本练习题。都是入门级的水准,希望大家踊跃尝试编写。

脚本题目

  1. 编写脚本,计算 1 到 100 的总和;

  2. 编写脚本,输入一个数字 n 并计算 1 到这个数的总和。要求:如果这个数小于等于 1,要求重新输入,直到输入大于 1 的数字为止;

  3. 编写脚本,把/root/目录下的所有目录复制到/tmp/目录;

  4. 编写脚本,批量建立用户,要求用户名的格式为 user_00/user_01,建立 100 个,且用户同属于 users 组;

  5. 编写脚本,在/cjk/目录下的所有文件「不含目录」的文件名后面加.bak;

  6. 编写脚本,给系统中所有已存在的用户打个招呼,格式参考为 hello penndu and your id is 1000。

参考答案

一题:

1
2
3
4
5
6
7
#!/bin/bash
sum=0
for i in `seq 1 100`
do
sum=$[$i+$sum]
done
echo $sum

二题:

1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
n=0
while [ $n -lt 1 ]
do
read -p "Please input a number, it must greater than 1: " n
done
sum=0
for i in `seq 1 $n`
do
sum=$[$i+$sum]
done
echo $sum

三题:

1
2
3
4
5
6
7
8
#!/bin/bash
cd /root/
for f in `ls`
do
if[ -d $f ] ; then
cd -r $f /tmp/
fi
done

四题:

1
2
3
4
5
6
#!/bin/bash
groupadd users
for i in `seq -w 0 99`
do
useradd -g users user_$i
done

五题:

1
2
3
4
5
6
7
8
#!/bin/bash
cd /cjk/
for f in `ls`
do
if[ -f $f ] ; then
mv $f $f.bak
fi
done

六题:

1
2
3
4
5
6
7
#!/bin/bash
for i in `cat /etc/passwd`
do
username=`echo $i | cut -d : -f 1`
id=`echo $i | cut -d : -f 3`
echo "hello $username and your id is $id"
done

VPS 云主机测试脚本

2020年10月24日 00:00

该段脚本来源于互联网,这里做了些简单的修改,主要删除了一些无用的代码,内部测试规则没有任何修改。脚本中使用国外源进行下载速度测试,针对国内主机可能不准,仅供参考!

脚本介绍

本段代码可以显示出云主机使用的 CPU 型号,主频大小,缓存大小,硬盘容量和内存等信息,并测试硬盘的读写速度,以及下载速度「一般云主机服务商的下行速度不限制」

使用方式特别简单,在云主机使用 vi 命令新建个文件,将上述脚本复制到文件中并赋予执行权限,直接运行即可。

测试脚本

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
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env bash
if [ ! -e '/usr/bin/wget' ]; then
echo "Error: wget command not found. You must be install wget command at first."
exit 1
fi
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
PLAIN='\033[0m'
get_opsy() {
[ -f /etc/redhat-release ] && awk '{print ($1,$3~/^[0-9]/?$3:$4)}' /etc/redhat-release && return
[ -f /etc/os-release ] && awk -F'[= "]' '/PRETTY_NAME/{print $3,$4,$5}' /etc/os-release && return
[ -f /etc/lsb-release ] && awk -F'[="]+' '/DESCRIPTION/{print $2}' /etc/lsb-release && return
}
next() {
printf "%-70s\n" "-" | sed 's/\s/-/g'
}
speed_test() {
local speedtest=$(wget -4O /dev/null -T300 $1 2>&1 | awk '/\/dev\/null/ {speed=$3 $4} END {gsub(/\(|\)/,"",speed); print speed}')
local ipaddress=$(ping -c1 -n `awk -F'/' '{print $3}' <<< $1` | awk -F'[()]' '{print $2;exit}')
local nodeName=$2
printf "$YELLOW%-32s$GREEN%-24s$RED%-14s$PLAIN\n" "$nodeName" "$ipaddress" "$speedtest"
}
speed_test_v6() {
local speedtest=$(wget -6O /dev/null -T300 $1 2>&1 | awk '/\/dev\/null/ {speed=$3 $4} END {gsub(/\(|\)/,"",speed); print speed}')
local ipaddress=$(ping6 -c1 -n `awk -F'/' '{print $3}' <<< $1` | awk -F'[()]' '{print $2;exit}')
local nodeName=$2
printf "$YELLOW%-32s$GREEN%-24s$RED%-14s$PLAIN\n" "$nodeName" "$ipaddress" "$speedtest"
}
speed() {
speed_test 'http://cachefly.cachefly.net/100mb.test' 'CacheFly'
speed_test 'http://speedtest.tokyo.linode.com/100MB-tokyo.bin' 'Linode, Tokyo, JP'
speed_test 'http://speedtest.singapore.linode.com/100MB-singapore.bin' 'Linode, Singapore, SG'
speed_test 'http://speedtest.london.linode.com/100MB-london.bin' 'Linode, London, UK'
speed_test 'http://speedtest.frankfurt.linode.com/100MB-frankfurt.bin' 'Linode, Frankfurt, DE'
speed_test 'http://speedtest.fremont.linode.com/100MB-fremont.bin' 'Linode, Fremont, CA'
speed_test 'http://speedtest.dal05.softlayer.com/downloads/test100.zip' 'Softlayer, Dallas, TX'
speed_test 'http://speedtest.sea01.softlayer.com/downloads/test100.zip' 'Softlayer, Seattle, WA'
speed_test 'http://speedtest.fra02.softlayer.com/downloads/test100.zip' 'Softlayer, Frankfurt, DE'
speed_test 'http://speedtest.sng01.softlayer.com/downloads/test100.zip' 'Softlayer, Singapore, SG'
speed_test 'http://speedtest.hkg02.softlayer.com/downloads/test100.zip' 'Softlayer, HongKong, CN'
}
io_test() {
(LANG=C dd if=/dev/zero of=test_$$ bs=64k count=16k conv=fdatasync && rm -f test_$$ ) 2>&1 | awk -F, '{io=$NF} END { print io}' | sed 's/^[ \t]*//;s/[ \t]*$//'
}
calc_disk() {
local total_size=0
local array=$@
for size in ${array[@]}
do
[ "$size" == "0" ] && size_t=0 || size_t=`echo ${size:0:${#size}-1}`
[ "`echo ${size:(-1)}`" == "K" ] && size=0
[ "`echo ${size:(-1)}`" == "M" ] && size=$( awk 'BEGIN{printf "%.1f", '$size_t' / 1024}' )
[ "`echo ${size:(-1)}`" == "T" ] && size=$( awk 'BEGIN{printf "%.1f", '$size_t' * 1024}' )
[ "`echo ${size:(-1)}`" == "G" ] && size=$size_t
total_size=$( awk 'BEGIN{printf "%.1f", '$total_size' + '$size'}' )
done
echo $total_size
}
cname=$( awk -F: '/model name/ {name=$2} END {print name}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
cores=$( awk -F: '/model name/ {core++} END {print core}' /proc/cpuinfo )
freq=$( awk -F: '/cpu MHz/ {freq=$2} END {print freq}' /proc/cpuinfo | sed 's/^[ \t]*//;s/[ \t]*$//' )
tram=$( free -m | awk '/Mem/ {print $2}' )
uram=$( free -m | awk '/Mem/ {print $3}' )
swap=$( free -m | awk '/Swap/ {print $2}' )
uswap=$( free -m | awk '/Swap/ {print $3}' )
up=$( awk '{a=$1/86400;b=($1%86400)/3600;c=($1%3600)/60} {printf("%d days, %d hour %d min\n",a,b,c)}' /proc/uptime )
load=$( w | head -1 | awk -F'load average:' '{print $2}' | sed 's/^[ \t]*//;s/[ \t]*$//' )
opsy=$( get_opsy )
arch=$( uname -m )
lbit=$( getconf LONG_BIT )
kern=$( uname -r )
ipv6=$( wget -qO- -t1 -T2 ipv6.icanhazip.com )
disk_size1=($( LANG=C df -ahPl | grep -wvE '\-|none|tmpfs|devtmpfs|by-uuid|chroot|Filesystem' | awk '{print $2}' ))
disk_size2=($( LANG=C df -ahPl | grep -wvE '\-|none|tmpfs|devtmpfs|by-uuid|chroot|Filesystem' | awk '{print $3}' ))
disk_total_size=$( calc_disk ${disk_size1[@]} )
disk_used_size=$( calc_disk ${disk_size2[@]} )
clear
next
echo "CPU model : $cname"
echo "Number of cores : $cores"
echo "CPU frequency : $freq MHz"
echo "Total size of Disk : $disk_total_size GB ($disk_used_size GB Used)"
echo "Total amount of Mem : $tram MB ($uram MB Used)"
echo "Total amount of Swap : $swap MB ($uswap MB Used)"
echo "System uptime : $up"
echo "Load average : $load"
echo "OS : $opsy"
echo "Arch : $arch ($lbit Bit)"
echo "Kernel : $kern"
next
io1=$( io_test )
echo "I/O speed(1st run) : $io1"
io2=$( io_test )
echo "I/O speed(2nd run) : $io2"
io3=$( io_test )
echo "I/O speed(3rd run) : $io3"
ioraw1=$( echo $io1 | awk 'NR==1 {print $1}' )
[ "`echo $io1 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw1=$( awk 'BEGIN{print '$ioraw1' * 1024}' )
ioraw2=$( echo $io2 | awk 'NR==1 {print $1}' )
[ "`echo $io2 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw2=$( awk 'BEGIN{print '$ioraw2' * 1024}' )
ioraw3=$( echo $io3 | awk 'NR==1 {print $1}' )
[ "`echo $io3 | awk 'NR==1 {print $2}'`" == "GB/s" ] && ioraw3=$( awk 'BEGIN{print '$ioraw3' * 1024}' )
ioall=$( awk 'BEGIN{print '$ioraw1' + '$ioraw2' + '$ioraw3'}' )
ioavg=$( awk 'BEGIN{printf "%.1f", '$ioall' / 3}' )
echo "Average I/O speed : $ioavg MB/s"
next
printf "%-32s%-24s%-14s\n" "Node Name" "IPv4 address" "Download Speed"
speed && nex

注意:在测试下载速度时,会因为网络状况的不同,测试时间不同,如果不想等了,可以直接终止运行。

natapp 树莓派开机启动脚本

2020年8月19日 00:00

natapp 是基于 ngrok 的反向代理软件,通过在公网和本地运行的 Web 服务器之间建立一个安全的通道。natapp 可捕获和分析所有通道上流量,以便于后期分析和重放。

运行 natapp 客户端

1
chmod a+x /usr/natapp/natapp

注意:在官网下载客户端,放在目录/usr/natapp 中运行上面命令。

创建配置文件

1
2
[default]
authtoken=

注意:根据官网提供的 authtoken 将配置写入 config.ini,放置在/usr/natapp 目录。

测试运行情况

1
./natapp

注意:在/usr/natapp 目录执行上面命令,测试穿透应用,确保无误后关闭客户端。

服务运行脚本

将下面的代码保存名为 natapp 放在/etc/init.d 目录:

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
#!/bin/sh -e
### BEGIN INIT INFO
# Provides: natapp.cn
# Required-Start: $network $remote_fs $local_fs
# Required-Stop: $network $remote_fs $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: autostartup of natapp for RaspberryPi
### END INIT INFO


NAME=natapp
DAEMON=/usr/natapp/$NAME
PIDFILE=/var/run/$NAME.pid

[ -x "$DAEMON" ] || exit 0

case "$1" in
start)
if [ -f $PIDFILE ]; then
echo -n "$NAME already running"
echo "."
else
echo "Starting $NAME..."
start-stop-daemon -S -x $DAEMON -p $PIDFILE -m -b -o -q || return 2
echo "."
fi
;;
stop)
echo "Stoping $NAME..."
start-stop-daemon -K -p $PIDFILE -s TERM -o -q || return 2
rm -rf $PIDFILE
echo "."
;;
restart)
$0 stop && sleep 2 && $0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
exit 0

开启服务命令:

1
/etc/init.d/natapp start

关闭服务命令:

1
/etc/init.d/natapp stop

重启服务命令:

1
/etc/init.d/natapp restart

开机启动命令:

1
/etc/init.d/update-rc.d natapp defaults 90

取消开机启动:

1
/etc/init.d/update-rc.d -f natapp remove

Hexo 页面源代码压缩脚本

2020年7月5日 00:00

通过 Hexo 程序生成的页面,其源代码会产生大量的空行,不仅影响排错,且会占用本地、网络资源。今天杜老师为大家分享一段 Python 的代码,可以对其进行压缩!

压缩脚本

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
#!/usr/bin/env python3
# coding: UTF-8
import re,os
def minify_html(filename):
with open(filename,'r',encoding='utf-8') as p:
with open(filename+'.tmp','w',encoding='utf-8') as t:
while True:
l = p.readline()
if not l:
break
else:
if re.search('\S',l):
t.write(l)
os.remove(filename)
os.rename(filename+'.tmp',filename)
print('%s 已压缩!'%filename)
def yasuo(dir_path):
if dir_path[len(dir_path)-1] == '/':
dir_path = dir_path[:len(dir_path)-1]
file_list = os.listdir(dir_path)
for i in file_list:
if i.find('html') > 0:
minify_html(dir_path+'/'+i)
elif os.path.isdir(dir_path+'/'+i) and not re.match('\.|\_',i):
yasuo("%s/%s"%(dir_path,i))

yasuo('/Hexo/public')

注意:请将脚本最后一行的/Hexo,修改为您 Hexo 的运行目录,并保存为.py 结尾的执行文件,每次 hexo g 后运行该脚本就行了!

压缩效果

效果见图:

抢一个阿里云香港服务器

2024年8月18日 01:39

“抢”,为什么要用“抢”呢?因为真的很难买到。估计是在模仿小米的饥饿营销吧。

前几日是在谁那里看到阿里云香港主机,30M带宽,才24元/月,有点心动,了解了一番,才发现是阿里云香港轻量服务器,1G2核1T流量30M带宽(峰值)配置。比起腾讯轻量服务器稍微划算了些。但是基本上都是售罄的状态,每日0点放货。所以手速不快,基本上抢不到。不过我发现GitHub有个抢这个的脚本,基于Python写的,我今晚第一次用就抢到了。

20240818002352.jpg
阿里云香港轻量服务器

自动抢阿里云24元香港轻量服务器脚本:GitHub地址

下载这个脚本sample.py,修改sample.py 填写以下两个字段: access_key_id='' access_key_secret='',这在阿里云——AccessKey管理里可以新建得到。

阿里云充值

第一步也是最关键的,就是给阿里云账号充24块钱,这是香港主机一个月的费用,以免自动脚本因为没有付款而订单失败。

准备Python环境

我是在虚拟机上配置的Python环境,第一次弄,基于Debian。Debian 12默认安装了Python 3,可以使用以下命令验证是否已安装:

python3 --version

如果您看到了Python的版本信息,则表示已成功安装。如果没有安装,则可以使用以下命令安装Python 3:

apt install python3

然后安装pip,pip是Python的包管理器,用于安装和管理Python软件包。因为这个脚本需要安装阿里云SDK,需要用到pip。您可以使用以下命令在Debian 12上安装pip:

apt install python3-pip

安装完成后,您可以使用以下命令验证pip是否安装成功:

pip3 --version

安装阿里云SDK

你可以通过运行脚本(python3 sample.py)看到需要的SDK。

第一个是alibabacloud_swas_open20200601,通过pip命令安装:

pip install alibabacloud_swas_open20200601==3.0.0

如果出现下图所示的错误,error: externally-managed-environment,即“外部管理环境”错误,但这不是一个 bug。

20240818005039.jpg
error: externally-managed-environment

我的解决方法是简单粗暴——强制删除此警告,回归到熟悉的操作。

mv /usr/lib/python3.x/EXTERNALLY-MANAGED /usr/lib/python3.x/EXTERNALLY-MANAGED.bk

将 “x” 替换为实际版本。。

还有其他解决方案呢,详细可以参见这篇文章

然后你就可以正常安装SDK了。

第二个SDK是alibabacloud_tea_openapi,安装命令:

pip3 install alibabacloud_tea_openapi

第三个SDK是alibabacloud-tea-console,安装命令:

pip3 install alibabacloud-tea-console

然后你在运行脚本就会出现售罄的信息,那说明SDK组件都安装成功了。

python3 sample.py
code: 400, 该套餐每日限量售卖,当日售出量已达上限,如有需求请次日购买 request id:......................................

定时脚本

通过crontab –e将脚本添加到定时任务里,设置每日0点运行任务即可。

0 0 * * * python3 /root/sample.py

然后service cron restart重启定时任务,service cron status查看任务状态。

20240818011336.jpg
定时任务状态

OK,大功告成!剩下的就等待下一个0点凯旋的消息吧!

那么你的阿里云香港服务器是通过什么方式买的呢?

我也简单SFTP上传和下载以及SSH测试了下上传和下载的速度,不知道是不是因为现在这个点比较闲,峰值很高。

20240818002029.jpg
sftp上传速度
20240818012106.jpg
sftp下载速度
20240818003124.jpg
wget速度

网上有人测评,说阿里云香港服务器线路不是很好,还不如新加坡线路快。我先用一个月试试。如果不满意还是可以退款。毕竟这么抢手的东西,我想也不会差很多。我唯一不满意的就是有流量限制,我买服务器就不喜欢限制流量。目前没有想到用它来做什么,不过既然是香港主机,通过它看向世界还是不错的路径,嘎嘎。

版权声明: 本文采用 BY-NC-SA 协议进行授权,如无注明均为原创,转载请注明转自 皇家元林
本文链接: 抢一个阿里云香港服务器
❌
❌