通常,我们的网站存储空间、网络受限,会将图片和网站分开进行存储和“解耦”,方便后续使用 CDN 加速时,图片和网站可以分开使用不同方案;也方便网站迁移时,只迁移网站本体。
不知道有没有小伙伴想过: 在自己的腾讯云轻量应用服务器上,部署 Git 服务端作为图床仓库,重新定向工作空间到网站目录,并使用 Git hook 实现图片的 WebP 压缩与水印? 这次就给大家浅浅分享一下。
Git
Git 相信大家都不陌生,它是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。Git 由 Linux 之父 Linus 于 2005 年创建,目前由 Git 软件基金会管理。
Git 的核心思想是分布式,推送内容使用 Hash 进行差异化校验,使得 Git 具有更高的可靠性和更快的速度。Git 还支持离线工作,这意味着你可以在没有网络连接的情况下进行开发,然后将其推送到远程仓库。也正是这个特性,使得 Git 成为了一个非常流行的版本控制系统。而我们,也可以使用这些特性,来创建一个图床。
想一想,本地存储图片,之后使用 Git 推送到远程仓库,是不是很方便呢?
如果是写文章,对于一些草稿图片,甚至还可以使用 Git 拉出分支,在文章完成后,合并主分支,统一上线。保持工作台干净,岂不美哉?
#mermaid-svg-rlaET8uHjfjzUToV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rlaET8uHjfjzUToV .error-icon{fill:#552222;}#mermaid-svg-rlaET8uHjfjzUToV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rlaET8uHjfjzUToV .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-rlaET8uHjfjzUToV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rlaET8uHjfjzUToV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rlaET8uHjfjzUToV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rlaET8uHjfjzUToV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rlaET8uHjfjzUToV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rlaET8uHjfjzUToV .marker.cross{stroke:#333333;}#mermaid-svg-rlaET8uHjfjzUToV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rlaET8uHjfjzUToV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rlaET8uHjfjzUToV .cluster-label text{fill:#333;}#mermaid-svg-rlaET8uHjfjzUToV .cluster-label span{color:#333;}#mermaid-svg-rlaET8uHjfjzUToV .label text,#mermaid-svg-rlaET8uHjfjzUToV span{fill:#333;color:#333;}#mermaid-svg-rlaET8uHjfjzUToV .node rect,#mermaid-svg-rlaET8uHjfjzUToV .node circle,#mermaid-svg-rlaET8uHjfjzUToV .node ellipse,#mermaid-svg-rlaET8uHjfjzUToV .node polygon,#mermaid-svg-rlaET8uHjfjzUToV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rlaET8uHjfjzUToV .node .label{text-align:center;}#mermaid-svg-rlaET8uHjfjzUToV .node.clickable{cursor:pointer;}#mermaid-svg-rlaET8uHjfjzUToV .arrowheadPath{fill:#333333;}#mermaid-svg-rlaET8uHjfjzUToV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rlaET8uHjfjzUToV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rlaET8uHjfjzUToV .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-rlaET8uHjfjzUToV .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-rlaET8uHjfjzUToV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rlaET8uHjfjzUToV .cluster text{fill:#333;}#mermaid-svg-rlaET8uHjfjzUToV .cluster span{color:#333;}#mermaid-svg-rlaET8uHjfjzUToV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rlaET8uHjfjzUToV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
是
否
开始
本地存储图片/拉取 Git 仓库
是否为草稿图片
创建 Git 分支
推送到远程仓库
合并主分支
发布图片
Bare 裸仓库
平时,我们使用 Git 时,一般会使用工作区,也就是我们平时写代码的地方。
进入
.git
目录,就可以看到版本控制区:
但是,我们在服务器上部署的 Git 仓库,不需要工作空间,只需要版本库,用于提供给客户端进行拉取和推送。所以,在服务器上,我们就可以使用裸仓库,作为图床仓库:
# 创建一个裸仓库git init --bare
hook 钩子
Git 提供了钩子机制,允许我们在 Git 仓库中添加自定义脚本,以在特定事件发生时执行。这些事件包括:提交、推送、合并、拉取等。钩子脚本可以在仓库的
.git/hooks
目录中找到。
我们可以使用这些钩子脚本,来执行一些自定义操作,比如: 重新定向工作空间,以及后续的图片压缩、水印等操作。
裸仓库同样提供了 hook 钩子。比如,我们可以在
hooks/post-receive
中,编写脚本,实现重新定向工作空间:
#!/bin/zsh# 重新定向工作空间,pathToWebSite 为网站目录,pathToBarePath 为裸仓库目录git --work-tree=/pathToWebSite --git-dir=/pathToBarePath checkout -f
这样,本地推送图片到服务器上的 Git 裸仓库的流程就是:
#mermaid-svg-V8dvuPHXDCOmwqxm {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-V8dvuPHXDCOmwqxm .error-icon{fill:#552222;}#mermaid-svg-V8dvuPHXDCOmwqxm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-V8dvuPHXDCOmwqxm .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-V8dvuPHXDCOmwqxm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-V8dvuPHXDCOmwqxm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-V8dvuPHXDCOmwqxm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-V8dvuPHXDCOmwqxm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-V8dvuPHXDCOmwqxm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-V8dvuPHXDCOmwqxm .marker.cross{stroke:#333333;}#mermaid-svg-V8dvuPHXDCOmwqxm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-V8dvuPHXDCOmwqxm .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-V8dvuPHXDCOmwqxm text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-V8dvuPHXDCOmwqxm .actor-line{stroke:grey;}#mermaid-svg-V8dvuPHXDCOmwqxm .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-V8dvuPHXDCOmwqxm .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-V8dvuPHXDCOmwqxm #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-V8dvuPHXDCOmwqxm .sequenceNumber{fill:white;}#mermaid-svg-V8dvuPHXDCOmwqxm #sequencenumber{fill:#333;}#mermaid-svg-V8dvuPHXDCOmwqxm #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-V8dvuPHXDCOmwqxm .messageText{fill:#333;stroke:#333;}#mermaid-svg-V8dvuPHXDCOmwqxm .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-V8dvuPHXDCOmwqxm .labelText,#mermaid-svg-V8dvuPHXDCOmwqxm .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-V8dvuPHXDCOmwqxm .loopText,#mermaid-svg-V8dvuPHXDCOmwqxm .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-V8dvuPHXDCOmwqxm .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-V8dvuPHXDCOmwqxm .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-V8dvuPHXDCOmwqxm .noteText,#mermaid-svg-V8dvuPHXDCOmwqxm .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-V8dvuPHXDCOmwqxm .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-V8dvuPHXDCOmwqxm .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-V8dvuPHXDCOmwqxm .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-V8dvuPHXDCOmwqxm .actorPopupMenu{position:absolute;}#mermaid-svg-V8dvuPHXDCOmwqxm .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-V8dvuPHXDCOmwqxm .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-V8dvuPHXDCOmwqxm .actor-man circle,#mermaid-svg-V8dvuPHXDCOmwqxm line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-V8dvuPHXDCOmwqxm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
本地计算机
腾讯云轻量应用服务器
Git 裸仓库
网站目录(Nginx)
推送图片到 Git 裸仓库
接收推送
触发 post-receive 钩子
更新网站目录
本地计算机
腾讯云轻量应用服务器
Git 裸仓库
网站目录(Nginx)
既然 hook 是 shell 脚本,那么我们就可以使用 shell 脚本来实现图片的 WebP 压缩与水印了。
其实方法很多,比如:
imagemagick
,它是一个功能强大的图片处理工具,支持多种图片格式的转换,以及图片的裁剪、缩放、旋转、水印、滤镜等操作。
但是我更习惯用 python 的
Pillow
库,同样,它是一个强大的图像处理库,支持多种图片格式的转换。
WebP 格式
WebP 既支持有损压缩也支持无损压缩,相较于 PNG 格式,同样支持透明通道。在质量相同的情况下,WebP 也具有更小的文件体积。
所以,使用 WebP 格式,可以节省很间,进而提高网站内图片的加载速度; WebP 格式也支持渐进式加载,还可以进一步提高用户体验。
操作前提
本文的操作前提,是什么呢?首先是要有一台 Linux 服务器,比如:我就是使用腾讯云的轻量应用服务器。
其实也可以买 腾讯云的云服务器 (CVM) 选配更强大的 CPU ,处理 WebP 压缩速度更快。
但是,我测试了一下,我使用的腾讯云轻量应用服务器,CPU 模拟型号是 Intel® Xeon® Gold 6133 CPU @ 2.50GHz,处理本文的 WebP 并行任务非常足够。
软件方面,在腾讯云轻量应用服务器上,安装好 Git 和 Python:
# 安装 Gitapt update &&aptinstallgit -y
# 安装 Pythonaptinstall python3 python3-pip -y
与此同时,创建一个 Git 裸仓库,作为图床仓库:
# 创建一个裸仓库git init imageHost.git --bare
图片转 WebP
如何将图片转成 WebP 格式呢? 前文已经说到,使用 Pillow 库。
Pillow 库支持多种图片格式的转换,包括:
JPEG
、
PNG
、
GIF
、
BMP
、
TIFF
、
PPM
、
WebP
等。
按道理我们在腾讯云轻量应用服务器使用的是 Linux 镜像,是可以安装 Linux 的 imagemagick 库的。感兴趣的小伙伴可以尝试一下。
当然,其实你也可以使用存储桶的 WebP 转换功能,比如:腾讯云的 COS 存储桶。
其实我也有用过(大概 2021 年的时候?),改天有机会,给大家介绍一下。
Pillow 库
我们可以很方便地实现图片的 WebP 转换:
from PIL import Image
defsave_as_webp(image_target, target_path):"""
将图像保存为 WebP 格式,并进行优化设置.
Args:
image_target (PIL.Image.Image): 待保存的图像对象.
target_path (str): 保存图像的目标路径.
"""# 保存图像文件为 WebP 格式# quality: 图像质量,范围0-100,越高质量越好,但文件越大# optimize: 启用无损优化,减小文件大小# lossless: 启用无损压缩,保证图像质量# method: 压缩方法,取值0-6,越大压缩比越大,但质量略有下降# save_all: 保存动画的所有帧# progressive: 启用渐进式显示
image_target.save(target_path,'webp', quality=80, optimize=True, lossless=False, method=6,
save_all=True,
progressive=True)if __name__ =="__main__":# 假设图像对象为 image_obj
image_obj = Image.open("path/to/image.jpg")# 定义保存路径
target_path ="path/to/save/image.webp"# 保存为 WebP 格式
save_as_webp(image_obj, target_path)
添加水印
Pillow 库同样支持添加水印,只需要把水印图片“贴”到目标图片上即可:
from PIL import Image, ImageDraw, ImageFont
defadd_watermark(input_path, watermark_path, output_path):"""
在图像上添加水印.
Args:
input_path (str): 原始图像的路径.
watermark_path (str): 水印图像的路径.
output_path (str): 添加水印后的图像保存路径.
"""# 打开原始图像
image = Image.open(input_path)# 打开水印图像
watermark = Image.open(watermark_path)# 获取原始图像和水印图像的尺寸
image_width, image_height = image.size
watermark_width, watermark_height = watermark.size
# 计算水印的位置,置于右下角
x = image_width - watermark_width -20
y = image_height - watermark_height -20# 将水印图像叠加到原始图像上
image.paste(watermark,(x, y), watermark)# 保存结果图像
image.save(output_path)# 示例用法
add_watermark("path/to/image.jpg","path/to/watermark.png","path/to/output.jpg")
一般,水印的位置在图片的下方,并且水印需要设置透明度,在图片的尺寸过小时候,取消水印:
with Image.open(input_path)as image:
original_size = os.path.getsize(input_path)# 计算水印的放置位置以底部居中
bg_width, bg_height = image.size
wm_width, wm_height = wm_img.size
position =((bg_width - wm_width)//2, bg_height - wm_height -30)# 底部居中坐标# 创建一个新的透明图层用于合并,以防背景颜色受影响
image_target = Image.new('RGBA', image.size,(255,255,255,0))# 完全透明图层
image_target.paste(image,(0,0))# 将背景图片粘贴到透明图层上# 粘贴水印到新图层的底部中心位置,透明度已由水印图片自身定义,无需额外调整if bg_width >512*1.5and watermark_mode:
image_target.paste(wm_img, position, mask=wm_img.split()[3])# 使用alpha通道作为遮罩确保透明度正确
最终的流程就是:
#mermaid-svg-IlwmP2dgVoPTE5M3 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-IlwmP2dgVoPTE5M3 .error-icon{fill:#552222;}#mermaid-svg-IlwmP2dgVoPTE5M3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IlwmP2dgVoPTE5M3 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-IlwmP2dgVoPTE5M3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IlwmP2dgVoPTE5M3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IlwmP2dgVoPTE5M3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IlwmP2dgVoPTE5M3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IlwmP2dgVoPTE5M3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IlwmP2dgVoPTE5M3 .marker.cross{stroke:#333333;}#mermaid-svg-IlwmP2dgVoPTE5M3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IlwmP2dgVoPTE5M3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IlwmP2dgVoPTE5M3 .cluster-label text{fill:#333;}#mermaid-svg-IlwmP2dgVoPTE5M3 .cluster-label span{color:#333;}#mermaid-svg-IlwmP2dgVoPTE5M3 .label text,#mermaid-svg-IlwmP2dgVoPTE5M3 span{fill:#333;color:#333;}#mermaid-svg-IlwmP2dgVoPTE5M3 .node rect,#mermaid-svg-IlwmP2dgVoPTE5M3 .node circle,#mermaid-svg-IlwmP2dgVoPTE5M3 .node ellipse,#mermaid-svg-IlwmP2dgVoPTE5M3 .node polygon,#mermaid-svg-IlwmP2dgVoPTE5M3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IlwmP2dgVoPTE5M3 .node .label{text-align:center;}#mermaid-svg-IlwmP2dgVoPTE5M3 .node.clickable{cursor:pointer;}#mermaid-svg-IlwmP2dgVoPTE5M3 .arrowheadPath{fill:#333333;}#mermaid-svg-IlwmP2dgVoPTE5M3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IlwmP2dgVoPTE5M3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IlwmP2dgVoPTE5M3 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-IlwmP2dgVoPTE5M3 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-IlwmP2dgVoPTE5M3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IlwmP2dgVoPTE5M3 .cluster text{fill:#333;}#mermaid-svg-IlwmP2dgVoPTE5M3 .cluster span{color:#333;}#mermaid-svg-IlwmP2dgVoPTE5M3 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IlwmP2dgVoPTE5M3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
是
否
开始
读取原始图像
图像尺寸 >= 512 * 1.5?
添加水印
跳过添加水印
保存为WebP格式
结束
文章内的图片,就是这样转换的。
Git 差异化文件
Git 作为版本控制工具,可以很方便地实现差异化文件检录,可能平时大家用习惯了 JetBrains、GitHub Desktop 等工具,但是,Git 的命令行强大到可怕。
我们如果要实现两个 commit 的差异化文件,只需要使用
git diff
命令即可:
# 比较两个 commit 的差异gitdiff<commit-id><commit-id>
比如:比较 Hash 值为
6abbb89127c806928666b12374dfa013ef95f8b8
和 Hash 值为
5fe2590034f4922c427ab74bf948af46c2627d99
的两个 commit 的差异:
是不是有点抽象? 这里我们可以使用类似的命令
git difftree
并追加一下参数:
--no-commit-id
:输出的差异信息中不包含提交 ID;--name-status
:仅显示文件名和状态(如添加、修改、删除等),而不显示具体的差异内容;-r
:递归地比较两个树中的所有子树。
这样的结果就豁然开朗了:
这个时候,如果两次 commit 存在差异,那么可能的输出结果就是:
# 修改文件
M modified_file.png
# 添加文件
A new_file.png
# 删除文件
D deleted_file.jpg
# 重命名文件、移动文件
R old_name.png new_name.pg
发现了什么?🤔 没错,我们在 shell 内,可以使用标准化输出的方式,格式化参数文件。
hook 实现
现在,我们看看如何使用 hook 实现自动化部署。首先是工作分区的重定向和参数的定义:
# 定义图片文件后缀(需要转换为 WebP 格式的文件后缀)image_extensions=(".png"".jpg"".jpeg"".PNG")# 网站目标目录WEB_DIR="/www/webRoot/imagehost.mintimate.cn"# 工作空间临时检录目录WORK_SPACE_DIR="/home/git/mySpace/imagehost.mintimate.cn"# 定义需要跳过的文件前缀skip_prefixes=("emoticon""emoji")# Python Fle PathPYTHON_MAIN="/home/git/PythonTool"# 检录工作空间到目标目录git --work-tree=$WORK_SPACE_DIR --git-dir=/home/git/mySource/imageHost.git checkout -f
因为,我们提交内容的时候,难免会提交一些无关紧要的文件,比如:表情包、emoji 等,所以,我们需要过滤掉这些文件,并定义需要转换的文件后缀以及需要跳过的文件前缀,配合函数完成逻辑判断:
# 定义一个函数,用于检查文件路径是否以需要跳过的前缀开头check_skip_prefix(){localfilepath=$1forprefixin"${skip_prefixes[@]}";doif[["$filepath"=="$prefix"* ]];thenreturn0# 返回 0 表示匹配到了需要跳过的前缀fidonereturn1# 返回 1 表示没有匹配到需要跳过的前缀}# 定义一个函数,用于检查文件是否为图片is_image_file(){localfilepath=$1forextin"${image_extensions[@]}";doif[["$filepath"== *"$ext"]];thenreturn0# 返回 0 表示是图片文件fidonereturn1# 返回 1 表示不是图片文件}
定义日志输出目录:
# 定义输出目录OUTPUT_DIR="/home/git/runLog"# 确保输出目录存在mkdir -p $OUTPUT_DIR# 获取当前日期和时间,格式为 YYYYMMDD-HHMMSSNOW=$(date +"%Y%m%d-%H%M%S")# 定义输出文件,包含时间戳OUTPUT_FILE="${OUTPUT_DIR}/${NOW}_Change.log"
之后,标准化我们上文使用
git difftree
命令的输出:
# 读取标准输入(oldrev newrev refname)whileread oldrev newrev refname
do# 获取变更的文件列表echo"Changes in $refname:">>$OUTPUT_FILE# 使用 git diff-tree 来查看变更git diff-tree --no-commit-id --name-status -r $oldrev$newrev|whileread status_flag file1 file2
docase$status_flagin
M|A)echo"Modify: $file1">>$OUTPUT_FILE;;
D)echo"Delete: $file1">>$OUTPUT_FILE;;
R)echo"MV $file1 To $file2">>$OUTPUT_FILE;;esacdonedone
最后,对文件进行二次读取,判断是否需要使用 Python 脚本进行转换:
# 使用 case 语句处理不同的操作whileread line;docase$linein
Modify*)filepath=$(echo $line |awk'{print $2}')
process_file "$filepath" modify
;;
Delete*)filepath=$(echo $line |awk'{print $2}')rm -f "$WEB_DIR/$filepath"rm -f "$WEB_DIR/${filepath%.*}.webp";;
MV*)src=$(echo $line |awk'{print $2}')dst=$(echo $line |awk'{print $3}')rm -f "$WEB_DIR/$src"rm -f "$WEB_DIR/${src%.*}.webp"
process_file "$dst" move
;;esacdone<$OUTPUT_FILE
当然,
process_file
函数的实现就比较简单了,直接调用 Python 脚本即可:
# 使用 Python WebP解析脚本process_file(){localfilepath=$1localaction=$2# 判断是否存在上级目标目录mkdir -p "$(dirname"$WEB_DIR/$filepath")"# 检查文件路径是否以需要跳过的前缀开头
check_skip_prefix "$filepath"if[$? -eq 0];thencp"$WORK_SPACE_DIR/$filepath""$WEB_DIR/$filepath"returnfi# 检查文件是否为图片
is_image_file "$filepath"if[$? -eq 0];then# 执行 python 脚本nohup$PYTHON_MAIN/bin/python $PYTHON_MAIN/image2WebpForGit.py -w -s "$WORK_SPACE_DIR/$filepath" -t "$WEB_DIR/${filepath%.*}.webp">>$OUTPUT_FILE_PY2>&1&else# 如果不是图片,执行 cp 命令cp"$WORK_SPACE_DIR/$filepath""$WEB_DIR/$filepath"fi}
需要注意,这里我预留了
action
参数,但是我没有使用。
最终效果
最后,我们来看看效果,经过 commit 和 push 操作推送到我们自己的 Git 仓库之后,进而存储到腾讯云轻量应用服务器 Linux 的硬盘存储内,可以查看日志:
与此同时,我们也可以在
web
目录下查看转换后的图片:
看看转换后的图片和原始图片的大小对比:
同时,本篇文章内的图片,也是使用上述方法转换的,
对于性能的消耗,也是微乎其微的,我们可以在腾讯云轻量应用服务器的后台,看到性能监控曲线:
END
好啦,本篇文章就到这里,感谢阅读。之后的步骤,就看每个人的想法了。比如我就是使用 Nginx 作为反向代理,将转换后的图片直接返回给用户,这样就可以减少服务器的负担了。
有时候也会套一层 CDN,这样就可以加速图片的访问了。
相关代码已经开源,可以访问 https://github.com/Mintimate/GitHookPng2WebP 查看。
最后,制作教程不易,寻找教程也不易,找到志同道合的小伙伴更是知音难觅。如果你对云服务器、CDN、云数据库和Linux等云计算感兴趣,亦或者喜欢编程、设计、产品、运营等领域,欢迎加入我们的开发者爱好群,一起交流学习: 812198734 (目前可能就我一个人?毕竟才刚刚创建 ~)。
版权归原作者 Mintimate 所有, 如有侵权,请联系我们删除。