2

I have a compiled program main.bin that is supposed to print:

hello world
another line

This program generates a segmentation fault right after printing the first line.

If I run it in the shell (zsh), I get this:

Hello world
[1]    3503 segmentation fault (core dumped)  ./main.bin

However, when I try to redirect and use the partial stdout, there is nothing. This is due to lost stdout buffer. So using the unbuffer tool, I get it working:

$ unbuffer ./main.bin > tee out.log
Hello world
$ cat out.log
Hello world

Good. Now I want to also capture that segmentation fault message given by the shell:

$ (sh -c ./main.bin) 2> err.log
Hello world
$ cat err.log
Segmentation fault (core dumped)

Ok, I can do separately get both. But when I try to capture them together, I cannot find a way other than calling main.bin twice. Just using unbuffer in a subshell will not generate the segmentation fault. And calling the program alone will not print the output.


My target is to make a script that prints in stdout the (perhaps partial) output of the program, and in stderr any segmentation fault, stack overflow, etc that the shell may generate due to a buggy program.

My current solution (not anymore, I posted an answer) is a script with this:

subject="$1"
out=$(unbuffer "$subject")
err=$(sh -c "$subject" 2>&1 1>/dev/null)
echo ">o> $out"
>&2 echo ">e> $err"

Is there a more elegant way to achieve this, other than just calling main.bin twice in a script, and echoing to each std{out,err}? I have been reading other similar entries here [1] [2] [3], but they are cumbersome, or don't directly map to my problem.

2 Answers2

0

Use &> for redirection!

echo foo &> /dev/null

Check out https://tldp.org/LDP/abs/html/io-redirection.html, too.

0

A potential answer is to use two different scripts:

  • subrun.sh: here I extract the stderr to a file
./main.bin 2>err.log;
  • run.sh: here I collect the un-buffered stdout, and print each out to its corresponding place. Also, return the return code given by main.bin
echo "">out.log>err.log
unbuffer ./subrun.sh > out.log
ret_code="$?"
cat out.log #cat to stdout
cat err.log >&2 # cat to stderr
return $ret_code # return program's return code
  • you can use script /dev/null (which is installed by default) instead of unbuffer. 2. you are "solving" an x/y problem: what you should do instead is checking the exit status $? which will tell you if the process was killed by SEGV
  • –  Oct 11 '21 at 10:23