点击(此处)折叠或打开
- #!/bin/sh
- #
- # watch.sh - a simple version of the watch utility, written in sh
- #
- who | sort > prev # 第一次查看,结果放到prev文件中
- while true
- do
- sleep 30 # 等一会儿
- who | sort > current # 再次查看,结果放到current文件中
- echo "Logged out:"
- comm -23 prev current # -23表示不显示第二个文件独有的,也不显示两个文件共有的,所以这里只显 #示第一个文件prev中有的用户,也就是说明这些用户当前已经不在线了,即lo #g out了
- echo "Logged in:"
- comm -13 prev current # -13表示不显示第一个文件独有的,也不显示两个文件共有的,所以这里只 #显示第二个文件current中有的用户,也就是说明这些用户是新来的,即log #on了
- mv current prev # 把当前文件current命名为prev,下次循环时,这个prev就表示之前存在的 # 用户了。
- done
- #!/bin/sh
- #
- # note: the list of users has to have one name per line
- #
- #
- FILE=$1 #$1表示第一个参数,$0表示命令本身
- if test -z "$FILE" #-z表示文件名长度如果为0,则test判断结果为真
- then
- if test ! -f $HOME/.watchees #如果没传入文件,则判断$HOME下面是否有规则文件.watchees
- then
- echo "usage: watch.sh userlist" #如果不存在,则报错
- exit 1
- fi
- fi
- NAMES=`wc -w < $FILE` #获取文件中字符串个数
- LINES=`wc -l < $FILE` #获取文件长度
- if test $NAMES -ne $LINES ; then #如果长度不等于字符串个数, 因为事先要求文件中每个用户名 #就占一行,所以用户名总数就等于行数
- echo "file $FILE must have one name per line" #报错
- exit 2
- fi
- # file has to be sorted, because we plan to use join
- sort -o $FILE $FILE #对用户名排序,并输出到本文件。
- # main loop now
- who | sort | join - $FILE >prev # 这里主要是有个join操作,"-"表示从标准输入读入,也就是从 #sort后的结果输入,然后和$FILE中的内容进行join, 把两个文 #件相同的部分合成一行
- while true #
- do
- sleep 10 # wait a while
- who | sort | join - $FILE > current # get current user list
- echo "Logged out:" # print header
- comm -23 prev current # and results
- echo "Logged in:" # header
- comm -13 prev current # and results
- mv current prev # make now past
- done
[lizhuohua@lizhuohua-phy Program]$ cat lizhuohua
11
22
33
44
[lizhuohua@lizhuohua-phy Program]$ cat lizhuohua1
11
22
44
55
[lizhuohua@lizhuohua-phy Program]$ join lizhuohua lizhuohua1
11
22
44
所以上面脚本中join的作用就是只把文件中有的用户名从who的结果中过滤出来,而不是监控所有用户的登录状况。
现在再增加一些需求,仅仅当有新用户登录或注销,才打印结果,而不是每个循环都打印结果
- #!/bin/sh
- #
- # note: the list of users has to have one name per line
- #
- FILE=$1
- if test -z "$FILE"
- then
- if test ! -f $HOME/.watchees
- then
- echo "usage: watch.sh userlist"
- exit 1
- fi
- fi
- NAMES=`wc -w < $FILE`
- LINES=`wc -l < $FILE`
- if test $NAMES -ne $LINES ; then
- echo "file $FILE must have one name per line"
- exit 2
- fi
- # file has to be sorted, because we plan to use join
- sort -o $FILE $FILE
- # create a scratch file
- SCRATCH=`mktemp /tmp/watch.XXXXXX` #create一个tmp文件
- trap "rm -f $SCRATCH; exit 0" 0 2 3 15 #设置一个信号捕捉器,当有0(正常退出), 2( #SIGINT), 3(SIGQUIT),15(SIGTERM)信 #号到来时候,执行命令,删除临时文件。
- # main loop now
- who | sort | join - $FILE >prev
- while true
- do
- sleep 10
- who | sort | join - $FILE > current
- # compute results into scratch fle
- comm -23 prev current> $SCRATCH #把比较结果写入临时文件
- # and only print the file if non-empty
- if test -s $SCRATCH ; then #判断临时文件的大小是否为0,如果大于0,说明 #有新用户登录,再输出
- echo "Logged out:"
- cat $SCRATCH
- fi
- # same logic for other one
- comm -13 prev current > $SCRATCH
- if test -s $SCRATCH ; then #判断临时文件的大小是否为0,如果大于0,说明 #有用户注销,再输出
- echo "Logged in:"
- cat $SCRATCH
- fi
- mv current prev
- done
现在再增加一些需求。who命令除了列出用户名,还列出来登录时间,终端名称等。这些信息都是不需要的,去掉这些信息
- #!/bin/sh
- #
- FILE=$1
- if test -z "$FILE"
- then
- if test ! -f $HOME/.watchees
- then
- echo "usage: watch.sh userlist"
- exit 1
- fi
- fi
- NAMES=`wc -w < $FILE`
- LINES=`wc -l < $FILE`
- if test $NAMES -ne $LINES ; then
- echo "file $FILE must have one name per line"
- exit 2
- fi
- # file has to be sorted, because we plan to use join
- sort -o $FILE $FILE
- # create a scratch file
- SCRATCH=`mktemp /tmp/watch.XXXXXX`
- trap "rm -f $SCRATCH; exit 0" 0 2 3 15
- # main loop now
- # first get initial list
- who | cut -d" " -f1 | sort -u | join - $FILE >prev #cut命令 -d指出分割符是空格 -f指出需要的字段是第一 #个,比如who的结果是“(unknown) tty2 2012-10-29 23: #30 (:1)”, cut处理后就是"(unkonwn)"
- while true
- do
- sleep 10
- who | cut -d" " -f1 | sort -u | join - $FILE > current
- # compute results into scratch fle
- comm -23 prev current> $SCRATCH
- # and only print the file if non-empty
- if test -s $SCRATCH ; then
- echo "Logged out:"
- cat $SCRATCH
- fi
- # same logic for other one
- comm -13 prev current > $SCRATCH
- if test -s $SCRATCH ; then
- echo "Logged in:"
- cat $SCRATCH
- fi
- mv current prev
- done
再增加一个需求, 不再使用prev和current文件,而都采用临时文件,并且程序退出时候删除临时文件。
- #!/bin/sh
- #
- # note: the list of users has to have one name per line
- #
- FILE=$1
- if test -z "$FILE"
- then
- if test ! -f $HOME/.watchees
- then
- echo "usage: watch.sh userlist"
- exit 1
- fi
- fi
- NAMES=`wc -w < $FILE`
- LINES=`wc -l < $FILE`
- if test $NAMES -ne $LINES ; then
- echo "file $FILE must have one name per line"
- exit 2
- fi
- # file has to be sorted, because we plan to use join
- sort -o $FILE $FILE
- # create a scratch file
- SCRATCH=`mktemp /tmp/watch.XXXXXX`
- CURR=`mktemp /tmp/watch.XXXXXX` #用临时文件代替current文件
- PREV=`mktemp /tmp/watch.XXXXXX` #用临时文件代替prev文件
- trap "rm -f $SCRATCH $CURR $PREV; exit 0" 0 2 3 15 #程序退出时候删除所有临时文件。
- # main loop now
- # first get initial list
- who | cut -d" " -f1 | sort -u | join - $FILE >$PREV
- while true # true is a program: exit(0);
- do
- sleep 10 # wait a while
- who | cut -d" " -f1 | sort -u | join - $FILE > $CURR
- # compute results into scratch fle
- comm -23 $PREV $CURR> $SCRATCH
- # and only print the file if non-empty
- if test -s $SCRATCH ; then
- echo "Logged out:"
- cat $SCRATCH
- fi
- # same logic for other one
- comm -13 $PREV $CURR > $SCRATCH
- if test -s $SCRATCH ; then
- echo "Logged in:"
- cat $SCRATCH
- fi
- mv $CURR $PREV
- done