shell脚本中的奇怪输出

时间:2016-09-20 10:33:48

标签: linux bash shell

我在编写shell脚本时遇到了一件非常奇怪的事情。

最初我有以下脚本。

OUTPUT_FOLDER=/home/user/output
HOST_FILE=/home/user/host.txt
LOG_DIR=/home/user/log
SLEEPTIME=60

mkdir -p $OUTPUT_FOLDER

while true
do
    rm -f $OUTPUT_FOLDER/*
    DATE=`date +"%Y%m%d"`
    DATETIME=`date +"%Y%m%d_%H%M%S"`
    pssh -h $HOST_FILE -o $OUTPUT_FOLDER
    while read host
    do
        numline=0
        while read line
        do
            if [[ $numline == 0 ]]
            then
                FIELD1=`echo $line | cut -d':' -f2 | cut =d' ' -f2`
            fi
            ((numline+=1))
        done < ${OUTPUT_FOLDER}/${host}
        echo "$DATETIME,$FIELD1" >> ${LOG_DIR}/${DATE}.log
    done < $HOST_FILE
    sleep $SLEEPTIME
done

当我运行此脚本时,每隔60秒,我会在日志文件中看到$DATETIME,$FIELD1值。

有什么奇怪的,就是每隔30秒左右,在第一分钟过去之后,我会看到20160920_120232,,这意味着有输出应该没有,我猜是因为我删除了我的输出文件夹FIELD1的内容为空。

更奇怪的是,在尝试调试时,我添加了一些echo语句来打印到我的日志文件,然后我删除了这些行。然而,在第一分钟过后,它们每30秒左右继续打印一次。

陌生的是,我随后在while true区块内注释掉了所有内容,即

OUTPUT_FOLDER=/home/user/output
HOST_FILE=/home/user/host.txt
LOG_DIR=/home/user/log
SLEEPTIME=60

mkdir -p $OUTPUT_FOLDER

while true
do
: << 'END'
    rm -f $OUTPUT_FOLDER/*
    DATE=`date +"%Y%m%d"`
    DATETIME=`date +"%Y%m%d_%H%M%S"`
    pssh -h $HOST_FILE -o $OUTPUT_FOLDER
    while read host
    do
        numline=0
        while read line
        do
            if [[ $numline == 0 ]]
            then
                FIELD1=`echo $line | cut -d':' -f2 | cut =d' ' -f2`
            fi
            ((numline+=1))
        done < ${OUTPUT_FOLDER}/${host}
        echo "$DATETIME,$FIELD1" >> ${LOG_DIR}/${DATE}.log
    done < $HOST_FILE
    sleep $SLEEPTIME
END
done

即使使用此脚本,我希望不会将任何内容打印到我的日志文件中,我会看到我之前删除的echo语句以及空FIELD1的行。我已经检查过每次运行正确版本的脚本。

发生了什么事?

2 个答案:

答案 0 :(得分:2)

我不确定,这可能是搞砸的实际原因。您在行号cut中使用22的行为不正确,可能会无意中损坏FIELD1

FIELD1=`echo $line | cut -d':' -f2 | cut =d' ' -f2`
#                                        ^ incorrect usage of the delimiter '-d' flag

应该用作

FIELD1=`echo $line | cut -d':' -f2 | cut -d' ' -f2`
#                                        ^ Proper usage of the '-d' flag with space delimiter

我试图捕获管道命令输出以查看最后一个命令是否成功,以下是我的观察。

echo $line | cut -d':' -f2 | cut =d' ' -f2;echo "${PIPESTATUS[@]}"
cut: =d : No such file or directory     # --> Error from the failed 'cut' command
0 0 1                                   # --> Return codes of each of the command being piped

此外,如果您是bash纯粹主义者,则您已避免使用旧``样式命令扩展并使用$(cmd)语法,例如

FIELD1=$(echo "$line" | cut -d':' -f2 | cut -d' ' -f2)

另一种更简单的方法是避免使用cut&amp; echo并进行纯粹的bash字符串操作。

假设您的$line包含:非限制字符串,例如"What Hell:Hello World",并且您正试图提取World部分,如我所见,只是做

FIELD1="${line##* }"   # Strips-off characters until last occurrence of whitespace

答案 1 :(得分:1)

我试图重现它并且不能。这个脚本没有理由(当你有评论时)产生任何输出。

有几种情况:

  1. 正如其他人所指出的,可能还有一些其他脚本写入您的日志文件
  2. 您可能在其他终端上运行了此脚本的少数实例
  3. 您可能每隔5分钟从crontab运行一次此脚本
  4. 为了排除可能性,请做一个&#34; ps -aef&#34;并查看所有可能类似于脚本名称的进程。要从crontab中捕获内容,您可能需要观察&#34; ps -aef&#34;的输出。更长的时间(或只是检查crontab条目)。