saleyn / erlexec

Execute and control OS processes from Erlang/OTP
https://hexdocs.pm/erlexec/readme.html
Other
525 stars 139 forks source link

Exit codes appear to be x256 too large #148

Closed ewildgoose closed 3 years ago

ewildgoose commented 3 years ago

Hi, using Linux (musl) and I think possibly also OSX, I see the exit codes on failure are multiplied by 256? Is this intended?

If intended, the further issue is that the "success_exit_code" param will not accept values larger than 255.

That said, I came here with a feature request... Could we support multiple success_exit_code values. use case is that I want to call "conntrack", which inconveniently returns an exit value of 0 or 1 depending on whether it managed to flush anything

I think the following lines (from an elixir iex session) demonstrate the main issue:

iex(10)> :exec.run('/bin/sh -c \'exit 3\'', [:sync, :stdout, :stderr, {:success_exit_code, 255}]) {:error, [exit_status: 768]} iex(11)> :exec.run('/bin/sh -c \'exit 3\'', [:sync, :stdout, :stderr, {:success_exit_code, 256}]) {:error, {:invalid_option, {:success_exit_code, 256}}} iex(12)> :exec.run('/bin/shs -c \'exit 3\'', [:sync, :stdout, :stderr]) {:error, [exit_status: 32512, stderr: ["/bin/sh: /bin/shs: not found\n"]]} iex(13)> :exec.run('/bin/sh -c \'exit 3\'', [:sync, :stdout, :stderr]) {:error, [exit_status: 768]} iex(14)> :exec.run('/bin/sh -c \'exit 1\'', [:sync, :stdout, :stderr]) {:error, [exit_status: 256]} iex(15)> :exec.run('/bin/sh -c \'exit 2\'', [:sync, :stdout, :stderr]) {:error, [exit_status: 512]}

saleyn commented 3 years ago

You have to use exec:status(ExitCode) to decode exit status. See docs.

1> exec:status(768).                                             
{status,3}

Regarding supporting multiple success_exit_code values - I can't promise it might be available anytime soon. You can run your conntrack command like so:

:exec.run("your-conntrack-command; A=$?; [ $A -eq 1 ] && exit 0 || exit $A", [...])

Here's example in the shell:

$ for i in {0..3}; do sh -c 'sh -c "exit '$i'"; A=$?; [ $A -eq 1 ] && exit 0 || exit $A'; echo $?; done
0
0
2
3