查看源代码 application 行为 (内核 v10.2)
通用 OTP 应用程序函数
在 OTP 中,application 表示一个实现特定功能的组件,可以作为一个单元启动和停止,并且可以在其他系统中重用。此模块与应用程序控制器交互,该进程在每个 Erlang 运行时系统启动。此模块包含用于控制应用程序的函数(例如,启动和停止应用程序),以及用于访问有关应用程序信息的函数(例如,配置参数)。
应用程序由应用程序规范定义。该规范通常位于名为 Application.app
的应用程序资源文件中,其中 Application
是应用程序名称。有关应用程序规范的详细信息,请参阅 app
。
此模块也可以看作是根据 OTP 设计原则作为监督树实现的应用程序的行为。如何启动和停止树的定义应位于应用程序回调模块中,该模块导出一组预定义的函数。
有关应用程序和行为的详细信息,请参阅 OTP 设计原则。
另请参阅
概要
回调:回调模块
如果配置参数已更改,则在代码替换后,应用程序会调用此函数。
在应用程序即将停止时,在关闭应用程序的进程之前,将调用此函数。
每当使用 start/1,2
启动应用程序时,都会调用此函数来启动应用程序的进程。如果应用程序按照 OTP 设计原则构建为监督树,则表示启动树的顶级监督者。
当启动期间不同应用程序中的进程需要同步时,使用包含的应用程序启动应用程序。
每当应用程序停止时都会调用此函数。它旨在与 Module:start/2
相反,并执行任何必要的清理工作。返回值将被忽略。
函数
等效于 start(Application)
,但对于已启动的应用程序返回 ok
。
等效于 start(Application, Type)
,但对于已启动的应用程序返回 ok
。
返回 Application
的配置参数及其值。
返回 Application
的应用程序规范键及其值。如果省略参数,则默认为调用进程的应用程序。
返回进程 Pid
或模块 Module
所属的应用程序的名称。
返回 Application
的配置参数 Par
的值。
与 get_env/2
的工作方式类似,但当配置参数 Par
不存在时返回值 Def
。
返回 Application
的应用程序规范键 Key
的值。
返回在 Application
根目录运行的监督者的 Pid
。
将应用程序的应用程序规范加载到应用程序控制器中。它还会加载任何包含的应用程序的应用程序规范。请注意,该函数不会加载 Erlang 目标代码。
返回一个列表,其中包含有关使用 load/1,2
加载的应用程序和包含的应用程序的信息。Application
是应用程序名称。Description
和 Vsn
分别是其 description
和 vsn
应用程序规范键的值。
更改 Application
在当前节点上运行的权限。必须使用 load/1,2
加载应用程序,该函数才能生效。
为多个应用程序设置配置 Config
。
设置 Application
的配置参数 Par
的值。
启动 Application
。如果未加载,应用程序控制器会先使用 load/1
加载它。它确保加载任何包含的应用程序,但不启动它们。这假定在 Application
的代码中处理。
此函数旨在由属于应用程序的进程在应用程序启动时调用,以确定启动类型,该类型为 StartType
或 local
。
停止 Application
。应用程序主服务器调用 Module:prep_stop/1
(如果定义了此类函数),然后告诉应用程序的顶级监督者关闭(请参阅 supervisor
)。
接管在另一个节点 Node
上执行的分布式应用程序 Application
。
从应用程序控制器卸载 Application
的应用程序规范。它还会卸载任何包含的应用程序的应用程序规范。请注意,该函数不会清除 Erlang 目标代码。
删除 Application
的配置参数 Par
及其值。
返回一个列表,其中包含有关当前正在运行的应用程序的信息。
类型
-type application_opt() :: {description, Description :: string()} | {vsn, Vsn :: string()} | {id, Id :: string()} | {modules, [Module :: module()]} | {registered, Names :: [Name :: atom()]} | {applications, [Application :: atom()]} | {included_applications, [Application :: atom()]} | {env, [{Par :: atom(), Val :: term()}]} | {start_phases, [{Phase :: atom(), PhaseArgs :: term()}] | undefined} | {maxT, MaxT :: timeout()} | {maxP, MaxP :: pos_integer() | infinity} | {mod, Start :: {Module :: module(), StartArgs :: term()}}.
应用程序可用的内置选项。
有关选项的说明,请参阅 app。
-type application_spec() :: {application, Application :: atom(), AppSpecKeys :: [application_opt()]}.
应用程序规范。
-type restart_type() :: permanent | transient | temporary.
应用程序应具有的重启行为类型。
应用程序在当前节点上启动的原因。
-type tuple_of(_T) :: tuple().
元素类型为 T
的元组。
回调:回调模块
-callback config_change(Changed, New, Removed) -> ok when Changed :: [{Par, Val}], New :: [{Par, Val}], Removed :: [Par], Par :: atom(), Val :: term().
如果配置参数已更改,则在代码替换后,应用程序会调用此函数。
Changed
是一个参数-值元组列表,包含所有值已更改的配置参数。
New
是一个参数-值元组列表,包含所有已添加的配置参数。
Removed
是一个包含所有已移除参数的列表。
在应用程序即将停止时,在关闭应用程序的进程之前,将调用此函数。
State
是从 Module:start/2
返回的状态,如果未返回状态则为 []
。NewState
是任意项,并传递给 Module:stop/1
。
该函数是可选的。如果未定义,则进程将终止,然后调用 Module:stop(State)
。
-callback start(StartType :: start_type(), StartArgs :: term()) -> {ok, pid()} | {ok, pid(), State :: term()} | {error, Reason :: term()}.
每当使用 start/1,2
启动应用程序时,都会调用此函数来启动应用程序的进程。如果应用程序按照 OTP 设计原则构建为监督树,则表示启动树的顶级监督者。
StartType
定义启动的类型。
normal
如果是正常启动。normal
也适用于以下情况:应用程序是分布式的,并且由于从另一个节点故障转移而当前节点启动了该应用程序,并且应用程序规范键start_phases == undefined
。{takeover,Node}
如果应用程序是分布式的,并且由于从Node
接管而当前节点启动了该应用程序,或者是由于调用了takeover/2
,或者是由于当前节点比Node
具有更高的优先级。{failover,Node}
如果应用程序是分布式的,并且由于从Node
故障转移而当前节点启动了该应用程序,并且应用程序规范键start_phases /= undefined
。
StartArgs
是由应用程序规范键 mod
定义的 StartArgs
参数。
该函数应返回 {ok,Pid}
或 {ok,Pid,State}
,其中 Pid
是顶级监管进程的 pid,State
是任意项。如果省略,则 State
默认为 []
。如果稍后停止应用程序,则 State
将传递给 Module:prep_stop/1
。
-callback start_phase(Phase, StartType, PhaseArgs) -> ok | {error, Reason} when Phase :: atom(), StartType :: start_type(), PhaseArgs :: term(), Reason :: term().
当启动期间不同应用程序中的进程需要同步时,使用包含的应用程序启动应用程序。
启动阶段由应用程序规范键 start_phases == [{Phase,PhaseArgs}]
定义。 对于包含的应用程序,阶段集合必须是为包含应用程序定义的阶段集合的子集。
该函数针对主应用程序和所有包含的应用程序的每个启动阶段(如为主应用程序定义)调用,前提是定义了启动阶段。
有关 StartType
的说明,请参见 Module:start/2
。
每当应用程序停止时都会调用此函数。它旨在与 Module:start/2
相反,并执行任何必要的清理工作。返回值将被忽略。
State
是 Module:prep_stop/1
的返回值(如果存在此类函数)。 否则,State
取自 Module:start/2
的返回值。
函数
-spec ensure_all_started(Applications, Type, Mode) -> {ok, Started} | {error, AppReason} when Applications :: atom() | [atom()], Type :: restart_type(), Mode :: serial | concurrent, Started :: [atom()], AppReason :: {atom(), term()}.
Applications
可以是表示多个应用程序的 atom/0
或 atom/0
的列表。
此函数等效于在每个应用程序的所有尚未启动的依赖项上重复调用 start/1,2
。 如果可选依赖项可用,也将加载并启动它们。
Mode
参数控制是否应以 serial
模式(一次一个)或 concurrent
模式启动应用程序。 在并发模式下,会构建依赖关系图,并并发递归地启动该图的叶子。 在这两种模式下,都不能断言应用程序的启动顺序。 如果未提供,则默认为 serial
。
对于成功启动或已启动的应用程序(但是,已从 AppNames
列表中省略),返回 {ok, AppNames}
。
该函数针对错误报告 {error, {AppName,Reason}}
,其中 Reason
是启动特定依赖项时 start/1,2
返回的任何可能的原因。
如果发生错误,则会停止由该函数启动的应用程序,以使正在运行的应用程序集恢复到其初始状态。
-spec ensure_started(Application) -> ok | {error, Reason} when Application :: atom(), Reason :: term().
等效于 start(Application)
,但对于已启动的应用程序返回 ok
。
-spec ensure_started(Application, Type) -> ok | {error, Reason} when Application :: atom(), Type :: restart_type(), Reason :: term().
等效于 start(Application, Type)
,但对于已启动的应用程序返回 ok
。
-spec get_all_env(Application) -> Env when Application :: atom(), Env :: [{Par :: atom(), Val :: term()}].
返回 Application
的配置参数及其值。
如果指定的应用程序未加载,或者执行调用的进程不属于任何应用程序,则该函数返回 []
。
-spec get_all_key(Application) -> undefined | Keys when Application :: atom(), Keys :: {ok, [{Key :: atom(), Val :: term()}, ...]}.
返回 Application
的应用程序规范键及其值。如果省略参数,则默认为调用进程的应用程序。
如果指定的应用程序未加载,则该函数返回 undefined
。 如果执行调用的进程不属于任何应用程序,则该函数返回 []
。
-spec get_application() -> undefined | {ok, Application} when Application :: atom().
-spec get_application(PidOrModule) -> undefined | {ok, Application} when PidOrModule :: (Pid :: pid()) | (Module :: module()), Application :: atom().
返回进程 Pid
或模块 Module
所属的应用程序的名称。
如果指定的进程不属于任何应用程序,或者指定的进程或模块不存在,则该函数返回 undefined
。
-spec get_env(Application, Par) -> undefined | {ok, Val} when Application :: atom(), Par :: atom(), Val :: term().
返回 Application
的配置参数 Par
的值。
如果满足以下任一条件,则返回 undefined
- 指定的应用程序未加载。
- 配置参数不存在。
- 执行调用的进程不属于任何应用程序。
-spec get_env(Application, Par, Def) -> Val when Application :: atom(), Par :: atom(), Def :: term(), Val :: term().
与 get_env/2
的工作方式类似,但当配置参数 Par
不存在时返回值 Def
。
-spec get_key(Application, Key) -> undefined | {ok, Val} when Application :: atom(), Key :: atom(), Val :: term().
返回 Application
的应用程序规范键 Key
的值。
如果满足以下任一条件,则返回 undefined
- 指定的应用程序未加载。
- 规范键不存在。
- 执行调用的进程不属于任何应用程序。
-spec get_supervisor(Application) -> undefined | {ok, Pid} when Pid :: pid(), Application :: atom().
返回在 Application
根目录运行的监督者的 Pid
。
如果指定的应用程序不存在或未定义回调模块,则该函数返回 undefined
。
-spec load(AppDescr) -> ok | {error, Reason} when AppDescr :: Application | (AppSpec :: application_spec()), Application :: atom(), Reason :: term().
等效于 load(AppDescr, [])
。
-spec load(AppDescr, Distributed) -> ok | {error, Reason} when AppDescr :: Application | (AppSpec :: application_spec()), Application :: atom(), Distributed :: {Application, Nodes} | {Application, Time, Nodes} | default, Nodes :: [node() | tuple_of(node())], Time :: pos_integer(), Reason :: term().
将应用程序的应用程序规范加载到应用程序控制器中。它还会加载任何包含的应用程序的应用程序规范。请注意,该函数不会加载 Erlang 目标代码。
可以通过其名称 Application
指定应用程序。 在这种情况下,应用程序控制器将在代码路径中搜索应用程序资源文件 Application.app
并加载其中包含的规范。
应用程序规范也可以直接指定为元组 AppSpec
,其格式和内容如 app
中所述。
如果 Distributed == {Application,[Time,]Nodes}
,则应用程序变为分布式。 此参数将覆盖内核配置参数 distributed
中应用程序的值。 Application
必须是应用程序名称(与第一个参数中的相同)。 如果节点崩溃并且指定了 Time
,则应用程序控制器会等待 Time
毫秒,然后再尝试在另一个节点上重新启动应用程序。 如果未指定 Time
,则默认为 0
,并且应用程序会立即重新启动。
Nodes
是可以在其中运行应用程序的节点名称列表,从左到右优先级排列。 可以使用元组对节点名称进行分组,以指示它们具有相同的优先级。
示例
Nodes = [cp1@cave, {cp2@cave, cp3@cave}]
这意味着应用程序最好在 cp1@cave
启动。 如果 cp1@cave
宕机,则应在 cp2@cave
或 cp3@cave
启动应用程序。
如果 Distributed == default
,则使用内核配置参数 distributed
中应用程序的值。
-spec loaded_applications() -> [{Application, Description, Vsn}] when Application :: atom(), Description :: string(), Vsn :: string().
返回一个列表,其中包含有关使用 load/1,2
加载的应用程序和包含的应用程序的信息。Application
是应用程序名称。Description
和 Vsn
分别是其 description
和 vsn
应用程序规范键的值。
-spec permit(Application, Permission) -> ok | {error, Reason} when Application :: atom(), Permission :: boolean(), Reason :: term().
更改 Application
在当前节点上运行的权限。必须使用 load/1,2
加载应用程序,该函数才能生效。
如果已加载但未启动的应用程序的权限设置为 false
,则 start
返回 ok
,但该应用程序在权限设置为 true
之前不会启动。
如果正在运行的应用程序的权限设置为 false
,则会停止该应用程序。 如果稍后将权限设置为 true
,则会重新启动该应用程序。
如果应用程序是分布式的,则将权限设置为 false
意味着该应用程序将根据其分布配置启动或移动到另一个节点(请参见 load/2
)。
在应用程序启动、停止或成功移动到另一个节点之前,该函数不会返回。 但是,在某些情况下,如果权限设置为 true
,则即使应用程序未启动,该函数也会返回 ok
。 当应用程序由于依赖于其他尚未启动的应用程序而无法启动时,情况就是如此。 当这些应用程序启动时,也将启动 Application
。
默认情况下,所有应用程序都在所有节点上加载,权限为 true
。 可以使用内核配置参数 permissions
配置权限。
-spec set_env(Config) -> ok when Config :: [{Application, Env}], Application :: atom(), Env :: [{Par :: atom(), Val :: term()}].
等效于 set_env(Config, [])
。
-spec set_env(Config, Opts) -> ok when Config :: [{Application, Env}], Application :: atom(), Env :: [{Par :: atom(), Val :: term()}], Opts :: [{timeout, timeout()} | {persistent, boolean()}].
为多个应用程序设置配置 Config
。
它等效于单独调用每个应用程序的 set_env/4
,但效率更高。给定的 Config
在配置设置之前会进行验证。
set_env/2
使用标准的 gen_server
超时值(5000 毫秒)。如果需要其他超时值,可以指定选项 timeout
,例如,在应用程序控制器负载很重的情况下。
可以将选项 persistent
设置为 true
,以保证使用 set_env/2
设置的参数在加载时不会被应用程序资源文件中定义的参数覆盖。这意味着持久值在应用程序加载后以及应用程序重新加载时都会保持不变。
如果一个应用程序被多次给定,或者如果一个应用程序的同一个键被多次给定,则行为是未定义的,并且会记录一条警告消息。在未来的版本中,将会引发错误。
警告
仅当您了解自己在做什么时才使用此函数,也就是说,在您自己的应用程序上使用。当应用程序读取该值的时间和频率时,它非常依赖于应用程序和配置参数。不小心使用此函数可能会使应用程序处于奇怪、不一致和功能失常的状态。
-spec set_env(Application, Par, Val, Opts) -> ok when Application :: atom(), Par :: atom(), Val :: term(), Opts :: [{timeout, timeout()} | {persistent, boolean()}].
设置 Application
的配置参数 Par
的值。
set_env/4
使用标准的 gen_server
超时值(5000 毫秒)。如果需要其他超时值,可以指定选项 timeout
,例如,在应用程序控制器负载很重的情况下。
如果在应用程序加载之前调用 set_env/4
,则文件 Application.app
中指定的应用程序环境值会覆盖先前设置的值。这对于应用程序重新加载也是如此。
可以将选项 persistent
设置为 true
,以保证使用 set_env/4
设置的参数在加载时不会被应用程序资源文件中定义的参数覆盖。这意味着持久值在应用程序加载后以及应用程序重新加载时都会保持不变。
警告
仅当您了解自己在做什么时才使用此函数,也就是说,在您自己的应用程序上使用。当应用程序读取该值的时间和频率时,它非常依赖于应用程序和配置参数。不小心使用此函数可能会使应用程序处于奇怪、不一致和功能失常的状态。
-spec start(Application, Type) -> ok | {error, Reason} when Application :: atom(), Type :: restart_type(), Reason :: term().
启动 Application
。如果未加载,应用程序控制器会先使用 load/1
加载它。它确保加载任何包含的应用程序,但不启动它们。这假定在 Application
的代码中处理。
应用程序控制器检查应用程序规范键 applications
的值,以确保在此应用程序启动之前需要启动的所有应用程序都正在运行。如果缺少应用程序且该应用程序未标记为可选,则返回 {error,{not_started,App}}
,其中 App
是缺少的应用程序的名称。请注意,此函数不会尝试启动 applications
中列出的任何应用程序,甚至包括可选的应用程序。有关递归启动当前应用程序及其依赖项的信息,请参阅 ensure_all_started/1,2
。
验证后,应用程序控制器将为应用程序创建一个应用程序主进程。应用程序主进程成为应用程序中所有进程的组长。I/O 将转发到之前的组长,但这只是一种识别属于该应用程序的进程的方法。例如,用于从任何进程找到自身,或者相反地,在它终止时杀死所有进程。
应用程序主进程通过调用应用程序规范键 mod
定义的应用程序回调函数 Module:start/2
来启动应用程序。
参数 Type
指定应用程序的类型。如果省略,则默认为 temporary
。
- 如果永久应用程序终止,则所有其他应用程序和整个 Erlang 节点也将终止。
- 如果瞬态应用程序终止
- 且
Reason == normal
,则会报告此情况,但不会终止其他应用程序。 - 异常终止,则所有其他应用程序和整个 Erlang 节点也将终止。
- 且
- 如果临时应用程序终止,则会报告此情况,但不会终止其他应用程序。
请注意,始终可以通过调用 stop/1
来显式停止应用程序。无论应用程序的类型如何,都不会影响其他应用程序。
另请注意,瞬态类型实际上用处不大,因为当监管树终止时,原因会设置为 shutdown
,而不是 normal
。
-spec start_type() -> StartType | undefined | local when StartType :: start_type().
此函数旨在由属于应用程序的进程在应用程序启动时调用,以确定启动类型,该类型为 StartType
或 local
。
有关 StartType
的描述,请参阅 Module:start/2
。
如果仅重新启动应用程序的部分(由监管器),或者如果在启动之外调用该函数,则返回 local
。
如果执行调用的进程不属于任何应用程序,则该函数返回 undefined
。
停止 Application
。应用程序主服务器调用 Module:prep_stop/1
(如果定义了此类函数),然后告诉应用程序的顶级监督者关闭(请参阅 supervisor
)。
这意味着整个监管树,包括包含的应用程序,将以相反的启动顺序终止。关闭后,应用程序主进程将调用 Module:stop/1
。Module
是应用程序规范键 mod
定义的回调模块。
最后,应用程序主进程终止。请注意,以应用程序主进程作为组长的所有进程,即从属于应用程序的进程生成的进程,也将终止。
停止时,应用程序仍处于加载状态。
要停止分布式应用程序,必须在它可以执行的所有节点上(即,在它已启动的所有节点上)调用 stop/1
。在应用程序当前执行的节点上调用 stop/1
将停止其执行。应用程序不会在节点之间移动,因为在其他节点上调用 stop/1
之前,会在应用程序当前执行的节点上调用 stop/1
。
-spec takeover(Application, Type) -> ok | {error, Reason} when Application :: atom(), Type :: restart_type(), Reason :: term().
接管在另一个节点 Node
上执行的分布式应用程序 Application
。
在当前节点上,通过调用 Module:start({takeover,Node},StartArgs)
来重新启动应用程序。Module
和 StartArgs
是从加载的应用程序规范中检索的。在启动完成之前,即当 Module:start/2
和任何对 Module:start_phase/3
的调用都返回时,不会停止其他节点上的应用程序。
因此,在接管期间,应用程序的两个实例同时运行,以便可以将数据从旧实例传输到新实例。如果这不是可接受的行为,则可以在启动新实例时关闭旧实例的部分。但是,应用程序不能完全停止,至少顶层监管器必须保持活动状态。
有关 Type
的描述,请参阅 start/1,2
。
从应用程序控制器卸载 Application
的应用程序规范。它还会卸载任何包含的应用程序的应用程序规范。请注意,该函数不会清除 Erlang 目标代码。
-spec unset_env(Application, Par, Opts) -> ok when Application :: atom(), Par :: atom(), Opts :: [{timeout, timeout()} | {persistent, boolean()}].
删除 Application
的配置参数 Par
及其值。
unset_env/3
使用标准的 gen_server
超时值(5000 毫秒)。如果需要其他超时值,可以指定选项 timeout
,例如,在应用程序控制器负载很重的情况下。
unset_env/3
还允许传递 persistent 选项(请参阅 set_env/4
)。
警告
仅当您了解自己在做什么时才使用此函数,也就是说,在您自己的应用程序上使用。当应用程序读取该值的时间和频率时,它非常依赖于应用程序和配置参数。不小心使用此函数可能会使应用程序处于奇怪、不一致和功能失常的状态。
-spec which_applications(Timeout) -> [{Application, Description, Vsn}] when Timeout :: timeout(), Application :: atom(), Description :: string(), Vsn :: string().
返回一个列表,其中包含有关当前正在运行的应用程序的信息。
Application
是应用程序名称。Description
和 Vsn
分别是其 description
和 vsn
应用程序规范键的值。
在应用程序控制器负载很重的情况下,可以指定 Timeout
参数。