I've got a shell script doing connection performance test, that I timeout if it takes too long.

Upon timeout, it logs the results of a few commands so I can make myself an idea of the system status at the time of failure. I would like to run some commands depending on which phase of the test it timed-out.

I came up with the following script:


function testing()
    #do some testing

    #do some testing

    #do some testing

function logonerror(){
    if [ "$TESTCASE" = "FIRST" ]; then                  
       #logging command relevant to first test case
    elif [ "$TESTCASE" = "SECOND" ]; then                  
       #logging command relevant to second test case
    elif [ "$TESTCASE" = "THIRD" ]; then                  
       #logging command relevant to third test case                   
    #some additional standard logging

timeout 7200 cat  <( testing )
if (($? == 124)); then

The only issue I have is that it doesn't matter which phase it timed-out, when doing the logging it always think it is at the initial phase.

How can I make sure that the test phase information get correctly updated?

  • after the first function you can exit the script & then check the second script with exit. – Mongrel Jan 18 '16 at 9:17
  • @AngRed: if I understood you correctly, that would mean splitting my script in two, and I would like to avoid that if possible. – Eldros Jan 18 '16 at 9:22
  • just to understand were you have an error, you can try that – Mongrel Jan 18 '16 at 9:28

Your first problem is:


let handles math. Assignments made in a let statement will assign integer values. In a shell arithmetic context the FIRST, SECOND, THIRD values you're assigning to $TESTCASE all evaluate to zero because they're considered to be unset variable names - not literal values.

unset FIRST
echo "$TESTCASE"



echo "$TESTCASE"


So every assignment you do assigns the same value to $TESTCASE unless any variables named FIRST, SECOND, THIRD, or INITIAL are exported into its environment before it is run.

To assign the string FIRST to the shell variable $TESTCASE you should do:

echo "$TESTCASE"


You might also consider case:

    case $TESTCASE in
    (1)   : logging commands relevant to 1st test case
    (2)   : logging commands relevant to 2nd test case
    (3)   : logging commands relevant to 3rd test case
    esac; : logging commands relevant to all test cases
    case $TESTCASE in
    (1) : do some testing
    (2) : do some testing
    (3) : do some testing

    trap  cleanup         EXIT
{   trap 'logonerror >&2; exit' PIPE
    for TESTCASE in 1 2 3; do testing; done >&2;:
}|{ read -t 7200; kill -PIPE -0; }
| improve this answer | |
  • I'm liking your solution, but there is no timeout anymore, which is important to me. – Eldros Jan 18 '16 at 12:19
  • @Eldros - this wasn't meant to preclude that block you had at the bottom, just the bits that it redefines. You can still use that of course. Put the for ... done in your <( process substitution ). – mikeserv Jan 18 '16 at 13:01
  • I've tested your solution, setting the timeout so it would interrupt the different testcases, but it always logged as if it were in the initial phase, the errlog function never being overwritten. – Eldros Jan 19 '16 at 9:33
  • @Eldros - oh, yeah. It's cause the defines don't take from without the subshell - just a sec. But can you tell me though what $! is supposed to be a return code or are you testing the PID for the last backgrounded process? Return codes come in $?, by the way. – mikeserv Jan 19 '16 at 9:36
  • My bad it is supposed to be $? I will edit that right away, – Eldros Jan 19 '16 at 9:40

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.