Mnesia 在 Yaws 运行 时无法创建表,但在 Erlang shell 运行 时可以

Mnesia can't create tables when ran by Yaws, but can when ran from the Erlang shell

我有一个 .yaws 文件,它调用我编写的 authenticate 模块中的 setup/0 函数,我将其放在 ebin 目录中。当我从 Erlang shell 调用 authenticate:setup/0 时,它会创建一个 table 就好了,但是当我在浏览器中加载 something.yaws 时,它会调用 authenticate:setup/0 函数,它 returns {aborted,{bad_type,users,disc_copies,nonode@nohost}}(something.yaws 只是 returns 嵌入 html 的 authenticate:setup/0 的 return 值用于调试目的) .

这是 setup/0 函数:

setup() ->
    mnesia:create_schema([node()]),
    mnesia:start(),
    mnesia:create_table(users, [{type, set}, {record_name, user}, {disc_copies, [node()]}, {attributes, record_info(fields, user)}]).

这是 user 记录:

-record(user, {username, hashed_pw, salt}).

(在浏览器中试过后,我试过从 Erlang shell 调用它,所以不会干扰它。)

如果我运行yaws --mnesiadir /usr/local/lib/yaws-appmods/mnesia/,我得到

Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:8:8] [async-threads:10] [kernel-poll:true]

Eshell V8.1  (abort with ^G)
1> 
=INFO REPORT==== 7-Nov-2016::00:04:49 ===
Yaws: Using config file /etc/yaws/yaws.conf

=INFO REPORT==== 7-Nov-2016::00:04:49 ===
Yaws: Using global subconfig file /etc/yaws/conf.d/localhost.conf

=INFO REPORT==== 7-Nov-2016::00:04:49 ===
Ctlfile : /home/username/.yaws/yaws/default/CTL

=INFO REPORT==== 7-Nov-2016::00:04:49 ===
Yaws: Listening to 0.0.0.0:8080 for <1> virtual servers:
 - http://localhost:8080 under /usr/share/yaws/www
rd(user, {username, hashed_pw, salt}).
user
2> mnesia:create_schema([node()]), mnesia:start(), mnesia:create_table(users, [{type, set}, {record_name, user}, {disc_copies, [node()]}, {attributes, record_info(fields, user)}]).
{aborted,{bad_type,users,disc_copies,nonode@nohost}}

如果我 运行 Erlang shell 中的相同 erlang 代码以 erl -mnesia dir '"/usr/local/lib/yaws-appmods/mnesia/"' 开头,它工作得很好。

当你 运行 Yaws 时,传递命令行选项 --mnesiadir dir 告诉它你希望它存储 mnesia 数据的位置。该选项的 dir 参数应该是您希望数据所在目录的路径名。例如,传递 --mnesiadir /tmp 将导致 Yaws 将 mnesia 数据存储在 /tmp 目录中。

顺便说一句,如果你传递一个 mnesia dir 选项将 mnesia 数据目录设置为不存在的东西,你可以在没有 Yaws 的 Erlang shell 中看到同样的错误:

$ erl -mnesia dir '"/xyzfoo"'
Erlang/OTP 19 [erts-8.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V8.1  (abort with ^G)
1> rd(user, {username, hashed_pw, salt}).
user
2> mnesia:create_schema([node()]), mnesia:start(), mnesia:create_table(users, [{type, set}, {record_name, user}, {disc_copies, [node()]}, {attributes, record_info(fields, user)}]).
{aborted,{bad_type,users,disc_copies,nonode@nohost}}

在这里,我们假设没有这样的目录/xyzfoo。第一个 Erlang shell 命令定义了您正在使用的相同 user 记录,第二个命令执行与您的 authenticate:setup/0 函数相同的步骤。如图所示,它 returns 与您在 Yaws 中看到的错误相同。

请注意,此处显示的目录名称 '"/xyzfoo"' 的不寻常引号是将选项正确传递给 Erlang shell 所必需的(无论如何,在典型的基于 UNIX 的系统上),是' Yaws --mnesiadir 选项不需要。另请注意,Erlang 选项是一个连字符后跟两个单词 mnesiadir,然后是引用的目录名称,而对于 Yaws,选项是一个单词 mnesiadir 前面是两个连字符,后跟一个普通的目录名称。

编辑:如果在为 Yaws 设置 mnesia 目录后您仍然遇到问题,那是因为您试图在 mnesia 已经 运行ning 之后创建您的模式。当 Yaws 看到 --mnesiadir 选项时,它会启动 mnesia 应用程序。因此,您应该在 运行 Yaws 之前创建您的模式,或者在创建您的模式之前停止 mnesia。将您的 authenticate:setup/0 函数更改为以下内容,它将在 Yaws 中运行:

setup() ->
    mnesia:stop(),
    mnesia:create_schema([node()]),
    mnesia:start(),
    mnesia:create_table(users, [{type, set}, {record_name, user}, {disc_copies, [node()]}, {attributes, record_info(fields, user)}]).