This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
api:rc:zh [2023/10/12 17:03] hfsr [RC脚本方法] |
api:rc:zh [2023/11/30 08:02] (current) hfsr [RC API] |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== RC API ====== | ====== RC API ====== | ||
- | RC系统将脚本作为服务自动运行,主要用于在系统启动时自动执行脚本。它是OpenOS提供的众多自动执行脚本工具之一,其余可参阅[[tutorial:autorun_options|此页面]]。 | + | RC系统以服务的形式自动运行脚本,它主要用于在系统启动时自动执行脚本。RC系统是OpenOS提供的众多自动执行脚本工具之一,其余可参阅[[tutorial:autorun_options|此页面]]。 |
OpenOS的RC系统受到了[[https://wiki.gentoo.org/wiki/OpenRC|OpenRC]]的启发。"RC"的含义是"run command"(运行指令)。 | OpenOS的RC系统受到了[[https://wiki.gentoo.org/wiki/OpenRC|OpenRC]]的启发。"RC"的含义是"run command"(运行指令)。 | ||
- | RC系统由两大部分组成:[[api:rc:zh#RC脚本|RC脚本]]与[[api:rc:zh#RC控制器|RC控制器]]. | + | RC系统由两大部分组成:[[api:rc:zh#RC脚本|RC脚本]]与[[api:rc:zh#RC控制器|RC控制器]]。 |
===== RC脚本 ===== | ===== RC脚本 ===== | ||
- | RC脚本是由用户编写,并由RC控制器管理的lua模块。此百科将讲述如何编写你自己的RC脚本。 "被启用的"RC脚本指被配置为开机启动的脚本。RC控制器还可以单独启动或停止某个RC脚本,而无需启用或禁用此脚本。 | + | RC脚本是由用户编写,并由RC控制器管理的lua模块。此百科将讲述如何编写你自己的RC脚本。 "启用的"RC脚本指被配置为开机启动的脚本。RC控制器也可以单独启动或停止某个RC脚本的运行,无需启用或禁用此脚本。 |
- | RC脚本至少需要满足[[api:rc:zh#最简配置|最简配置]]。它们的[[api:rc:zh#RC脚本方法|方法]]api很灵活,并且可以配合[[api:rc:zh#RC脚本配置|RC脚本配置]]使用。 | + | RC脚本至少需要满足[[api:rc:zh#最简配置|最简配置]]。它们的[[api:rc:zh#RC脚本方法|方法]]API很灵活,并且可以配合[[api:rc:zh#RC脚本配置|RC脚本配置]]使用。 |
==== 最简配置 ==== | ==== 最简配置 ==== | ||
- | 要创建一个名为"custom"的rc脚本,你至少需要一个文件:`/etc/rc.d/custom.lua`,其中至少定义一个函数。 | + | 要创建一个名为"custom"的RC脚本,你至少需要一个文件:`/etc/rc.d/custom.lua`,其中至少定义一个函数。 |
```lua | ```lua | ||
Line 21: | Line 21: | ||
``` | ``` | ||
- | 这个包含一个`start`函数的`custom.lua`文件已经足以定义一个rc脚本了。 | + | 这个仅包含一个`start`函数的`custom.lua`文件已经足以定义一个RC脚本了。 |
- | 善于观察的读者会发现,上述最简样例的`start`函数并未指定`local`作用域。这是故意而为之的。RC脚本会被加载到沙盒环境中,这些全局函数就充当了调用来源与RC控制器之间的接口。你脚本中所有你想让RC控制器访问的方法都必须定义为全局方法。 | + | 善于观察的读者会发现,上述最简样例中的`start`函数并未指定`local`作用域。这是故意而为的。RC脚本会被加载到沙盒环境中,这些全局函数就充当了调用来源与RC控制器之间的接口。你脚本中所有你想让RC控制器访问的方法都必须定义为全局方法。 |
OpenOS自带一份RC脚本的样例,请查看`/etc/rc.d/example.lua`。 | OpenOS自带一份RC脚本的样例,请查看`/etc/rc.d/example.lua`。 | ||
Line 29: | Line 29: | ||
==== RC脚本方法 ==== | ==== RC脚本方法 ==== | ||
- | 对一般读者而言,有关RC脚本环境细节的内容似乎偏离了RC系统入门的主题。但对于好奇或者有疑问的读者而言,这些信息会有所帮助。RC脚本会被加载(lua `load`)到一个继承了所有OpenOS全局方法的沙箱环境中。你在RC脚本中编写的全局函数只能从RC系统中访问,不会污染OpenOS全局环境。你的脚本[[api:rc:zh#RC脚本配置|配置]]同样位于沙箱环境中,以全局变量`args`的形式存在。同时还应注意,你的脚本只会加载一次,此后会保存在缓存中。 | + | 对一般读者而言,有关RC脚本环境细节的内容似乎偏离了RC系统入门的主题。但对于好奇或者有疑问的读者而言,这些信息会有所帮助。RC脚本会被(用lua的`load`函数)加载到一个继承了所有OpenOS全局方法的沙箱环境中。你在RC脚本中编写的全局函数只能从RC系统中访问,不会污染OpenOS全局环境。你脚本的[[api:rc:zh#RC脚本配置|配置]]同样位于沙箱环境中,以全局变量`args`的形式存在。同时还应注意,你的脚本只会加载一次,此后会保存在缓存中。 |
- | RC脚本名称是指你添加到`/etc/rc.d/`目录的lua文件名(不含后缀)。 | + | RC脚本名称是指你添加到`/etc/rc.d/`目录的lua文件名(不含后缀)。 |
请在RC脚本文件中把你的RC方法定义为全局函数。请注意,RC系统在任何情况下都不会对RC脚本方法的返回值作出任何响应。异常所抛出的任何数据都会被输出到stderr,如果stderr不可用则会输出到`/tmp/event.log`。 | 请在RC脚本文件中把你的RC方法定义为全局函数。请注意,RC系统在任何情况下都不会对RC脚本方法的返回值作出任何响应。异常所抛出的任何数据都会被输出到stderr,如果stderr不可用则会输出到`/tmp/event.log`。 | ||
Line 37: | Line 37: | ||
在RC系统中,只有两个RC方法具有特殊地位:`start`和`stop`。 | 在RC系统中,只有两个RC方法具有特殊地位:`start`和`stop`。 | ||
- | - `start()` | + | - `start()` |
- | + | 一个正常的RC脚本中只需定义一个`start`方法。RC系统在设计时假定RC脚本都是可被启动的。并且在涉及[[api:rc:zh#RC控制器|控制器]]的多种工作流中,系统都会利用`start`方法。 | |
- | 一个正常的RC脚本中只需要定义一个`start`方法。RC系统在设计时假定RC脚本都是可以被启动的。并且在[[api:rc:zh#RC控制器|控制器]]的多种工作流中,系统只会利用`start`方法。 | + | \\ |
- | + | - `stop()` | |
- | - `stop()` | + | RC脚本中可以定义一个停止方法(可选)。启用的RC脚本(即配置为自动启动的脚本)只会在系统启动时调用`start`方法,但假如脚本定义了`stop`方法,那么`rc <脚本名> restart`会有如下的默认行为。 |
- | + | 如果RC控制器被要求`restart`(重启)某个脚本,它会先调用`stop`方法,紧接着调用`start`方法。请注意若脚本中显式定义了`restart`方法,则控制器会调用定义的方法,而不是执行前文的默认行为。 | |
- | RC脚本中可以定义一个停止方法(可选)。被启用的RC脚本(也即配置为自动启动的脚本)只会在系统启动时调用`start`方法,但是`rc <脚本名> restart`在脚本的`stop`方法有定义时具有默认行为:如果RC控制器被要求`restart`(重启)某个脚本,它会先调用`stop`方法,紧接着调用`start`方法。请注意如果脚本中明确定义了`restart`方法,则控制器会调用此方法,而不是执行前文的默认行为。 | + | \\ |
- | + | - `<方法名>([参数...])` | |
- | - `<方法名>([参数...])` | + | 编写RC脚本时不仅可以定义`start`和`stop`方法,还可以定义任意多的方法。用户不会直接调用这些方法,而是利用RC控制器来间接调用它们。因此有了下文所示的通用调用语法,RC控制器可用其调用任意名称的RC脚本方法。 |
- | + | `rc <模块名> <方法名> [参数...]` | |
- | 编写RC脚本时不仅可以定义`start`和`stop`方法,还可以定义任意多的方法。用户不会直接调用这些方法,而是会利用RC控制器来调用它们。因此我们提供了此语法,rc控制器可以用其调用任意名称的RC脚本方法。 | + | 此处的`模块名`指你的RC脚本名称(即位于你的`/etc/rc.d/`目录下的`.lua`文件名,不含后缀)。`方法名`指你在脚本文件中定义的全局方法。`参数...`是你想传递的任意命令行参数。甚至`start`和`stop`方法也可通过此方式调用。 |
- | + | ||
- | `# rc <模块名> <方法名> [参数...]` | + | |
- | + | ||
- | 此处的`模组名`指你的rc脚本名称(即位于你的`/etc/rc.d/`目录下的`.lua`文件名,不含后缀)。`方法名`指你在脚本文件中定义的全局方法。`参数...`是你想传递的任意命令行参数。`start`和`stop`方法也可以用此方式调用。 | + | |
==== RC脚本配置 ==== | ==== RC脚本配置 ==== | ||
- | 你可以在`/etc/rc.cfg`文件中自定义脚本配置 (文件的语法必须可被lua读取)。假设你的rc脚本位置为`/etc/rc.d/foo.lua`,则此模块的名称为`foo`,其在配置文件中的域(field)名称也需要为`foo`。OpenOS提供的样例rc脚本`example`也涉及了这一点。模块包含`/etc/rc.d/example.lua`脚本文件,并且`/etc/rc.cfg`配置文件中有: | + | 你可以在`/etc/rc.cfg`文件中定义自己的脚本配置(语法必须符合lua可读取的标准)。假设你的RC脚本位置在`/etc/rc.d/foo.lua`,则其模块名为`foo`,其在配置文件中的字段名称(键名)也需要为`foo`。OpenOS提供的样例RC脚本`example`也涉及了这一点。此模块的脚本文件为`/etc/rc.d/example.lua`,同时`/etc/rc.cfg`配置文件中有: |
```lua | ```lua | ||
Line 62: | Line 58: | ||
``` | ``` | ||
- | `enabled`列表由[[api:rc#The RC Controller|controller]]维护,但是`example`域(field)中存储的是`example`rc脚本的配置。领域的值可以是任何lua值,不只是字符串。当然也包含列表。你脚本的配置值会被加载到你的脚本环境中。在你的脚本中你可以通过名为`args`的全局域(field)访问你的配置。请再回头查看`example.lua`脚本的代码,注意它对`args`变量的用法。你的脚本和配置会同时由控制器加载和缓存。 | + | `enabled`列表由[[api:rc:zh#RC控制器|控制器]]维护,但`example`字段中存储的是`example`RC脚本的配置。字段的值可以是任何lua值,不只是字符串。当然也包含表。脚本的配置值会被加载到你的脚本环境中。在脚本中你可以通过名为`args`的全局字段来访问你的配置。请再回头查看`example.lua`脚本的代码,注意它对`args`变量的用法。你的脚本和配置只会由控制器加载和缓存一次。 |
===== RC控制器 ===== | ===== RC控制器 ===== | ||
- | rc控制器提供了一个命令行接口,你可以在shell中通过`rc`指令访问(`/bin/rc.lua`)。还提供了一个一个运行库,你可以通过`require("rc")`来访问。 | + | RC控制器提供了一个命令行接口,你可以在shell中通过`rc`命令(`/bin/rc.lua`)访问。还提供了一个运行库,你可以通过`require("rc")`来访问。 |
- | 在rc控制器中维护着一份列表,表中记录了被配置为开机时启动的rc脚本。rc控制器中还缓存了已加载的rc脚本。 | + | RC控制器维护着一份列表,表中记录了配置为开机时执行的RC脚本。RC控制器中还缓存了已加载的RC脚本。 |
- | 和其他启动选项,如autorun和`.shrc`,启用的rc脚本只会在每次OpenOS启动时自动执行一次。 | + | 不像其他自启动方案,如autorun和`.shrc`,启用的RC脚本只会在OpenOS启动时自动执行一次。 |
==== 命令行接口 ==== | ==== 命令行接口 ==== | ||
- | `rc` | + | `rc` |
- | + | 调用所有启用的RC脚本的`start`方法。 | |
- | 调用所有被启用的rc脚本的`start`方法 | + | \\ |
- | + | `rc <模块名> enable` | |
- | `rc <模块名> enable` | + | 将名为<模块名>的RC脚本添加到“自启动”RC脚本的列表中。下次开机启动时将会自动调用<模块名>.start()。 |
- | + | \\ | |
- | 将名为<模块名>的rc脚本添加到“自启动”rc脚本的列表中。下次开机启动时将会自动调用<模块名>.start()。 | + | `rc <模块名> disable` |
- | + | 将名为<模块名>的RC脚本从“自启动”RC脚本的列表中移除。下次启动时名为<模块名>的脚本不会自启动。 | |
- | `rc <模块名> disable` | + | \\ |
- | + | `rc <模块名> restart` | |
- | 将名为<模块名>的rc脚本从“自启动”rc脚本的列表中移除。下次启动时名为<模块名>的脚本不会自启动。 | + | 若名为<模块名>的脚本同时定义了`stop()`和`start()`方法,则依次调用它们。 |
- | + | \\ | |
- | `rc <模块名> restart` | + | `rc <模块名> <方法名> [参数...]` |
- | + | 调用名为<模块名>的RC脚本中定义的<方法名>方法,如果有[参数...],则将它们作为函数参数传递给此方法。 | |
- | 如果名为<模块名>的脚本同时定义了`stop()`和`start()`方法,则调用它们。 | + | |
- | + | ||
- | `rc <模块名> <方法名> [参数...]` | + | |
- | + | ||
- | 调用名为<模块名>的rc脚本中定义的<方法名>方法,如果有[参数...],则将它们作为函数参数传递给此方法。 | + | |
==== RC API ==== | ==== RC API ==== | ||
- | - `unload(moduleName: string)` | + | - `unload(moduleName: string)` |
- | + | 你可以卸载RC脚本,以将其从RC缓存中移除。此功能可用于重置配置文件,或是清理脚本的全局定义。在调试时此功能用处极大,你可以在不重启电脑的前提下重新加载脚本代码。 | |
- | 你可以卸载你的rc脚本,同时它也会从rc缓存中移除。此功能用于重置配置文件或是清理脚本全局变量。在调试时此功能用处极大,你可以在不重启电脑的前提下重新加载脚本代码 | + | |
目录 | 目录 |