檢視原始碼 簡介
本節描述在 UNIX 嵌入式系統上運行 Erlang 的特定問題。它描述了與非嵌入式系統相比,安裝和啟動 Erlang 的差異。
關於如何創建目標系統的詳細資訊,請參閱系統原則章節中的建立和升級目標系統。
在 Windows 上運行時,無需進行特殊考量。應該透過 erlsrv
來啟動 Erlang。
安裝嵌入式系統
本節是有關於安裝嵌入式系統。以下主題將被探討
- 建立使用者和安裝目錄
- 安裝嵌入式系統
- 設定開機時自動啟動
- 更改重新啟動的權限
- 設定 TERM 環境變數
本節中的幾個步驟需要對作業系統有專業知識。其中大部分需要超級使用者權限。
建立使用者和安裝目錄
建議嵌入式環境由普通使用者運行,也就是說,該使用者沒有超級使用者權限。
在本節中,假設使用者名稱為 otpuser
,且該使用者的家目錄為
/home/otpuser
還假設在 otpuser
的家目錄中,有一個名為 otp
的目錄,其完整路徑為
/home/otpuser/otp
此目錄是嵌入式環境的安裝目錄。
安裝嵌入式系統
安裝嵌入式系統的程序與一般系統相同(請參閱安裝指南以及系統原則章節中的建立和升級目標系統),但以下情況除外:
- (壓縮的)歸檔檔案應解壓縮到上述定義的安裝目錄中。
- 不需要將啟動腳本連結到像
/usr/local/bin
這樣的標準目錄。
設定開機時自動啟動
真正的嵌入式系統必須在系統開機時啟動。本節說明使用 init.d
啟動腳本來實現此目的所需的必要設定。
如果將下面顯示的腳本檔案添加到 /etc/rc3.d
目錄中,則嵌入式系統和所有應用程式將自動啟動。該檔案必須由 root
擁有且可讀取。它的名稱不能隨意指定;建議使用以下名稱
S75otp.system
有關初始化(和終止)腳本及其命名方式的更多詳細資訊,請參閱作業系統上的 init.d
文件。
#!/bin/sh
#
# File name: S75otp.system
# Purpose: Automatically starts Erlang and applications when the
# system starts
# Author: janne@erlang.ericsson.se
# Resides in: /etc/rc3.d
#
if [ ! -d /usr/bin ]
then # /usr not mounted
exit
fi
killproc() { # kill the named process(es)
pid=`/usr/bin/ps -e |
/usr/bin/grep -w $1 |
/usr/bin/sed -e 's/^ *//' -e 's/ .*//'`
[ "$pid" != "" ] && kill $pid
}
# Start/stop processes required for Erlang
case "$1" in
'start')
# Start the Erlang emulator
#
su - otpuser -c "/home/otpuser/otp/bin/start" &
;;
'stop')
killproc beam
;;
*)
echo "Usage: $0 { start | stop }"
;;
esac
上述腳本中引用的檔案 /home/otpuser/otp/bin/start
正是啟動 Erlang 中描述的 start
腳本。該 start
腳本中的腳本變數 $OTPROOT
對應於本節中使用的以下範例路徑
/home/otpuser/otp
應相應地編輯 start
腳本。
上述腳本中使用 killproc
程序可以與呼叫 erl_call
結合使用,例如
$SOME_PATH/erl_call -n Node init stop
若要優雅地關閉 Erlang,請參閱 erl_interface
中的 erl_call(1)
手冊頁,以取得有關使用 erl_call
的詳細資訊。但是,這需要 Erlang 作為分散式節點運行,但情況並非總是如此。
不得移除 killproc
程序。此處的目的是從運行級別 3(具有網路資源的多使用者模式)移動到運行級別 2(沒有此類資源的多使用者模式),其中不應運行 Erlang。
更改重新啟動的權限
如果要於 啟動 Erlang 的 start
腳本中設定 HEART_COMMAND
環境變數,並且將值設定為 reboot
命令的路徑,也就是說
HEART_COMMAND=/usr/sbin/reboot
那麼必須如下更改 /usr/sbin/reboot
的所有權和檔案權限
chown 0 /usr/sbin/reboot
chmod 4755 /usr/sbin/reboot
另請參閱 Kernel 中的 heart
手冊頁。
設定 TERM 環境變數
當 Erlang 執行階段系統從 S75otp.system
腳本自動啟動時,必須設定 TERM
環境變數。以下是一個最小的設定
TERM=dumb
這要加到 start
腳本中。
啟動 Erlang
本節說明如何啟動嵌入式系統。涉及四個程式,它們通常位於 <ERL_INSTALL_DIR>/bin
目錄中。唯一的例外是 start
程式,它可以位於任何位置,也是唯一一個必須由使用者修改的程式。
在嵌入式系統中,通常沒有互動式 shell。但是,操作員可以透過命令 to_erl
連接到 Erlang 系統。然後,操作員會連線到 Erlang shell,並且可以給予普通的 Erlang 命令。透過此 shell 與系統的所有互動都會記錄在一個特殊的目錄中。
基本上,程序如下
- 當機器啟動時,會呼叫
start
) 程式。 - 它呼叫
run_erl
,它會設定好讓操作員可以連接到系統的內容。 - 它呼叫
start_erl
,它會呼叫正確版本的erlexec
(它位於<ERL_INSTALL_DIR>/erts-EVsn/bin
中),並使用正確的boot
和config
檔案。
程式
start
此程式是在機器啟動時呼叫。可以修改或重寫它以適合特殊系統。預設情況下,必須將它命名為 start
並位於 <ERL_INSTALL_DIR>/bin
中。可以使用 SASL 應用程式中的設定參數 start_prg
來使用另一個啟動程式。
啟動程式必須如下所示呼叫 run_erl
。它還必須採用一個可選參數,預設值為 <ERL_INSTALL_DIR>/releases/start_erl.data
。
此程式是用來設定靜態參數和環境變數,例如 -sname Name
和 HEART_COMMAND
來重新啟動機器。
<RELDIR>
目錄是安裝新版本封包的位置,以及版本處理器保留有關版本資訊的位置。如需更多資訊,請參閱 SASL 中的 release_handler
手冊頁。
以下腳本說明了程式的預設行為
#!/bin/sh
# Usage: start [DataFile]
#
ROOTDIR=/usr/local/otp
if [ -z "$RELDIR" ]
then
RELDIR=$ROOTDIR/releases
fi
START_ERL_DATA=${1:-$RELDIR/start_erl.data}
$ROOTDIR/bin/run_erl /tmp/ $ROOTDIR/log "exec $ROOTDIR/bin/start_erl \
$ROOTDIR $RELDIR $START_ERL_DATA" > /dev/null 2>&1 &
以下腳本說明了修改,其中節點被賦予名稱 cp1
,並且先前的腳本中添加了環境變數 HEART_COMMAND
和 TERM
#!/bin/sh
# Usage: start [DataFile]
#
HEART_COMMAND=/usr/sbin/reboot
TERM=dumb
export HEART_COMMAND TERM
ROOTDIR=/usr/local/otp
if [ -z "$RELDIR" ]
then
RELDIR=$ROOTDIR/releases
fi
START_ERL_DATA=${1:-$RELDIR/start_erl.data}
$ROOTDIR/bin/run_erl /tmp/ $ROOTDIR/log "exec $ROOTDIR/bin/start_erl \
$ROOTDIR $RELDIR $START_ERL_DATA -heart -sname cp1" > /dev/null 2>&1 &
如果要啟動無磁碟和/或唯讀用戶端節點,則檔案 start_erl.data
位於主節點的用戶端目錄中。因此,START_ERL_DATA
行看起來如下所示
CLIENTDIR=$ROOTDIR/clients/clientname
START_ERL_DATA=${1:-$CLIENTDIR/bin/start_erl.data}
run_erl
此程式用於啟動模擬器,但您不會連接到 shell。to_erl
用於連線到 Erlang shell。
Usage: run_erl pipe_dir/ log_dir "exec command [parameters ...]"
這裡
pipe_dir/
為/tmp/
(預設情況下,to_erl
使用此名稱)。log_dir
是寫入日誌檔的位置。- 會執行
command [parameters]
。 - 寫入
stdin
和stdout
的所有內容都會記錄在log_dir
中。
日誌檔會寫入 log_dir
中。每個日誌檔的名稱格式為 erlang.log.N
,其中 N 是一個從 1 到 5 的世代編號。每個日誌檔最多可容納 100 kB 的文字。隨著時間的推移,在日誌檔案目錄中會找到以下日誌檔
erlang.log.1
erlang.log.1, erlang.log.2
erlang.log.1, erlang.log.2, erlang.log.3
erlang.log.1, erlang.log.2, erlang.log.3, erlang.log.4
erlang.log.2, erlang.log.3, erlang.log.4, erlang.log.5
erlang.log.3, erlang.log.4, erlang.log.5, erlang.log.1
...
每一行中最右邊的日誌檔是最近的。也就是說,最新的檔案是編號最高的檔案,如果已經有四個檔案,則是最新的檔案是跳過前的那個檔案。
當開啟日誌檔案(用於附加或建立)時,時間戳記會寫入該檔案。如果 15 分鐘內沒有任何內容寫入日誌檔案,則會插入一條記錄,表示我們仍然存活。
如需更多詳細資訊,請參閱 ERTS 文件中的 run_erl
。
to_erl
此程式用於連接到使用 run_erl
啟動的執行中 Erlang 執行階段系統。
Usage: to_erl [pipe_name | pipe_dir]
這裡 pipe_name
預設為 /tmp/erlang.pipe.N
。
若要從 shell 斷開連接而不退出 Erlang 系統,請輸入 Ctrl-D
。
start_erl
此程式使用設定的參數 -boot
和 -config
啟動 Erlang 模擬器。它從名為 start_erl.data
的檔案中讀取有關這些檔案位置的資料,該檔案位於 <RELDIR>
中。每個新版本都會引入一個新的資料檔案。此檔案由 Erlang 中的版本處理器自動產生。
以下腳本說明了該程式的行為
#!/bin/sh
#
# This program is called by run_erl. It starts
# the Erlang emulator and sets -boot and -config parameters.
# It should only be used at an embedded target system.
#
# Usage: start_erl RootDir RelDir DataFile [ErlFlags ...]
#
ROOTDIR=$1
shift
RELDIR=$1
shift
DataFile=$1
shift
ERTS_VSN=`awk '{print $1}' $DataFile`
VSN=`awk '{print $2}' $DataFile`
BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin
EMU=beam
PROGNAME=`echo $0 | sed 's/.*\///'`
export EMU
export ROOTDIR
export BINDIR
export PROGNAME
export RELDIR
exec $BINDIR/erlexec -boot $RELDIR/$VSN/start -config $RELDIR/$VSN/sys $*
如果一個無碟且/或唯讀的客戶端節點,其 SASL 組態參數 static_emulator
設定為 true
即將啟動,則必須變更 -boot
和 -config
旗標。
由於此類客戶端無法讀取新的 start_erl.data
檔案(該檔案無法動態變更)。啟動和組態檔案始終從相同的位置獲取(但如果已安裝新版本,則內容會更新)。
每當新版本永久化時,release_handler
會將這些檔案複製到主節點上客戶端目錄中的 bin
目錄中。
假設與上述相同的 CLIENTDIR
,最後一行應如下所示
exec $BINDIR/erlexec -boot $CLIENTDIR/bin/start \
-config $CLIENTDIR/bin/sys $*