我想将日志输出分配给“line”,我尝试了以下方法
line=tail -1000 /var/log/syslog
但它不起作用。
myscript 如下所示
#!/bin/bash
line=`tail -1000 /var/log/syslog`
d1=$(date --date="-10 min" "+%b %_d %H:%M")
d2=$(date "+%b %_d %H:%M")
while read line; do
[[ $line > $d1 && $line < $d2 || $line =~ $d2 ]] && echo $line
done
答案1
尝试这个改变
fd=""
tmplog="/tmp/temp_${$$}_${RANDOM}"
tail -1000 /var/log/syslog > "$tmplog"
exec {fd}<"$tmplog"
while IFS='' read -r -u $fd line || [[ -n $line ]]; do
#your commands here
done
exec {fd}>&-
rm "$tmplog"
工作原理:分配fd
为变量。使用脚本 PID 和内置的“随机”数字创建一个临时文件(您也可以使用 mktemp 命令代替它)。打开文件描述符fd
以读取临时文件。使用 while 循环并将其IFS
设置为无,并运行带有-u
读取选项的read 命令fd
。使用相同的变量将命令放入循环内line
。关闭文件描述符。删除临时文件。
答案2
你的作业工作得很好——尽管$( ... )
比反引号更健壮、风格更好。但read line
不读书从行,它从 stdin 读取(终端,因为你没有重定向它)进入行,破坏之前的内容。尝试以下之一:
data=$(tail -1000 /file)
while read line; do echo "$line"; done <<<"$data"
# bash ksh zsh but maybe not older shells
# or
while read line; do echo "$line"; done < <(tail -1000 file)
# ditto
data=$(tail -1000 /file)
echo "$data" | while read line; do echo "$line"; done
# or
tail -1000 file | while read line; do echo "$line"; done
# most shells, but any var set (or other shell change made) within the loop
# will disappear on _some_ shells because pipelines are run in subshells
在循环中添加适当的命令。
一般来说,要保持数据不受破坏,read
如-r
EnterUserNameHere 所示,但系统日志条目的结构非常合理,在我能想到的任何情况下都不需要它。 OTOH 添加它不会造成伤害,并且是很好的做法。
请注意,在某些月份的第一天,比较日期字符串将不起作用;例如,如果 now-10min 是“Nov 31 23:55”,现在是“Dec 01 00:05”,那么实际上在这两个时间之间的所有日期字符串都将失败考试$line > $d1 && $line < $d2