2

I have script that reads lines from a file, processes each line. I'd like to be able to do some "post-processing" in a way that even when the script didn't finish reading all lines because I pressed Ctrl+C it would still do the post processing. To achieve this I'm trying to do both of the following:

  1. redirect stdout to a file; Later do the post-processing from that file, however I'd like to see what's going on, so I'd like to redirect to "tee"
  2. trap Ctrl+C and do the post processing there

I managed to make either 1 or 2 work, but not both at the same time:

#!/bin/bash

# 2. Either this works 
# trap ctrl-c and call ctrl_c()
trap ctrl_c INT
function ctrl_c() {
    echo "** Trapped CTRL-C"
}

# 1. Or this works    
LOGFILE=/tmp/${FILE}.tee
rm ${LOGFILE}
exec > >(tee ${LOGFILE}) 2>&1

function post_process() {
    # use ${LOGFILE}
}

egrep "(${URL_PATH})" ${FILE} |
    while read LINE ; do
        #...
    done

post_process
  • Not sure I understand WHERE you're stuck. What if you add post_process to the ctrl_c function and use the tee redirection for the while loop only? – RudiC Oct 17 '18 at 11:04
  • It sounds like a good idea. How do I do the redirection only for the while? – Gavriel Oct 17 '18 at 11:10
  • @Gavriel with exec 3>&1 >output; ...; exec >&3. But please read my answer -- you do not have to do that. – mosvy Oct 17 '18 at 11:28
1

You should ignore the ^C / SIGINT in the post-process function:

preprocess(){
   yes baa
}
postprocess(){
   sed 's/a/z/g'
}
preprocess | { trap '' INT; postprocess; sleep 1; echo DONE; }

When you run that pipeline and press ^C, preprocess will be killed, but postprocess will continue running until all the output produced by preprocess has been consumed.

Notice that the trap '' INT (with an empty string as the handler) will also ignore SIGINT in the subprocesses; do not replace it with eg. trap 'echo INT trapped' INT because that will cause any sed, etc. to be killed too by '^C', despite the signal being handled in the parent process.

  • I couldn't make it work. Note: pre-process prints to stdout and I'd like it to keep showing what's it's doing + write to a file, that's why I'm trying to use tee. I don't find where to put "exec > >(tee ${LOGFILE}) 2>&1" or something similar, because anywhere I try it it causes the trap not to work – Gavriel Oct 17 '18 at 12:11
  • 1
    preprocess | tee logfile | { trap '' INT; postprocess; } ---or--- preprocess | { trap '' INT; postprocess | tee logfile; } – mosvy Oct 17 '18 at 12:16
  • Thanks. This works for me: trap ctrl_c INT ; preprocess | tee logfile ; postprocess – Gavriel Oct 17 '18 at 12:46

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.