[erlang-questions] SSH SCP

Siraaj Khandkar <>
Tue Jul 24 16:01:42 CEST 2012


Restoring back to inline ;)
See bottom.

On Jul 18, 2012, at 1:41 PM,  wrote:

>> On Jul 16, 2012, at 3:39 PM,  wrote:
>> 
>>> Hello,
>>> 
>>> I d like to ask about the SSH module found in OTP. I would like to use
>>> the SCP command (which uses ssh) via Erlang (SSH module). Is there
>>> anybody, who can explain me, how to do it? I have googled and searched
>>> million times, but nothing... (I have also tried it using os:cmd/1 and a
>>> seld-made shell loop)
>> 
>> 
>> I haven't gotten around to file transfers (with OTP ssh app) yet, but I
>> did manage to mostly figure-out the basics of using the SSH app, and can
>> give you a jump start.
>> 
>> For the simplest example of doing something useful, lets say we want a
>> an escript that sort-of mimics an ssh command. First, make sure you have
>> an SSH directory (~/.ssh) and a pub-priv key pair (~/.ssh/id_dsa and
>> ~/.ssh/id_dsa.pub) that is NOT password protected. This last part is
>> important, because at this time the ssh app does not yet support
>> password-protected keys [1]. After you have the key pair, the simplest
>> implementation could look something like this:
>> 
>> 
>>    #! /usr/bin/env escript
>> 
>>    %%% ----------------------------------------------------------------------
>>    %%% file: ssh.erl
>>    %%% ----------------------------------------------------------------------
>> 
>> 
>>    main([User, Address, Port, Command]) ->
>>        ok = crypto:start(),
>>        ok = ssh:start(),
>> 
>>        Timeout = 5000,
>>        SSHDirectory = filename:join(os:getenv("HOME"), ".ssh"),
>> 
>>        ConnectOptions = [
>>            {user, User},
>>            {connect_timeout, Timeout},
>>            {silently_accept_hosts, true},
>>            {user_interaction, true},
>>            {user_dir, SSHDirectory}
>>        ],
>> 
>>        case ssh:connect(Address, list_to_integer(Port), ConnectOptions) of
>>            {ok, ConnRef} ->
>>                case ssh_connection:session_channel(ConnRef, Timeout) of
>>                    {ok, ChannId} ->
>>                        ssh_connection:exec(ConnRef, ChannId, Command, Timeout),
>>                        Data = collect_data(),
>>                        io:format("~s~n", [Data]);
>> 
>>                    {error, Reason} ->
>>                        io:format("~p~n", [Reason])
>>                end;
>>            {error, Reason} ->
>>                io:format("~p~n", [Reason])
>>        end;
>> 
>>    main(_) ->
>>        io:format("USAGE: ssh.erl <user> <address> <port> <command>~n").
>> 
>> 
>>    collect_data() -> collect_data([]).
>>    collect_data(Data) ->
>>        receive
>>            {ssh_cm, _, {data, _, _, Datum}} ->
>>                collect_data([Datum | Data]);
>> 
>>            {ssh_cm, _, {closed, _}} ->
>>                lists:reverse(Data);
>> 
>>            {ssh_cm, _} ->
>>                collect_data(Data)
>>        end.
>> 
>> 
>> For a more extended example of the use of the above code, see my Cluster
>> Commander project [2], particularly commander_worker_otp.erl module. I
>> also took advantage of OS's ssh/scp commands (as an alternative to OTP
>> ssh and as the only, for now, way to do scp), see
>> commander_worker_os.erl module and os_cmd/1 function in
>> commander_lib.erl module.
>> 
>> The above uses ssh_connection:exec/4 to just send a command string to
>> the remote host and receive the resulting data, but, for more
>> interesting uses, you can also use ssh_connection:send/3-5 and push any
>> data you want to the remote host (assuming it knows how to interpret
>> it).
>> 
>> For a more interesting example, see Kenji Rikitake's sshrpc [3] [4] and
>> my (uber-early and half-baked) attempts at implementing the ssh_channel
>> behavior for my needs [5].
>> 
>> 
>> [1] - http://erlang.org/pipermail/erlang-questions/2010-April/050637.html
>> [2] - https://github.com/ibnfirnas/cluster-commander
>> [3] - https://github.com/jj1bdx/sshrpc
>> [4] - http://www.erlang-factory.com/conference/SFBay2010/speakers/kenjirikitake
>> [5] - https://github.com/ibnfirnas/data-mill
>> 
> Hello,
> 
> Thank you for your quick answer, Siraaj, but I'd like to do the inverse of
> what you described below. I'd like to start an SSH daemon with Erlang (OTP
> SSH), and use it with the following command:
> scp filename_on_my_pc host:path
> (copying)
> 
> I start Erlang SSH like this:
>  start() ->
>    crypto:start(),
>    ssh:start(),
>    Shell = myshell(),
>    ssh:daemon({0,0,0,0}, 45678, [{pwdfun, fun check_pwd/2},
>       {system_dir, "/home/.../global-ssh-host-keys"},
>       {ssh_cli,{ssh_cli, [Shell]}},
>       {subsystems,
>       [{"sftp", {ssh_sftpd, [
>               {vsn,       3}
>           ]}}]}]).
> Shell is a self-written simple shell, but it has no job here, 'cause using
> scp command is something like giving the ssh command a parameter (I think).
> 
> I know this is an improper way of using scp because ssh_cli tries to parse
> "scp -t path" (this is the command which is called via ssh by scp) as an
> Erlang term.  I d like to ask you to give me instructions. How can I set up a
> working Erlang ssh deamon (working with scp)?

I see. I'd be interested in getting that to work as well, but haven't gotten
all the way there last time I played with it :)

This is where I left off, hopefully it'll be of use to you:

https://github.com/ibnfirnas/data-mill/blob/master/apps/datamill_reclaimer/src/datamill_reclaimer_ssh_server.erl

I'm still interested in completing this and want to revisit it at some point,
its just low on my priority queue at this time. Please let me know if you get
further along!


-- 
Siraaj Khandkar
.o.
..o
ooo




More information about the erlang-questions mailing list