System.cmd/3 with pty access

747 views
Skip to first unread message

Nokan Emiro

unread,
Dec 5, 2015, 7:24:20 PM12/5/15
to elixir-lang-talk
Hi,

How can I launch an external application from an Elixir (escript) app?  I'm on Linux and what I need is to allow full pty access to the executed program.
:os.cmd and System.cmd is not ceding terminal access.

    iex> System.cmd "tty", []
    {"not a tty\n", 1}

How can this be done?

Would it be possible to improve System.cmd/3 in a future release to support this?

N.

Booker Bense

unread,
Dec 6, 2015, 1:10:42 PM12/6/15
to elixir-lang-talk
The way to do this is via Erlang ports. I would highly recommend the Porcelain library for 
working with Erlang Ports. 


- Booker C. Bense

Nokan Emiro

unread,
Dec 6, 2015, 4:20:42 PM12/6/15
to elixir-lang-talk

Maybe I'm trying to do it in the wrong way but I can't get the right result.  This is how far I got:

    io  = IO.binstream :stdio,  1
    err = IO.binstream :stderr, 1
    Porcelain.exec "tty", [], in: io, out: io, err: err

This still prints "not a tty".

I just want to launch a text editor (vi, for instance) to allow the user to edit a file and continue my job when he exits the editor.

Booker Bense

unread,
Dec 6, 2015, 5:19:41 PM12/6/15
to elixir-lang-talk
This is actually much trickier than originally thought from your initial question. 
I thought you wanted to interact with stdout, stdout from an external process. 

Porcelain is fine for that. I've tried playing around with this. 

Porcelain.shell("/usr/bin/vi /tmp/foobar < /dev/tty > /dev/tty")

and this

Porcelain.shell("/usr/bin/vi /tmp/foobar < /dev/ttys006 > /dev/ttys006")

The first doesn't work at all on OS X and the second does allow me
to at least open vi, but it does not work well. 

This is one of the places where things that are easy in other languages are
fairly complex in Elixir. 

I did some poking around in ex_top and I think the magic is in this line. 

Port.open({:spawn, "tty_sl -c -e"}, [:binary, :eof])

Still digging... 

- Booker C. Bense

Theron Boerner

unread,
Dec 6, 2015, 6:08:26 PM12/6/15
to elixir-lang-talk
Take a look at http://saleyn.github.io/erlexec/ which allows running commands in a pty.

Running OS commands with pseudo terminal (pty)

% Execute a command without a pty
37> exec:run("echo hello", [sync, stdout]).
{ok, [{stdout,[<<"hello\n">>]}]}

% Execute a command with a pty
38> exec:run("echo hello", [sync, stdout, pty]).
{ok,[{stdout,[<<"hello">>,<<"\r\n">>]}]}

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/8d0ec7cf-5985-4698-8311-cefa3aa2c476%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Jim Freeze

unread,
Dec 6, 2015, 9:35:17 PM12/6/15
to elixir-l...@googlegroups.com
One of the things you may want to try is to run this from a compiled script and NOT from iex.

Try mix escript.build and do your tests from the compiled script.

That may at least fix the case where vi is runnable, but the results were not working well.

Jim



For more options, visit https://groups.google.com/d/optout.



--
Dr. Jim Freeze, Ph.D.

Nokan Emiro

unread,
Dec 10, 2015, 5:16:29 PM12/10/15
to elixir-lang-talk

Many thanks for all of you who took time to dig up ideas for my problem.

Unfortunately I'm still stuck with this.  The closest I got is to execute a shell command (with
:os.cmd or Porcelain) with stdin, stdout and stderr redirected to the proper pts device.  The problem
here is that I cannot get the name of the device currently in use from within the Erlang VM.
Another problem is that, for instance, :os.cmd 'vi /some/file </dev/pts/1 >/dev/pts/1 2>&1'
launches an editor, but it has a somewhat strange behaviour (for example, ESC has no effect,
just when followed by an Enter).

Erlexec does not work for me.  I can execute external programs but I'm unable to execute
it within the same pty session.  The :pty option just makes no difference to how it works
without the directive.

I think Erlang (and thus Elixir) misses this very low level features that is commonplace in
other environments.  Creating a command line tool that launches an external editor (think
about  `git commit`  without the "-m <message>" option) is impossible here.  I understand
that Erlang has different strengths, but this would be very nice for developing command
line tools to have better os process controll.  It would be very important to gain a foothold
as a new technology at my company.

Is this something that is very hard or impossible in the Erlang VM?  Should I give it up
and use another language for this project, or there's a solution in Elixir?


Greg Vaughn

unread,
Dec 12, 2015, 1:44:13 PM12/12/15
to elixir-l...@googlegroups.com
At last year's ElixirConf James Smith demonstrated some code that interacted with nethack. I forgot the details, but perhaps it'll help with your situation. You can watch the video http://confreaks.tv/videos/elixirconf2014-writing-command-line-applications-with-elixir

-Greg
> --
> You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/0ba1e7a7-1b0f-4a9b-87bd-c03c227e98d9%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages