Erlang ssh shell question

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Erlang ssh shell question

Mattsson, Tommy

Hi,

First time writer here on the erlang questions list :)


I am wondering if anyone knows about how the erlang ssh handles I/O? More details can be found below.


Erlang version: 21.0



Start of SSH server on testing (Windows) machine:

application:ensure_all_started(ssh),
Options = [{system_dir, filename:join(SSHPath, "daemon")}, {user_dir, ?DIR}, {subsystems, [ssh_sftpd:subsystem_spec([{cwd, SSHPath}])]}], 

ssh:daemon(?ipaddr, ?port, Options]).

Test module:
-module(sshtest).
sshIO() ->
   io:format("test1~n"),
   io:format("test2\n"),
  test3.


Test run from my own machine:
> ssh $IPADDR 'sshtest:sshIO().'
test3

For some reason any io:format/io:fwrite does not travel back over the SSH connection. If I connect to some Linux machine that already has a (non-erlang) SSH server running and I try to run some random bash script then any echo I have in the script will travel back over the SSH connection.

A test I did with a bash script towards a Linux server, 
Bash script (~/test.sh):

echo "test1"

echo "test2"

echo "test3"


Test run from my own machine:
> ssh $IPADDR ./test.sh

test1

test2

test3

This is how I'd like it to work.


I have been googling and reading the documentation for the ssh and related modules to no avail in regards to finding a solution to this problem. 

Other than this I/O problem the ssh connection works perfectly for me 😊

Hopefully someone here on the list has some insight into how this works.

Thankful for any help I can get :)
Best regards,

Tommy






_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Erlang ssh shell question

Hans Nilsson R (AL/EAB)
Hi,

Try

5> ssh:daemon(1234, [{system_dir,...}, {shell,fun(Usr,Hst) -> spawn(fun() -> io:format("Hello ~p ~p~n",[Usr,Hst]), L1 = io:get_line("&& "), io:format("Got ~p~n", [L1]) end) end}]).
{ok,<0.110.0>}
6>

Sorry for the one-liner. The fun() a bit edited, I hope I got it right:

    fun(Usr,Hst) ->
           spawn(fun() ->
                    io:format("Hello ~p ~p~n",[Usr,Hst]),
                    L1 = io:get_line("&& "),
                    io:format("Got ~p~n", [L1])
                 end)
    end


Note the option shell and the spawn, it is essential.
You don't need the subsystem option.  The user_dir option defaults to the $HOME/.ssh of the user that started erl.

Now in bash:

~$ ssh -p 1234 localhost
Hello "USERNAME" {{127,0,0,1},60088}
&& some command
Got "some command\n"
Connection to localhost closed.
~$

Hope this helps.
/Hans



On 11/2/18 10:05 AM, Mattsson, Tommy wrote:

> Hi,
>
> First time writer here on the erlang questions list :)
>
>
> I am wondering if anyone knows about how the erlang ssh handles I/O? More details can be found below.
>
>
> Erlang version: 21.0
>
>
>
> Start of SSH server on testing (Windows) machine:
>
> application:ensure_all_started(ssh),
> Options = [{system_dir, filename:join(SSHPath, "daemon")}, {user_dir, ?DIR}, {subsystems, [ssh_sftpd:subsystem_spec([{cwd, SSHPath}])]}],
>
> ssh:daemon(?ipaddr, ?port, Options]).
>
> Test module:
> -module(sshtest).
> sshIO() ->
>    io:format("test1~n"),
>    io:format("test2\n"),
>   test3.
>
>
> Test run from my own machine:
>> ssh $IPADDR 'sshtest:sshIO().'
> test3
>
>
> For some reason any io:format/io:fwrite does not travel back over the SSH connection. If I connect to some Linux machine that already has a (non-erlang) SSH server running and I try to run some random bash script then any echo I have in the script will travel back over the SSH connection.
>
> A test I did with a bash script towards a Linux server,
> Bash script (~/test.sh):
>
> echo "test1"
>
> echo "test2"
>
> echo "test3"
>
>
> Test run from my own machine:
>> ssh $IPADDR ./test.sh
>
> test1
>
> test2
>
> test3
>
> This is how I'd like it to work.
>
>
> I have been googling and reading the documentation for the ssh and related modules to no avail in regards to finding a solution to this problem.
>
> Other than this I/O problem the ssh connection works perfectly for me 😊
>
> Hopefully someone here on the list has some insight into how this works.
>
> Thankful for any help I can get :)
> Best regards,
>
> Tommy
>
>
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Erlang ssh shell question

Per Hedeland
Hi Tommy! (and Hans:-)

Hans, I *think* you are misunderstanding Tommy's question. More
speculation below, since I haven't actually verified how ssh(3)
works... When using e.g. the OpenSSH client,

$ ssh <host>

makes a "shell" request per
https://tools.ietf.org/html/rfc4254#section-6.5 , while

$ ssh <host> <cmd>

makes an "exec" request. I think Tommy is happy with how "shell" works,
but you seem to be changing it to a pretty boring implementation.:-) And
I think Tommy's question is about "exec" not associating 'standard_io'
with the SSH channel - thus if you use "exec" to call a function that
prints something, the output is lost.

I'm not sure there is anything "wrong" with that though - for an SSH
server running "directly" on *nix, it is obvious that "exec" should
associate stdio with the SSH channel, since <cmd> is *nix shell command,
and it's pretty fundamental that you want any output (and exit code)
that it produces. But for the Erlang/OTP SSH server, <cmd> is
(apparently) an Erlang function call, and sending only what the call
returns (in text form) back through the channel is not unreasonable per
se.

But maybe there could be an option to ssh:daemon() to make it do the
same thing with 'standard_io' for "exec" as it does for "shell" - I
can't see one in the man page. And I can't think of a way that the
called function could set it up. But I assume that it's possible to
do-it-all yourself via the 'ssh_cli' option.

--Per

On 2018-11-02 10:37, Hans Nilsson R wrote:

> Hi,
>
> Try
>
> 5> ssh:daemon(1234, [{system_dir,...}, {shell,fun(Usr,Hst) -> spawn(fun() -> io:format("Hello ~p ~p~n",[Usr,Hst]), L1 = io:get_line("&& "), io:format("Got ~p~n", [L1]) end) end}]).
> {ok,<0.110.0>}
> 6>
>
> Sorry for the one-liner. The fun() a bit edited, I hope I got it right:
>
>     fun(Usr,Hst) ->
>            spawn(fun() ->
>                     io:format("Hello ~p ~p~n",[Usr,Hst]),
>                     L1 = io:get_line("&& "),
>                     io:format("Got ~p~n", [L1])
>                  end)
>     end
>
>
> Note the option shell and the spawn, it is essential.
> You don't need the subsystem option.  The user_dir option defaults to the $HOME/.ssh of the user that started erl.
>
> Now in bash:
>
> ~$ ssh -p 1234 localhost
> Hello "USERNAME" {{127,0,0,1},60088}
> && some command
> Got "some command\n"
> Connection to localhost closed.
> ~$
>
> Hope this helps.
> /Hans
>
>
>
> On 11/2/18 10:05 AM, Mattsson, Tommy wrote:
>> Hi,
>>
>> First time writer here on the erlang questions list :)
>>
>>
>> I am wondering if anyone knows about how the erlang ssh handles I/O? More details can be found below.
>>
>>
>> Erlang version: 21.0
>>
>>
>>
>> Start of SSH server on testing (Windows) machine:
>>
>> application:ensure_all_started(ssh),
>> Options = [{system_dir, filename:join(SSHPath, "daemon")}, {user_dir, ?DIR}, {subsystems, [ssh_sftpd:subsystem_spec([{cwd, SSHPath}])]}],
>>
>> ssh:daemon(?ipaddr, ?port, Options]).
>>
>> Test module:
>> -module(sshtest).
>> sshIO() ->
>>    io:format("test1~n"),
>>    io:format("test2\n"),
>>   test3.
>>
>>
>> Test run from my own machine:
>>> ssh $IPADDR 'sshtest:sshIO().'
>> test3
>>
>>
>> For some reason any io:format/io:fwrite does not travel back over the SSH connection. If I connect to some Linux machine that already has a (non-erlang) SSH server running and I try to run some random bash script then any echo I have in the script will travel back over the SSH connection.
>>
>> A test I did with a bash script towards a Linux server,
>> Bash script (~/test.sh):
>>
>> echo "test1"
>>
>> echo "test2"
>>
>> echo "test3"
>>
>>
>> Test run from my own machine:
>>> ssh $IPADDR ./test.sh
>>
>> test1
>>
>> test2
>>
>> test3
>>
>> This is how I'd like it to work.
>>
>>
>> I have been googling and reading the documentation for the ssh and related modules to no avail in regards to finding a solution to this problem.
>>
>> Other than this I/O problem the ssh connection works perfectly for me =

>>
>> Hopefully someone here on the list has some insight into how this works.
>>
>> Thankful for any help I can get :)
>> Best regards,
>>
>> Tommy
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Erlang ssh shell question

Mattsson, Tommy

Hi Per and Hans,


Thank you both for your replies! 😊
Per is correct, I want to execute "ssh <host> <cmd>" from a regular shell (bash, etc.) and have it connect to the Erlang SSH shell that I started on <host> and give me output like there was "echo test1", "echo test2" in a bash script. 


I will look into if I can make use of the exec functionality for the Erlang SSH server. I looked at it earlier but it seemed to me that its intended use was for an Erlang SSH client connecting to an Erlang SSH server so I dismissed that as an option.

If all else fails I could look into the ssh_cli option and see if I can have an Erlang SSH shell handle I/O differently than the default.


Best regards,

Tommy


From: Per Hedeland <[hidden email]>
Sent: Friday, November 2, 2018 11:30:33 AM
To: Hans Nilsson R; Mattsson, Tommy
Cc: [hidden email]
Subject: Re: [erlang-questions] Erlang ssh shell question
 
Hi Tommy! (and Hans:-)

Hans, I *think* you are misunderstanding Tommy's question. More
speculation below, since I haven't actually verified how ssh(3)
works... When using e.g. the OpenSSH client,

$ ssh <host>

makes a "shell" request per
https://tools.ietf.org/html/rfc4254#section-6.5 , while

$ ssh <host> <cmd>

makes an "exec" request. I think Tommy is happy with how "shell" works,
but you seem to be changing it to a pretty boring implementation.:-) And
I think Tommy's question is about "exec" not associating 'standard_io'
with the SSH channel - thus if you use "exec" to call a function that
prints something, the output is lost.

I'm not sure there is anything "wrong" with that though - for an SSH
server running "directly" on *nix, it is obvious that "exec" should
associate stdio with the SSH channel, since <cmd> is *nix shell command,
and it's pretty fundamental that you want any output (and exit code)
that it produces. But for the Erlang/OTP SSH server, <cmd> is
(apparently) an Erlang function call, and sending only what the call
returns (in text form) back through the channel is not unreasonable per
se.

But maybe there could be an option to ssh:daemon() to make it do the
same thing with 'standard_io' for "exec" as it does for "shell" - I
can't see one in the man page. And I can't think of a way that the
called function could set it up. But I assume that it's possible to
do-it-all yourself via the 'ssh_cli' option.

--Per

On 2018-11-02 10:37, Hans Nilsson R wrote:
> Hi,
>
> Try
>
> 5> ssh:daemon(1234, [{system_dir,...}, {shell,fun(Usr,Hst) -> spawn(fun() -> io:format("Hello ~p ~p~n",[Usr,Hst]), L1 = io:get_line("&& "), io:format("Got ~p~n", [L1]) end) end}]).
> {ok,<0.110.0>}
> 6>
>
> Sorry for the one-liner. The fun() a bit edited, I hope I got it right:
>
>     fun(Usr,Hst) ->
>            spawn(fun() ->
>                     io:format("Hello ~p ~p~n",[Usr,Hst]),
>                     L1 = io:get_line("&& "),
>                     io:format("Got ~p~n", [L1])
>                  end)
>     end
>
>
> Note the option shell and the spawn, it is essential.
> You don't need the subsystem option.  The user_dir option defaults to the $HOME/.ssh of the user that started erl.
>
> Now in bash:
>
> ~$ ssh -p 1234 localhost
> Hello "USERNAME" {{127,0,0,1},60088}
> && some command
> Got "some command\n"
> Connection to localhost closed.
> ~$
>
> Hope this helps.
> /Hans
>
>
>
> On 11/2/18 10:05 AM, Mattsson, Tommy wrote:
>> Hi,
>>
>> First time writer here on the erlang questions list :)
>>
>>
>> I am wondering if anyone knows about how the erlang ssh handles I/O? More details can be found below.
>>
>>
>> Erlang version: 21.0
>>
>>
>>
>> Start of SSH server on testing (Windows) machine:
>>
>> application:ensure_all_started(ssh),
>> Options = [{system_dir, filename:join(SSHPath, "daemon")}, {user_dir, ?DIR}, {subsystems, [ssh_sftpd:subsystem_spec([{cwd, SSHPath}])]}],
>>
>> ssh:daemon(?ipaddr, ?port, Options]).
>>
>> Test module:
>> -module(sshtest).
>> sshIO() ->
>>    io:format("test1~n"),
>>    io:format("test2\n"),
>>   test3.
>>
>>
>> Test run from my own machine:
>>> ssh $IPADDR 'sshtest:sshIO().'
>> test3
>>
>>
>> For some reason any io:format/io:fwrite does not travel back over the SSH connection. If I connect to some Linux machine that already has a (non-erlang) SSH server running and I try to run some random bash script then any echo I have in the script will travel back over the SSH connection.
>>
>> A test I did with a bash script towards a Linux server,
>> Bash script (~/test.sh):
>>
>> echo "test1"
>>
>> echo "test2"
>>
>> echo "test3"
>>
>>
>> Test run from my own machine:
>>> ssh $IPADDR ./test.sh
>>
>> test1
>>
>> test2
>>
>> test3
>>
>> This is how I'd like it to work.
>>
>>
>> I have been googling and reading the documentation for the ssh and related modules to no avail in regards to finding a solution to this problem.
>>
>> Other than this I/O problem the ssh connection works perfectly for me =

>>
>> Hopefully someone here on the list has some insight into how this works.
>>
>> Thankful for any help I can get :)
>> Best regards,
>>
>> Tommy
>>
>>
>>
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Erlang ssh shell question

Hans Nilsson R (AL/EAB)
Hi Tommy and Hi Per too :)

Sorry for my sloppy reading of your first mail, but now I think I understand you.

To start an Erlang server executing "shell" or "exec" commands you just start a normal server (= daemon):
Erlang/OTP 21 [erts-10.1.1] [source-3094642] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

2> ssh:daemon(1236, [{system_dir,"XXX"}]).  % (will get ~/.ssh as user_dir where ~ is the home of the user that started erl)

and elsewhere in a bash:

~$ ssh -p 1236 localhost
Eshell V10.1.1  (abort with ^G)
1> io:write(hej).
hejok
2> exit().
~$

or, for "exec":

~$ ssh -p 1236 localhost 1+2.
3
~$

etc.


Now as I understand, you want to do I/O in the command and expect:

~$ ssh -p 1236 localhost 'io:write(hejsan).'
hejsan
~$

but you get:

~$ ssh -p 1236 localhost 'io:write(hejsan).'
ok
~$

and hejsan is written in the shell of the server started above.


You could start your own exec command interpreter with the option 'exec' to the server:

(See http://erlang.org/doc/man/ssh.html#type-exec_daemon_option
 but NOTE: ERROR in that one.....
  should be
      {exec, {direct, 'exec_fun/1'() | 'exec_fun/2'() | 'exec_fun/3'()} }
 )

Example:
9> ssh:daemon(1237, [{system_dir,"XXX"}, {exec, {direct,  fun(Cmd) -> {ok, {got,Cmd}} end  }}]).

and from a separate bash shell:

~$ ssh -p 1237 localhost 'io:write(hejsan).'
{got,"io:write(hejsan)."}~$

This gives a clue on what to do:
"Just" write something executing the command grabbing the output and return it in that {direct,fun(Cmd)...} as a string...

Now I think that not returning I/O from an exec command is a bug. However I can't look into that now and probably not on this side of christmas.
IF you should like to dig into this, the central function is ssh_cli:handle_ssh_msg/2 line 114.  The clause with the head:
    handle_ssh_msg({ssh_cm, ConnectionHandler,  {exec, ChannelId, WantReply, Cmd}}, S0) ->

There are comments in that code which could give you some clues.  There is also a comment with "The F communicates via standard io:write/read.".
That makes me belive that I accidently changed some functionality when I restructured this part. I will look into that too, but not now.

I hope you got some ideas, and just ask if you wonder about something. And Pull Requests are welcome!

/Hans

On 11/6/18 9:24 AM, Mattsson, Tommy wrote:

> Hi Per and Hans,
>
> Thank you both for your replies! 😊
> Per is correct, I want to execute "ssh <host> <cmd>" from a regular shell (bash, etc.) and have it connect to the Erlang SSH shell that I started on <host> and give me output like there was "echo test1", "echo test2" in a bash script.
>
>
> I will look into if I can make use of the exec functionality for the Erlang SSH server. I looked at it earlier but it seemed to me that its intended use was for an Erlang SSH client connecting to an Erlang SSH server so I dismissed that as an option.
>
> If all else fails I could look into the ssh_cli option and see if I can have an Erlang SSH shell handle I/O differently than the default.
>
>
> Best regards,
>
> Tommy
>
> ________________________________
> From: Per Hedeland <[hidden email]>
> Sent: Friday, November 2, 2018 11:30:33 AM
> To: Hans Nilsson R; Mattsson, Tommy
> Cc: [hidden email]
> Subject: Re: [erlang-questions] Erlang ssh shell question
>
> Hi Tommy! (and Hans:-)
>
> Hans, I *think* you are misunderstanding Tommy's question. More
> speculation below, since I haven't actually verified how ssh(3)
> works... When using e.g. the OpenSSH client,
>
> $ ssh <host>
>
> makes a "shell" request per
> https://tools.ietf.org/html/rfc4254#section-6.5 , while
>
> $ ssh <host> <cmd>
>
> makes an "exec" request. I think Tommy is happy with how "shell" works,
> but you seem to be changing it to a pretty boring implementation.:-) And
> I think Tommy's question is about "exec" not associating 'standard_io'
> with the SSH channel - thus if you use "exec" to call a function that
> prints something, the output is lost.
>
> I'm not sure there is anything "wrong" with that though - for an SSH
> server running "directly" on *nix, it is obvious that "exec" should
> associate stdio with the SSH channel, since <cmd> is *nix shell command,
> and it's pretty fundamental that you want any output (and exit code)
> that it produces. But for the Erlang/OTP SSH server, <cmd> is
> (apparently) an Erlang function call, and sending only what the call
> returns (in text form) back through the channel is not unreasonable per
> se.
>
> But maybe there could be an option to ssh:daemon() to make it do the
> same thing with 'standard_io' for "exec" as it does for "shell" - I
> can't see one in the man page. And I can't think of a way that the
> called function could set it up. But I assume that it's possible to
> do-it-all yourself via the 'ssh_cli' option.
>
> --Per
>
> On 2018-11-02 10:37, Hans Nilsson R wrote:
>> Hi,
>>
>> Try
>>
>> 5> ssh:daemon(1234, [{system_dir,...}, {shell,fun(Usr,Hst) -> spawn(fun() -> io:format("Hello ~p ~p~n",[Usr,Hst]), L1 = io:get_line("&& "), io:format("Got ~p~n", [L1]) end) end}]).
>> {ok,<0.110.0>}
>> 6>
>>
>> Sorry for the one-liner. The fun() a bit edited, I hope I got it right:
>>
>>     fun(Usr,Hst) ->
>>            spawn(fun() ->
>>                     io:format("Hello ~p ~p~n",[Usr,Hst]),
>>                     L1 = io:get_line("&& "),
>>                     io:format("Got ~p~n", [L1])
>>                  end)
>>     end
>>
>>
>> Note the option shell and the spawn, it is essential.
>> You don't need the subsystem option.  The user_dir option defaults to the $HOME/.ssh of the user that started erl.
>>
>> Now in bash:
>>
>> ~$ ssh -p 1234 localhost
>> Hello "USERNAME" {{127,0,0,1},60088}
>> && some command
>> Got "some command\n"
>> Connection to localhost closed.
>> ~$
>>
>> Hope this helps.
>> /Hans
>>
>>
>>
>> On 11/2/18 10:05 AM, Mattsson, Tommy wrote:
>>> Hi,
>>>
>>> First time writer here on the erlang questions list :)
>>>
>>>
>>> I am wondering if anyone knows about how the erlang ssh handles I/O? More details can be found below.
>>>
>>>
>>> Erlang version: 21.0
>>>
>>>
>>>
>>> Start of SSH server on testing (Windows) machine:
>>>
>>> application:ensure_all_started(ssh),
>>> Options = [{system_dir, filename:join(SSHPath, "daemon")}, {user_dir, ?DIR}, {subsystems, [ssh_sftpd:subsystem_spec([{cwd, SSHPath}])]}],
>>>
>>> ssh:daemon(?ipaddr, ?port, Options]).
>>>
>>> Test module:
>>> -module(sshtest).
>>> sshIO() ->
>>>    io:format("test1~n"),
>>>    io:format("test2\n"),
>>>   test3.
>>>
>>>
>>> Test run from my own machine:
>>>> ssh $IPADDR 'sshtest:sshIO().'
>>> test3
>>>
>>>
>>> For some reason any io:format/io:fwrite does not travel back over the SSH connection. If I connect to some Linux machine that already has a (non-erlang) SSH server running and I try to run some random bash script then any echo I have in the script will travel back over the SSH connection.
>>>
>>> A test I did with a bash script towards a Linux server,
>>> Bash script (~/test.sh):
>>>
>>> echo "test1"
>>>
>>> echo "test2"
>>>
>>> echo "test3"
>>>
>>>
>>> Test run from my own machine:
>>>> ssh $IPADDR ./test.sh
>>>
>>> test1
>>>
>>> test2
>>>
>>> test3
>>>
>>> This is how I'd like it to work.
>>>
>>>
>>> I have been googling and reading the documentation for the ssh and related modules to no avail in regards to finding a solution to this problem.
>>>
>>> Other than this I/O problem the ssh connection works perfectly for me =
>
>>>
>>> Hopefully someone here on the list has some insight into how this works.
>>>
>>> Thankful for any help I can get :)
>>> Best regards,
>>>
>>> Tommy
>>>
>>>
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> [hidden email]
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Erlang ssh shell question

Mattsson, Tommy

Hi Hans!

I've started to look into this. I did a trace using redbug and as far as I can tell I don't end up in the section with the comment "The F communicates via standard io:write/read." but rather end up in the section with the comment "%% Exec called and the shell is the default shell (= Erlang shell).". 

This was assuming that the I/O not coming back for the exec case is a bug. 


My redbug output:

% 14:10:33 <22297.5495.0>({ssh_client_channel,init,1})
% ssh_cli:handle_ssh_msg({ssh_cm,<22297.4959.0>,
        {exec,1,false, "sshtest:sshIO()."}}, 
        {state,undefined,undefined,undefined,undefined,undefined, {shell,start,[]}, undefined})

Which means, as far as I can tell, that no I/O is given back (there is no I/O handling from what I can see in the function ssh_clki:exec_in_erlang_default_shell/1.

Thanks for any help I can get 😊
Best regards,
Tommy Mattsson




From: Hans Nilsson R <[hidden email]>
Sent: Tuesday, November 6, 2018 10:43 AM
To: Mattsson, Tommy; Per Hedeland
Cc: [hidden email]
Subject: Re: [erlang-questions] Erlang ssh shell question
 
Hi Tommy and Hi Per too :)

Sorry for my sloppy reading of your first mail, but now I think I understand you.

To start an Erlang server executing "shell" or "exec" commands you just start a normal server (= daemon):
Erlang/OTP 21 [erts-10.1.1] [source-3094642] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

2> ssh:daemon(1236, [{system_dir,"XXX"}]).  % (will get ~/.ssh as user_dir where ~ is the home of the user that started erl)

and elsewhere in a bash:

~$ ssh -p 1236 localhost
Eshell V10.1.1  (abort with ^G)
1> io:write(hej).
hejok
2> exit().
~$

or, for "exec":

~$ ssh -p 1236 localhost 1+2.
3
~$

etc.


Now as I understand, you want to do I/O in the command and expect:

~$ ssh -p 1236 localhost 'io:write(hejsan).'
hejsan
~$

but you get:

~$ ssh -p 1236 localhost 'io:write(hejsan).'
ok
~$

and hejsan is written in the shell of the server started above.


You could start your own exec command interpreter with the option 'exec' to the server:

(See http://erlang.org/doc/man/ssh.html#type-exec_daemon_option
 but NOTE: ERROR in that one.....
  should be
      {exec, {direct, 'exec_fun/1'() | 'exec_fun/2'() | 'exec_fun/3'()} }
 )

Example:
9> ssh:daemon(1237, [{system_dir,"XXX"}, {exec, {direct,  fun(Cmd) -> {ok, {got,Cmd}} end  }}]).

and from a separate bash shell:

~$ ssh -p 1237 localhost 'io:write(hejsan).'
{got,"io:write(hejsan)."}~$

This gives a clue on what to do:
"Just" write something executing the command grabbing the output and return it in that {direct,fun(Cmd)...} as a string...

Now I think that not returning I/O from an exec command is a bug. However I can't look into that now and probably not on this side of christmas.
IF you should like to dig into this, the central function is ssh_cli:handle_ssh_msg/2 line 114.  The clause with the head:
    handle_ssh_msg({ssh_cm, ConnectionHandler,  {exec, ChannelId, WantReply, Cmd}}, S0) ->

There are comments in that code which could give you some clues.  There is also a comment with "The F communicates via standard io:write/read.".
That makes me belive that I accidently changed some functionality when I restructured this part. I will look into that too, but not now.

I hope you got some ideas, and just ask if you wonder about something. And Pull Requests are welcome!

/Hans

On 11/6/18 9:24 AM, Mattsson, Tommy wrote:
> Hi Per and Hans,
>
> Thank you both for your replies! 😊
> Per is correct, I want to execute "ssh <host> <cmd>" from a regular shell (bash, etc.) and have it connect to the Erlang SSH shell that I started on <host> and give me output like there was "echo test1", "echo test2" in a bash script.
>
>
> I will look into if I can make use of the exec functionality for the Erlang SSH server. I looked at it earlier but it seemed to me that its intended use was for an Erlang SSH client connecting to an Erlang SSH server so I dismissed that as an option.
>
> If all else fails I could look into the ssh_cli option and see if I can have an Erlang SSH shell handle I/O differently than the default.
>
>
> Best regards,
>
> Tommy
>
> ________________________________
> From: Per Hedeland <[hidden email]>
> Sent: Friday, November 2, 2018 11:30:33 AM
> To: Hans Nilsson R; Mattsson, Tommy
> Cc: [hidden email]
> Subject: Re: [erlang-questions] Erlang ssh shell question
>
> Hi Tommy! (and Hans:-)
>
> Hans, I *think* you are misunderstanding Tommy's question. More
> speculation below, since I haven't actually verified how ssh(3)
> works... When using e.g. the OpenSSH client,
>
> $ ssh <host>
>
> makes a "shell" request per
> https://tools.ietf.org/html/rfc4254#section-6.5 , while
>
> $ ssh <host> <cmd>
>
> makes an "exec" request. I think Tommy is happy with how "shell" works,
> but you seem to be changing it to a pretty boring implementation.:-) And
> I think Tommy's question is about "exec" not associating 'standard_io'
> with the SSH channel - thus if you use "exec" to call a function that
> prints something, the output is lost.
>
> I'm not sure there is anything "wrong" with that though - for an SSH
> server running "directly" on *nix, it is obvious that "exec" should
> associate stdio with the SSH channel, since <cmd> is *nix shell command,
> and it's pretty fundamental that you want any output (and exit code)
> that it produces. But for the Erlang/OTP SSH server, <cmd> is
> (apparently) an Erlang function call, and sending only what the call
> returns (in text form) back through the channel is not unreasonable per
> se.
>
> But maybe there could be an option to ssh:daemon() to make it do the
> same thing with 'standard_io' for "exec" as it does for "shell" - I
> can't see one in the man page. And I can't think of a way that the
> called function could set it up. But I assume that it's possible to
> do-it-all yourself via the 'ssh_cli' option.
>
> --Per
>
> On 2018-11-02 10:37, Hans Nilsson R wrote:
>> Hi,
>>
>> Try
>>
>> 5> ssh:daemon(1234, [{system_dir,...}, {shell,fun(Usr,Hst) -> spawn(fun() -> io:format("Hello ~p ~p~n",[Usr,Hst]), L1 = io:get_line("&& "), io:format("Got ~p~n", [L1]) end) end}]).
>> {ok,<0.110.0>}
>> 6>
>>
>> Sorry for the one-liner. The fun() a bit edited, I hope I got it right:
>>
>>     fun(Usr,Hst) ->
>>            spawn(fun() ->
>>                     io:format("Hello ~p ~p~n",[Usr,Hst]),
>>                     L1 = io:get_line("&& "),
>>                     io:format("Got ~p~n", [L1])
>>                  end)
>>     end
>>
>>
>> Note the option shell and the spawn, it is essential.
>> You don't need the subsystem option.  The user_dir option defaults to the $HOME/.ssh of the user that started erl.
>>
>> Now in bash:
>>
>> ~$ ssh -p 1234 localhost
>> Hello "USERNAME" {{127,0,0,1},60088}
>> && some command
>> Got "some command\n"
>> Connection to localhost closed.
>> ~$
>>
>> Hope this helps.
>> /Hans
>>
>>
>>
>> On 11/2/18 10:05 AM, Mattsson, Tommy wrote:
>>> Hi,
>>>
>>> First time writer here on the erlang questions list :)
>>>
>>>
>>> I am wondering if anyone knows about how the erlang ssh handles I/O? More details can be found below.
>>>
>>>
>>> Erlang version: 21.0
>>>
>>>
>>>
>>> Start of SSH server on testing (Windows) machine:
>>>
>>> application:ensure_all_started(ssh),
>>> Options = [{system_dir, filename:join(SSHPath, "daemon")}, {user_dir, ?DIR}, {subsystems, [ssh_sftpd:subsystem_spec([{cwd, SSHPath}])]}],
>>>
>>> ssh:daemon(?ipaddr, ?port, Options]).
>>>
>>> Test module:
>>> -module(sshtest).
>>> sshIO() ->
>>>    io:format("test1~n"),
>>>    io:format("test2\n"),
>>>   test3.
>>>
>>>
>>> Test run from my own machine:
>>>> ssh $IPADDR 'sshtest:sshIO().'
>>> test3
>>>
>>>
>>> For some reason any io:format/io:fwrite does not travel back over the SSH connection. If I connect to some Linux machine that already has a (non-erlang) SSH server running and I try to run some random bash script then any echo I have in the script will travel back over the SSH connection.
>>>
>>> A test I did with a bash script towards a Linux server,
>>> Bash script (~/test.sh):
>>>
>>> echo "test1"
>>>
>>> echo "test2"
>>>
>>> echo "test3"
>>>
>>>
>>> Test run from my own machine:
>>>> ssh $IPADDR ./test.sh
>>>
>>> test1
>>>
>>> test2
>>>
>>> test3
>>>
>>> This is how I'd like it to work.
>>>
>>>
>>> I have been googling and reading the documentation for the ssh and related modules to no avail in regards to finding a solution to this problem.
>>>
>>> Other than this I/O problem the ssh connection works perfectly for me =
>
>>>
>>> Hopefully someone here on the list has some insight into how this works.
>>>
>>> Thankful for any help I can get :)
>>> Best regards,
>>>
>>> Tommy
>>>
>>>
>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> erlang-questions mailing list
>>> [hidden email]
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>>
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>


_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions