如果从 bash 脚本执行,则乱码邮件命令

Scrambled mail command if executed from bash script

我正在编写一个简单的 Bash 脚本来执行备份并在命令失败的情况下在最后发送一封带有修改主题的邮件。

这是脚本片段:

BACKUP_CMD="ls -1" # Just an example command
MAIL_RECIPIENTS="me@domain" # Recipient addresses (space separated list)
MAIL_SUBJECT="Backup script" # Mail subject
MAIL_FAIL_SUBJECT_PREPEND="[!!! ---FAILURE--- !!!] "
MAIL_CMD="mail -a \"Content-Type: text/plain; charset=UTF-8\" -s \"SUBJECT\" RECIPIENTS" # Mail send command

# Execute backup
output="$($BACKUP_CMD)"
status=$?

# Check exit status code and compose the mail message
echo $status
if [ "$status" -eq "0" ]; then
    mail_subject=$MAIL_SUBJECT
    mail_text="${output}"
else
    mail_subject="$MAIL_FAIL_SUBJECT_PREPEND $MAIL_SUBJECT"
    mail_text="$output\n\nExit status code: $status"
fi

# Compose the mail command with subject and recipients list
mail_cmd=$MAIL_CMD
mail_cmd="${mail_cmd/SUBJECT/$mail_subject}"
mail_cmd="${mail_cmd/RECIPIENTS/$MAIL_RECIPIENTS}"

echo "$mail_text" | ${mail_cmd}

邮件未发送,脚本退出并出现此错误 send-mail:

send-mail: RCPT TO:<Backup", charset=UTF-8"@server.domain> (501 5.1.3 Bad recipient address syntax)
Can't send mail: sendmail process failed with error code 1

邮件命令末尾似乎有 bash "scrambles" 个参数。

我无法理解的是,如果我打印 $mail_cmd 它似乎是正确的:

mail -a "Content-Type: text/plain; charset=UTF-8" -s "Backup script" me@domain

我哪里错了?

你的脚本可以用一些 bash 我相信的数组修复:

backup_cmd=(ls -1)
mail_cmd2=(mail -a "Content-Type: text/plain; charset=UTF-8" -s)

...

output=$("${backup_cmd[@]}")

...

mail_cmd=("${mail_cmd2[@]}")
mail_cmd+=("$mail_subject")
mail_cmd+=( $MAIL_RECIPIENTS )
# MAIL_RECIPIENTS  should be changed to a bash array too!
echo "$mail_text" | "${mail_cmd[@]}"

但是重构脚本并创建一个函数会更好:

mail_cmd() {
    local subject recipients
    subject=""
    shift
    recipients=("$@")
    mail -a "Content-Type: text/plain; charset=UTF-8" -s "$subjsect" "${recipients[@]}"
}

mail_recipients=( "me@domain" "other@otherdomain" )

...

printf "%s\n" "$mail_text" | mail_cmd "$subject" "${mail_recipients[@]}"

备注:

  • 通常使用 UPPER_CASE_VARIABLES 从脚本导出变量,而不是本地变量。
  • 您也可以导出函数。

I print $mail_cmd it is correct

但是 space 分离发生了,但是 " 引用解释没有。我的意思是行:

mail -a "Content-Type: text/plain; charset=UTF-8" -s "Backup script" me@domain

解释为(加单引号):

mail -a '"Content-Type:' 'text/plain;' 'charset=UTF-8"' -s '"Backup' 'script"' me@domain

mail 失败,因为前。 text/plain 不是有效的邮件地址。

mail_text="$output\n\nExit status code: $status"

这里的\n不是换行符,而是字面上的\斜杠和nn字符。您可以使用简单的 $'\n' 构造嵌入换行符,例如:

 mail_text="$output"$'\n\n'"Exit status code: $status"