Why System.cmd produce error at runtime, but works in iex?

I am running this command when handling a message in a channel:

{output, _} = System.cmd("ngspice", ["-b", file_path], stderr_to_stdout: true)

but I got error:

** (stop) :enoent
    (elixir) lib/system.ex:634: System.cmd("ngspice", ["-b", "/var/folders/8g/p8wtd8g17z973rpjrz5dx4_h0000gn/T/file.cir-1562036839-82456-1yu64di"], [stderr_to_stdout: true])

however, if I run the command in the error log System.cmd("ngspice", ["-b", "/var/folders/8g/p8wtd8g17z973rpjrz5dx4_h0000gn/T/file.cir-1562036839-82456-1yu64di"], [stderr_to_stdout: true]) in iex console, it works as expected without error.

any idea?

How is the instance started that doesn’t work?

Is it perhaps started in an environment that has a shorter PATH with less entries and ngspice is not visible for it?

Check System.get_env("PATH") and compare the results.

I start the instance using mix phx.server

Its strange that command System.cmd I used already worked with certain inputs to ngspice, but when I change the params of input passed for ngspice, ex: the content of file_path, I get that error ** (stop) :enoent, although it works fine for the same input at iex

What could be the reason of error? how can I get deeper details rather than just ** (stop) :enoent ?

I still think @nobbz may be onto something here because “enoent” when trying to execute command, usually means there is no such entry in $PATH environment variable.

I suspect you start the app with iex from your shell, that has the $PATH environment properly set up. As in terminal window. And then you may start the app different way that doesn’t set the $PATH properly, possibly as systemd/init script or maybe some other way? Or do you start “iex -S mix phx.server” which works, and then from the same shell you start “mix phx.server” and this doesn’t?

1 Like

As @hubertlepicki says, the only reason how System.cmd/3 might throw an :enoent is when the specified command couldn’t be found, as this is the only argument that actually gets searched from elixir.

If some of the files you pass as argument weren’t found, that would have been handled by the executable you call and reported via its return value and/or its output channels.

Also it is documented exactly like this:

  • :enoent - the command does not point to an existing file

The file_path does exist, as I do create it before I use it, as here:

{:ok, fd, file_path} = Temp.open "file.cir"
    IO.write fd, netlist
    File.close fd
    {output, _} = System.cmd("ngspice", ["-b", file_path], stderr_to_stdout: true)# "/Users/Apple/Projects/ngspice-server/temp.cir"])
    File.rm file_path
    output

could it be not fully ready to be accessed by ngspice ? as I do close the file and directly use it?

We are talking about PATH, an environment variable.

Have you checked it as asked in Why System.cmd produce error at runtime, but works in iex??

Have you tried an absolute path to ngspice rather than relying on it beeing in the PATH?

Have you already answered whether or not the problem persists when starting your application from the same terminal as you did with iex?

We really do not care for the list of arguments, since elixir does not do anything with it but passing to the started OS process. The only way an :enoent can happen is, that elixir can’t find the command specified in the first argument to System.cmd/3.

Ok, I will check when I get home, thanks

maybe use System.find_executable("ngspice") as a guard around or maybe even in startup to check that this dependency is available
https://hexdocs.pm/elixir/System.html#find_executable/1

thanks all, the problem has gone, I used full path to the library…

1 Like