檢視原始碼 應用程式 行為 (Elixir v1.16.2)
一個用於處理應用程式和定義應用程式回呼的模組。
應用程式是包裝 Erlang/OTP 軟體的慣用語法。簡單來說,它們類似於其他程式語言中常見的「函式庫」概念,但具有一些額外的特性。
應用程式是一個實作特定功能的元件,具有標準化的目錄結構、設定檔和生命週期。應用程式會「載入」、「啟動」和「停止」。每個應用程式也有自己的環境,提供一個統一的 API 來設定每個應用程式。
開發人員通常會與應用程式環境及其回呼模組互動。因此,在深入探討應用程式資源檔案和生命週期之前,這些將會是我們首先探討的主題。
應用程式環境
每個應用程式都有自己的環境。環境是一個關鍵字清單,將原子對應到術語。請注意,此環境與作業系統環境無關。
預設情況下,應用程式的環境是一個空清單。在 Mix 專案的 mix.exs
檔案中,您可以在 application/0
中設定 :env
鍵
def application do
[env: [db_host: "localhost"]]
end
現在,在您的應用程式中,您可以使用 fetch_env!/2
等函式來讀取此環境
defmodule MyApp.DBClient do
def start_link() do
SomeLib.DBClient.start_link(host: db_host())
end
defp db_host do
Application.fetch_env!(:my_app, :db_host)
end
end
在 Mix 專案中,應用程式及其依賴項的環境可以透過 config/config.exs
和 config/runtime.exs
檔案來覆寫。前者在建置時載入,在您的程式碼編譯之前載入,而後者在執行時載入,就在您的應用程式啟動之前。例如,使用您應用程式的人可以如下覆寫其 :db_host
環境變數
import Config
config :my_app, :db_host, "db.local"
有關更多資訊,請參閱 Mix
模組中的「組態」區段。您也可以使用 put_env/3
和 delete_env/2
等函式,動態變更應用程式環境。
函式庫中的環境
函式庫很少使用組態檔
config/config.exs
和config/runtime.exs
。函式庫通常在mix.exs
的application/0
函式中定義其環境。組態檔反而是由應用程式用來組態其函式庫。
讀取其他應用程式的環境
每個應用程式都負責自己的環境。不要使用此模組中的函式直接存取或修改其他應用程式的環境。每當您變更應用程式環境時,Elixir 的建置工具只會重新編譯屬於該應用程式的檔案。因此,如果您讀取其他應用程式的應用程式環境,您可能會依賴過時的組態,因為您的檔案並不會在組態變更時重新編譯。
編譯時期環境
在先前的範例中,我們在執行時期讀取應用程式環境
defmodule MyApp.DBClient do
def start_link() do
SomeLib.DBClient.start_link(host: db_host())
end
defp db_host do
Application.fetch_env!(:my_app, :db_host)
end
end
換句話說,應用程式 :my_app
的環境金鑰 :db_host
只有在 MyApp.DBClient
有效啟動時才會被讀取。雖然在執行時期讀取應用程式環境是首選方法,但在某些罕見情況下,您可能想使用應用程式環境來組態特定專案的編譯。但是,如果您嘗試在函式外存取 Application.fetch_env!/2
defmodule MyApp.DBClient do
@db_host Application.fetch_env!(:my_app, :db_host)
def start_link() do
SomeLib.DBClient.start_link(host: @db_host)
end
end
您可能會看到警告和錯誤
warning: Application.fetch_env!/2 is discouraged in the module body,
use Application.compile_env/3 instead
iex:3: MyApp.DBClient
** (ArgumentError) could not fetch application environment :db_host
for application :my_app because the application was not loaded nor
configured
這是因為在定義模組時,應用程式環境尚未提供。幸運的是,警告告訴我們如何解決此問題,改用 Application.compile_env/3
defmodule MyApp.DBClient do
@db_host Application.compile_env(:my_app, :db_host, "db.local")
def start_link() do
SomeLib.DBClient.start_link(host: @db_host)
end
end
這裡的差別在於 compile_env
預期預設值會作為引數提供,而不是使用 mix.exs
的 def application
函式。此外,透過使用 compile_env/3
,Mix 等工具會儲存編譯期間使用的值,並在系統每次啟動時將編譯值與執行時期值進行比較,如果不同就會引發錯誤。
無論如何,應避免編譯時期環境。只要有可能,在執行時期讀取應用程式環境應為首選。
應用程式回呼模組
應用程式可以載入、啟動和停止。一般來說,Mix 等建置工具會負責為你啟動應用程式及其所有依賴項,但你也可以透過呼叫手動執行
{:ok, _} = Application.ensure_all_started(:some_app)
當應用程式啟動時,開發人員可以設定執行自訂程式碼的回呼模組。開發人員使用此回呼啟動應用程式監督樹。
這樣做的第一步是在 mix.exs
檔案中的 application/0
定義中新增一個 :mod
鍵。它預期一個元組,其中包含應用程式回呼模組和啟動引數(通常為空清單)
def application do
[mod: {MyApp, []}]
end
提供給 :mod
的 MyApp
模組需要實作 Application
行為。這可以透過在該模組中放入 use Application
並實作 start/2
回呼來完成,例如
defmodule MyApp do
use Application
def start(_type, _args) do
children = []
Supervisor.start_link(children, strategy: :one_for_one)
end
end
use Application
當你
use Application
時,Application
模組會設定@behaviour Application
並定義stop/1
函式的可覆寫定義,這是 Erlang/OTP 所要求的。
start/2
回呼必須產生並連結一個監督程式,並傳回 {:ok, pid}
或 {:ok, pid, state}
,其中 pid
是監督程式的 PID,而 state
是選用的應用程式狀態。 args
是提供給 :mod
選項的元組的第二個元素。
傳遞給 start/2
的 type
引數通常為 :normal
,除非是在已設定應用程式接管和故障轉移的分布式設定中。分布式應用程式不在本文件說明的範圍內。
當應用程式正在關閉時,其 stop/1
回呼會在執行時期停止監督樹後被呼叫。此回呼允許應用程式執行任何最終清理。引數是 start/2
傳回的狀態(如果有的話),否則為 []
。 stop/1
的傳回值會被忽略。
透過使用 Application
,模組會取得 stop/1
的預設實作,它會忽略其引數並傳回 :ok
,但它可以被覆寫。
應用程式回呼模組也可以實作可選的回呼 prep_stop/1
。如果存在,prep_stop/1
會在監督樹狀結構終止之前呼叫。其引數是 start/2
傳回的狀態(如果有的話),否則為 []
,而其傳回值會傳遞給 stop/1
。
應用程式資源檔案
在上述各節中,我們已在 mix.exs
檔案的 application/0
節中設定應用程式。最終,Mix 會使用此設定來建立 應用程式資源檔案,這是一個稱為 APP_NAME.app
的檔案。例如,OTP 應用程式 ex_unit
的應用程式資源檔案稱為 ex_unit.app
。
您可以在 Mix.Tasks.Compile.App
的文件了解有關產生應用程式資源檔案的更多資訊,也可以透過執行 mix help compile.app
來取得。
應用程式生命週期
載入應用程式
應用程式會載入,這表示執行時期會尋找並處理其資源檔案
Application.load(:ex_unit)
#=> :ok
當載入應用程式時,其資源檔案中指定的環境會與設定檔中的任何覆寫項目合併。
載入應用程式不會載入其模組。
實際上,您很少手動載入應用程式,因為那是啟動程序的一部分,說明如下。
啟動應用程式
應用程式也會啟動
Application.start(:ex_unit)
#=> :ok
編譯應用程式後,執行系統就是啟動目前應用程式及其相依項目的問題。與其他語言不同,Elixir 沒有負責啟動系統的 main
程序。相反地,您會啟動一個或多個應用程式,每個應用程式都有自己的初始化和終止邏輯。
當應用程式啟動時,Application.load/1
會自動呼叫(如果尚未呼叫)。接著,它會檢查資源檔案中 applications
鍵所列出的依賴項是否已啟動。如果至少有一個依賴項未啟動,則會產生錯誤狀況。像 ensure_all_started/1
等函式會負責為您啟動應用程式及其所有依賴項。
如果應用程式未設定回呼模組,則會在這個時候啟動。否則,會呼叫其 start/2
回呼。執行階段會儲存此函式傳回的頂層監督 PID 以供後續使用,也會儲存傳回的應用程式狀態(如果有)。
停止應用程式
已啟動的應用程式最後會停止
Application.stop(:ex_unit)
#=> :ok
已定義停止沒有回呼模組的應用程式,但除了某些系統追蹤之外,實際上不會執行任何操作。
停止有回呼模組的應用程式有三個步驟
- 如果存在,呼叫選用回呼
prep_stop/1
。 - 終止頂層監督。
- 呼叫必要的回呼
stop/1
。
傳遞給回呼的引數與 start/2
選用傳回的狀態有關,並記載於上方關於回呼模組的章節中。
重要的是,第 2 步驟會造成封鎖。終止監督會觸發子項終止的遞迴鏈,因此會依序關閉所有後代流程。stop/1
回呼只會在終止整個監督樹狀結構後呼叫。
呼叫 System.stop/1
可以乾淨地關閉執行中的系統。它會以與啟動時相反的順序關閉每個應用程式。
預設情況下,來自作業系統的 SIGTERM 會自動轉換為 System.stop/0
。您也可以透過 :os.set_signal/2
函式更明確地控制作業系統訊號。
工具
Mix 建置工具會自動執行大部分的應用程式管理工作。例如,mix test
會在執行測試之前自動啟動您的應用程式依賴項和應用程式本身。mix run --no-halt
會啟動您目前的專案,可用於啟動長時間執行的系統。請參閱 mix help run
。
開發人員也可以使用 mix release
建置發行版。發行版可以將您的所有原始碼和 Erlang VM 封裝到一個目錄中。發行版也讓您可以明確控制每個應用程式的啟動方式和順序。它們還提供更簡化的機制,用於啟動和停止系統、除錯、記錄和系統監控。
最後,Elixir 提供了諸如 escripts 和 archives 等工具,它們是封裝應用程式的不同機制。這些工具通常用於開發人員之間必須共享工具時,而不是作為部署選項。有關更多詳細資訊,請參閱 mix help archive.build
和 mix help escript.build
。
進一步資訊
有關應用程式的更多詳細資訊,請查看 :application
Erlang 模組 的文件,以及 應用程式 部分的 OTP 設計原則使用者指南。
摘要
函式
取得 app 的目錄。
傳回 app_dir/1
中指定的路徑。
在編譯時讀取應用程式環境。
從巨集中在編譯時讀取應用程式環境。
在編譯時讀取應用程式環境或引發例外。
從巨集中在編譯時讀取應用程式環境或引發例外。
從指定的 app
環境中刪除 key
。
確保指定的 app
或 apps
及其子應用程式已啟動。
確保指定的 app
已載入。
確保指定的 app
已使用 restart_type/0
啟動。
傳回 app
環境中 key
的值,以元組表示。
傳回 app
環境中 key
的值。
格式化 start/2
、ensure_started/2
、stop/1
、load/1
和 unload/1
傳回的錯誤原因,傳回字串。
傳回 app
的所有金鑰值對。
取得給定模組的應用程式。
傳回 app
環境中 key
的值。
載入給定的 app
。
傳回已載入應用程式的資訊清單。
同時設定多個應用程式的環境。
將 value
設定為給定 app
的 key
。
傳回 app
的規格。
傳回 app
規格中 key
的值。
使用 restart_type/0
啟動給定的 app
。
傳回目前正在執行的應用程式資訊清單。
停止給定的 app
。
卸載給定的 app
。
類型
@type app() :: atom()
@type application_key() ::
:start_phases
| :mod
| :applications
| :optional_applications
| :included_applications
| :registered
| :maxT
| :maxP
| :modules
| :vsn
| :id
| :description
@type key() :: atom()
@type restart_type() :: :permanent | :transient | :temporary
指定應用程式的類型
:permanent
- 如果app
終止,所有其他應用程式和整個節點也會終止。:transient
- 如果app
以:normal
原因終止,會回報,但不會終止其他應用程式。如果暫時性應用程式異常終止,所有其他應用程式和整個節點也會終止。:temporary
- 如果app
終止,會回報,但不會終止其他應用程式(預設值)。
請注意,始終可以透過呼叫 stop/1
明確停止應用程式。無論應用程式的類型為何,都不會影響其他應用程式。
另請注意,:transient
類型幾乎沒有實際用途,因為當監督樹終止時,原因會設定為 :shutdown
,而不是 :normal
。
@type state() :: term()
@type value() :: term()
回呼
@callback config_change(changed, new, removed) :: :ok when changed: keyword(), new: keyword(), removed: [atom()]
如果應用程式環境已變更,則在程式碼升級後呼叫回呼。
changed
是應用程式環境中變更的鍵值清單。 new
是包含所有新鍵值清單的關鍵字清單。 removed
是包含所有已移除鍵值的清單。
在停止應用程式之前呼叫。
此函式會在頂層監督程式終止之前呼叫。它會接收 start/2
傳回的狀態(如果有的話),否則會接收 []
。傳回值稍後會傳遞給 stop/1
。
@callback start(start_type(), start_args :: term()) :: {:ok, pid()} | {:ok, pid(), state()} | {:error, reason :: term()}
在啟動應用程式時呼叫。
此函式會在使用 Application.start/2
(以及其上的函式,例如 Application.ensure_started/2
)啟動應用程式時呼叫。此函式應啟動應用程式的頂層程序(如果應用程式遵循 OTP 設計原則,應為應用程式監督樹的頂層監督程式)。
start_type
定義應用程式的啟動方式
:normal
- 如果啟動為正常啟動,或如果應用程式是分散式的,並且因為從另一個節點故障轉移而啟動於目前節點,且應用程式規格鍵:start_phases
為:undefined
,則使用此選項。{:takeover, node}
- 如果應用程式是分散式的,並且因為節點node
上的故障轉移而啟動於目前節點,則使用此選項。{:failover, node}
- 如果應用程式是分散式的,並且因為節點node
上的故障轉移而啟動於目前節點,且應用程式規格鍵:start_phases
不為:undefined
,則使用此選項。
start_args
是傳遞給 :mod
規格鍵中應用程式的引數(例如,mod: {MyApp, [:my_args]}
)。
此函數應回傳 {:ok, pid}
或 {:ok, pid, state}
,如果啟動成功的話。pid
應為頂層監控者的 PID。state
可以是任意項目,如果省略的話會預設為 []
;如果應用程式稍後停止,state
會傳遞給 stop/1
回呼(更多資訊請參閱 stop/1
回呼的文件)。
use Application
未提供 start/2
回呼的預設實作。
@callback start_phase(phase :: term(), start_type(), phase_args :: term()) :: :ok | {:error, reason :: term()}
在同步階段啟動應用程式。
此函數會在 start/2
完成後,但在 Application.start/2
回傳前呼叫。它會在應用程式(和任何包含的應用程式)規格中定義的每個啟動階段呼叫一次,順序與列出的順序相同。
在停止應用程式後呼叫。
此函數會在應用程式停止後呼叫,也就是在它的監控樹停止後。它應執行與 start/2
回呼相反的動作,並執行任何必要的清理。此回呼的回傳值會被忽略。
state
是 start/2
回傳的狀態(如果有的話),否則為 []
。如果選用的回呼 prep_stop/1
存在,state
會是它的回傳值。
use Application
定義此函數的預設實作,它什麼都不做,只回傳 :ok
。
函數
取得 app 的目錄。
此資訊是根據程式碼路徑回傳的。以下是一個範例
File.mkdir_p!("foo/ebin")
Code.prepend_path("foo/ebin")
Application.app_dir(:foo)
#=> "foo"
即使目錄是空的,而且沒有 .app
檔案,它仍會基於名稱「foo/ebin」視為應用程式目錄。名稱可能包含破折號 -
,它會視為應用程式版本,並在查詢目的中移除它
File.mkdir_p!("bar-123/ebin")
Code.prepend_path("bar-123/ebin")
Application.app_dir(:bar)
#=> "bar-123"
傳回 app_dir/1
中指定的路徑。
如果 path
是字串,則會將其用作 app_dir/1
內的路徑。如果 path
是字串清單,則會將其串接(請參閱 Path.join/1
),並將結果用作 app_dir/1
內的路徑。
範例
File.mkdir_p!("foo/ebin")
Code.prepend_path("foo/ebin")
Application.app_dir(:foo, "my_path")
#=> "foo/my_path"
Application.app_dir(:foo, ["my", "nested", "path"])
#=> "foo/my/nested/path"
在編譯時讀取應用程式環境。
類似於 get_env/3
,但它必須用於在編譯時讀取值。這允許 Elixir 追蹤配置值在編譯時和執行時之間的變更。
第一個引數是應用程式名稱。第二個引數 key_or_path
是一個原子鍵或用於在搜尋配置時穿透的路徑,從原子鍵開始。
例如,假設有以下配置
config :my_app, :key, [foo: [bar: :baz]]
我們可以在編譯時透過以下方式存取它
Application.compile_env(:my_app, :key)
#=> [foo: [bar: :baz]]
Application.compile_env(:my_app, [:key, :foo])
#=> [bar: :baz]
Application.compile_env(:my_app, [:key, :foo, :bar])
#=> :baz
也可以將預設值提供為第三個引數。如果路徑中任何鍵在途中遺失,則會使用預設值
Application.compile_env(:my_app, [:unknown, :foo, :bar], :default)
#=> :default
Application.compile_env(:my_app, [:key, :unknown, :bar], :default)
#=> :default
Application.compile_env(:my_app, [:key, :foo, :unknown], :default)
#=> :default
提供路徑有助於讓 Elixir 知道大型配置中只有特定路徑會依賴於編譯時。
從巨集中在編譯時讀取應用程式環境。
通常,開發人員會使用 compile_env/3
。此函數只能從旨在動態讀取編譯環境的巨集中呼叫。
它預期第一個參數為 Macro.Env
,其中 Macro.Env
通常是巨集中的 __CALLER__
。如果 Macro.Env
來自函式,它會引發錯誤。
在編譯時讀取應用程式環境或引發例外。
這與 compile_env/3
相同,但如果組態不存在,它會引發 ArgumentError
。
@spec compile_env!(Macro.Env.t(), app(), key() | list()) :: value()
從巨集中在編譯時讀取應用程式環境或引發例外。
通常,開發人員會使用 compile_env!/2
。此函式只能從旨在動態讀取編譯環境的巨集中呼叫。
它預期第一個參數為 Macro.Env
,其中 Macro.Env
通常是巨集中的 __CALLER__
。如果 Macro.Env
來自函式,它會引發錯誤。
從指定的 app
環境中刪除 key
。
它接收與 put_env/4
相同的選項。傳回 :ok
。
@spec ensure_all_started(app() | [app()], type: restart_type(), mode: :serial | :concurrent ) :: {:ok, [app()]} | {:error, term()}
@spec ensure_all_started(app() | [app()], restart_type()) :: {:ok, [app()]} | {:error, term()}
確保指定的 app
或 apps
及其子應用程式已啟動。
第二個參數可能是 t:restart_type/1
(為了與 start/2
一致)或關鍵字清單。
選項
:type
- 如果應用程式應在:permanent
、:temporary
或:transient
中啟動。有關更多資訊,請參閱t:restart_type/1
。:mode
- (自 v1.15.0 起) 如果應用程式應串列或並行啟動。此選項需要 Erlang/OTP 26+。
確保指定的 app
已載入。
與 load/1
相同,但如果應用程式已載入,則傳回 :ok
。
@spec ensure_started(app(), restart_type()) :: :ok | {:error, term()}
確保指定的 app
已使用 restart_type/0
啟動。
與 start/2
相同,但如果應用程式已啟動,則傳回 :ok
。
傳回 app
環境中 key
的值,以元組表示。
如果組態參數不存在,函式會傳回 :error
。
警告
您必須使用此函式僅讀取自己的應用程式環境。請勿讀取其他應用程式的環境。
資訊中的應用程式環境
如果您正在撰寫供其他開發人員使用的函式庫,通常建議避免使用應用程式環境,因為應用程式環境實際上是一個全域儲存。有關更多資訊,請閱讀我們的 函式庫指南。
傳回 app
環境中 key
的值。
如果組態參數不存在,會引發 ArgumentError
。
警告
您必須使用此函式僅讀取自己的應用程式環境。請勿讀取其他應用程式的環境。
資訊中的應用程式環境
如果您正在撰寫供其他開發人員使用的函式庫,通常建議避免使用應用程式環境,因為應用程式環境實際上是一個全域儲存。有關更多資訊,請閱讀我們的 函式庫指南。
格式化 start/2
、ensure_started/2
、stop/1
、load/1
和 unload/1
傳回的錯誤原因,傳回字串。
傳回 app
的所有金鑰值對。
取得給定模組的應用程式。
這個應用程式是透過分析所有已載入應用程式的規格來定位的。如果模組未列在任何應用程式規格中,則會傳回 nil
。
傳回 app
環境中 key
的值。
如果組態參數不存在,函式會傳回 default
值。
警告
您必須使用此函式僅讀取自己的應用程式環境。請勿讀取其他應用程式的環境。
函式庫中的應用程式環境
如果您正在撰寫供其他開發人員使用的函式庫,通常建議避免使用應用程式環境,因為應用程式環境實際上是一個全域儲存。有關更多資訊,請閱讀我們的 函式庫指南。
範例
get_env/3
通常用於讀取 OTP 應用程式的組態。由於 Mix 組態通常用於組態應用程式,因此我們將以此為例說明。
考慮一個新的應用程式 :my_app
。 :my_app
包含一個資料庫引擎,支援資料庫池。資料庫引擎需要知道這些資料庫的組態,而這些組態是由 :my_app
環境中的鍵值對提供的。
config :my_app, Databases.RepoOne,
# A database configuration
ip: "localhost",
port: 5433
config :my_app, Databases.RepoTwo,
# Another database configuration (for the same OTP app)
ip: "localhost",
port: 20717
config :my_app, my_app_databases: [Databases.RepoOne, Databases.RepoTwo]
由 :my_app
使用的資料庫引擎需要知道有哪些資料庫,以及資料庫組態為何。資料庫引擎可以呼叫 Application.get_env(:my_app, :my_app_databases, [])
來擷取資料庫清單(由模組名稱指定)。
然後,引擎可以遍歷清單中的每個儲存庫,並呼叫 Application.get_env(:my_app, Databases.RepoOne)
等來擷取每個儲存庫的組態。在此情況下,每個組態都會是關鍵字清單,因此你可以使用 Keyword
模組或甚至是 Access
模組中的函式來遍歷它,例如
config = Application.get_env(:my_app, Databases.RepoOne)
config[:ip]
載入給定的 app
。
為了載入,.app
檔案必須在載入路徑中。所有 :included_applications
也將會載入。
載入應用程式不會啟動它或載入其模組,但它會載入其環境。
傳回已載入應用程式的資訊清單。
同時設定多個應用程式的環境。
提供的組態不應該
- 列出同一個應用程式超過一次
- 在同一個應用程式中列出同一個金鑰超過一次
如果未滿足這些條件,它會引發例外。
它接收與 put_env/4
相同的選項。傳回 :ok
。
將 value
設定為給定 app
的 key
。
選項
:timeout
- 變更的逾時時間(預設為5_000
毫秒):persistent
- 在應用程式載入和重新載入時保留給定的值
如果在載入應用程式之前呼叫 put_env/4
,.app
檔案中指定的應用程式環境值將會覆寫先前設定的值。
當需要保證使用此函式設定的參數不會在載入時被應用程式資源檔案中定義的參數覆寫時,可以將 :persistent
選項設定為 true
。這表示在載入應用程式以及重新載入應用程式後,永久值仍會保留。
@spec spec(app()) :: [{application_key(), value()}] | nil
傳回 app
的規格。
傳回下列金鑰
:description
:id
:vsn
:modules
:maxP
:maxT
:registered
:included_applications
:optional_applications
:applications
:mod
:start_phases
如需所有欄位的說明,請參閱 Erlang 應用程式規格。
請注意,環境不會傳回,因為它可以透過 fetch_env/2
存取。如果應用程式未載入,則傳回 nil
。
@spec spec(app(), application_key()) :: value() | nil
傳回 app
規格中 key
的值。
請參閱 spec/1
以取得支援的金鑰。如果指定的規格參數不存在,此函式將會引發例外。如果應用程式未載入,則傳回 nil
。
@spec start(app(), restart_type()) :: :ok | {:error, term()}
使用 restart_type/0
啟動給定的 app
。
如果 app
未載入,則會先使用 load/1
載入應用程式。在 .app
檔案的 :included_applications
金鑰中定義的任何包含應用程式也會載入,但它們不會啟動。
此外,在 :applications
金鑰中列出的所有應用程式都必須在這個應用程式之前明確啟動。否則,會傳回 {:error, {:not_started, app}}
,其中 app
是遺失應用程式的名稱。
如果您想要自動載入並啟動 app
的所有相依項,請參閱 ensure_all_started/2
。
傳回目前正在執行的應用程式資訊清單。
停止給定的 app
。
停止時,應用程式仍會載入。
卸載給定的 app
。
它也會卸載所有 :included_applications
。請注意,此函式不會清除應用程式模組。