【问题标题】:Bash is redirecting output from command only after script has finished只有在脚本完成后,Bash 才会重定向命令的输出
【发布时间】:2018-09-10 17:33:05
【问题描述】:

上下文

有一个愚蠢的脚本来检查一个进程是否在一组主机上运行,​​就像看门狗一样,正如我所说的那样,这是一个愚蠢的脚本,所以请记住它不是脚本标准的“完美”

问题

我已经运行bash -x 并且可以看到脚本完成了它的第一次检查而没有实际将命令的输出重定向到非常令人沮丧的文件,这意味着实际上每个主机都被评估为最后一个主机输出

代码

#!/bin/bash
FILE='OUTPUT'
for host in $(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {' print $2 ' })

do ssh -n -f $host -i <sshkey> 'ps ax | grep myprocess | wc -l' > $FILE 2> /dev/null
cat $FILE
if grep '1' $FILE ; then
 echo "Process is NOT running on $host"
 cat $FILE
else
 cat $FILE
 echo "ALL OK on $host"
fi
cat $FILE
done

脚本回溯

++ cat /etc/hosts
++ awk '{ print $2 }'
++ grep 'webserver.[2][1-2][0-2][0-9]'
+ for host in '$(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {'\'' print $2 '\''})'
+ ssh -n -f webserver.2100 -i <omitted> 'ps ax | grep myprocess | wc -l'
+ cat OUTPUT
+ grep 1 OUTPUT
+ cat OUTPUT
+ echo 'ALL OK on webserver.2100'
ALL OK on webserver.2100
+ cat OUTPUT
+ printf 'webserver.2100 checked \n'
webserver.2100 checked 
+ for host in '$(cat /etc/hosts | grep webserver.[2][1-2][0-2][0-9] | awk {'\'' print $2 '\''})'
+ ssh -n -f webserver.2101 -i <omitted> 'ps ax | grep myprocess | wc -l'
+ cat OUTPUT
2
+ grep 1 OUTPUT
+ cat OUTPUT
2
+ echo 'ALL OK on webserver.2101'
ALL OK on webserver.2101
+ cat OUTPUT
2
+ printf 'webserver.2101 checked \n'
webserver.2101 checked 

问题

如您所见,它没有为第一个主机注册任何内容,然后在完成后,它将数据通过管道传输到文件中,然后正在评估第二个主机以获取以前的主机数据...

我怀疑它与重定向有关,但在我看来这应该有效,但它不那么令人沮丧。

【问题讨论】:

  • 我建议用pgrep myprocess | wc -l替换ps ax | grep myprocess | wc -l
  • 我认为问题在于weberserv.2100 ssh 命令失败,因此只输出到stderr。您能否通过将错误输出重定向到/dev/null 以外的其他内容来检查这一点?
  • @jayant - 我已经验证两个主机都在线,它们都可以访问
  • @DannyWatson 不,您误解了正在发生的事情。到第一个主机的 ssh 将 nothing 返回到 stdout(可能是由于某种错误;您必须删除 stderr 重定向才能找出答案)。到第二台主机的 ssh 正在返回“2”(可能是因为它同时找到了您正在寻找的进程和 grep myprocess——这将在您使用的方法中间歇性发生,因此请改用 pgrep)。

标签: bash if-statement grep


【解决方案1】:

我认为您假设ps ax | grep myprocess 将始终返回至少一行(grep 进程)。我不确定那是真的。我会这样重写:

awk '/webserver.[2][1-2][0-2][0-9]/ {print $2}' /etc/hosts | while IFS= read -r host; do
    output=$( ssh -n -f "$host" -i "$sshkey" 'ps ax | grep "[m]yprocess"' )
    if [[ -z "$output" ]]; then
        echo "Process is NOT running on $host"
    else
        echo "ALL OK on $host"
    fi
done

这个技巧ps ax | grep "[m]yprocess" 有效地从 ps 输出中删除了 grep 进程:

  • 字符串myprocess”匹配正则表达式[m]yprocess”(即运行“myprocess”进程),但是
  • 字符串[m]yprocess”与正则表达式[m]yprocess不匹配"(这是正在运行的“grep”进程)

【讨论】:

  • 有趣的是,这似乎可行,我已将ps ax 替换为pgrep,因为如果我只是在寻找一个过程更有意义......你能告诉我为什么这样写当时和那里的文件,为什么我的脚本只在检查条件后才写入文件?
  • 我确定您的代码确实写入了文件,它只是写入了零字节
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 2014-11-17
  • 2021-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多