2016-09-20 82 views
0

编写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

有没有你不知道的后台进程? – Jokester

+0

您在进行更改后是否重新启动了此过程?并确保旧的过程真的没有运行? – yaccz

+0

'fuser -k/path/to/file',确保写入该文件的所有内容都已经死了,是你的朋友。或者只是'fuser/path/to/file',并确保包含句柄的进程列表符合您的期望。 –

回答

1

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

有几个情况:

  1. 正如其他人所指出的,可能有一些其他的脚本写日志文件
  2. 您可能将在其他终端
  3. 运行此脚本的几个实例
  4. 您可从crontab中运行此脚本每5分钟

为了排除可能性一次,做一个“PS -aef”,并检查了所有可能像第n过程你的脚本的一部分。为了从crontab中获得一些东西,你可能需要观察“ps -aef”的输出时间(或者只是检查crontab条目)。

+0

谢谢!事实证明,我确实有这个脚本的一些实例在后台运行。一旦我杀了他们,产量如预期。 – Rayne

2

我不确定,它可能是拧紧的真正原因。行号22中的cut的使用不正确,这可能会无意中破坏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 & echo并做纯bash字符串操作。

假设您的$line包含:不受限制的字符串,例如, "What Hell:Hello World"和你正在试图提取World一部分,我可以看到,只是做

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