zapateo
Hi everyone, this is my first post on this forum ![]()
I am learning Elixir and I wish to write my software/scripts with it, I really love the syntax.
One problem I encountered is launching a system command and interact with it through stdin/stdout.
For example something like:
System.cmd("sudo", ["whoami"])
System.cmd("vi", [])
doesn’t work at all because they require access to stdin/stdout (seems like they can’t find a tty).
I searched a lot on the web and I found some resources with some workaround (eg. using a GUI askpass for sudo or launching system commands in another terminal); such resources I have found are a bit old.
My question is: is the situation changed? Is there any way, for example using Ports, to make the commands above work “as expected” like in other programming language?
For example in Python I write:
import subprocess
subprocess.run("vi")
This is the only “missing feature” that prevents me from porting all my software and scripts to Elixir.
Thanks in advance ![]()
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 7- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
NobbZ
I know that
sudodoesn’t even usestdin/stdoutbut reads from the (virtual) tty directly. I assume similar forvi.To be honest, I wouldn’t even expect your python code to work…
And why port everything to Elixir? If you already have scripts in python that do their job, then keep them that way… I still prefer using
zshandpythonfor doing scripts that I run from the terminal or viacron.I use Elixir mainly for long running and daemon style applications.
benwilson512
Hi @zapateo, you may want to check out Porcelain – porcelain v2.0.3, it has a spawn function that should be relatively easy to use for something like this.
I do agree with @NobbZ overall with respect to this idea though. Use the right tool for the right job. If you already have functioning python scripts for this stuff and there isn’t internal concurrency issues that a port to Elixir would provide clear wins with, I’d consider whether a port like this provides value. If you want to do it for educational reasons then that’s perfectly fine, but if you’re trying to solve problems, consider whether the problem is a good fit for what you have or a better fit with Elixir.
outlog
+1 on porcelain, though check out GitHub - jayjun/rambo: Run your command. Send input. Get output. · GitHub as well, as I believe that supersedes porcelain.. (I have only ever used porcelain few years back to do some pdf scraping..)
zapateo
Thanks for your replies, guys!
I tried both
porcelainandrambo, they both look really cool for running systemprocesses/shell commands, but the problem still persist:
Anyway, thanks for the feedback about choosing the right tool for the right job.
Porting my software in Elixir has started just for learning purposes but ended
in an overcomplicated mission.
LostKobrakai
I’m not sure about the “not a terminal” problem, but usually if you want to continuously interact with an external program though stdin/stdout you should go for erlexec instead of rambo/porcelain.
jayjun
I do like Elixir as a scripting language except the BEAM is notoriously bad at working with external commands, even worse when those require the terminal.
For starters, this works.
But ports are really designed to work with external programs custom tailored for your Erlang app.
One assumption is Erlang must talk to your external process, so pipes are connected to the child’s standard input/output.
:nouse_stdiomeans “use file descriptors 3 and 4 instead” so vi inherits the terminal as standard input/output and things work as expected.System.cmd—which is simply a convenience wrapper around ports—won’t work because it is hardcoded to:use_stdio.Next,
Port.opendoes not block likesubprocess.run. To mimic that, you can ask for the:exit_statusthen block withreceive.Finally, child processes spawned by Erlang ports are detached from the controlling terminal. So programs that read from the terminal directly like
sudowon’t work. There’s no general workaround, only application-specific ones.As you can see, it’s an uphill battle but keep in mind that Python is first and foremost a scripting language. If you don’t need to call external programs,
.exsfiles and escripts are a pleasant way to automate. Otherwise, libraries can help ease some hurdles but not entirely.zapateo
Thanks a lot. Your answer clarified to me many aspects of the problem.
Also, the snippet you posted works as expected; so simple but very powerful, that it what I was looking for.