我有一个由一堆日志文件组成的日志目录,一旦发生系统事件就会创建一个日志文件。我想编写一个oneline bash脚本,它始终监视文件列表并在终端上显示新创建的文件的内容。这是它的样子:
目前,我只需要显示整个目录的内容:
for f in *; do cat $f; done
它缺乏我想要的监控功能。我的系统的一个限制是我没有 watch
命令。我也没有任何软件包管理器来安装花哨的工具。原始BSD就是我所拥有的。我确实有tail
,我想的是像tail -F $(ls)
这样的东西,但这会尾随每个文件而不是文件列表。
总之,我想修改我的脚本,以便我可以监视所有新创建的文件的内容。
答案 0 :(得分:2)
第一种方法 - 在你的dir中使用一个隐藏文件(在我的例子中它有一个名称.watch
)。然后你的单行可能看起来像:
for f in $(find . -type f -newer .watch); do cat $f; done; touch .watch
第二种方法 - 使用inotify-tools:https://unix.stackexchange.com/questions/273556/when-a-particular-file-arrives-then-execute-a-procedure-using-shell-script/273563#273563
答案 1 :(得分:2)
inotifywait
首先是这个小小的演示:
打开一个终端并运行:
ext=(php css other)
while :;do
subname=''
((RANDOM%10))||printf -v subname -- "-%04x" $RANDOM
date >/tmp/test$subname.${ext[RANDOM%3]}
sleep 1
done
这将创建名为/tmp/test.php
,/tmp/test.css
和/tmp/test.other
的随机文件,但随机(大约1次/ 10),名称将为/tmp/test-XXXX.[css|php|other]
,其中XXXX是十六进制随机数。
打开另一个终端并运行:
waitPaths=(/{home,tmp})
while read file ;do
if [ "$file" ] &&
( [ -z "${file##*.php}" ] || [ -z "${file##*.css}" ] ) ;then
(($(stat -c %Y-%X $file)))||echo -n new
echo file: $file, content:
cat $file
fi
done < <(
inotifywait -qme close_write --format %w%f ${waitPaths[*]}
)
这可能会产生类似的结果:
file: /tmp/test.css, content:
Tue Apr 26 18:53:19 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:21 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:23 CEST 2016
file: /tmp/test.css, content:
Tue Apr 26 18:53:25 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:27 CEST 2016
newfile: /tmp/test-420b.php, content:
Tue Apr 26 18:53:28 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:29 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:30 CEST 2016
file: /tmp/test.php, content:
Tue Apr 26 18:53:31 CEST 2016
waitPaths=(/{home,tmp})
可以写为waitPaths=(/home /tmp)
,也可以仅写入一个目录:waitPaths=/var/log
if
条件搜索与*.php
或*.css
匹配的文件名(($(stat -c %Y-%X $file)))||echo -n new
将比较创建和修改时间。inotifywait
-q
留下quiet
(不要打印超出要求)-m
用于监视器模式:命令不是终结,而是打印每个匹配事件。-e close_write
仅对指定类型的事件做出反应。-f %w%f
输出格式: path/file
有一个更复杂的样本:
在第二个控制台中,点击 Ctrl + C ,或者在新终端中,点击这个:
waitPaths=(/{home,tmp})
declare -A newFiles
while read path event file; do
if [ "$file" ] && ( [ -z "${file##*.php}" ] || [ -z "${file##*.css}" ] ); then
if [ "$event" ] && [ -z "${event//*CREATE*}" ]; then
newFiles[$file]=1
else
if [ "${newFiles[$file]}" ]; then
unset newFiles[$file]
echo NewFile: $file, content:
sed 's/^/>+ /' $file
else
echo file: $file, content:
sed 's/^/> /' $path/$file
fi
fi
fi
done < <(inotifywait -qme close_write -e create ${waitPaths[*]})
可能产生类似:
file: test.css, content:
> Tue Apr 26 22:16:02 CEST 2016
file: test.php, content:
> Tue Apr 26 22:16:03 CEST 2016
NewFile: test-349b.css, content:
>+ Tue Apr 26 22:16:05 CEST 2016
file: test.css, content:
> Tue Apr 26 22:16:08 CEST 2016
file: test.css, content:
> Tue Apr 26 22:16:10 CEST 2016
file: test.css, content:
> Tue Apr 26 22:16:13 CEST 2016
答案 2 :(得分:2)
使用 bashisms 之类的关联数组还有另一种解决方案:
样品:
wpath=/var/log
while : ;do
while read -a crtfile ;do
if [ "${crtfile:0:1}" = "-" ] &&
[ "${crtfile[8]##*.}" != "gz" ] &&
[ "${files[${crtfile[8]}]:-0}" -lt ${crtfile[4]} ] ;then
printf "\e[47m## %-14s :- %(%a %d %b %y %T)T ##\e[0m\n" ${crtfile[8]} -1
tail -c +$[1+${files[${crtfile[8]}]:-0}] $wpath/${crtfile[8]}
files[${crtfile[8]}]=${crtfile[4]}
fi
done < <( /bin/ls -l $wpath )
sleep 1
done
这将在.gz
中转储每个文件(文件名不以/var/log
结尾),并注意修改或新文件,然后转储新行。
在第一个终端控制台中,点击:
ext=(php css other)
( while :; do
subname=''
((RANDOM%10)) || printf -v subname -- "-%04x" $RANDOM
name=test$subname.${ext[RANDOM%3]}
printf "%-16s" $name
{
date +"%a %d %b %y %T" | tee /dev/fd/5
fortune /usr/share/games/fortunes/bofh-excuses
} >> /tmp/$name
sleep 1
done ) 5>&1
您需要使用 BOFH借口图书馆安装fortune
。
如果你真的没有fortune
,你可以改用:
LANG=C ext=(php css other)
( while :; do
subname=''
((RANDOM%10)) || printf -v subname -- "-%04x" $RANDOM
name=test$subname.${ext[RANDOM%3]}
printf "%-16s" $name
{
date +"%a %d %b %y %T" | tee /dev/fd/5
for ((1; RANDOM%5; 1))
do
printf -v str %$[RANDOM&12]s
str=${str// /blah, }
echo ${str%, }.
done
} >> /tmp/$name
sleep 1
done ) 5>&1
这可能会输出如下内容:
test.css Thu 28 Apr 16 12:00:02
test.php Thu 28 Apr 16 12:00:03
test.other Thu 28 Apr 16 12:00:04
test.css Thu 28 Apr 16 12:00:05
test.css Thu 28 Apr 16 12:00:06
test.other Thu 28 Apr 16 12:00:07
test.php Thu 28 Apr 16 12:00:08
test.css Thu 28 Apr 16 12:00:09
test.other Thu 28 Apr 16 12:00:10
test.other Thu 28 Apr 16 12:00:11
test.php Thu 28 Apr 16 12:00:12
test.other Thu 28 Apr 16 12:00:13
在第二个终端控制台中,点击:
declare -A files
wpath=/tmp
while :; do
while read -a crtfile; do
if [ "${crtfile:0:1}" = "-" ] && [ "${crtfile[8]:0:4}" = "test" ] &&
( [ "${crtfile[8]##*.}" = "css" ] || [ "${crtfile[8]##*.}" = "php" ] ) &&
[ "${files[${crtfile[8]}]:-0}" -lt ${crtfile[4]} ]; then
printf "\e[47m## %-14s :- %(%a %d %b %y %T)T ##\e[0m\n" ${crtfile[8]} -1
tail -c +$[1+${files[${crtfile[8]}]:-0}] $wpath/${crtfile[8]}
files[${crtfile[8]}]=${crtfile[4]}
fi
done < <(/bin/ls -l $wpath)
sleep 1
done
这将每秒
用于监视目录中的所有条目
-
),test
开头的文件名,css
或php
,tail -c
和这可能会输出如下内容:
## test.css :- Thu 28 Apr 16 12:00:09 ##
Thu 28 Apr 16 12:00:02
BOFH excuse #216:
What office are you in? Oh, that one. Did you know that your building was built over the universities first nuclear research site? And wow, aren't you the lucky one, your office is right over where the core is buried!
Thu 28 Apr 16 12:00:05
BOFH excuse #145:
Flat tire on station wagon with tapes. ("Never underestimate the bandwidth of a station wagon full of tapes hurling down the highway" Andrew S. Tannenbaum)
Thu 28 Apr 16 12:00:06
BOFH excuse #301:
appears to be a Slow/Narrow SCSI-0 Interface problem
## test.php :- Thu 28 Apr 16 12:00:09 ##
Thu 28 Apr 16 12:00:03
BOFH excuse #36:
dynamic software linking table corrupted
Thu 28 Apr 16 12:00:08
BOFH excuse #367:
Webmasters kidnapped by evil cult.
## test.css :- Thu 28 Apr 16 12:00:10 ##
Thu 28 Apr 16 12:00:09
BOFH excuse #25:
Decreasing electron flux
## test.php :- Thu 28 Apr 16 12:00:13 ##
Thu 28 Apr 16 12:00:12
BOFH excuse #3:
electromagnetic radiation from satellite debris
注意:如果某个文件在两次检查之间被修改了一次以上,则下次检查时将打印所有修改。
答案 3 :(得分:1)
如果你愿意,你可以把它塞进一行,但我建议你只在后台运行脚本:
#!/bin/bash
[ ! -d "$1" ] && {
printf "error: argument is not a valid directory to monitory.\n"
exit 1
}
while :; fname="$1/$(inotifywait -q -e modify -e create --format '%f' "$1")"; do
cat "$fname"
done
将查看作为第一个参数给出的目录,以及cat
该目录中的任何新文件或已更改文件。例如:
$ bash watchdir.sh my_logdir &
然后cat
中的my_logdir
新文件或已更改的文件将会出现。
答案 4 :(得分:0)
虽然不是很好,但下面给出(并重复)当前目录中最新文件的最后50行:
while true; do tail -n 50 $(ls -Art | tail -n 1); sleep 5; done
答案 5 :(得分:0)
您可以使用cronjob刷新每一分钟:
$crontabe -e
* * * * * /home/script.sh
如果您需要在不到一分钟的时间内刷新,可以在脚本中使用“sleep”命令。