0

I have a script that attempts to log its actions. There's a single tee in there that does all of this. Currently, when the $LOG_FILE cannot be written to the script dies. Instead, I would like it to just not write to a log file.

In the script, the part that's logged looks something like this:

for foo in "${array_of_foos[@]"; do
  {get bar from foo} | sort -u
done | xargs -n 100 -P 20 bar_processor.sh |& tee "$LOG_FILE"

When the user does not want to write a log file, can I just set LOG_FILE=/dev/null or is there some better way to handle that? Note that this script is not and will never be run as root.

2
  • 2
    Why would the script just die if $LOG_FILE can't be written to? I don't think tee should just up and die even itself if it can't write to a file, let alone kill the whole script. Unless you're using set -e, but you didn't mention that.
    – ilkkachu
    Sep 10, 2021 at 9:29
  • It dies because I kill it, due to not being sure how to handle a non-logging use case. Thus this question. :)
    – OstermanA
    Sep 10, 2021 at 21:18

1 Answer 1

2

In order to handle either a log file that's writable or a log file that doesn't yet exist but that is in a writable directory, the most reliable approach is to try it:

LOG_FILE=loggit.log
( printf "" >>"$LOG_FILE" ) 2>/dev/null || LOG_FILE=/dev/null

# ...
echo "Stuff to be logged" >>"$LOG_FILE"
some | pipeline >>"$LOG_FILE"

In your particular situation you want output to be duplicated to stdout and to the log file, so you can now do this:

some | pipeline | tee -a "$LOG_FILE"

If you want to do different things depending on whether or not you have a meaningful log file, we can handle this with a more complex scenario: you can set LOG_FILE= (ie to nothing) in the snippet above, and then test it in your later code:

[[ -n "$LOG_FILE" ]] && echo "Stuff to be logged" >>"$LOG_FILE"

and you can execute code unconditionally, while still logging if possible, with a construct like this:

some | pipeline >>"${LOG_FILE:-/dev/null}"
some | pipeline | tee -a "${LOG_FILE:-/dev/null}"

Also see my answer to another question Ways to append text to a file about a method to avoid repeating "${LOG_FILE:-/dev/null}" each time.

6
  • wouldn't just LOG_FILE=${LOG_FILE:-/dev/null} do for avoiding repeating the default value? :)
    – ilkkachu
    Sep 10, 2021 at 9:30
  • @ilkkachu there are two situations here. The first one is the easiest - all writes to the log file go to "$LOG_FILE" regardless. The second situation uses the empty/not-empty state of "$LOG_FILE" to identify whether or not certain sections of code should be run at all. In this scenario you can't assign /dev/null to the variable because then it's no longer an empty string so you can't test that Sep 10, 2021 at 10:31
  • You are correct that if I just want something as simple as >>${LOG_FILE:-/dev/null} that's trivial, but I want it to always print to screen and conditionally write to file. I'm not sure how to handle that without doing something insane like buffering the log in an array. That seems like a terrible solution, but I'm not seeing any other safe ways to do that.
    – OstermanA
    Sep 10, 2021 at 21:20
  • @OstermanA I've added the necessary command structure for you to have output to stdout and optionally to a log file Sep 11, 2021 at 7:10
  • @roaima OK, so tee -a /dev/null is "safe" to use? That makes sense. Are there any circumstances where it's not safe to do this?
    – OstermanA
    Sep 12, 2021 at 8:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .