【问题标题】:Copying files from one server to other via erlang code通过erlang代码将文件从一台服务器复制到另一台服务器
【发布时间】:2015-08-25 01:37:10
【问题描述】:

我想将文件从一台服务器(比如A)复制到其他服务器(比如B)。场景是->用户向我发送二进制文件(视频、zip 或照片)。我把这个写给@ A 的 987654324@。现在在下一步中,我希望将其复制到 B。我使用了 os:cmd(scp ----) 命令。但它给出了类似的错误->

Permission denied, please try again.
Permission denied, please try again.
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

我认为它要求输入 B 的密码。我如何在scp 命令中配置密码,或者在 erlang 中是否有其他方法可以做到这一点?

【问题讨论】:

  • 如果你有一个有效的 ssh-key,并且这个 ssh-key 的公共部分在服务器 Bs authorized_keys 列表中,应该没有问题。看:g-loaded.eu/2005/11/10/ssh-with-keys解释

标签: erlang ejabberd scp mnesia


【解决方案1】:

如果两台服务器都使用 erlang 分发协议连接,则可以使用 Erlang File I/O。 (您也可以通过 TCP 或 UDP 或任何其他网络进行此操作,但更复杂)。

让我们使用在同一台机器上运行的两个“服务器”来演示它(它在网络上的工作方式相同,但您必须正确连接它们)。首先我们为每个服务器创建目录和文件foo的内容进行传输:

$ mkdir a b
$ echo Hello World > a/foo

让我们在不同的目录中启动两个服务器:

$ cd a
a$ erl -sname a
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V7.0  (abort with ^G)
(a@hynek-notebook)1>

和另一个控制台中的第二个服务器:

$ cd b
b$ erl -sname b
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V7.0  (abort with ^G)
(b@hynek-notebook)1>

现在我们检查b 服务器上还没有任何内容:

(b@hynek-notebook)1> ls().
ok
(b@hynek-notebook)2>

现在我们可以连接节点,检查它们是否连接并读取文件foo

(a@hynek-notebook)1> net_kernel:connect('b@hynek-notebook').
true
(a@hynek-notebook)2> net_adm:ping('b@hynek-notebook').
pong
(a@hynek-notebook)3> ls().
foo
ok
(a@hynek-notebook)4> {ok, Bin} = file:read_file("foo").
{ok,<<"Hello World\n">>}
(a@hynek-notebook)5>

并使用rpc:call/4 将文件写入服务器b

(a@hynek-notebook)5> rpc:call('b@hynek-notebook', file, write_file, ["bar", Bin]).
ok
(a@hynek-notebook)6>

在服务器b上查看结果:

(b@hynek-notebook)2> ls().
bar
ok
(b@hynek-notebook)3> {ok, Bin} = file:read_file("bar").
{ok,<<"Hello World\n">>}
(b@hynek-notebook)4>

对于较大的文件,您不应在一个大二进制文件中传输整个文件。不幸的是,您至少需要来自发送方或接收方的一些代码支持。您可以将文件处理程序从一个节点传输到另一个节点,但调用 file:open/2 的进程必须继续运行。这就是你不能只使用{ok, FH} = rpc:call(Node, file, open, [FN, [write]]). 的原因,这太糟糕了。一种方法是制作一个非常简单的服务器,它可以打开一个文件并继续运行。

(b@hynek-notebook)4> Self = self().
<0.40.0>
(b@hynek-notebook)5> F = fun() -> Self ! file:open("baz", [write]), receive close -> ok end end.
#Fun<erl_eval.20.54118792>
(b@hynek-notebook)6> FS = spawn_link('a@hynek-notebook', F).
<7329.48.0>
(b@hynek-notebook)7> {ok, FH} = receive X -> X end.
{ok,<7329.49.0>}
(b@hynek-notebook)8> file:write(FH, Bin).
ok
(b@hynek-notebook)9> FS ! close.
close
(b@hynek-notebook)10>

我们希望文件baz 在服务器a 上有适当的内容:

(a@hynek-notebook)6> ls().
baz     foo
ok
(a@hynek-notebook)7> {ok, _} = file:read_file("baz").
{ok,<<"Hello World\n">>}
(a@hynek-notebook)8>

另一种选择是编写一个服务器,它将接收块并写入它们而不是发送文件处理程序。还有许多其他选项,如何使用 HTTP 或您自己的协议以及使用file:send_file/2,5 和许多其他方式使用直接 TCP 连接。

【讨论】:

    猜你喜欢
    • 2016-02-26
    • 2021-06-22
    • 2014-05-17
    • 1970-01-01
    • 2011-12-03
    • 2020-06-18
    • 2018-07-08
    • 2011-02-05
    • 2011-02-06
    相关资源
    最近更新 更多