简体   繁体   中英

How do I properly print a multi-line variable in an e-mail sent from a BASH script?

I have a BASH script that runs various sysadmin functions and system checks. If a check fails, a variable is set to 1 . There are only a couple types of errors that can happen, so I have variables named to describe the error such as $login_error and $timeout .

At the end of the script, if an error was encountered, an e-mail is sent to my team. In the e-mail, I include a brief error message describing what the error was. The problem I'm getting is that the error messages contain a \\n character, but my embedded e-mail doesn't preserve the newlines.

I'll show you what I mean. Here's the function that checks for failures and e-mails me:

checkFailure () {
    if [[ $error_encountered -eq 1 ]]; then

    [[ $timeout -eq 1 ]] && msg="Error 1: The device timed out\n"
    [[ $login_error -eq 1 ]] && msg="${msg}Error 2: Failed to login to device\n"
    [[ $sky_fall -eq 1 ]] && msg="${msg}Error 3: The sky is falling\n"

    { /usr/bin/nc <ip_of_my_sendmail_box> << EOF
mail from: server@domain.com
rcpt to: me@domain.com
data
to: me@domain.com
subject: Error during systems check
Content-Type: text/plain

$(printf "%b" "$msg")

Sent on: $(date)
.
quit
EOF
    } 1>/dev/null

}

Now, every thing here works as intended except that the newlines in $msg get seemingly stripped from my e-mail. If I wasn't e-mailing this text, then printf will happily interpret the newlines and show me two lines with text.

Let's say that an error 1 and an error 2 happened, I'll get this in my e-mail:

Error 1: The device timed outError 2: Failed to login to device

Why no new line?

If I change the $msg texts to have two \\n\\n characters at the end, like so:

[[ $timeout -eq 1 ]] && msg="Error 1: The device timed out\n\n"
[[ $login_error -eq 1 ]] && msg="${msg}Error 2: Failed to login to device\n\n"

then I get this in the e-mail:

Error 1: The device timed out

Error 2: Failed to login to device

Notice the extra new line between them now.

Does anyone know why I either get no newline or two newlines, but never the desired one newline.

Try ANSI-C quoting :

msg=""
[[ $timeout     -eq 1 ]] && msg+=$'Error 1: The device timed out\n'
[[ $login_error -eq 1 ]] && msg+=$'Error 2: Failed to login to device\n'
[[ $sky_fall    -eq 1 ]] && msg+=$'Error 3: The sky is falling\n'

Your sub-shell is spitting out the newline but the heredoc expansion is dropping it as it is unquoted.

Try printf %b $msg in your shell to see the idea.

You need to use something like printf %s\\\\n "$(printf %b "$msg")" to get what you want.

Thanks for the replies Glenn and Etan! However, I think I found the issue.

Turns out that the problem was more with Outlook (which I use to read the e-mails). It was stripping the line-breaks for those particular lines. I don't know why though.

this post describes the issue I was seeing.

My fix, as recommended by that post, was to add /t character to the end of each $msg line. This tricked Outlook into not stripping the line-breaks.

I have no idea why other parts of my heredoc don't get their line-breaks stripped by Outlook. For example, I also cat a log file into the heredoc that's full of new lines, and that shows up fine. Oh well...

Edit: This post also has good info on this behavior by Outlook.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM