npm cb() never called 别再瞎清缓存:先看 Node 和 npm 匹不匹配

老项目上手,npm install 直接崩: npm ERR! cb() never called!npm ERR! This is an error with npm itself. Please report this error at: npm ERR! <https://npm.community>网上一搜全是"清缓存、删 node_modules、换镜像"这种模板答案。真去清了,然后再跑就变成: ERROR: npm v11.17.0 is known not to run on Node.js v14.21.3. This version of npm supports the following node versions: `^20.17.0 || >=22.9.0`SyntaxError: Unexpected token '&&='这才是真面目——Node 版本和 npm 版本对不上。 症状识别 看到这两种就是版本冲突:cb() never called(npm 内部逻辑走到不该走的分支) SyntaxError: Unexpected token (npm 用了新语法,老 Node 不认识,比如 &&= 是 Node 15+ 才有的)不是包坏了、不是 registry 挂了、也不是缓存的锅。 Node 与 npm 的兼容表Node 版本 兼容的 npmNode 14 npm 6 ~ 8Node 16 npm 7 ~ 8Node 18 npm 9 ~ 10Node 20 npm 10 ~ 11Node 22 npm 10 ~ 11跨太多档就会互相不认。npm 11 明确要求 Node >= 20.17 或 >= 22.9。 正确修法 方案一:直接升 Node(推荐) 用 nvm: nvm install 22 nvm use 22 nvm alias default 22 node -v npm -vNode 22 + npm 10/11,是现在最省事的组合。 方案二:必须用老 Node,就降 npm 比如项目锁死 Node 14: npm install -g npm@6 # 或 npm install -g npm@8但注意——大部分现代依赖已经放弃了 Node 14,长远还是得升。 方案三:项目里锁定引擎(推荐) package.json 里加: { "engines": { "node": ">=20.17" } }结合 nvm use 和 .nvmrc: echo "22" > .nvmrc nvm use # 自动读 .nvmrc新人 clone 下来 nvm use 就切对了。 如果只是普通 cb() never called Node/npm 版本没问题,仍然报的情况下才走"缓存派"步骤: npm cache clean --force rm -rf node_modules package-lock.json npm install --legacy-peer-deps顺带换个镜像加速: npm config set registry https://registry.npmmirror.com一句话总结 看到 cb() never called 别急着删 node_modules,先 node -v && npm -v 对一下兼容表。绝大多数是 Node 版本跟不上 npm。

npm ERR! cb() never called 修复:npm 与 Node.js 版本不兼容的根因

npm ERR! cb() never called! 看起来像 npm 内部崩溃,但真正的根因通常是 npm 版本与当前 Node.js 版本不兼容。 最常见根因:版本不匹配 错误表现: ERROR: npm v11.17.0 is known not to run on Node.js v14.21.3. This version of npm supports the following node versions: `^20.17.0 || >=22.9.0`.SyntaxError: Unexpected token '&&=' at wrapSafe (internal/modules/cjs/loader.js:1029:16)npm 11 内部使用了 &&= 逻辑赋值运算符,这是 ES2021 特性,Node.js 14 不支持,导致 npm 自身启动时语法解析失败。 解决方案:切换 Node.js 版本 # 查看当前版本 node -v npm -v# 用 nvm 切换到兼容版本 nvm install 22 nvm use 22# 验证 node -v # v22.x.x npm -v # 10.x.x 或更高通用修复流程 如果版本兼容但仍然报错: 1. 升级 npm npm install -g npm@latest2. 清理缓存重装 npm cache clean --force rm -rf node_modules rm package-lock.json npm installmacOS 还可以删除整个 npm 缓存目录: rm -rf ~/.npm3. 切换国内镜像 国内网络拉包失败时: npm config set registry https://registry.npmmirror.com npm install4. 老项目依赖冲突 npm install --legacy-peer-depsnpm 与 Node.js 版本对照npm 版本 最低 Node.js 要求npm 11 Node.js 20.17 / 22.9+npm 10 Node.js 18+npm 9 Node.js 14.17+npm 8 Node.js 12+用 nvm 安装 LTS 版本可以拿到对应版本的 npm: nvm install --lts nvm use --lts

cp 报错 cannot overwrite non-directory:目录被同名文件占位

某次要把 pojie/ 目录复制进 wpa-dictionary/ 里,cp 一直报错: $ cp -r pojie/ wpa-dictionary/pojie cp: cannot overwrite non-directory 'wpa-dictionary/pojie' with directory 'pojie/'$ cp -r pojie wpa-dictionary/ cp: cannot overwrite non-directory 'wpa-dictionary/pojie' with directory 'pojie'$ cp -f pojie wpa-dictionary/ cp: -r not specified; omitting directory 'pojie'问题原因 这个报错不是 cp 参数写错了,而是 目标路径 wpa-dictionary/pojie 已经存在一个普通文件,cp 不允许用目录去覆盖一个非目录。 先用 ls -l 确认: $ ls -l wpa-dictionary/pojie -rw-r--r-- 1 root root 1234 Jun 15 10:00 wpa-dictionary/pojie看到开头是 - 说明它是普通文件。而你想执行的 cp -r pojie wpa-dictionary/ 实际上等于 cp -r pojie wpa-dictionary/pojie——目标名字已经被文件占了。 三种处理方式 方案一:删除同名文件 如果目标位置那个文件本来就没用,直接删掉再复制: rm -f wpa-dictionary/pojie cp -r pojie wpa-dictionary/方案二:换个目标名 不想删旧文件的话,改个新名字: cp -r pojie wpa-dictionary/pojie_new方案三:先看清目录结构 用 tree 看一眼当前目录状态,避免以后再踩: tree -L 2 .或者两条 ls -ld 直接对比属性: ls -ld pojie ls -ld wpa-dictionary/pojie看到一个是 d 开头(目录)、一个是 - 开头(文件),就知道冲突在哪里了。 一句话总结 cp: cannot overwrite non-directory = 目标位置已被同名普通文件占位。要么删掉旧文件,要么换个目标名。

Linux cp 报错 cannot overwrite non-directory with directory:原因和解决方法

cp -r pojie/ wpa-dictionary/pojie # cp: cannot overwrite non-directory 'wpa-dictionary/pojie' with directory 'pojie/'这个错误不是 cp 参数写错,而是目标路径 wpa-dictionary/pojie 已经存在一个普通文件,不是目录。 诊断 ls -ld wpa-dictionary/pojie如果输出以 - 开头,说明是普通文件: -rw-r--r-- 1 root root 1234 Jun 15 wpa-dictionary/pojie如果是目录会以 d 开头: drwxr-xr-x 2 root root 4096 Jun 15 wpa-dictionary/pojie解决方案 方案 1:删除目标文件后再复制 rm -f wpa-dictionary/pojie cp -r pojie wpa-dictionary/方案 2:复制到不同名称 cp -r pojie wpa-dictionary/pojie_backup方案 3:先移动目标文件 mv wpa-dictionary/pojie wpa-dictionary/pojie.bak cp -r pojie wpa-dictionary/cp 目录行为说明 cp -r src dst 的行为取决于 dst 是否存在:目标是否存在 行为dst 不存在 把 src 复制为 dst(改名)dst 是目录 把 src 整体放进 dst/srcdst 是普通文件 报错:cannot overwrite non-directory例如: # 目标目录 backup/ 不存在 cp -r project/ backup/ # 结果:backup/ 就是 project/ 的副本# 目标目录 backup/ 已存在 cp -r project/ backup/ # 结果:backup/project/(嵌套了一层)注意末尾斜杠的影响:cp -r pojie/ dst 和 cp -r pojie dst 行为可能不同(前者复制内容,后者复制整个目录)。 rsync 作为替代 目录同步推荐用 rsync,语义更清晰,且支持增量更新: # 把 pojie/ 的内容同步到 wpa-dictionary/pojie/ rsync -av pojie/ wpa-dictionary/pojie/# 只复制新文件,跳过已存在的 rsync -av --ignore-existing pojie/ wpa-dictionary/pojie/# 删除目标中源没有的文件(镜像同步) rsync -av --delete pojie/ wpa-dictionary/pojie/rsync 在处理已存在目标时不会报上面的错误,会直接合并或覆盖。

看 free -h 别只盯 free 那列:available 才是真

服务器一查内存: $ free -h total used free shared buff/cache available Mem: 14Gi 10Gi 146Mi 0.0Ki 4.2Gi 4.1Gi Swap: 0B 0B 0B看到 free: 146Mi 就觉得"内存要爆了"——不对,Linux 从来不闲着,它会把空闲内存拿去做各种缓存。 各列到底是什么列 含义total 总内存used 已被进程占用free 完全空闲,谁都没在用(少不代表不好)shared tmpfs / shared memory 占用buff/cache 内核用作 page cache / dentry 缓存available 实际还能分配给程序的内存(这个才是真)关键:buff/cache 是弹性的——一旦有程序需要内存,内核会立刻回收 cache 让出来。所以真正衡量"还剩多少"的指标是 available,不是 free。 上面例子里 available = 4.1Gi,说明还能舒服再开 4G 内存的程序,没问题。 buff/cache 具体缓存什么Page cache:读过的文件内容缓存在内存里,下次读同一文件秒回 Dentry cache:目录项缓存,让 ls / find 之类操作更快 Inode cache:文件元数据(大小、时间戳)缓存 Buffers:块设备 IO 缓冲这些都是性能加速——把内存"用起来"总比闲着好。 手动清 cache 极少用得上,但知道一下: sync # 先把脏页刷盘 echo 3 > /proc/sys/vm/drop_caches # 清所有 cache1 = 清 page cache 2 = 清 dentry + inode 3 = 全清清完 free -h 里 free 会瞬间变大——但系统 IO 性能会立刻下降,因为所有文件读要重新从磁盘拉。生产上除非做基准测试,不然不要清。 Swap = 0 的风险 上面的例子 Swap: 0B。开 swap 有一个好处:内存暂时不够时,把不活跃页面换到磁盘,避免 OOM Killer 杀进程。 没 swap 的情况,某个进程突然吃到 15G 内存,系统会直接触发 OOM Killer: Killed process 12345 (python) Killed process 23456 (mysqld)杀谁看 oom_score(内核给每个进程算一个"该杀分数"),基本是"占内存多、优先级低"的先中招。 加个 swap(4G) sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile验证: free -h # Swap: 4.0Gi ...开机自动挂载: echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstabSwap 大小经验:内存 < 2G:swap 是内存的 2 倍 内存 2-8G:swap 等于内存 内存 > 8G:swap 2-4G 或者干脆不开(数据库服务器)找谁在吃内存 RSS 排序(真实占用物理内存): ps aux --sort=-rss | head -20或者 top 里按 M 排。列 RES才是实际占用,VIRT(虚拟内存)意义不大。 看某个进程详情: cat /proc/<PID>/status | grep -E 'VmRSS|VmSize'看具体是哪部分: pmap -x <PID> | tail -1MySQL / Redis / Java 类"吃内存大户" 这些程序的内存占用大多是配置定的:MySQL:innodb_buffer_pool_size,默认可能占 70% 内存 Redis:maxmemory,不配就吃到爆 Java:-Xmx 设堆大小,不设 JVM 会按机器算上生产前把这些参数对着物理内存卡好,不然多进程叠加轻松超总内存。 Linux OOM 前的预警 看 dmesg 有没有: sudo dmesg -T | grep -i "oom\|killed"Out of memory: Killed process 12345 (python) total-vm:15234567kB看到这个说明已经杀过了。生产上应该主动监控——node_exporter + Prometheus 采 node_memory_MemAvailable_bytes,跌破阈值发告警。 一句话总结 free -h 看的是 available,不是 free;buff/cache 是好东西不是问题。没 swap 的服务器建议加 4G 兜底,主要吃内存的程序(MySQL / Redis / Java)参数要卡死。