If your tagging for this question is correct and you're genuinely using bash (which is to say that your script starts with #!/bin/bash, or if not started via a shebang you use bash yourscript rather than sh yourscript), you might as well take advantage of it.
# extended bash math syntax
if (( (max - total) < 6 )) && (( idle <= (max / 4) )); then
warn "$total" "$process" "$max" "$idle"
fi
If, for whatever reason, you don't want to use (( )), you can still use [[ ]], which gives you a test context with its own extended syntax:
# extended bash test syntax
if [[ $((max - total)) -lt 6 && $idle -le $(bc -l <<<"$max*0.25") ]]; then
warn "$total" "$process" "$max" "$idle"
fi
...whereas if you want to be compatible with POSIX sh, you need to end the test before you can put in a shell-level logical-AND operator.
# corrected POSIX-compliant test syntax
if [ "$((max - total))" -lt 6 ] && [ "$idle" -le "$(bc -l <<<"$max*0.25")" ]; then
warn "$total" "$process" "$max" "$idle"
fi
To understand why, let's look at how your original command would parse, if you changed the (utterly incorrect) | symbol to && instead:
# Equivalent (longer form) of the original code, with pipe corrected to logical-AND
if [ $(($max - $total)) -lt 6; then
if [ $idle -le $(($max \* 0.25 | bc -l)) ] ]; then
warn $total $process $max $idle
fi
fi
Note that this is running, as a single command, [ $(($max - $total)) -lt 6.
[ is not special shell syntax -- it's just a command. In older shells it was actually /usr/bin/[; today, there's also a [ builtin as well, but other than being faster to execute, it behaves exactly the same way as it would have were it executing the old, external command.
That [ command expects to be passed a ] as its last argument, since there's no ] after the -lt 6, you get a syntax error and it exits.
Similarly, your code would then (if the first command succeeded) run [ $idle -le $(($max \* 0.25 | bc -l)) ] ]. Here, you have a [ command passed two ]s on the end; it simply doesn't know what to do with the second one.
#!/bin/bashrather than#!/bin/sh, you've got much more flexible syntax available.( max >= 11 ))is easier to read than[ "$max" -ge 11 ], after all. You could also use[[ ]]for an extended test context, which would let you use&&internally (rather than having that result in the unexpected end of one command and beginning of another).|is the wrong operator --foo | barruns bothfooandbarat the same time, connecting the output offooto the input ofbar. By contrast, what you want here is to runbaronly iffoocompletes successfully -- which a short-circuiting logical AND operator,&&, will do.