tcoopman

tcoopman

I’m trying to run a shell command with a pipe operator in it. For example “sleep 0.1 | echo foo”. At first I tried to do this with System.cmd:

System.cmd("sleep", ["0.1", "|", "echo", "foo"])

But this results in /usr/bin/sleep: invalid time interval '|', invalid time interval 'echo'....

So next I tried to use :os.cmd:

:os.cmd("sleep 0.1 | echo foo")

But whatever I do to execute this I get:

:os.cmd("sleep 0.1 | echo foo")
** (FunctionClauseError) no function clause matching in :os.validate/1    
    
    The following arguments were given to :os.validate/1:
    
        # 1
        "sleep 0.1 | echo foo"
    
    (kernel) os.erl:281: :os.validate/1
    (kernel) os.erl:237: :os.cmd/1

Looking into the code of :os (otp/lib/kernel/src/os.erl at master · erlang/otp · GitHub) is see that :os.validate expects atoms? But in the erlang docs there are no atoms used (os — OTP 29.0.2 (kernel 11.0.2))

Showing Posts 1 to 9

tcoopman

tcoopman OP

I’ve just been able to solve my own problem.
If I do: os.cmd(:"sleep 0.1 | echo foo") it works.

So I need to pass an atom to os.cmd.

idi527

idi527

Or :os.cmd('sleep 0.1 | echo foo').

iex(1)> :os.cmd('sleep 0.1 | echo foo')
'foo\n'

It works with atoms and character lists. Doesn’t seem to work with binaries.

I would try to avoid creating new atoms for each command you might want to run since they are not garbage collected.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

System.cmd does not run a shell, so pipes, redirects, and so on aren’t supported. System.cmd is basically the closest thing that Elixir has to fork.

:os.cmd is definitely handy, but take great care if any of the stuff in your command comes from users (like filenames). You risk letting users run arbitrary programs.

alco

alco

It is strange that :os.cmd accepts an atom for the command name, looks like a historical accident.

In general, functions from the Erlang standard library take character lists where in Elixir you would use a string. To make it more confusing, the Erlang type for such lists is called string(). I recommend taking a look at this cheat sheet if you still feel confused.

Going back to your problem, Ben has already done a good job explaining the difference between Elixir’s System.cmd and Erlang’s :os.cmd. In the source code for :os.cmd you can see it actually spawns a shell appropriate for the current OS and evaluates the string you’ve passed to the function in that shell.

Replicating this behaviour for your particular example using System.cmd is easy:

System.cmd("sh", ["sleep 0.1 | echo foo"])
OvermindDL1

OvermindDL1

Not entirely. A lot of the ‘base’ functions get the string value of atoms, it makes it cheap and efficient to pass around something like sed instead of having to do "sed" in the original erlang (plus it’s fantastic since atoms in erlang can have @ in them without quoting too!). Calling other programs was generally used to access their stdin/stdout, not for argument parsing and ‘doing’ other stuff. :slight_smile:

(Do note, the sed and "sed" above in erlang, in elixir would be :sed and 'sed' respectively.)

Qqwy

Qqwy

TypeCheck Core Team

Why is this an advantage for calling functions that happen to also accept atoms and not only charlists?

OvermindDL1

OvermindDL1

Overall less space for repeatedly used ‘strings’, atoms are essentially interned/flyweight’d strings after all (and lists of integers are anything but lightweight in memory, even if they are very fast iterables). Not really an issue nowadays, but Erlang is old remember. ^.^

As for the @ bit, it’s because they are used in areas on the VM such as server names, cookies, etc… Like in elixir you’d have to do :"username@server" where in erlang you’d just do username@server, nothing else needed, which is a great boon when manually doing a lot of work at the console or putting those in erlang config files. But of course, the ecosystem handles that better now and so things like Elixir don’t even support @ in unquoted atoms unlike Erlang. ^.^;

tcoopman

tcoopman OP

System.cmd("sh", ["sleep 0.1"]) results in /usr/bin/sh: sleep 0.1: No such file or directory {"", 127}. So this solution doesn’t seem to work

alco

alco

I made a mistake in the invocation. To evaluate a string in sh, the -c has to be passed first:

System.cmd("sh", ["-c", "sleep 0.1"])
10
Post #9
— All posts loaded —

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
jaybe78
Hello, I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter). The diffic...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New

Other Trending Topics Top

CodeSync
Hologram: The Journey to Local-First Elixir in the Browser - Bart Blast | ElixirConf EU 2026 https://www.youtube.com/watch?v=qqpNovT7cys...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews