While designing my monitoring tool, and working and treregex, I found the ssh documentation and realize that it can be very useful for my tool.
A simple question needed to be answered, is the ssh module able to easily spawn a remote process for me ?
To verify, I tried to build a remote tail module called ssh_tail :)
From the ssh documentation user_dir let you decide where you want to store keys, from my experience it's better to use a separate directory from the ~/.ssh.
It happens that latest version of ssh add meta information to their files that the ssh module can't handle. (more on this in another post).
For the test I wanted to do a "tail -f" on a specific file ie "/var/log/syslog".
ssh_cm is responsible for starting a shell, and sending commands to the remote shell process. I send
Don't forget the final '\n' character, since you won't get any results if you don't send it :p
(I didn't think of that while testing for the first time and think that the code didn't work at all...)
ssh_cm sends various message to the calling process, more important tuples are
Data holds what you want, and in our case a line sent by the tail process...
The callback defined at the beginning is then executed:
To conclude this simple module is able to spawn a remote "tail -f" using a ssh connection and using a callback function on every data received.
The code was designed from the ssh_ssh module that you can find in the ssh module source code, because the ssh documentation is really sparse for now...
Оригинал
A simple question needed to be answered, is the ssh module able to easily spawn a remote process for me ?
To verify, I tried to build a remote tail module called ssh_tail :)
-module(ssh_tail). -export([tail/3]). -define(TIMEOUT, 5000). tail(Host, User, Pass) -> case ssh_cm:connect(Host, 22, [{user_dir, "/var/tmp/ssh"}, {user, User}, {password, Pass}]) of {ok, CM} -> session(CM, fun(X) -> io:format("-ssh: ~p~n", [X]) end); Error -> Error end.
From the ssh documentation user_dir let you decide where you want to store keys, from my experience it's better to use a separate directory from the ~/.ssh.
It happens that latest version of ssh add meta information to their files that the ssh module can't handle. (more on this in another post).
For the test I wanted to do a "tail -f" on a specific file ie "/var/log/syslog".
session(CM, Callback) -> case ssh_cm:session_open(CM, ?TIMEOUT) of {ok, Channel} -> case ssh_cm:shell(CM, Channel) of ok -> ssh_cm:send(CM, Channel, "tail --follow=name /var/log/syslog\n"), ssh_loop(CM, Channel, Callback); Error -> error_logger:error_msg("Error: ~p~n", [Error]) end; Error -> error_logger:error_msg("Session Error: ~p~n", [Error]) end.
ssh_cm is responsible for starting a shell, and sending commands to the remote shell process. I send
tail --follow=name /var/log/syslog\n
Don't forget the final '\n' character, since you won't get any results if you don't send it :p
(I didn't think of that while testing for the first time and think that the code didn't work at all...)
ssh_loop(CM, Channel, Callback) -> receive stop -> % Closing channel % ssh_cm:detach(CM, ?TIMEOUT), ssh_cm:close(CM, Channel); {ssh_cm, CM, {data, _Channel, 0, Data}} -> Callback(Data), ssh_loop(CM, Channel, Callback); {ssh_cm, CM, {data, Channel, Type, Data}} -> io:format("extended (~p): ~p~n", [Type, Data]), ssh_loop(CM, Channel, Callback); {ssh_cm, CM, {closed, _Channel}} -> ssh_cm:detach(CM, ?TIMEOUT); E -> error_logger:info_msg("[~p] Received: ~p~n", [?MODULE, E]), ssh_loop(CM, Channel, Callback) end.
ssh_cm sends various message to the calling process, more important tuples are
{ssh_cm, CM, {data, _Channel, 0, Data}}
Data holds what you want, and in our case a line sent by the tail process...
The callback defined at the beginning is then executed:
tail(Host, User, Pass) -> case ssh_cm:connect(Host, 22, [{user_dir, "/var/tmp/ssh"}, {user, User}, {password, Pass}]) of {ok, CM} -> session(CM, fun(X) -> % Our Callback io:format("-ssh: ~p~n", [X]) % simple display... end); Error -> Error end.
To conclude this simple module is able to spawn a remote "tail -f" using a ssh connection and using a callback function on every data received.
The code was designed from the ssh_ssh module that you can find in the ssh module source code, because the ssh documentation is really sparse for now...
Оригинал