Erlang и bash скрипты (escript) - PullRequest
3 голосов
/ 25 мая 2020

Я новичок в Erlang и хочу объединить сценарий bash с узлом и функцией Erlang. У меня есть одна база данных Mnesia, в которой мы go переходим в узел Erlang и запускаем несколько функций, но я хочу запустить эти функции через какой-нибудь bash скрипт, чтобы я мог использовать эти bash выходные данные скрипта в другом месте. Моя оболочка Erlang: -

sudo /opt/butler_server/bin/butler_server remote_console
Erlang/OTP 20 [erts-9.3.3.6] [source] [64-bit] [smp:28:28] [ds:28:28:10] [async-threads:10] 

Eshell V9.3.3.6  (abort with ^G)
(butler_server@localhost)1> 

И внутри этой оболочки, когда мы запускаем функцию ниже, она работает нормально и также выдает вывод. Обратите внимание, что order_node, pps_manager - это имя модуля в базе данных, а get_by_id, send_order_related_notification, update_status_of_order_node - функции в этом модуле.

f().

ChangeStatus =
fun() ->
        {ok,C2}=order_node:search_by([{status,equal,inventory_awaited}],key),

        io:format("Total Orders ~p", [length(C2)]),

        lists:foreach(fun(Id) ->
                              io:format("Orders ~p~n", [Id]),
                              order_node:update_status_of_order_node(Id,cancelled),
                              pps_manager:send_order_related_notification(element(2,order_node:get_by_id(Id)))
                      end, C2)
end.

ChangeStatus().

Пожалуйста, дайте мне знать, как я могу запустить приведенный выше фрагмент кода в оболочке Erlang, используя сценарий bash.

1 Ответ

3 голосов
/ 26 мая 2020

Когда вы используете escript, вы запускаете новую виртуальную машину Erlang, поэтому, если вы действительно хотите подключиться к работающему узлу, вам нужно использовать что-то вроде expect .

Однако с escript вы можете запустить новый узел и добавить его в работающий кластер, а с помощью методов в модуле rp c вы можете запустить код в исходном кластере:

Допустим, у вас есть узел, начинающийся с erl -name main@127.0.0.1 -setcookie cookie, тогда escript

#!/usr/bin/env escript
%%! -name escript@127.0.0.1 -hidden -setcookie cookie
main([RemoteNodeString]) ->
    io:format("Escript node: ~p~n", [node()]),
    RemoteNode = list_to_atom(RemoteNodeString),
    io:format("~p's node(): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, node, [])]),
    io:format("~p's nodes(): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, nodes, [])]),
    ok.

напечатает

$> ./test.escript main@127.0.0.1
Escript node: 'escript@127.0.0.1'
'main@127.0.0.1''s node(): 'main@127.0.0.1'
'main@127.0.0.1''s nodes(): []

(Обратите внимание, что список основных узлов пуст благодаря -hidden flag ).

Помимо того факта, что его скрипт не запускает какой-либо полезный код, здесь есть три проблемы:

1
Имя узла escript: поскольку имена в кластере erlang или на одном и том же хосте должны быть уникальными, это может быть проблемой, если есть вероятность, что escript запускается дважды одновременно. Вы можете решить эту проблему, сгенерировав случайное имя (в Erlang или bash, пример для Erlang):

#!/usr/bin/env escript
%%! -hidden -setcookie cookie
main([RemoteNodeString]) ->
    RandomTail = (<< <<($0 + rand:uniform(10)-1)>> || _ <- lists:seq(1,8) >>),
    RandomName = binary_to_atom(<<"escript", RandomTail/binary, "@127.0.0.1">>, utf8),
    io:format("Escript node: ~p~n", [RandomName]),
    net_kernel:start([RandomName, longnames]),
    RemoteNode = list_to_atom(RemoteNodeString),
    io:format("~p's node(): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, node, [])]),
    io:format("~p's nodes(): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, nodes, [])]),
    io:format("~p's nodes(hidden): ~p~n", [RemoteNode, rpc:call(RemoteNode, erlang, nodes, [hidden])]),
    ok.

$> ./test2.escript main@127.0.0.1 
Escript node: 'escript45560706@127.0.0.1'
'main@127.0.0.1''s node(): 'main@127.0.0.1'
'main@127.0.0.1''s nodes(): []
'main@127.0.0.1''s nodes(hidden): ['escript45560706@127.0.0.1']

Однако имя узла escript - это атом, атомы не G C 'd, и предел атомов, хотя и действительно высокий, присутствует. Это может быть или не быть проблемой для вас, в зависимости от вашей конфигурации и схемы использования.

2
Исходное имя узла и готовка ie: для подключения к main@127.0.0.1 вам нужно знать имя, если оно было запущено с длинными или короткими именами (если в части хоста есть точка, вам нужны длинные имена) и повар ie. Эта информация находится в файле vm.args (или в строке оболочки).
Если не было установлено значение cook ie, Erlang создает случайный файл и помещает его в $HOME.

3
Сетевое подключение к исходному узлу: для распределенного протокола Erlang требуется порт 4369 (для EPMD ) и диапазон узлов (доступен для конфигурации с inet_dist_listen_min и * 1048). *) достижим. 1052 *bash подстановка процесса не работает, потому что скрипт использует файл: позиция , а подстановка процесса представляет собой конвейер).

...