简体   繁体   English

使用Bash脚本的邮件输出

[英]Mail output with Bash Script

SSH from Host A to a few hosts (only one listed below right now) using the SSH Key I generated and then go to a specific file, grep for a specific word with a date of yesterday .. then I want to email this output to myself. 使用生成的SSH密钥从主机A到几台主机(现在仅在下面列出的一台主机)进行SSH,然后转到特定文件,grep表示日期为昨天的特定单词..然后我想将此输出通过电子邮件发送给我。

It is sending an email but it is giving me the command as opposed to the output from the command. 它正在发送电子邮件,但给了我命令,而不是命令的输出。

#!/bin/bash

HOST="XXXXXXXXXXXXXXXXXX, XXXXXXXXXXXXX"

DATE=$(date -d "yesterday")

INVALID=' cat /xxx/xxx/xxxxx | grep 'WORD' | sed 's/$/.\n/g' | grep "$DATE"'

COUNT=$(echo "$INVALID" | wc -c)

for x in $HOSTS

do
ssh BLA@"$x" $COUNT

if [ "$COUNT" -gt 1 ];
then

    EMAILTEXT=""
        if [ "$COUNT" -gt 1 ];
        then
                EMAILTEXT="$INVALID"
        fi
fi

done | echo -e "$EMAILTEXT" | mail XXXXXXXXXXX.com

This isn't properly an attempt to answer your question, but I think you should be aware of some fundamental problems with your code. 这不是试图回答您的问题的正确方法,但是我认为您应该意识到代码的一些基本问题。

INVALID=' cat /xxx/xxx/xxxxx | grep 'WORD' | sed 's/$/.\n/g' | grep "$DATE"'

This assigns a simple string to the variable INVALID . 这为变量INVALID分配了一个简单的字符串。 Because of quoting issues, s/$/.\\n/g is not quoted at all, and will probably be mangled by the shell. 由于存在引用问题,因此根本不会引用s/$/.\\n/g ,并且可能会被shell破坏。 (You cannot nest single quotes -- the first single-quoted string extends from the first quote to the next one, and then WORD is outside of any quotes, followed by the next single-quoted string, etc.) (您不能嵌套单引号-第一个单引号的字符串从第一个引号延伸到下一个引号,然后WORD在任何引号之外,然后是下一个单引号字符串,依此类推。)

If your intent is to execute this as a command at this point, you are looking for a command substitution; 如果您打算在此时将其作为命令执行,则您正在寻找命令替代品。 with the multiple layers of uselessness peeled off, perhaps something like 剥夺了无用的多层性,也许像

INVALID=$(sed -n -e '/WORD/!d' -e "/$DATE/s/$/./p" /xxx/xxx/xxxx)

which looks for a line matching WORD and $DATE and prints the match with a dot appended at the end -- I believe that's what your code boils down to, but without further insights into what this code is supposed to do, it's impossible to tell if this is what you actually need. 它会寻找与WORD$DATE匹配的行,并在匹配项的末尾附加一个点-我认为这就是您的代码的精髓所在,但是如果不进一步了解此代码应该做什么,就无法分辨如果这是您真正需要的。

COUNT=$(echo "$INVALID" | wc -c)

This assigns a number to $COUNT . 这将为$COUNT分配一个数字。 With your static definition of INVALID , the number will always be 62; 使用INVALID的静态定义,该数字始终为62; but I guess that's not actually what you want here. 但我想这实际上不是您想要的。

for x in $HOSTS    
do
  ssh BLA@"$x" $COUNT

This attempts to execute that number as a command on a number of remote hosts (except the loop is over HOSTS and the variable containing the hosts is named just HOST ). 这试图在多个远程主机上作为命令执行该编号(除非循环通过HOSTS并且包含主机的变量仅命名为HOST )。 This cannot possibly be useful, unless you have a battery of commands named as natural numbers which do something useful on these remote hosts; 除非您拥有一系列称为自然数的命令,这些命令在这些远程主机上做有用的事情,否则这可能不会有用。 but I think it's safe to assume that that is not what is supposed to be going on here (and if it was, it would absolutely be necessary to explain this in your question). 但是我认为可以肯定地说,这不是这里应该发生的事情(如果确实如此,则绝对有必要在您的问题中对此进行解释)。

  if [ "$COUNT" -gt 1 ];
  then

    EMAILTEXT=""
        if [ "$COUNT" -gt 1 ];
        then
                EMAILTEXT="$INVALID"
        fi
  fi

So EMAILTEXT is either an empty string or the value of INVALID. 因此, EMAILTEXT是空字符串或INVALID的值。 You assigned it to be a static string above, which is probably the source of your immediate question. 您将其分配为上面的静态字符串,这可能是您的直接问题的根源。 But even if it was somehow assigned to a command on the local host, why do you need to visit remote hosts and execute something there? 但是,即使以某种方式将其分配给本地主机上的命令,您为什么还需要访问远程主机并在那里执行某些操作? Or is your intent actually to execute the command on each remote host and obtain the output? 还是您实际上打算在每个远程主机上执行命令并获取输出?

done | echo -e "$EMAILTEXT" | mail XXXXXXXXXXX.com

Piping into echo makes no sense at all, because it does not read its standard input. 用管道echo根本没有意义,因为它不读取其标准输入。 You should probably just have a newline after done ; 你或许应该只是后一个换行符done ; though a possibly more useful arrangement would be to have your loop produce output which we then pipe to mail . 尽管可能更有用的安排是让您的循环产生输出,然后我们通过管道发送到mail

Purely speculatively, perhaps something like the following is what you actually want. 纯粹是推测性的,也许您真正想要的是以下内容。

for host in $HOSTS; do
    ssh BLA@"$host" sed -n -e '/WORD/!d' -e "/$DATE/s/$/./p" /xxx/xxx/xxxx |
    grep . || echo INVALID
done | mail XXXXXXXXXXX.com

If you want to check that there is strictly more than one line of output (which is what the -gt 1 suggests) then this may need to be a little bit more complicated. 如果要检查是否存在多于一行的输出(这是-gt 1建议),则可能需要稍微复杂一点。

Your command substitution is not working. 您的命令替换无效。 You should read up on how it works but here are the problem lines: 您应该阅读它的工作原理,但这是问题所在:

COUNT=$(echo "$INVALID" | wc -c)
[...]
ssh BLA@"$x" $COUNT

should be: 应该:

COUNT_CMD="'${INVALID} | wc -c'"
[...]
COUNT=$(ssh BLA@"$x" $COUNT_CMD)

This inserts the value of $INVALID into the string, and puts the whole thing in single quotes. 这会将$INVALID的值插入字符串,并将整个内容放在单引号中。 The single quotes are necessary for the ssh call so the pipes aren't evaluated in the script but on the remote host. ssh调用必须使用单引号,因此不会在脚本中而是在远程主机上评估管道。 ( COUNT is changed to COUNT_CMD for readability/clarity.) (出于可读性/清晰度,将COUNT更改为COUNT_CMD 。)

EDIT: 编辑:

I misread the question and have corrected my answer. 我看错了问题,并且更正了我的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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