我正试图使用pubsub将firebase auth:export
调度到bucket中。我的目的是每天备份auth(firebase auth:export
的输出对我来说非常好(。
这是我尝试过的pubsub:
const functions = require('firebase-functions')
const exec = require("child_process").exec
const datetime = new Date();
const formattedDate = datetime.toISOString().slice(0,10)
const commandString = `firebase auth:export auth_export_${formattedDate}.json --format=JSON &&
gsutil -m cp -r auth_export_${formattedDate}.json gs://backup_firebase_auth_daily &&
rm auth_export_${formattedDate}.json`
exports.scheduledFirebaseAuthExport = functions.pubsub
.schedule('every 24 hours')
.onRun(() => {
return exec(commandString, (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
process.exit();
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
process.exit();
return;
}
console.log(stdout);
process.exit();
});
});
但我得到以下错误:
/bin/sh: 1: firebase: not found
我认为这是因为我不能在运行pubsub的任何环境中运行命令行脚本。
欢迎使用Google Cloud API或firebase备份firebase auth的任何其他方法。
我认为这是因为我无法在中运行命令行脚本运行pubsub的任何环境。
实际上,您不能在Cloud Function中执行命令行脚本(既不是Firebase CLI命令,也不是gsutil命令(,这就是;"环境";代码的运行位置(这里Pub/Sub是触发云函数的机制(。
另一方面;Firebase CLI也可以编程地用作标准节点模块";,如这里所解释的,您可以通过Cloud Function执行CLI的一些命令。
注意,单词";一些";上面是粗体,因为正如在同一个Github页面中所解释的:
注意:当在云函数等有限环境中使用时,并非所有
firebase-tools
命令将以编程方式工作,因为它们需要访问本地文件系统。
这正是CCD_ 5命令的情况;将活动项目的用户帐户导出到JSON或CSV文件";。
因此,不幸的是,不可能通过云函数自动执行此命令。
使用Google Cloud API获得firebase auth备份的任何其他方法或者欢迎使用firebase。
一种方法是使用Admin SDK:您可以批量检索整个用户列表,例如将其存储在受保护的Firestore集合(或任何其他存储解决方案(中。这可以从云功能(例如调度的云功能(或您自己的运行Node.js、Java、Python等的服务器触发。
正如其他答案已经指出的那样,您可以使用云函数通过Auth.export((将Auth文件导出到临时路径。然后,在同一函数中,您可以将该文件上传到bucket。整个过程可能看起来像这样:
const {Storage} = require("@google-cloud/storage");
const client = require("firebase-tools");
const split = require("split");
const path = require("path");
const os = require("os");
const fs = require("fs");
exports.scheduledExportAuthData = functions.pubsub.schedule("every 24 hours")
.onRun(async (context) => {
// Google Cloud data
const projectId = "your_firebase_project_id";
const bucketName = "your_google_cloud_bucket";
// Path parameters
const exportPathPrefix = "authExports/authExport_";
const currentDate = admin.firestore.Timestamp.now().toDate();
const exportPath = exportPathPrefix + currentDate.toISOString().split("T")[0] + ".json";
const tempPath = path.join(os.tmpdir(), path.basename(exportPath));
// Init Storage
const storage = new Storage();
const bucket = storage.bucket(bucketName);
// Export Auth file in temporary path
await client.auth
.export(tempPath, {project: projectId})
.catch( (error) => console.log(`Error exporting Auth data: ${error}`));
// Uploading the auth file to the GC bucket
await bucket
.upload(tempPath, {
destination: exportPath,
})
.catch( (error) => console.log(`Error uploading Auth file: ${error}`));
// Once the file has been uploaded delete the temporary file to free up disk space.
fs.unlinkSync(tempPath);
});
然而,我不知道这种方法在大型数据库中的性能。
此外,您还可以删除存储桶中早于X天的导出文件。你可以在同一个(或其他(函数中完成,在末尾添加类似的内容:
exports.scheduledExportAuthData = functions.pubsub.schedule("every 24 hours")
.onRun(async (context) => {
.....
// Delete Auth exports older than 14 days
const expirationDays = 14;
// Lists files in the bucket filtered by the export path prefix
// and delete them the last modified date meets the criteria
const options = {
prefix: exportPathPrefix,
};
const [files] = await bucket.getFiles(options);
files.forEach( (file) => {
const fileDate = file.updated;
if ((currentDate-fileDate)/86400000 > expirationDays) {
bucket.file(file.name)
.delete()
.catch( (error) => console.log(`Error deleting Auth file: ${error}`));
}
});
});
您也可以删除旧的导出,而不是使用最后一段代码,在您的bucket中添加对象生命周期规则。例如,要删除超过14天的身份验证导出,可以使用捕获中的配置:谷歌云存储桶生命周期配置
firebase-tools
现在提供auth.export()
功能。参见回购
请参阅此处的云功能示例实现:备份firebase用户
import * as tools from 'firebase-tools'
// Export users to a temporary file
await tools.auth.export(path, { project: projectId })