【问题标题】:fs.writeFile fails without error when writing to a specific (not full) partition写入特定(未满)分区时,fs.writeFile 失败且没有错误
【发布时间】:2018-08-31 19:09:52
【问题描述】:

我正在为网络上的网站图标实现图像缓存。在某一时刻,我有网站图标的 URL,并将其发送到我的页面,一切都很好。

现在,我将图标写入磁盘,使用我使用 URL 组件构建的伪唯一文件名。

这也有效,但只有当我写信给/tmp/!?

这是我的代码:

router.get('/favicon', function(req, res) {
  favicon(req.query.url, function(err, iconUrl) {
    if (iconUrl) {
      var u = Url.parse(iconUrl);
      request.get({url: iconUrl}, function (err, response, body) {
        if (!err && typeof body !== 'undefined') {
          var h = u.host.replace(/\//g, ''),
              p = u.path.replace(/\//g, ''),
              fileName;

          fileName = path.join('/tmp', h + '.' + p);
          // fileName = path.join(__dirname, '..', 'cache', h + '.' + p);

          fs.writeFile(fileName, body, function(err) {
            if(err)
              console.log(err);
            else
              console.log("SAVED! (%s)", fileName);
          });
        } else {
          console.log('### ERROR iconUrl: (%s) err: (%s)', iconUrl, err);
        }
      });
      res.send(iconUrl);
    } else {
      res.status(500).send('No icon found');
    }
  });
});

这是在客户端(网络浏览器)端调用的,如下所示:

$.get("/favicon", {
  url: decodeURI(feedHost),
  dataType: "json",
  timeout: 2000
}, function(iconURL) {
  console.info('OK (icon: %s)', iconURL);
}).done(function(iconURL) {
  console.info('OK (icon: %s)', iconURL);
}).fail(function() {
  console.error('ERROR');
});

我虽然这是一个“磁盘已满”的问题,但不是,这是这台机器上的分区表,/home 分区内的项目目录(我的图像缓存目录所在的位置),/tmp/ 是,好吧,在/

# df -h   
Filesystem      Size  Used Avail Use% Mounted on
udev            1.9G     0  1.9G   0% /dev
tmpfs           388M  6.3M  382M   2% /run
/dev/sda6        19G   14G  3.8G  79% /
tmpfs           1.9G   23M  1.9G   2% /dev/shm
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/loop0       82M   82M     0 100% /snap/core/4206
/dev/loop1      128M  128M     0 100% /snap/shotcut/20
/dev/loop2       82M   82M     0 100% /snap/core/4110
/dev/loop3       82M   82M     0 100% /snap/core/4017
/dev/loop4      298M  298M     0 100% /snap/shotcut/17
/dev/loop5      128M  128M     0 100% /snap/shotcut/21
/dev/sda5       121G  102G   14G  89% /home
tmpfs           388M   12K  388M   1% /run/user/1000

因此,当我使用上面的代码时,一切正常,/tmp/ 以异步方式填充图像,完美。

一旦我删除文件路径的前导/ - 当然指向有效路径 - 然后复制一个、两个、最多 3 个图标,然后该过程以某种方式失败,触发 .fail() 方法一个客户端,但服务器上没有任何错误

帮助!

问题:

  • 什么可能导致这个奇怪的“写入 2 或 3 个文件然后停止”问题?注意:服务器使用PM2 启动。
  • 我的 ajax 调用 (JQuery $.get()) 正确吗?为什么它会使页面中的其他 ajax 调用失败,而不是轻轻地出错然后继续?

更新

原来我没有在/tmp/ 中保存正确的图像文件;我现在正在使用此代码:

router.get('/favicon', function(req, res) {

  favicon(req.query.url, function(err, iconUrl) {
    if (iconUrl) {

      if (!iconUrl.startsWith('..') && Url.parse(iconUrl)) {

        var u = Url.parse(iconUrl),
            h = u.host.replace(/\//g, ''),
            p = u.path.replace(/\//g, ''),
            fileName;

        fileName = path.join('/tmp/cache', h + '.' + p);
        // fileName = path.join(__dirname, '..', 'cache', h + '.' + p);

        let stream = fs.createWriteStream(fileName);
        stream.on('finish', function () {
          console.log("SAVED %s (%s)", fileName, iconUrl);
        }).on('error', function (err) {
          console.log("NOT SAVED %s (%s)", fileName, err);
        });
        request(iconUrl).pipe(stream);

      } else {
        console.log('iconUrl NOT OK: (%s)', iconUrl);
      }

      res.send(iconUrl);
    } else {
      res.status(500).send('No icon found');
    }
  });
});

现在保存的文件是正确的图像文件;但是问题仍然存在,我现在已经在其他几台 (Linux) 机器 上测试了这段代码,包括生产网络服务器,同样的事情!无法在项目 repo 中保存(超过少数)文件,但如果我使用 /tmp/* 作为文件路径,一切都很好!

这让我发疯了,请让我摆脱这种痛苦:|

更新 2

我设法写入了我的主分区。我唯一不能写入的地方是项目目录内(包括)任何目录

【问题讨论】:

  • 看起来文件名包含一些特殊字符。您可以添加 console.log(fileName) 并查看它失败的文件吗?
  • 嗨,亚历克斯;当我这样做时,我得到了我也可以在缓存中看到的 2 或 3 个文件的名称,它们都被命名为 subdomain.domain.tld.filename.extension。但同样,任何地方都不会触发错误:(请记住,当我使用 /tmp/ 时,相同的文件被复制得很好。
  • 嗯,好吧,我看不到你是否会转储错误...你可以在 function(err, response, body) { 之后添加 if (err) console.error(err) 吗?
  • 我还进行了各种测试,其中 fileName 只是 Math.random() 但结果相同:/tmp 很好,本地 repo 路径失败:(
  • 是的,Alex,我 am 正在测试 body 是否有错误。也不需要测试request.get(),因为它没有失败。我的意思是,如果我删除整个 if (!err && typeof body !== 'undefined') 一切运行正常。

标签: node.js express fs


【解决方案1】:

好的,我发现了。罪魁祸首是the pm2 watcher,它会在整个项目范围内编写某些内容时重新启动服务器。

这就是(很难找到,如果它写在某个我不知道在哪里的地方)我可以将图像文件写入磁盘上的任何地方在项目目录中的原因 没有任何错误,只是服务器缓慢而混乱的崩溃;感谢您的耐心等待。

所以我创建了以下 pm2 进程管理文件(通过运行 pm2 ecosystem simple 感谢this answer

{
  "apps" : [{
    "name"            : "petrolette",
    "script"          : "./bin/www",
    "watch"           : true,
    "ignore_watch"    : ["favicons-cache"],
    "log_date_format" : "YYYY-MM-DD HH:mm",
    "env": {
      "PORT": 8666,
      "FAVICONS_CACHE_DIR": "favicons-cache"
    },
    "env_production" : {
      "NODE_ENV": "production"
    }
  }]
}

所以现在我的favicons-cache 目录受到了监视进程的保护,作为奖励,它的名称现在是一个ENV var,所以我可以使用process.env.FAVICONS_CACHE_DIR 访问它:)

【讨论】:

    猜你喜欢
    • 2014-05-07
    • 1970-01-01
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-08
    相关资源
    最近更新 更多