我在编写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
的行。我已经检查过每次运行正确版本的脚本。
发生了什么事?
答案 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)
我试图重现它并且不能。这个脚本没有理由(当你有评论时)产生任何输出。
有几种情况:
为了排除可能性,请做一个&#34; ps -aef&#34;并查看所有可能类似于脚本名称的进程。要从crontab中捕获内容,您可能需要观察&#34; ps -aef&#34;的输出。更长的时间(或只是检查crontab条目)。