javascript - 缩略图云功能失败并显示“错误:EBUSY:资源繁忙或锁定,rmdir '/tmp/thumbs' at Error (native)”
问题描述
我的 Firebase 云函数失败并出现以下错误:
Error: EBUSY: resource busy or locked, rmdir '/tmp/thumbs' at Error (native)
通过我的功能,我为上传的图片创建缩略图并将它们保存到 Firebase 存储。我构建以下代码的方式一切正常(除了每个函数调用都失败)。但我担心由于 tmp 文件夹中的旧文件没有被删除,我的 tmp 文件夹会填满不必要的文件。
import * as functions from 'firebase-functions'
import {tmpdir} from 'os'
import {join, dirname} from 'path'
import * as sharp from 'sharp'
import * as fs from 'fs-extra'
import * as admin from "firebase-admin"
const storage = admin.storage()
/* Saves thumbnails for all userPics uploaded to Google Cloud Storage */
export const thumbnailCreator = functions.storage
.object()
.onFinalize(async object => {
const bucket = storage.bucket(object.bucket)
const filePath = object.name
const fileName = filePath.split('/').pop()
const bucketDir = dirname(filePath)
const workingDir = join(tmpdir(), 'thumbs')
/* Temporary: Creates a random number for the sourceFilePath
* because currently bucket.file(filePath).download does not seem to overwrite
* existing files and fs.rmdir(workingDir) does throw that error... */
const randomNr = Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15)
const tmpFilePath = join(workingDir, `source_${randomNr}.png`)
if (!object.contentType.includes('image')) {
console.log('exiting function (no image)')
return false
}
if (fileName.includes('thumb@')) {
console.log('exiting function (already a thumbnail')
return false
}
// 1. Ensure thumbnail dir exists
await fs.ensureDir(workingDir)
// 2. Download Source File
await bucket.file(filePath).download({
destination: tmpFilePath
})
// 3. Resize the images and define an array of upload promises
const sizes = [64, 128, 256, 512]
const uploadPromises = sizes.map(async size => {
const thumbName = `thumb@${size}_${fileName}`
const thumbPath = join(workingDir, thumbName)
// Resize source image
await sharp(tmpFilePath)
.rotate()
.resize(size, size)
.toFile(thumbPath)
// Upload to GCS
const file = await bucket.upload(thumbPath, {
destination: join(bucketDir, thumbName),
predefinedAcl: 'publicRead'
})
})
// 4. Run the upload operations
await Promise.all(uploadPromises)
// 5. Cleanup remove the tmp/thumbs from the filesystem
return fs.rmdir(workingDir)
// TODO: This fails every time -> also tried with fs.remove(workingDir), same issue.
})
如您所见,我处理它的方式是为 source.png 的文件名提供 GUID,因为下次调用该函数时,它不会覆盖已经下载的文件bucket.file(filePath).download()
。
但是我想清理我的 tmp 文件夹,但我无法弄清楚为什么该文件夹“忙或被锁定”。有没有办法在尝试删除它之前解锁它?
更新 - DOUG 的解决方案
正如道格在下面回答的那样,在删除文件夹之前删除所有文件是可行的。所以我最终这样做了:
// 5. Cleanup remove the tmp/thumbs from the filesystem
await fs.emptyDir(workingDir)
await fs.remove(workingDir)
解决方案
我不知道这是否会导致 EBUSY,但是 rmdir(节点的版本和同名的 unix 命令行)要求目录在调用之前为空。您将文件留在了那里,这可能会导致 rmdir 失败。尝试单独删除每个生成的文件,然后删除目录。
推荐阅读
- java - 在单击按钮时创建的项目在 JFrame 中不可见
- python - 尽管加载了最佳权重,但 EarlyStopping 并未停止模型
- logistic-regression - scikit-learn 和 dask-ml LogisticRegression 的不同结果
- deep-learning - 点云数据集的归一化(特征缩放)
- grep - 为什么 grep 返回部分匹配列表,然后退出,将文件的其余部分视为二进制文件?
- python - 如何在 python 中使用 x、y 和 z 制作强度图?
- javascript - JS拆分字符串和每个拆分的返回索引
- android - 如何使用 Dagger2 将自定义对象从活动类传递到存储库类?
- c# - MetaTextScore 如何被“注入”到 MongoDb Linq 查询中
- julia - 广播操作的内存分配