如果条件失败,当邮件服务器无法将日志上传到 ftp 服务器时通知管理员

如果条件失败,当邮件服务器无法将日志上传到 ftp 服务器时通知管理员

我目前正在研究一种解决方案,每当我的邮件服务器无法将文件传输到我的 ftp 服务器时,它都会通知我。(目前我的日志每晚轮换一次,并立即上传到单独的 ftp 服务器)

当前配置如下:


HOST="..."
USER="..."
PASS="..."
DIR="/var/log/maillogs/"
LATEST="$(ls -t $DIR | head -n 2 | tail-n 1)"
FILE=$(basename $LATEST)

error=$(ftp -n $HOST  <<EOF
quote USER $USER
quote PASS $PASS
prompt
lcd /var/log/maillogs/
cd /home/MailLog
put $FILE
quit
EOF
)
if [ $(echo $error | grep "failed")=="failed" ]
then
        *Sending Mail via sendmail*
fi

由于某种原因,if 条件总是返回 true,所以无论文件是否能够传输,我都会收到一封邮件。

有人知道,当传输日志失败时,我该如何更改 if 语句才能真正获取邮件?

我也尝试过 的方法 if [ $? -ne 0 ],但我不太清楚如何测试它是否真的有效。我尝试提供虚假 IP 或错误的用户登录,但这样做只会收到不同的错误。

答案1

[是一个内置命令,遵循与其他命令相同的语法规则 - 参数必须用引号引起来并用空格分隔。

具体来说,运算符 like==应为单独的参数,因此不能省略其周围的空格。如果省略,则不会将其解释为运算符 - 整个运算符将被解释为[ one_arg ]单参数模式,[当参数非空时,将返回成功。

[ $(echo $error | grep "failed") = "failed" ]
                                ^ ^

(此外,操作符只是=。虽然 bash 接受[ x == y ],但这是非标准的。)

此外,任何字符串扩展都$(...)需要用引号引起来 - 否则它们会在空格处被分割,并可能成为多个参数(或更糟):

[ "$(echo "$error" | grep failed)" = failed ]
  ^                              ^

尽管如此,你实际上[根本不需要这里 - shell 的if接受任何命令,因此您可以直接使用返回的退出状态grep

if echo "$error" | grep -qs failed; then
    echo "It failed :("
fi

进行子字符串检查的另一种方法是case块:

case $error in
    *failed*)
        echo "Fail :("
        ;;
    *)
        echo "Success!"
        ;;
esac

如果你的脚本专门使用 Bash(即如果它有#!/bin/bash或类似的东西),你可以使用[[关键字来简化它,有一些特殊的语法规则——左边的参数实际上不需要用引号引起来,相等运算符是==,但更有用的是右边的值可以是通配符比较:

if [[ $error == *failed* ]]; then
    echo "Fail :("
fi

所有这些都与您的 shell 脚本有关,但说实话?完全抛弃 FTP 并将其替换为例如 SFTP(通过 SSH 运行,您很可能已经拥有它)。

HOST="..."
USER="..."
# no PASS, it uses your id_rsa
DIR="/var/log/maillogs/"
LATEST="$(ls -t $DIR | head -n 2 | tail-n 1)"
FILE=$(basename $LATEST)

scp -p "$LATEST" "$USER@$HOST:/home/MailLog/" || {
    echo "Fail :("
}

更好的办法是,设置远程系统日志,例如使用 syslog-ng,这样就可以传输消息居住到服务器。

相关内容