1  嵌入式 Solaris

1  嵌入式 Solaris

本节介绍 OTP 中与 Solaris 相关的操作系统特定部分。

Solaris 在具有 64 MB 总内存的系统上大约占用 17 MB 的 RAM。这为应用程序留下了大约 47 MB 的空间。如果系统使用交换,这些数字无法改善,因为不必要的守护进程会被交换出去。但是,如果禁用交换,或者系统中的交换空间资源有限,那么有必要终止不必要的守护进程。

通过使用核心用户支持安装,可以最大限度地减少 Solaris 需要的磁盘空间。它需要大约 80 MB 的磁盘空间。这只会安装启动和运行 Solaris 所需的最小软件。通过删除不必要的单个文件,可以进一步减少磁盘空间。但是,除非磁盘空间是关键资源,否则所需要的努力和所涉及的风险是不可接受的。

本节介绍如何安装嵌入式系统。将考虑以下主题

  • 创建用户和安装目录
  • 安装嵌入式系统
  • 配置启动时自动启动
  • 使硬件看门狗可用
  • 更改重启权限
  • 设置 TERM 环境变量
  • 添加补丁
  • 在应用程序 os_mon 中安装模块 os_sup

本节中的几个过程需要具备 Solaris 操作系统的专业知识。对于其中大多数,需要超级用户权限。

建议由普通用户运行嵌入式环境,即没有超级用户权限的用户。

在本节中,假设用户名为 otpuser,并且该用户的 home 目录为

        /export/home/otpuser

还假设在 otpuser 的 home 目录中,有一个名为 otp 的目录,其完整路径为

        /export/home/otpuser/otp

该目录是嵌入式环境的 **安装目录**。

安装嵌入式系统的过程与普通系统相同(请参见安装指南),除了以下内容

  • 压缩的磁带归档文件需要解压缩到上面定义的安装目录中。
  • 无需将启动脚本链接到标准目录,例如 /usr/local/bin

真正的嵌入式系统必须在系统启动时启动。本节介绍实现此目标所需配置。

如果将下面显示的脚本文件添加到目录 /etc/rc3.d 中,则嵌入式系统和所有应用程序将自动启动。该文件必须由 root 拥有并可读。它的名称不能任意指定;建议使用以下名称

        S75otp.system

有关初始化(和终止)脚本以及其命名的更多详细信息,请参见 Solaris 文档。

#!/bin/sh
#  
#  File name:  S75otp.system
#  Purpose:    Automatically starts Erlang and applications when the 
#              system starts
#  Author:     [email protected]
#  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 "/export/home/otpuser/otp/bin/start" &
        ;;
'stop')
        killproc beam
        ;;
*)
        echo "Usage: $0 { start | stop }"
        ;;
esac

上面脚本中提到的文件 /export/home/otpuser/otp/bin/start 正是 **启动 Erlang** 中描述的 start 脚本。该 start 脚本中的脚本变量 $OTPROOT 对应于本节中使用的以下示例路径

        /export/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 不应在此模式下运行。

对于在 Force Computers 的 VME 板上运行的 Solaris,可以激活板载硬件看门狗,前提是将 VME 总线驱动程序添加到操作系统中(另请参见安装问题)。

另请参见内核中的 heart(3) 手册页。

如果要在 **启动 Erlang** 中的 start 脚本中设置 HEART_COMMAND 环境变量,并且如果要将其值设置为 Solaris reboot 命令的路径,即

        HEART_COMMAND=/usr/sbin/reboot

那么必须更改 /usr/sbin/reboot 的所有权和文件权限,如下所示

        chown 0 /usr/sbin/reboot
        chmod 4755 /usr/sbin/reboot

另请参见内核中的 heart(3) 手册页。

当 Erlang 运行时系统从 S75otp.system 脚本自动启动时,必须设置 TERM 环境变量。以下是最小设置

        TERM=sun

这需要添加到 start 脚本中。

为了使 Solaris 2.5.1 上的刷新文件系统数据到磁盘功能正常运行,必须将编号为 103640-02 的特定版本补丁添加到操作系统中。可能还需要其他补丁,请参见发行版 README 文件 <ERL_INSTALL_DIR>/README

以下四个安装过程需要超级用户权限

安装
  • 复制 syslogd 的 Solaris 标准配置文件
    • 复制 syslogd 的 Solaris 标准配置文件。该文件通常名为 syslog.conf 并且位于目录 /etc 中。
    • 副本的文件名必须为 syslog.conf.ORIG。目录位置是可选的;通常它为 /etc。执行此操作的简单方法是发出以下命令
      cp /etc/syslog.conf /etc/syslog.conf.ORIG
  • 创建 Erlang 特定的 syslogd 配置文件
    • 创建之前制作的备份副本的编辑副本。
    • 文件名必须为 syslog.conf.OTP。路径必须与备份副本相同。
    • 配置文件的格式可以在 syslog.conf(5) 手册页中找到,方法是发出命令 man syslog.conf
    • 通常会添加一行,该行将声明
      • 要由 Erlang 监督的信息类型
      • 接收信息的命名管道(实际上是一个命名管道)的名称
    • 例如,如果只想监督来自 UNIX 内核的信息,则该行将以 kern.LEVEL 开头。有关 LEVEL 的可能值,请参见 syslog.conf(5)
    • 在至少一个制表符字符之后,添加的行将包含 syslogd 在其中写入其信息的命名管道的完整名称。路径必须与文件 syslog.conf.ORIGsyslog.conf.OTP 的路径相同。文件名必须为 syslog.otp
    • 如果文件 syslog.conf.ORIGsyslog.conf.OTP 的目录为 /etc,则 syslog.conf.OTP 中的行如下所示
      kern.LEVEL                /etc/syslog.otp
  • 检查配置文件的文件权限
    • 配置文件应具有 rw-r--r-- 文件权限,并且由 root 拥有。
    • 执行此操作的简单方法是发出以下命令
      chmod 644 /etc/syslog.conf
      chmod 644 /etc/syslog.conf.ORIG
      chmod 644 /etc/syslog.conf.OTP
    • 注意,如果文件 syslog.conf.ORIGsyslog.conf.OTP 不在目录 /etc 中,则必须修改第二和第三条命令中的文件路径。
  • 修改 mod_syslog 实用程序的文件权限和所有权
    • 必须修改 mod_syslog 实用程序的文件权限和所有权。
    • 二进制可执行文件的完整名称是从应用程序 os_mon 在文件系统中的位置派生的,方法是添加 /priv/bin/mod_syslog。因此,二进制可执行文件的通用完整名称为

      <$OTPROOT>/lib/os_mon-<REV>/priv/bin/mod_syslog

      **示例:** 如果 otp-root 的路径为 /usr/otp,则 os_mon 应用程序的路径为 /usr/otp/lib/os_mon-1.0(假设修订版为 1.0),并且二进制可执行文件的完整名称为 /usr/otp/lib/os_mon-1.0/priv/bin/mod_syslog

    • 二进制可执行文件必须由 root 拥有,具有 rwsr-xr-x 文件权限,特别是用户的 setuid 位必须设置。
    • 执行此操作的简单方法是发出以下命令

      cd <$OTPROOT>/lib/os_mon-<REV>/priv/bin/mod_syslog
      chmod 4755 mod_syslog
      chown root mod_syslog
测试应用程序配置文件

以下过程不需要 root 权限

  • 确保应用程序 os_monos_sup 模块的配置参数正确。
  • 浏览应用程序配置文件(**不要** 编辑它)。应用程序配置文件的完整名称是从 os_mon 应用程序在文件系统中的位置派生的,方法是添加 /ebin/os_mon.app

    因此,该文件的通用完整名称为

    <$OTPROOT>/lib/os_mon-<REV>/ebin/os_mon.app.

    **示例:** 如果 otp-root 的路径为 /usr/otp,则 os_mon 应用程序的路径为 /usr/otp/lib/os_mon-1.0 (假设修订版为 1.0),并且二进制可执行文件的完整名称为 /usr/otp/lib/os_mon-1.0/ebin/os_mon.app

  • 确保以下配置参数具有正确的值
参数 功能 标准值
start_os_sup 指定是否要启动 os_sup 硬件上的第一个实例为 true;其他实例为 false
os_sup_own (1)备份副本和(2)Erlang 特定的 syslogd 配置文件的目录 "/etc"
os_sup_syslogconf syslogd 的 Solaris 标准配置文件的完整名称 "/etc/syslog.conf"
error_tag 发送到 Erlang 运行时系统中的错误记录器的消息的标记 std_error

表 1.1:  配置参数

如果 os_mon.app 中列出的值不适合您的需求,**不要** 编辑该文件。相反,在 **系统配置文件** 中 **覆盖** 这些值,该文件的完整路径名在命令行上提供给 erl

**示例:** 应用程序配置文件的内容

          [{os_mon, [{start_os_sup, true}, {os_sup_own, "/etc"}, 
          {os_sup_syslogconf, "/etc/syslog.conf"}, {os_sup_errortag, std_error}]}].
相关文档

请参见 os_mon(3) 应用程序、内核中的 application(3) 手册页以及 ERTS 中的 erl(1) 手册页。

硬件看门狗计时器由 heart 端口程序控制,需要安装包含 VME 总线驱动程序的包 FORCEvme。但是,该驱动程序可能会与 Sun 的 mcp 驱动程序发生冲突,导致系统拒绝启动。要解决此问题,需要将以下行添加到 /etc/system

  • exclude: drv/mcp
  • exclude: drv/mcpzsa
  • exclude: drv/mcpp
警告

建议添加这些行以避免冲突。冲突可能导致系统无法启动。

本节描述嵌入式系统如何启动。涉及四个程序,它们通常位于 <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 并位于 <ERL_INSTALL_DIR>/bin 中。可以使用另一个启动程序,方法是在 SASL 应用程序中使用配置参数 start_prg

启动程序必须调用 run_erl,如下所示。它还必须接受一个可选参数,该参数默认为 <ERL_INSTALL_DIR>/releases/start_erl.data

此程序用于设置静态参数和环境变量,例如 -sname NameHEART_COMMAND 以重启机器。

<RELDIR> 目录是安装新发布包的地方,也是发布处理程序保存有关发布信息的目录。有关更多信息,请参阅 SASL 中的 release_handler(3) 手册页。

以下脚本说明了程序的默认行为

#!/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=sun
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}

此程序用于启动仿真器,但您不会连接到 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 分钟内没有向日志文件写入任何内容,则会插入一条记录,表明我们还活着。

此程序用于连接到使用 run_erl 启动的正在运行的 Erlang 运行时系统。

Usage: to_erl [pipe_name | pipe_dir]

这里 pipe_name 默认为 /tmp/erlang.pipe.N

要在不退出 Erlang 系统的情况下断开 Shell 连接,请键入 Ctrl-D

此程序使用参数 -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 $*