You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Cloud bucket.upload()函数无响应问题排查求助

问题排查与修复建议

针对你遇到的bucket.upload()在异步嵌套调用中无响应的问题,以下是具体的排查方向和修复方案:

1. 优先修复变量污染问题

你的uploadFolder函数中存在目标路径变量被循环篡改的问题:每次循环都会修改传入的destFileName,导致后续文件的上传路径变成初始路径/第一个文件名/第二个文件名这种错误格式,可能触发GCS的路径权限问题或静默阻塞。

修复后的uploadFolder代码:

const path = require('path');
const fs = require('fs').promises; // 建议用fs.promises替代回调式readdir,代码更简洁

async function uploadFolder(folderPath, destBasePath){
    try {
        const files = await fs.readdir(folderPath);
        for (const file of files) {
            if (path.extname(file) === ".bson") {
                const filePath = path.join(folderPath, file); // 用path.join避免路径分隔符兼容问题
                // 用临时变量存储目标路径,不修改原参数
                const destFileName = path.join(destBasePath, path.basename(file));
                console.log(`待上传: 本地路径=${filePath} | 云端路径=${destFileName}`);
                await uploadFile(filePath, destFileName);
            }
        }
    } catch (err) {
        console.error("读取文件夹失败:", err);
        throw err; // 抛出错误让上层处理,避免静默失败
    }
};

2. 增强上传过程的日志与错误捕获

原uploadFile的错误捕获和日志输出不足,无法定位上传阻塞的具体原因。修改后添加进度监听、详细日志,并确保错误被上层感知:

async function uploadFile(filePath, destFileName) {
    const options = {
        destination: destFileName,
        timeout: 30000, // 添加30秒超时,避免无限阻塞
    };
    console.log(`启动上传: ${filePath}`);
    try{
        // 监听上传进度,排查是否卡在某个阶段
        const uploadTask = bucket.upload(filePath, options);
        uploadTask.on('progress', (evt) => {
            const progress = ((evt.bytesWritten / evt.totalBytes) * 100).toFixed(2);
            console.log(`上传进度: ${progress}% (已传${evt.bytesWritten}/${evt.totalBytes}字节)`);
        });
        await uploadTask;
        console.log(`上传完成: ${destFileName}`);
    }
    catch(error){
        console.error(`上传失败 [${filePath}]:`, error.stack); // 输出错误栈,定位具体问题
        throw error; // 抛出错误中断流程,避免后续无效上传
    }
};

3. 排查Cron执行环境问题

Cron的执行环境与交互式Shell差异很大,这是定时任务常见的坑:

  • 脚本路径与工作目录:Cron默认工作目录是用户HOME,务必在Cron任务中指定脚本的绝对路径并切换工作目录,例如:
    # Cron任务示例
    0 0 * * * cd /absolute/path/to/your/script && node backup.js >> /var/log/backup.log 2>&1
    
  • 环境变量:Cron不会加载Shell的环境变量,需在脚本开头手动指定GCS认证文件的绝对路径:
    process.env.GOOGLE_APPLICATION_CREDENTIALS = "/absolute/path/to/your/service-account-key.json";
    
  • 日志输出:将Cron任务的输出重定向到日志文件,方便查看执行时的隐藏错误(如认证失败、文件不存在)。

4. 确保异步流程被完整等待

如果你的脚本入口直接调用backup()而未等待其完成,Cron启动的Node进程可能在上传完成前就被终止:

// 脚本入口必须完整等待异步流程
async function main() {
    try {
        const element = // 你的element获取逻辑
        await backup(element);
        console.log("备份全流程完成");
    } catch (err) {
        console.error("备份失败:", err);
        process.exit(1); // 非0退出码告知Cron任务失败
    }
}

main();

额外排查点

  • 确认localDump函数确实在文件完全写入磁盘后才resolve,避免读取未写完的.bson文件导致上传阻塞。
  • 测试在Cron环境中手动执行脚本(cd /path/to/script && node backup.js),复现问题并查看实时日志。
  • 检查GCS Bucket的权限:确保服务账号拥有storage.objects.create权限,且Bucket没有设置特殊的路径访问限制。

内容的提问来源于stack exchange,提问作者Shivi Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 07:12:49