Suppose we have fct defined like so:

fct() {
  echo words
  read -n1 x
  [ $x == q ] && exit

Calling fct works as expected, but if you need to trap its output, var=`fct`, exit does not work. According to what I found searching on the net, exit works, but it exit a spawned shell. It does work with kill -s KILL $$, so fct runs in the same process as =, just not the same context and exit quit only the context, not the shell.

Is there a way we can call fct to trap its output and let exit quit the same context as the equal? Or is there any other way than hard killing to stop the process?

  • The standard way to achieve something similar without making a mess: add a trap for SIGINT, and set a flag in the handler. Then check for said flag at convenient points in your script. You'll then be able to interupt your script with Ctrl-C. Nov 18 '16 at 4:51
  • 2
    "so fct runs in the same process as =, just not the same context " <- this is false. It runs in a separate process, the $$ variable is just not updated. This is the exact reason why $BASHPID exists (see documentation).
    – phemmer
    Nov 18 '16 at 13:31
  • Thanks @Patrick, you are right, it does not seem to be running in the same process id, I checked it with ps while it was sleeping (I added a sleep) and it spawn a subprocess. I looked at documentation and it does show a different $BASHPID if run in subshell (surrounded with single parentheses commands), but not surrounded with $(...) commands or backticks. So we cannot access it's output and let it exit.
    – kbenoit
    Nov 20 '16 at 16:51
  • @SatoKatsura, what I'm doing, is a script that is sourced initially to set the prompt and the environnement. The script need input from the user (choose an alternate environnement/project), but I want ^D to work. So that the user can quit the terminal if he realize he opened it accidentally.
    – kbenoit
    Nov 20 '16 at 17:31

I figured it out!

We can pass the stream through a temporary file! In linux, we can pass it through a file in /dev/shm, so that the data stays in memory. We can also wrap it in a funcion:

get_output() {
  $1 > /dev/shm/bash_pipe
  eval $2=`cat /dev/shm/bash_pipe`
  rm /dev/shm/bash_pipe

We can then use it like so: get_output fct var and you can use the output of fct with $var.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.