WWW.YOUINFO.SITE
标签聚合 磁盘

/tag/磁盘

LinuxDo 最新话题 · 2026-06-11 17:33:51+08:00 · tech

NewAPI 的日志目前是单表存储,已经看到太多佬友因为日志撑爆磁盘了,下面给出一种解决方式,可能不完全兼容,但是个人测试下来没有什么问题 与 NewAPI 版本无关,基本所有版本都可以用,我用的版本是 1.0.0-rc.10 自带的日志删除 最常用的是使用 NewAPI 自带的 “清理历史日志” 来进行删除 // 代码逻辑如下 // 直接按照时间戳删除 LOG_DB.Where("created_at < ?", targetTimestamp).Limit(limit).Delete(&Log{}) 这里有两个问题: Delete 的效率不高,或者说在数据量过大的情况下使用 Delete 带来的 IO 可能成为灾难 Delete 之后磁盘空间并不会回收,需要手动回收 通过数据库分片解决日志删除 适用于 MySQL,如果您是其他的 DB 如 Postgres / SQLite,将下面的内容提供给 AI 相信也会有对应的解决方案 分片的核心逻辑是,将日志拆分到对应的日期上,比如分片 logs_20260601 只存储当天的数据,在超出需要删除的日期后,比如 1 个月后的 2026/07/01,直接删除 logs_20260601 分片,分片占用的空间会立刻释放,对应的日志数据也会直接删除 不过这里要提示您,所有的 DB 变更都可能引入风险,请您在执行前通过 mysqldump 或者类似工具,导出完整的数据结构和数据内容,确保执行出现异常可以随时回滚 执行下面的步骤前,建议停机,否则可能导致数据不完整 ,如果数据完整性不在考虑范围内,也可以在线更新 Step 1 检查数据符合预期 (Read) 执行下面的查询语句,确保 count 为 0,即所有的日志的创建时间不为空 SELECT COUNT(*) AS null_created_at_count FROM logs WHERE created_at IS NULL; Step 2 创建临时表 (Write) CREATE TABLE logs_new LIKE logs; Step 3 添加准备分区语句 (Read) 通过下面的 SQL,可以获得一个建表 SQL,对 DB 无任何副作用,可以放心执行 下面的 @start_date 和 @end_date 两行,可以按照您的实际数据存储情况调整,下面的配置为创建 180 天前到 7 天后的分区,如果您的日志已经回收或删除过了,可以考虑缩减分区数量 SET time_zone = '+08:00'; 这里可以按照您的需求调整为具体的时区 分区必须提前创建,否则插入数据会有问题 ,所以您至少需要创建 7 天后的备用 SET SESSION group_concat_max_len = 1024 * 1024; SET time_zone = '+08:00'; SET @start_date = DATE_SUB(CURDATE(), INTERVAL 180 DAY); SET @end_date = DATE_ADD(CURDATE(), INTERVAL 7 DAY); WITH RECURSIVE dates AS ( SELECT @start_date AS d UNION ALL SELECT DATE_ADD(d, INTERVAL 1 DAY) FROM dates WHERE d < @end_date ) SELECT GROUP_CONCAT( CONCAT( ' PARTITION p', DATE_FORMAT(d, '%Y%m%d'), ' VALUES LESS THAN (', UNIX_TIMESTAMP(DATE_ADD(d, INTERVAL 1 DAY)), ')' ) ORDER BY d SEPARATOR ',\n' ) INTO @parts FROM dates; SET @sql = CONCAT( 'ALTER TABLE logs_new MODIFY `created_at` bigint NOT NULL, DROP PRIMARY KEY, DROP INDEX `idx_created_at_id`, ADD PRIMARY KEY (`id`, `created_at`) PARTITION BY RANGE (`created_at`) ( ', @parts, ', PARTITION pmax VALUES LESS THAN MAXVALUE )' ); SELECT @sql; Step 4 执行分区语句 (Write) 执行上一步输出的 SQL,会将新的 logs_new 表调整为分区表 Step 5 导入旧的数据 (Write) 取决于您的数据量,这一步可能会花费一些时间 INSERT INTO logs_new SELECT * FROM logs; Step 6 校验数据已经导入完成 (Read) 如果您是停机更新,确保两条 SQL 输出的内容是一致的 如果您是在线更新,确保数据接近或一致 SELECT "logs" as `table`, COUNT(*), MIN(created_at), MAX(created_at) FROM logs UNION SELECT "logs_new" as `table`, COUNT(*), MIN(created_at), MAX(created_at) FROM logs_new; Step 7 确认分区 (Read) 下面的 SQL 会打印新表的所有分区,以及每个分区的数据量 SELECT PARTITION_NAME, PARTITION_DESCRIPTION, TABLE_ROWS FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'logs_new' ORDER BY PARTITION_ORDINAL_POSITION; Step 8 切表 (Write) 切换流量到新表,执行完成后请检查 NewAPI 各组件各页面是否能正常工作,特别是依赖日志的内容 RENAME TABLE logs TO logs_old, logs_new TO logs; Step 9 创建自动回收创建/分区任务 (Write) MySQL 不会自动创建或者删除分区,需要您创建定时任务来实现,下面会给出创建/删除分区的任务,您可以按需添加 Step 9.1 开启 MySQL Event Scheduler 在数据库中执行下面的命令,通常需要 root 用户,无需重启 SET GLOBAL event_scheduler = ON; SHOW VARIABLES LIKE 'event_scheduler'; 在配置文件的 mysqld 章节,增加下面的配置,无需重启 这一步是为了保证,即使后面重启数据库,Event Scheduler 仍然会是开启状态 [mysqld] event_scheduler=ON Step 9.2 创建新建分区任务 下面的两个 SQL 都需要执行 第一个 SQL 中的 SET time_zone = '+08:00'; 可按需修改为您的时区 第二个 SQL 中的时间您可以修改为适用于您的服务的时间,目前设置的是每天的 02:00,用于控制定时触发的时机 DELIMITER $$ DROP PROCEDURE IF EXISTS sp_logs_create_future_partitions$$ CREATE PROCEDURE sp_logs_create_future_partitions() BEGIN DECLARE v_i INT DEFAULT 0; DECLARE v_d DATE; DECLARE v_partition_name VARCHAR(32); DECLARE v_less_than BIGINT; DECLARE v_exists INT DEFAULT 0; DECLARE v_sql TEXT; SET time_zone = '+08:00'; WHILE v_i <= 7 DO SET v_d = DATE_ADD(CURDATE(), INTERVAL v_i DAY); SET v_partition_name = CONCAT('p', DATE_FORMAT(v_d, '%Y%m%d')); SET v_less_than = UNIX_TIMESTAMP(DATE_ADD(v_d, INTERVAL 1 DAY)); SELECT COUNT(*) INTO v_exists FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'logs' AND PARTITION_NAME = v_partition_name; IF v_exists = 0 THEN SET v_sql = CONCAT( 'ALTER TABLE logs REORGANIZE PARTITION pmax INTO (', 'PARTITION ', v_partition_name, ' VALUES LESS THAN (', v_less_than, '), ', 'PARTITION pmax VALUES LESS THAN MAXVALUE', ')' ); SET @sql = v_sql; PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; SET v_i = v_i + 1; END WHILE; END$$ DELIMITER ; DROP EVENT IF EXISTS ev_logs_create_future_partitions; CREATE EVENT ev_logs_create_future_partitions ON SCHEDULE EVERY 1 DAY STARTS TIMESTAMP(CURRENT_DATE, '02:00:00') DO CALL sp_logs_create_future_partitions(); Step 9.3 创建删除分区任务 (可选) 这个是用于替代 NewAPI 自带的删除数据任务,如果您有需要可以配置这里的自动删除 第一个 SQL 中的 INTERVAL 180 DAY 表示删除 180 天之前的数据,可以按需修改, SET time_zone = '+08:00'; 也可按需修改为您的时区 第二个 SQL 中的时间您可以修改为适用于您的服务的时间,目前设置的是每天的 03:00,用于控制定时触发的时机 DELIMITER $$ DROP PROCEDURE IF EXISTS sp_logs_drop_old_partitions$$ CREATE PROCEDURE sp_logs_drop_old_partitions() BEGIN DECLARE v_cutoff_date DATE; DECLARE v_cutoff_ts BIGINT; DECLARE v_drop_partitions TEXT; DECLARE v_sql TEXT; SET time_zone = '+08:00'; SET v_cutoff_date = DATE_SUB(CURDATE(), INTERVAL 180 DAY); SET v_cutoff_ts = UNIX_TIMESTAMP(v_cutoff_date); SELECT GROUP_CONCAT(PARTITION_NAME ORDER BY PARTITION_ORDINAL_POSITION) INTO v_drop_partitions FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'logs' AND PARTITION_NAME REGEXP '^p[0-9]{8}$' AND CAST(PARTITION_DESCRIPTION AS UNSIGNED) <= v_cutoff_ts; IF v_drop_partitions IS NOT NULL AND v_drop_partitions <> '' THEN SET v_sql = CONCAT( 'ALTER TABLE logs DROP PARTITION ', v_drop_partitions ); SET @sql = v_sql; PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; END IF; END$$ DELIMITER ; DROP EVENT IF EXISTS ev_logs_drop_old_partitions; CREATE EVENT ev_logs_drop_old_partitions ON SCHEDULE EVERY 1 DAY STARTS TIMESTAMP(CURRENT_DATE, '00:10:00') DO CALL sp_logs_drop_old_partitions(); Step 9.4 检查任务 show events; SHOW PROCEDURE STATUS WHERE Db = DATABASE(); Step 10 大功告成 一切已准备就绪,请使用吧!数据库将按照您的配置自动创建新的分片,回收旧的分片,后续如果有调整,也可以直接修改 SQL 配置再次执行。 您可以定期通过下面的 SQL 来检查分区任务的运行状态和分区的数据量,请检查 pmax 分区数据量为 0,且已经创建了 7 天后的分区 SELECT PARTITION_NAME, PARTITION_DESCRIPTION, TABLE_ROWS FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'logs' ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 15; 1 个帖子 - 1 位参与者 阅读完整话题

v2ex · 2026-06-04 21:36:11+08:00 · tech

大家好。我做了一个 macOS 原生的磁盘分析 + 清理工具 Diskly ,今天发了 1.5.0,顺便来 V2 说几句。 为什么又造一个轮子 DaisyDisk / GrandPerspective 都用过。两件事我一直介意: 数字会骗人 。iCloud / OneDrive 里没下载的占位文件,系统会按"逻辑大小"算几十 GB——但你删掉根本腾不出空间。macOS 的 firmlink ( /Users 实际上是 /System/Volumes/Data/Users 的另一条路径)和硬链接会让同一份数据被算两遍—— 我的 2 TB 盘曾经被某工具扫出 6.46 TB 。 看清和动手是两件事 。可视化做完,清理这步要么没有,要么直接把你引去一堆"建议",一键删完你都不知道删了啥。 所以 Diskly 的几个产品决策都围绕这两点。 几件我较真的事 1. 数字必须诚实 全程按 本地实际占用 ( totalFileAllocatedSize )算,云占位文件计 0 。 firmlink + 硬链接按 (st_dev, st_ino) 整数键去重, 目录全去重 / 文件仅当 linkCount > 1 时去重 (常态零开销)。 实测扫 / :6.46 TB → 1.62 TB,与 df 报告基本一致(剩下的差额是 APFS clone 的固有现象,不假装修)。 2. 多入口起步,扫过的目录秒回 新建扫描页一屏装五种入口:拖拽 / ⌘O / 菜单 / Finder 服务 / 快速访问 + 最近扫描。 顶部的「 Pick up where you left off 」是 1.4.x 加的—— 扫过的结果还在内存里时,点一下秒回 (无需重扫);多份结果按内存预算淘汰,当前这份永不淘汰。 3. 等待也该有信息 扫几百万文件需要时间,但 进度条不该是空白的 。 1.5.0 里把扫描中页的下半区改了:加了一张 实时构成图 ——按已识别字节的分类铺一张 mini 矩形树图,跟扫描结束后的总览同款配色。等待时已经能看到"占大头的是啥类型",体验连续。 实现细节:复用 Treemap.layout 的 squarified 算法,9 个分类桶合成成一棵浅层 FileNode 树喂进去布局。每帧重建 9 节点 + 一次 squarify,O(9) 极快不会成为热点。 4. 清理是有分寸的 清理建议分两轨: 安全可删 / 建议检查 。默认只勾安全的。 安全档 :DerivedData 、 ~/Library/Caches 、SwiftPM .build 、Xcode iOS DeviceSupport 、CoreSimulator 缓存——可自动重建。 检查档 :node_modules 、长期未用应用、Docker 镜像——需要你自己判断。 差异化的几个点: node_modules 用 .git/logs/HEAD 修改时间判断仓库活跃度, < 90 天自动排除 (不调 git 子进程,避免触发 CLT 安装弹窗)。 应用最近使用走 Spotlight kMDItemLastUsedDate , 取不到不猜 (诚实降级,不编"很久没打开了")。 全部 移到废纸篓 ,30 天内可恢复。 并且每条建议都能 展开看实际要删的文件清单 ,删前可以逐条核对、单独取消: 5. 克制,且只属于你 菜单栏只占一个图标 + 一个百分比,点开才展开。 零遥测 。不弹广告、不催升级、不收集任何数据。 经 Apple 公证、官网直接分发。 1.5.0 干了啥 这一版改动比较大,主要是性能 + UX 修复。挑几个有意思的说: 树图悬停帧率 。之前 Canvas 同时画结构和高亮,鼠标每动一像素整张树图重绘 + 每个标签跑二分测量。拆成「结构层 + 高亮层」两层 Canvas, .equatable() 让 SwiftUI 在悬停时跳过结构层重渲染;标签宽度在 rebuild 时一次性 NSAttributedString.size() 二分截断好,绘制零度量。 下钻 /Applications 不再等几十秒 。Spotlight 元数据查询从串行改 DispatchQueue.concurrentPerform 并发 + URL-keyed 会话缓存。200~500 个 app × 30~80ms 串行 = 6~40s,改并发后摊到核数,体感明显。 内存底座 −150 MB 。 FileNode.id 从 UUID() 改 ObjectIdentifier(self) ——900 万节点 × 16 字节 UUID 是纯开销,ObjectIdentifier 是 class 自带的零开销 identity,Identifiable 协议照样满足。 ETA 终于准了 。旧算法用瞬时速率 EMA × 剩余字节,早期抖动剧烈、末期对小波动极敏感。改成「 已用时间外推 」: elapsed × (1 - fraction) / fraction ,稳得多。同时单调钳制下降即时反映、上升每帧最多 +5s,避免视觉抖动;前 3 秒不显示(预热),整理阶段不显示。 ETA 文案 i18n 修复 。 Formatting.duration 之前硬编码"秒/分/小时",英文模式下泄漏"2 分 48 秒"。改用 DateComponentsFormatter ,按 locale 自动出"2m 48s"/"2 分 48 秒"。 菜单栏「偏好设置…」真能打开了 。之前点了没反应—— NSApp.sendAction(Selector(("showSettingsWindow:"))) 在 popover dismiss 同步链不可靠,SwiftUI Settings scene 的注入 target 找不到。新实现 DispatchQueue.main.async 让 popover 先彻底关闭,然后按 ⌘, 快捷键 递归找主菜单 item 直接 performActionForItem (等价于用户从 App 菜单点击)。 无默认邮件客户端兜底 。这是 V2 提醒我考虑的:只用网页 Gmail / Outlook 的用户点 mailto 会失败。 SupportContact.openOrCopy 先 NSWorkspace.open ,失败时复制邮箱到剪贴板 + 弹原生 alert;设置里每处邮箱旁加独立「复制」小按钮。 完整 changelog: https://diskly.app.mahui.me/changelog 怎么装 brew install --cask mahui/tap/diskly 或者官网 https://diskly.app.mahui.me 直接下 .dmg 。 Apple 公证 + 时间戳签名 ,Gatekeeper 直接放行,不用右键打开。要求 macOS 14 Sonoma+,Universal 二进制(Apple Silicon + Intel)。 价格 $9.99 一次买断,5 台设备激活。 14 天全功能试用 ,试用结束才需要付费。 V2 老司机如果想体验完整版, 私信我邮箱给一把激活码 (几把够 V2er 用没问题)。 反馈 邮件:[email protected] V2 私信 任何 bug / 改进建议都欢迎,我会回 —— 昨天发了 Pier (菜单栏看端口/进程的小工具),今天又来打扰,如有问题欢迎拍。 技术栈 :Swift + SwiftUI 原生,SPM 可执行文件(不是 Xcode 工程)。扫描器固定 worker 池 + 共享队列分治,实测扫 935 万文件的 / 大约 90s 左右,峰值内存 ~5 GB 。

v2ex · 2026-06-01 07:03:15+08:00 · tech

一直以来都好好的,这几天突然收到通知,提示「备份磁盘不可用,当 XXX 可用时再次尝试备份」。 先是一轮排查,发现貌似群晖上的硬盘空间不够了,遂清理。 但清理并确认空间足够后,发现直接启动备份任务报错。然后尝试把任务删除、把群晖上原来的备份文件删除、Mac 和群晖都重启过,死活都是不行,始终还是报这个错。 让 Opus 4.8 一通乱查,也没解决。现在有点懵逼,不知道如何继续下去。。。

v2ex · 2026-06-01 03:26:34+08:00 · tech

一直以来都好好的,这几天突然收到通知,提示「备份磁盘不可用,当 XXX 可用时再次尝试备份」。 先是一轮排查,发现貌似群晖上的硬盘空间不够了,遂清理。 但清理并确认空间足够后,发现直接启动备份任务报错。然后尝试把任务删除、把群晖上原来的备份文件删除、Mac 和群晖都重启过,死活都是不行,始终还是报这个错。 让 Opus 4.8 一通乱查,也没解决。现在有点懵逼,不知道如何继续下去。。。

v2ex · 2026-05-31 23:54:34+08:00 · tech

一直以来都好好的,这几天突然收到通知,提示「备份磁盘不可用,当 XXX 可用时再次尝试备份」。 先是一轮排查,发现貌似群晖上的硬盘空间不够了,遂清理。 但清理并确认空间足够后,发现直接启动备份任务报错。然后尝试把任务删除、把群晖上原来的备份文件删除、Mac 和群晖都重启过,死活都是不行,始终还是报这个错。 让 Opus 4.8 一通乱查,也没解决。现在有点懵逼,不知道如何继续下去。。。

LinuxDo 最新话题 · 2026-05-28 00:49:38+08:00 · tech

这是 macOS 的安全拦截机制。该提示通常是因为安装包未签名或被系统安全策略拦截(并非真正损坏)。 可通过以下 终端(Terminal)命令解除限制: DMG 磁盘映像里的文件是“只读(Read-only)”的,系统无法写入任何修改,所以命令会全部报错。 请严格按照以下步骤操作即可解决: 第一步:把软件拖到“应用程序” 打开 Codex++ 的 DMG 挂载盘窗口。 将其中的 Codex++.app 图标,拖拽到你 Mac 的 “应用程序 (Applications)”文件夹中。 拖拽完成后,推出(Eject) 那个 DMG 磁盘映像。 第二步:对本地应用重新执行命令 打开“终端”。 输入并执行以下命令(此时路径已变为你的本地硬盘,允许读写): sudo xattr -r -d com.apple.quarantine /Applications/Codex++.app 输入你的 Mac 开机密码并回车。 1 个帖子 - 1 位参与者 阅读完整话题

v2ex · 2026-05-26 11:59:33+08:00 · tech

更新到 macOS Tahoe 26.5 之后,系统设置中无法正确显示磁盘所用空间,System Data 一直卡在 Calculating ,访达中也无法正常显示已用空间。但是运行磁盘急救没有问题。 网络上的解决方案五花八门,有让重新登录 Apple ID 的,有开启 Apple Intelligence 之后就正常的,还有让抹除重装的。 个人怀疑与我之前强开了 Apple Intelligence ,但是更新到 26.5 之后强开手段失效导致的问题。 推荐强开了 Apple Intelligence 的朋友们先不要更新的 26.5 ,真要更新也先把 Apple Intelligence 关掉。