10.3 MySQL Shell 插件

  • 10.3.1 创建 MySQL Shell 插件
  • 10.3.2 创建插件组
  • 10.3.3 MySQL Shell 插件示例

从 MySQL Shell 8.0.17 开始,您可以使用启动时加载的用户定义插件来扩展 MySQL Shell。插件可以用 JavaScript 或 Python 编写,它们包含的函数可以在 JavaScript 和 Python 模式下的 MySQL Shell 中使用。

10.3.1 创建 MySQL Shell 插件

  • 10.3.1.1 通用代码和包

MySQL Shell 插件可用于包含注册为 MySQL Shell 报告的函数(请参阅 第 10.1 节,“使用 MySQL Shell 进行报告”),以及作为扩展对象成员的函数,这些扩展对象可通过用户定义的 MySQL Shell 全局对象使用(请参见 第 10.2 节,“向 MySQL Shell 添加扩展对象”)。单个插件可以包含和注册多个函数,并且可以包含报告和扩展对象成员的混合。通过 MySQL Shell 插件注册为报告或扩展对象成员的函数在 MySQL 完成启动后立即可用。

MySQL Shell 插件是一个文件夹,其中包含适合该语言的初始化脚本( init.jsinit.py 文件)。初始化脚本是插件的入口点。插件只能包含一种语言的代码,因此,如果您要创建一个混合了 Python 中定义的成员和 JavaScript 中定义的成员的扩展对象,则必须将这些成员存储为单独的适合语言的插件。

为了在启动时自动加载 MySQL Shell 插件,其文件夹必须位于plugins MySQL Shell 用户配置路径的文件夹下。 MySQL Shell 在此位置搜索任何初始化脚本。 MySQL Shell 会忽略该 plugins位置中名称以点 (.) 开头的任何文件夹,但您用于插件文件夹的名称并不重要。

plugins该文件夹 的默认路径~/.mysqlsh/plugins在 Unix 和 %AppData%\MySQL\mysqlsh\pluginsWindows 上。通过定义环境变量,可以在所有平台上覆盖用户配置路径 MYSQLSH_USER_CONFIG_HOME。该变量的值%AppData%\MySQL\mysqlsh\在 Windows 或~/.mysqlsh/Unix 上替换。

当加载插件时发现错误时,会显示一条警告,并且错误详细信息可在 MySQL Shell 应用程序日志中找到。要查看有关加载过程的更多详细信息,请使用--log-level=debug启动 MySQL Shell 时的选项。

当加载 MySQL Shell 插件时,以下对象可用作全局变量:

  • 内置全局对象shell, dba, 和util.
  • Shell API 主模块mysql
  • X DevAPI 主模块mysqlx
  • AdminAPI 主模块dba

10.3.2 创建插件组

您可以通过将多个 MySQL Shell 插件的文件夹放置在该文件夹下的包含文件夹中来创建插件组 plugins。插件组可以包含使用 JavaScript 定义的插件和使用 Python 定义的插件的混合。插件组可用于组织具有共同点的插件,例如:

  • 提供特定主题报告的插件。
  • 重用相同公共代码的插件。
  • 将功能添加到同一扩展对象的插件。

如果该文件夹的子目录plugins不包含初始化脚本( init.jsinit.py 文件),MySQL Shell 会将其视为插件组,并在其子文件夹中搜索插件的初始化脚本。包含文件夹可以包含具有由插件组中的插件共享的代码的其他文件。对于插件的子文件夹,如果其名称以点 (.) 开头,则包含的文件夹将被忽略,否则该名称对于 MySQL Shell 来说并不重要。

例如,包含用户定义的 MySQL Shell 全局对象提供的所有功能的插件组 ext可以这样构造:

  • 该文件夹 C:\Users\exampleuser\AppData\Roaming\MySQL\mysqlsh\plugins\ext 是插件组的包含文件夹。
  • 插件的通用代码存储在该文件夹中 C:\Users\exampleuser\AppData\Roaming\MySQL\mysqlsh\plugins\ext\common.py
  • 插件组中的插件存储在该ext文件夹的子文件夹中,每个子文件夹都有一个 init.py文件,例如 C:\Users\exampleuser\AppData\Roaming\MySQL\mysqlsh\plugins\ext\helloWorld\init.py.
  • 插件从中导入公共代码 ext.common并使用其功能。

10.3.3 MySQL Shell 插件示例

示例 10.3 包含报告和扩展对象的 MySQL Shell 插件

此示例定义了一个 show_processes()用于显示当前正在运行的进程的函数,以及一个 kill_process()用于终止具有指定 ID 的进程的函数。show_processes()将是一个 MySQL Shell 报告,并且kill_process()将是一个扩展对象提供的函数。

该代码使用该 方法注册show_processes()为 MySQL Shell 报告。要注册 为 ,代码会检查全局对象和扩展对象是否已存在,如果不存在则创建并注册它们。然后将该 函数作为成员添加到 扩展对象中。 proc``shell.register_report()``kill_process()``ext.process.kill()``ext``process``kill_process()``process

插件代码保存为文件 ~/.mysqlsh/plugins/ext/process/init.py.启动时,MySQL Shell 会遍历plugins文件夹中的文件夹,找到该init.py文件,并执行代码。报告proc和函数kill()已注册并可供使用。如果全局对象ext和扩展对象process尚未被其他插件注册,则创建并注册它们,否则使用现有对象。

解释# Define a show_processes function that generates a MySQL Shell report def show_processes(session, args, options): query = "SELECT ID, USER, HOST, COMMAND, INFO FROM INFORMATION_SCHEMA.PROCESSLIST" if (options.has_key('command')): query += " WHERE COMMAND = '%s'" % options['command'] result = session.sql(query).execute(); report = [] if (result.has_data()): report = [result.get_column_names()] for row in result.fetch_all(): report.append(list(row)) return {"report": report} 1. Define a kill_process function that will be exposed by the global object 'ext' def kill_process(session, id): result = session.sql("KILL CONNECTION %d" % id).execute() 1. Register the show_processes function as a MySQL Shell report shell.register_report("proc", "list", show_processes, {"brief":"Lists the processes on the target server.", "options": [{ "name": "command", "shortcut": "c", "brief": "Use this option to list processes over specific commands." }]}) 1. Register the kill_process function as ext.process.kill() 1. Check if global object 'ext' has already been registered if 'ext' in globals(): global_obj = ext else: 1. Otherwise register new global object named 'ext' global_obj = shell.create_extension_object() shell.register_global("ext", global_obj, {"brief":"MySQL Shell extension plugins."}) 1. Add the 'process' extension object as a member of the 'ext' global object try: plugin_obj = global_obj.process except IndexError: 1. If the 'process' extension object has not been registered yet, do it now plugin_obj = shell.create_extension_object() shell.add_extension_object_member(global_obj, "process", plugin_obj, {"brief": "Utility object for process operations."}) 1. Add the kill_process function to the 'process' extension object as member 'kill' try: shell.add_extension_object_member(plugin_obj, "kill", kill_process, {"brief": "Kills the process with the given ID.", "parameters": [ { "name":"session", "type":"object", "class":"Session", "brief": "The session to be used on the operation." }, { "name":"id", "type":"integer", "brief": "The ID of the process to be killed." } ] }) except Exception as e: shell.log("ERROR", "Failed to register ext.process.kill ({0}).". format(str(e).rstrip()))