提问人:IMTheNachoMan 提问时间:10/7/2019 更新时间:11/23/2021 访问量:4876
检查触发器执行当前是否正在 Google Apps 脚本中运行
check if a trigger execution is currently running in Google Apps Scripts
问:
是否可以查看特定项目的触发器是否有任何活动/正在运行的执行?
我有一个一次性迁移脚本/项目,用于将数千个 Google 表格文件更新为新的模板格式。根据我的计算,该脚本将需要数小时才能运行。我们的 G-Suite Enterprise 环境的执行时间限制为 30 分钟。
我的代码是这样编写的,如果脚本失败,无论出于何种原因,我都可以重新运行它,它将从停止的地方继续。
有时,脚本会因其他原因(如内存错误或网络连接问题)而失败。
因此,我想设置一个 15 分钟的触发器来运行脚本。我希望它检查另一个执行是否仍在运行。如果是,那么它就会停止。如果不是,那么它将继续。
我知道如何使用来查看链接到项目的触发器,但我不知道如何找到正在运行的执行。ScriptApp.getProjectTriggers()
答:
- 您想知道脚本现在是否由时间驱动的触发器运行。
- 您希望使用 Google Apps 脚本来实现此目的。
如果我的理解是正确的,那么这个答案怎么样?请把这看作是几个答案之一。
溶液:
我认为您可以使用 Google Apps Script API 中的 processes.list 方法实现您的目标。当 Google Apps 脚本 API 中的 processes.list 方法在脚本由时间驱动的触发器运行期间被请求时,可以检索以下值。
{
"processes": [
{
"projectName": "sampleProject",
"functionName": "myFunction",
"processType": "TIME_DRIVEN",
"processStatus": "RUNNING", // <--- here
"userAccessLevel": "OWNER",
"startTime": "2019-10-07T00:00:00.000Z",
"duration": "36.145s"
}
]
}
在本例中,是 .脚本完成后,processStatus
将更改为 COMPLETED
。processStatus
RUNNING
检索 when is 信息的示例脚本如下。processStatus
RUNNING
用法:
1. 将云平台项目链接到 Google Apps 脚本项目
在这种情况下,需要将 Cloud Platform Project 链接到 Google Apps Script Project。关于如何链接它,你可以在这里看到它。
2. 启用 Google Apps 脚本 API
第二步,请在 API 控制台中启用 Google Apps Script API。关于如何启用它,您可以在此线程中看到它。
3. 运行示例脚本:
function sample() {
var scriptId = "###"; // Please set the script ID here.
var functionName = "###"; // Please set the function name here.
var url = "https://script.googleapis.com/v1/processes?userProcessFilter.functionName=" + functionName + "&userProcessFilter.scriptId=" + scriptId;
var res = UrlFetchApp.fetch(url, {headers: {Authorization: 'Bearer ' + ScriptApp.getOAuthToken()}});
var obj = JSON.parse(res);
var runningScript = obj.processes.filter(function(p) {return p.processType == "TIME_DRIVEN" && p.processStatus == "RUNNING"});
Logger.log(runningScript)
}
- 使用此脚本时,请添加 和 的范围。因此,请将它们添加到清单文件()。
https://www.googleapis.com/auth/script.external_request
https://www.googleapis.com/auth/script.processes
appsscript.json
- 使用此脚本时,请设置触发时间驱动触发器时运行的变量和变量。
scriptId
functionName
- 在此脚本中,当没有正在运行的 scrit 时,将返回。
[]
- 如果您想了解其他工艺类型,请修改 .
p.processType == "TIME_DRIVEN"
注意:
- 我认为在您的情况下,您还可以使用方法:processes.listScriptProcesses。
- 根据我的经验,当脚本完成时,有时会出现.但在这种情况下,它表示脚本已完成。
processStatus
UNKNOWN
引用:
如果我误解了你的问题,这不是你想要的方向,我很抱歉。
添加:
我认为使用Apps Script API的方法是一种解决方案。为了在不将云平台项目链接到 GAS 项目的情况下实现您的目标,在这里,我想提出一个解决方法。
在此解决方法中,我使用了 Drive API 的属性。使用云端硬盘 API 的属性时,可以将该属性检索到其他项目。所以在这里,我使用了Drive API的属性。请将此视为几种解决方法之一。
用法:
1. 在高级 Google 服务中启用 Drive API
首先,请在 Advanced Google 服务中启用 Drive API。
2. 示例脚本:
示例脚本 1:
请复制并粘贴以下脚本。它假设 的函数由时间驱动的触发器运行。runByTrigger
function runByTrigger(e) {
var fileId = "###"; // Please set the file ID.
if (e && "triggerUid" in e && e.triggerUid != "") {
Drive.Files.update({properties: [
{key: "processStatus", value: "RUNNING", visibility: "PUBLIC"},
{key: "processStartTime", value: new Date().toISOString(), visibility: "PUBLIC"},
]}, fileId);
}
// do something
// Here, please put your script.
if (e && "triggerUid" in e && e.triggerUid != "") {
Drive.Files.update({properties: [
{key: "processStatus", value: "COMPLETED", visibility: "PUBLIC"},
{key: "processStartTime", value: "", visibility: "PUBLIC"},
]}, fileId);
}
}
示例脚本 2:
此脚本用于检查脚本是否由时间驱动的触发器运行。请运行此脚本进行检查。您也可以使用此脚本,该脚本与包括 .runByTrigger
function myFunction() {
var fileId = "###"; // Please set the file ID.
var runningScript = Drive.Properties.get(fileId, "processStatus", {visibility: "PUBLIC"}).value;
if (runningScript == "RUNNING") {
var startTime = Drive.Properties.get(fileId, "processStartTime", {visibility: "PUBLIC"}).value;
Logger.log("Script is currently running. Start time is %s", startTime)
} else {
Logger.log("Script was finished.")
}
}
- 脚本 1 和 2 是同一个 ID。作为测试用例,如果脚本是独立脚本,请设置独立脚本的脚本 ID。如果脚本是容器绑定脚本,请设置 Google Docs 的文件 ID。
fileId
- When 由时间驱动的触发器运行,并放入文件的属性中。
runByTrigger
processStatus
processStartTime
- 如果脚本当前正在运行,则在运行函数时,日志中会显示。
myFunction
Script is currently running. Start time is {startTime}
- 如果脚本已完成但未运行,则显示在日志中。
Script was finished.
- 如果脚本当前正在运行,则在运行函数时,日志中会显示。
注意:
- 在此解决方法中,将使用 file 的属性。但我认为,例如,流程状态也可以保存到电子表格等。
引用:
评论
var obj = JSON.parse(res.getContentText());
var obj = JSON.parse(res);
这是最干净(同时也是最简单)的方法:
Google 为 Apps 脚本提供了一个内置工具,称为锁定服务。您可以使用它来避免在代码仍在运行时再次运行代码的任何部分(由您手动或通过触发器)。
只需将要从触发器调用的函数结构化为:
function functionName() {
let lock = LockService.getUserLock().tryLock(0);
if (lock.hasLock()) {
// Your code goes here.
};
};
现在,每当您的扳机触发时,它都会首先检查是否有锁。如果有,它将跳过该运行。如果没有,它将创建一个锁并开始执行您的代码。
评论