檢視原始碼 application 行為 (核心 v10.2)
通用的 OTP 應用程式函數
在 OTP 中,application 表示一個實現特定功能、可以作為一個單元啟動和停止,並且可以在其他系統中重複使用的元件。此模組與 application controller 互動,這個程序在每個 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
。 - 如果應用程式是分散式的,並且由於從另一個節點失效轉移而在目前節點上啟動,並且應用程式規格金鑰
start_phases == undefined
,則也是normal
。 - 如果應用程式是分散式的,並且由於從
Node
接管而在目前節點上啟動,則為{takeover,Node}
,無論是因為呼叫了takeover/2
還是因為目前節點的優先順序高於Node
。 - 如果應用程式是分散式的,並且由於從
Node
失效轉移而在目前節點上啟動,並且應用程式規格金鑰start_phases /= undefined
,則為{failover,Node}
。
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}
,應用程式會變成分散式。此引數會覆寫 Kernel 組態參數 distributed
中應用程式的值。Application
必須是應用程式名稱(與第一個引數中的名稱相同)。如果節點崩潰且指定了 Time
,則應用程式控制器會等待 Time
毫秒,然後才嘗試在另一個節點上重新啟動應用程式。如果未指定 Time
,則預設為 0
,且應用程式會立即重新啟動。
Nodes
是應用程式可以執行的節點名稱清單,優先順序由左至右。可以使用元組對節點名稱進行分組,以表示它們具有相同的優先順序。
範例
Nodes = [cp1@cave, {cp2@cave, cp3@cave}]
這表示應用程式最好在 cp1@cave
啟動。如果 cp1@cave
關閉,則應用程式將在 cp2@cave
或 cp3@cave
啟動。
如果 Distributed == default
,則會使用 Kernel 組態參數 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
。可以使用 Kernel 組態參數 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
也允許傳遞持久選項(請參閱 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
引數。