shell脚本中的奇怪输出
编写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
。我检查了我每次都运行正确的脚本版本。
这是怎么回事?
我试图重现它并不能。这个脚本没有理由(当你有评论时)产生任何输出。
有几个情况:
- 正如其他人所指出的,可能有一些其他的脚本写日志文件
- 您可能将在其他终端 运行此脚本的几个实例
- 您可从crontab中运行此脚本每5分钟
为了排除可能性一次,做一个“PS -aef”,并检查了所有可能像第n过程你的脚本的一部分。为了从crontab中获得一些东西,你可能需要观察“ps -aef”的输出时间(或者只是检查crontab条目)。
谢谢!事实证明,我确实有这个脚本的一些实例在后台运行。一旦我杀了他们,产量如预期。 – Rayne
我不确定,它可能是拧紧的真正原因。行号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
有没有你不知道的后台进程? – Jokester
您在进行更改后是否重新启动了此过程?并确保旧的过程真的没有运行? – yaccz
'fuser -k/path/to/file',确保写入该文件的所有内容都已经死了,是你的朋友。或者只是'fuser/path/to/file',并确保包含句柄的进程列表符合您的期望。 –