当前位置: 首页 > news >正文

hive 自动检测、自动重启、记录检测日志、自动清理日志

最终效果

  • 定时检测hive运行状态,进程不存在或者进程存在但是不监听端口的hiveserver2,自动重新拉起
  • 每次检测脚本执行的日志都会保存在log目录下.check文件,每一个月一个文件
  • 每月15日,删除2月前的检测日志
  • 开启hive自带日志输出后,日志不会删除,且较大,因此一并将过期的hive自带日志清空

https://blog.csdn.net/Brother_ning/article/details/127993943
从这个作者复制的,但是他的代码好像有点问题,修改后然后加以优化

定时检查脚本

vi $HIVE_HOME/hiveservice.sh

#!/bin/bashHIVE_LOG_DIR=$HIVE_HOME/log
CURRENT_TIME=$(date +"%Y-%m-%d %H:%M:%S")
# 日志清理,如果与hive默认日志命名风格一样,也会自动清理hive的日志
DT=$(date)
DT_2M=$(date -d "2 month ago")
CHECK_LOG=$HIVE_LOG_DIR/hive.log.$(date "+%Y-%m").check
CHECK_LOG_REG=$HIVE_LOG_DIR/hive.log.$(date -d "2 month ago" +"%Y-%m")-*
METASTORE_PORT=9083
HIVESERVER2_PORT=10000
# 最大连接数,超过这个数,则重启hive
MAX_WORKS=1800
if [ ! -d $HIVE_LOG_DIR ]
thenmkdir -p $HIVE_LOG_DIR
ficheck_process(){WORKS=$(netstat -anltp|grep $HIVESERVER2_PORT|wc -l)if [ "$WORKS" -gt $MAX_WORKS ]; thenecho "$CURRENT_TIME:链接数异常,重启hive" | tee -a $CHECK_LOGhive_stopsleep 5fipid=$(ps -ef 2>/dev/null | grep -v grep | grep -i $1 | awk '{print $2}')ppid=$(netstat -nltp 2>/dev/null | grep $2 | awk '{print $7}' | cut -d '/' -f 1)if [ -n "$pid" ] && [ -n "$ppid" ] && [ "$pid" = "$ppid" ]; thenecho $pidreturn 0 # 进程正在运行elsereturn 1 # 进程未运行fi
}hive_stop()
{metapid=$(check_process HiveMetastore $METASTORE_PORT)if [ -n "$metapid" ]; thenecho "$CURRENT_TIME:关闭Metastore进程" | tee -a $CHECK_LOG & kill -9 $metapidfiserver2pid=$(check_process HiveServer2 $HIVESERVER2_PORT)if [ -n "$server2pid" ]; thenecho "$CURRENT_TIME:关闭server2进程" | tee -a $CHECK_LOG & kill -9 $server2pidfi
}# wait方法不能随意使用,必须在启动执行后才能执行。
wait_start()
{local max_retries=100  # 设置最大重试次数 100次,重启时间200秒,如果200秒内没有启动成功,则认为启动失败。local retries=0       # 初始化重试计数器metapid=$(check_process HiveMetastore $METASTORE_PORT)server2pid=$(check_process HiveServer2 $HIVESERVER2_PORT)while { [ -z "$metapid" ] || [ -z "$server2pid" ]; } && [ $retries -lt $max_retries ]; dosleep 2echo "$(date +"%Y-%m-%d %H:%M:%S"):启动中($retries)。。。" | tee -a $CHECK_LOGmetapid=$(check_process HiveMetastore $METASTORE_PORT)server2pid=$(check_process HiveServer2 $HIVESERVER2_PORT)retries=$((retries + 1))done# 检查是否达到最大重试次数if [ $retries -ge $max_retries ]; thenecho "$CURRENT_TIME:达到最大重试次数,启动失败" | tee -a $CHECK_LOGexit 1  # 退出脚本,表示启动失败elseecho "$CURRENT_TIME:HIVE状态正常" | tee -a $CHECK_LOGfi
}kill_valid()
{PIDS=$(jps -m | grep $1 | awk '{print$1}')# 遍历所有PID并使用kill -9命令杀掉它们,防止hive挂掉,但是进程不退出for PID in $PIDS; dokill -9 $PIDecho "$CURRENT_TIME:kill无效的$1进程 $PID" | tee -a $CHECK_LOGsleep 3done
}hive_start()
{metapid=$(check_process HiveMetastore $METASTORE_PORT)if [ -z "$metapid" ]; thenkill_valid HiveMetaStoreecho "$CURRENT_TIME:Metastore启动中" | tee -a $CHECK_LOGnohup hive --service metastore 2>$HIVE_LOG_DIR/metastore.log 1>/dev/null &fiserver2pid=$(check_process HiveServer2 $HIVESERVER2_PORT)if [ -z "$server2pid" ]; thenkill_valid HiveServer2echo "$CURRENT_TIME:HiveServer2启动中" | tee -a $CHECK_LOGnohup hive --service hiveserver2 2>$HIVE_LOG_DIR/hiveServer2.log 1>/dev/null &fi
}status()
{metapid=$(check_process HiveMetastore $METASTORE_PORT)server2pid=$(check_process HiveServer2 $HIVESERVER2_PORT)if [ -n "$metapid" ] && [ -n "$server2pid" ]; thenecho "$CURRENT_TIME:HIVE状态正常" | tee -a $CHECK_LOGelseif [ -z "$metapid" ]; thenecho "$CURRENT_TIME:Metastore未运行" | tee -a $CHECK_LOGfiif [ -z "$server2pid" ]; thenecho "$CURRENT_TIME:HiveServer2未运行" | tee -a $CHECK_LOGfifi
}clean()
{echo "$CURRENT_TIME:清空日志 rm -rf $CHECK_LOG_REG" | tee -a $CHECK_LOGrm -rf $CHECK_LOG_REG
}case $1 in
"start")hive_startwait_start;;
"stop")hive_stopstatus;;
"restart")hive_stopsleep 3hive_startwait_start;;
"status")status;;
"clean")clean;;
*)echo Invalid Args!echo 'Usage: '$(basename $0)' start|stop|restart|status|clean';;
esac

定时调度

crontab -e
输入如下内容,注意修改环境变量,cron无法正常读取系统环境变量

#设置 HIVE_HOME 环境变量
HIVE_HOME=/data/soft/hive-3.1.2
# 每隔10分钟执行一次状态检测,有问题自动重启
*/10 * * * * sh $HIVE_HOME/hiveservice.sh start
# 每周天在0点01分执行一次 restart 任务
1 0 * * 0 sh $HIVE_HOME/hiveservice.sh restart >> $HIVE_HOME/log/cron.restart.log
# 每月15号清空2月前的hive日志
0 0 15 * * sh $HIVE_HOME/hiveservice.sh clean

crontab -l
检查crontab运行任务
tail -f /var/log/cron (centos)
cat /var/log/syslog (乌班图)

相关文章:

hive 自动检测、自动重启、记录检测日志、自动清理日志

最终效果 定时检测hive运行状态,进程不存在或者进程存在但是不监听端口的hiveserver2,自动重新拉起每次检测脚本执行的日志都会保存在log目录下.check文件,每一个月一个文件每月15日,删除2月前的检测日志开启hive自带日志输出后&…...

C++类和对象下详细指南

C类和对象下详细指南 1. 初始化列表与构造函数 1.1 初始化列表概述 初始化列表在C中用于初始化对象的成员变量,特别是当你需要在对象构造时就明确成员变量的值时。通过初始化列表,成员变量的初始化可以在进入构造函数体之前完成。这不仅可以提升性能&…...

【算法C++】构造回文字符串问题

问题描述 小C手中有一个由小写字母组成的字符串 s。她希望构造另一个字符串 t,并且这个字符串需要满足以下几个条件: t 由小写字母组成,且长度与 s 相同。t 是回文字符串,即从左到右与从右到左读取相同。t 的字典序要小于 s&…...

基于java线程池和EasyExcel实现数据异步导入

基于java线程池和EasyExcel实现数据异步导入 2.代码实现 2.1 controller层 PostMapping("import")public void importExcel(MultipartFile file) throws IOException {importService.importExcelAsync(file);}2.2 service层 Resource private SalariesListener sa…...

使用Layout三行布局(SemiDesign)

tips:Semi Design网址 :Semi Design 1、安装Semi # 使用 npm npm i douyinfe/semi-ui# 使用 yarn yarn add douyinfe/semi-ui# 使用 pnpm pnpm add douyinfe/semi-ui 2、引入Layout布局 import { Layout } from douyinfe/semi-ui;3、开始实现三行布局…...

缓存之美:万文详解 Caffeine 实现原理(下)

上篇文章:缓存之美:万文详解 Caffeine 实现原理(上) getIfPresent 现在我们对 put 方法有了基本了解,现在我们继续深入 getIfPresent 方法: public class TestReadSourceCode {Testpublic void doRead() …...

PHP防伪溯源一体化管理系统小程序

🔍 防伪溯源一体化管理系统,品质之光,根源之锁 🚀 引领防伪技术革命,重塑品牌信任基石 我们自豪地站在防伪技术的前沿,为您呈现基于ThinkPHP和Uniapp精心锻造的多平台(微信小程序、H5网页&…...

STM32——LCD

一、引脚配置 查看引脚 将上述引脚都设置为GPIO_Output 二、导入驱动文件 将 LCD 驱动的 Inc 以及 Src 中的 fonts.h,lcd.h 和 lcd.c 导入到自己工程的驱动文件中。 当然,后面 lcd 的驱动学习可以和 IMX6U 一块学。 三、LCD函数 void LCD_Clear(u16 Color); 功能…...

洛谷刷题1-3

比较巧妙,求最小公倍数,看多少个数一次循环,直接求解就好了,N的数量级比较大,一层循环也会超时,也用了点双指针的想法(归并排序) 这里很大的问题,主要是cin输入的时候遇到…...

Facebook 元宇宙与全球文化交流的新趋势

随着科技的快速发展,虚拟现实与增强现实技术逐渐成为全球社交平台的重要组成部分。Facebook(现改名为 Meta)率先将目光投向了元宇宙这一新兴领域,致力于打造一个超越传统社交媒体的虚拟空间,成为全球文化交流的新平台。…...

结构化布线系统分为六个子系统

文章目录 前言系统介绍1. 工作区子系统 (Work Area Subsystem)2. 水平布线子系统 (Horizontal Cabling Subsystem)3. 管理子系统 (Administration Subsystem)4. 干线(垂直)子系统 (Backbone Cabling Subsystem)5. 设备间子系统 (Equipment Room Subsyste…...

亿坊软件前端命名规范

在前端开发中,文件命名的重要性不言而喻。由于历史原因和个人习惯,不同的开发者在命名DOM结构、图片和CSS文件时,可能会产生不一致的情况。这不仅会导致维护成本增加,还会降低团队协作效率。因此,制定一套统一的命名规…...

单片机-STM32 IIC通信(OLED屏幕)(十一)

一、屏幕的分类 1、LED屏幕: 由无数个发光的LED灯珠按照一定的顺序排列而成,当需要显示内容的时候,点亮相关的LED灯即可,市场占有率很高,主要是用于户外,广告屏幕,成本低。 LED屏是一种用发光…...

【Qt】: QPointer详解

考古: 《Qt智能指针之QScopedPointer》 QPointer是Qt框架中的一个智能指针类,用于安全地管理QObject派生对象的指针。它的主要功能是自动将指针置为nullptr,当它所指向的QObject对象被销毁时。这在Qt应用程序中非常有用,因为QObj…...

15_业务系统基类

创建脚本 SystemRoot.cs 因为 业务系统基类的子类 会涉及资源加载服务层ResSvc.cs 和 音乐播放服务层AudioSvc.cs 所以在业务系统基类 提取引用资源加载服务层ResSvc.cs 和 音乐播放服务层AudioSvc.cs 并调用单例初始化 using UnityEngine; // 功能 : 业务系统基类 public c…...

C++中explicit关键字的介绍和使用详解

某一天突然发现Qt自动生成的类文件的构造函数前边都有explicit关键字,但是explicit关键字什么意思呐? 在C中,explicit是一个关键字,主要用于修饰构造函数或转换运算符,其作用是防止隐式类型转换或隐式构造行为。 下面…...

动态内存管理

本章重点 1.为什么存在动态内存分配 2.动态内存函数的介绍 3.malloc free calloc realloc 4.常见的动态内存错误 一.为什么存在动态内存分配 二.动态内存函数的介绍 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include &…...

Java 中的各种锁详解

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

进制之间转换

「 一、十进制 二进制 」 1.十进制转二进制&#xff1a;一直除以2直到商为0&#xff0c;再反向取余数。 例&#xff1a;13&#xff08;十进制&#xff09;转1101&#xff08;二进制&#xff09; 2.二进制转十进制:最后一位数开始是2^0&#xff0c;然后一直按照指数递增的方式…...

微信小程序获取位置服务

wx.getLocation({type: gcj02,success(res) {wx.log(定位成功);},fail(err) {wx.log(定位失败, err);wx.showModal({content: 请打开手机和小程序中的定位服务,success: (modRes) > {if (modRes.confirm) {wx.openSetting({success(setRes) {if (setRes.authSetting[scope.u…...

数据结构——实验八·学生管理系统

嗨~~欢迎来到Tubishu的博客&#x1f338;如果你也是一名在校大学生&#xff0c;正在寻找各种编程资源&#xff0c;那么你就来对地方啦&#x1f31f; Tubishu是一名计算机本科生&#xff0c;会不定期整理和分享学习中的优质资源&#xff0c;希望能为你的编程之路添砖加瓦⭐&…...

Linux应用编程(五)USB应用开发-libusb库

一、基础知识 1. USB接口是什么&#xff1f; USB接口&#xff08;Universal Serial Bus&#xff09;是一种通用串行总线&#xff0c;广泛使用的接口标准&#xff0c;主要用于连接计算机与外围设备&#xff08;如键盘、鼠标、打印机、存储设备等&#xff09;之间的数据传输和电…...

Swift语言探索:Sequence与Collection的详细解读

在Swift编程语言中&#xff0c;Sequence和Collection是两个非常重要的协议&#xff0c;它们定义了遍历和访问元素集合的方式。理解这两个协议不仅有助于我们更好地掌握Swift的集合类型&#xff0c;还能让我们在编写代码时更加灵活和高效。本文将详细解读Sequence与Collection&a…...

解锁C# EF/EF Core:从入门到进阶的技术飞跃

一、EF/EF Core 初相识 在.NET 开发的广阔天地中&#xff0c;Entity Framework (EF) 及其轻量级、可扩展、跨平台的版本 Entity Framework Core (EF Core)&#xff0c;犹如两颗璀璨的明星&#xff0c;照亮了数据访问层开发的道路。它们是开源的对象关系映射器&#xff08;ORM&…...

大模型搜广推?对算法工作的影响

大模型与传统应用结合的性质 长期看是一种范式革新。算力和模型定义的边界发生变化&#xff0c;选择生成式AI或大模型发展方向时&#xff0c;会不断发现新的增长曲线&#xff0c;目前在不断被验证。 现阶段大模型确实带来了增量信息&#xff0c;但推荐过程仍在原有流程基础上…...

【教程】最好的pytorch教程

文章目录 Materials for the Learn PyTorch for Deep Learning: Zero to Mastery course from: https://github.com/mrdbourke/pytorch-deep-learning/blob/main/01_pytorch_workflow.ipynb...

基于java线程池和EasyExcel实现异步导出

基于java线程池和EasyExcel实现异步导出 1.controller层 GetMapping("export") public void exportExcel(HttpServletResponse response) throws IOException, InterruptedException {exportService.exportExcel(response); }2. service public void exportExcel(H…...

vue3组件传值具体使用

问&#xff1a; left.vue文件调用接口获取了后端返回的urlLink字段&#xff0c;我该怎么传递给总的父组件index.vue中&#xff0c;我需要点击父组件的一个按钮来触发跳转&#xff1f; 回答&#xff1a; 在 Vue 3 中使用 TypeScript 和 setup 语法糖时&#xff0c;可以通过 e…...

《CPython Internals》阅读笔记:p336-p352

《CPython Internals》学习第 17天&#xff0c;p336-p352 总结&#xff0c;总计 17 页。 一、技术总结 1.GDB GDB 是 GNU Dbugger 的缩写。 (1)安装 sudo apt install gdb(2)创建 .gdbinit 文件 touch ~/.gdbinitvim ~/.gdbinit(3)配置 .gdbinit 文件 add-auto-load-saf…...

WPF基础 | WPF 常用控件实战:Button、TextBox 等的基础应用

WPF基础 | WPF 常用控件实战&#xff1a;Button、TextBox 等的基础应用 一、前言二、Button 控件基础2.1 Button 的基本定义与显示2.2 按钮样式设置2.3 按钮大小与布局 三、Button 的交互功能3.1 点击事件处理3.2 鼠标悬停与离开效果3.3 按钮禁用与启用 四、TextBox 控件基础4.…...

Langchain+讯飞星火大模型Spark Max调用

1、安装langchain #安装langchain环境 pip install langchain0.3.3 openai -i https://mirrors.aliyun.com/pypi/simple #灵积模型服务 pip install dashscope -i https://mirrors.aliyun.com/pypi/simple #安装第三方集成,就是各种大语言模型 pip install langchain-comm…...

2025年华为云一键快速部署幻兽帕鲁联机服务器教程

华为云如何快速部署幻兽帕鲁联机服务器&#xff1f;为了方便新手玩家搭建专属游戏联机服务器&#xff0c;华为云推出了云游戏专场&#xff0c;无需专业技术&#xff0c;新手小白也能一键快速部署幻兽帕鲁联机服务器&#xff01; 华为云快速部署幻兽帕鲁联机服务器教程如下&…...

Langchain+文心一言调用

import osfrom langchain_community.llms import QianfanLLMEndpointos.environ["QIANFAN_AK"] "" os.environ["QIANFAN_SK"] ""llm_wenxin QianfanLLMEndpoint()res llm_wenxin.invoke("中国国庆日是哪一天?") print(…...

C++AVL树(一)详解

文章目录 AVL树概念AVL树的插入平衡因子的更新旋转的规则左单旋右单旋抽象的情况h0h1h 2h 3 AVL树 概念 AVL树是一棵平衡二叉查找树&#xff0c;AVL树是空树&#xff0c;保证左右子树都是AVL树&#xff0c;AVL树要求高度差的绝对值不超过1&#xff0c;因为最好情况是1&#…...

ceph新增节点,OSD设备,标签管理(二)

一、访问客户端集群方式 方式一: 使用cephadm shell交互式配置 [rootceph141 ~]# cephadm shell # 注意&#xff0c;此命令会启动一个新的容器&#xff0c;运行玩后会退出&#xff01; Inferring fsid c153209c-d8a0-11ef-a0ed-bdb84668ed01 Inferring config /var/lib/ce…...

c++学习第七天

创作过程中难免有不足&#xff0c;若您发现本文内容有误&#xff0c;恳请不吝赐教。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考。 一、const成员函数 //Date.h#pragma once#include<iostream> using namespace std;class Date { public:Date…...

F/V/F/I频率脉冲信号转换器

F/V/F/I频率脉冲信号转换器 概述&#xff1a;捷晟达科技的JSD TFA-1001系列是一进一出频率脉冲信号转换器(F/V转换器),该频率转换器是将频率脉冲信号(方波、正弦波、锯齿波)转换成国际标准的模拟量电压(电流)信号,并远距离无失真传送到控制室(如:PLC,DCS,AD,PC采集系统)产品的输…...

SQLServer中DBCC INPUTBUFFER显示从客户端发送到 SQL Server 实例的最后一个语句

SQLServer中DBCC INPUTBUFFER显示从客户端发送到 SQL Server 实例的最后一个语句 1、本文内容 语法参数结果集权限示例 适用于&#xff1a; SQL ServerAzure SQL 数据库Azure SQL 托管实例 显示从客户端发送到 SQL Server 实例的最后一个语句。 2、语法 DBCC INPUTBUFFE…...

Mysql面试题----MySQL中CHAR和VARCHAR的区别

存储方式 CHAR&#xff1a;是一种固定长度的字符串类型。它会按照定义的长度来分配存储空间&#xff0c;无论实际存储的字符串长度是多少。例如&#xff0c;定义一个 CHAR (10) 的列&#xff0c;如果存储的值是 ‘ab’&#xff0c;那么它仍然会占用 10 个字符的存储空间&#…...

github汉化

本文主要讲述了github如何汉化的方法。 目录 问题描述汉化步骤1.打开github&#xff0c;搜索github-chinese2.打开项目&#xff0c;打开README.md3.下载安装脚本管理器3.1 在README.md中往下滑动&#xff0c;找到浏览器与脚本管理器3.2 选择浏览器对应的脚本管理器3.2.1 点击去…...

探索JavaScript前端开发:开启交互之门的神奇钥匙(二)

目录 引言 四、事件处理 4.1 事件类型 4.2 事件监听器 五、实战案例&#xff1a;打造简易待办事项列表 5.1 HTML 结构搭建 5.2 JavaScript 功能实现 六、进阶拓展&#xff1a;异步编程与 Ajax 6.1 异步编程概念 6.2 Ajax 原理与使用 七、前沿框架&#xff1a;Vue.js …...

什么是网络爬虫?Python爬虫到底怎么学?

最近我在研究 Python 网络爬虫&#xff0c;发现这玩意儿真是有趣&#xff0c;干脆和大家聊聊我的心得吧&#xff01;咱们都知道&#xff0c;网络上的信息多得就像大海里的水&#xff0c;而网络爬虫就像一个勤劳的小矿工&#xff0c;能帮我们从这片浩瀚的信息海洋中挖掘出需要的…...

React 中hooks之 React.memo 和 useMemo用法总结

1. React.memo 基础 React.memo 是一个高阶组件&#xff08;HOC&#xff09;&#xff0c;用于优化函数组件的性能&#xff0c;通过记忆组件渲染结果来避免不必要的重新渲染。 1.1 基本用法 const MemoizedComponent React.memo(function MyComponent(props) {/* 渲染逻辑 *…...

springboot基于微信小程序的手机银行系统

Spring Boot基于微信小程序的手机银行系统是一种结合现代Web技术和移动应用优势的创新金融服务平台。 一、系统背景与意义 随着信息技术的快速发展和用户对便捷金融服务需求的日益增长&#xff0c;传统手机银行系统的人工管理方法已逐渐显露出效率低下、安全性低以及信息传输…...

Kafka后台启动命令

#保存日志 nohup ./kafka-server-start.sh ../config/server.properties > /path/to/logfile.log 2>&1 &#不保存日志 nohup ./kafka-server-start.sh ../config/server.properties >/dev/null 2>&1 & nohup: 是一个Unix/Linux命令&#xff0c;用于…...

面试题目1

文章目录 C语言函数调用详细过程C语言中const与C中const的区别关系运算符有哪些互斥锁与读写锁的区别gcc的编译过程 C语言函数调用详细过程 调用函数&#xff1a;当程序执行到函数调用语句时&#xff0c;会将当前函数的返回地址、参数列表等信息压入栈中&#xff0c;然后跳转到…...

Android AutoMotive --CarService

1、AAOS概述 Android AutoMotive OS是谷歌针对车机使用场景打造的操作系统&#xff0c;它是基于现有Android系统的基础上增加了新特性&#xff0c;最主要的就是增加了CarService&#xff08;汽车服务&#xff09;模块。我们很容易把Android AutoMotive和Android Auto搞混&…...

CSDN 博客之星 2024:默语的技术进阶与社区耕耘之旅

CSDN 博客之星 2024&#xff1a;默语的技术进阶与社区耕耘之旅 &#x1f31f; 默语&#xff0c;是一位在技术分享与社区建设中坚持深耕的博客作者。今年&#xff0c;我有幸再次入围成为 CSDN 博客之星TOP300 的一员&#xff0c;这既是对过往努力的肯定&#xff0c;也是对未来探…...

【Vim Masterclass 笔记24】S10L43 + L44:同步练习10 —— 基于 Vim 缓冲区的各类基础操作练习(含点评课)

文章目录 S10L43 Exercise 12 - Vim Buffers1 训练目标2 操作指令2.1. 打开 buf* 文件2.2. 查看缓冲区 View the buffers2.3. 切换缓冲区 Switch buffers2.4. 同时编辑多个缓冲区 Edit multiple buffers at once2.5. 缓冲区的增删操作 Add and delete buffers2.6. 练习 Vim 内置…...

python如何使得pdf加水印后的大小尽可能小

在 Python 中为 PDF 添加水印并尽可能减少文件大小&#xff0c;可以采取以下优化策略&#xff1a; 1. 使用合适的库 常用的 PDF 处理库&#xff1a; PyMuPDF&#xff08;fitz&#xff09;&#xff1a;高效且优化的 PDF 处理reportlab pdfrw&#xff1a;可实现水印合并&#…...