[erlang-questions] limitations of erlang:open_port() and os:cmd()
Bengt Kleberg
bengt.kleberg@REDACTED
Mon Nov 1 17:38:39 CET 2010
Greetings,
This is probably not what you want, but the shell rc
(http://doc.cat-v.org/plan_9/4th_edition/papers/rc) has multiple exit
status from a pipe. Like this:
"Rc captures command exit status in the variable $status. For a simple
command the value of $status is just as described above. For a pipeline
$status is set to the concatenation of the statuses of the pipeline
components with | characters for separators."
bengt
On Fri, 2010-10-29 at 12:40 +0200, Matthias Lang wrote:
> Hi,
>
> I know of a few limitations when running external programs from
> Erlang, and I know a few workarounds.
>
> Does anyone know of limitations and/or workarounds I don't know about?
> Would be interesting to hear about them.
>
> The limitations I know of are:
>
> 1. There's no way to do flow control.
> 2. There's no way to kill a misbehaving process
> 3. There's no way to send eof _and_ get the process' exit status
>
> Expanding on those:
>
> --------------------
> 1. There's no way to do flow control
>
> Example:
> 1> os:cmd("cat /dev/zero").
> Crash dump was written to: erl_crash.dump
> eheap_alloc: Cannot allocate 1048656 bytes of memory (of type "heap_frag").
>
> Workaround 1.1:
> 1> os:cmd("cat /dev/zero | netcat -l -p 49152").
> User switch command --> s --> c
> 1> {ok, S} = gen_tcp:connect("localhost", 49152, [{active, once}]).
> {ok,#Port<0.607>}
> 2> flush().
> Shell got {tcp,#Port<0.607>, [0,0,0,0,0,0,0,0,0,0
>
> Suckage: depends on netcat, I'm not sure which process' exit status you get
>
> --------------------
> 2. There's no way to kill a misbehaving process
>
> Example:
> 1> os:cmd("wc /dev/zero").
>
> Workaround 2.1:
> Write a wrapper program which echoes the unix pid before exec()ing
> the actual command.
>
> Workaround 2.2:
> Write a wrapper program which forks() and copies IO to the child,
> terminating the child on eof.
>
> Suckage: you have to write a wrapper
>
> --------------------
> 3. There's no way to send eof _and_ get the process' exit status
>
> Example:
> 1> {ok, Bin} = file:read_file("/tmp/mml.tgz").
> {ok,<<31,139,8,0,100,129,202,76,0,3,236,93,9,120,20,85,
> 2> P = open_port({spawn, "tar -xzf -"}, [exit_status, binary]).
> #Port<0.535>
> 3> port_command(P, Bin).
> true
> 4> flush().
> ok
> 5> port_close(P).
> true
> 6> flush().
> ok
>
> Workaround 3.1:
> Abuse strace, using knowledge of the unix pid gained somehow:
>
> os:cmd("strace -p 7974 -e trace=process").
>
> Workaround 3.2:
> Go via netcat again, e.g.
>
> 2> P = open_port({spawn, "netcat -l -p 49152 | tar -xzf -"}, [exit_status, binary]).
> 3> {ok, S} = gen_tcp:connect("localhost", 49152, []).
> 4> gen_tcp:send(S, Bin), gen_tcp:close(S), flush().
>
> Suckage: probably only works on unix, requires netcat
>
>
>
> Matt
>
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED
>
More information about the erlang-questions
mailing list