檢視原始碼 簡介

本節描述在 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。

更改重新啟動的權限

如果要於 啟動 Erlangstart 腳本中設定 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 中),並使用正確的 bootconfig 檔案。

程式

start

此程式是在機器啟動時呼叫。可以修改或重寫它以適合特殊系統。預設情況下,必須將它命名為 start 並位於 <ERL_INSTALL_DIR>/bin 中。可以使用 SASL 應用程式中的設定參數 start_prg 來使用另一個啟動程式。

啟動程式必須如下所示呼叫 run_erl。它還必須採用一個可選參數,預設值為 <ERL_INSTALL_DIR>/releases/start_erl.data

此程式是用來設定靜態參數和環境變數,例如 -sname NameHEART_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_COMMANDTERM

#!/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]
  • 寫入 stdinstdout 的所有內容都會記錄在 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 $*