day20:早中晚输入问候程序|菜单执行对应命令|检测用户是否登录系统|系统是否被入侵|三行并一行...

1、编写一个问候程序,它根据当前的时间来执行,假设从夜里到中午为早晨,中午到下午六点为下午,下午六点到半夜为网上;

注释:可以用date +%H  来判断小时;              if  [  $h  -ge 0  ] &&  [  $h -lt  12  ]     来判读时区

[root@localhost_002 shell100]# date +%H
22

脚本如下

[root@localhost_002 shell100]# cat 41.sh 
#!/bin/bash
h=`date +%H`
if [ $h -ge 0 ] && [ $h -lt 12 ]
then
   echo "gond  morning."
elif [ $h -ge 12 ] && [ $h -lt 18 ]
then
  echo "good afternoon"
else
  echo "good evening"
fi

执行脚本;
[root@localhost_002 shell100]# sh 41.sh 
good evening

方法二:当然也可以用如下方法:使用 if 判断tag 打标记的方法;然后通过 case来循环

[root@localhost_002 shell100]# cat 41.1.sh 
#!/bin/bash
h=`date +%H`
if [ $h -ge 0 -a $h -lt 12 ]
then 
   tag=1
elif [ $h -ge 12 -a $h -lt 18 ]
then
   tag=2
elif [ $h -ge 18 -a $h -lt 21 ]
   then
   tag=3
else
   tag=4
fi
case $tag in 
    1)
    echo "good morning"
    ;;
    2)
    echo "good afternoon"
    ;;
    3)
    echo "good evening"
    ;;
    4)
    echo "bash is error"
    ;;
esac

执行;
[root@localhost_002 shell100]# sh -x 41.1.sh 
++ date +%H
+ h=23
+ '[' 23 -ge 0 -a 23 -lt 12 ']'
+ '[' 23 -ge 12 -a 23 -lt 18 ']'
+ '[' 23 -ge 18 -a 23 -lt 21 ']'
+ tag=4
+ case $tag in
+ echo 'bash is error'
bash is error

注释if 的语句用法: 如下两种格式:         并且 可以用   &&  或者    -a    来表示;

if  [ $h -ge 0 ]  &&  [ $h -lt  12 ]  then  tag=1    elif  [ 判断 ]  then   tag=2    elif  [ 判断 ]  then  tag=3   else   tag=4  

if  [ $h -ge 0   -a   $h  lt  12 ]

然后分别用 case  来循环;  case  $tag  in   1)  echo "gond  morning" ;;   2)  echo "......." ;;    3)   echo "......." ;;    4)  ".........." ;;    esac

2、写一个 shell  脚本,实现弹出菜单功能,用户根据显示的菜单从键盘选择执行对应的命令;

其实这个题可以用 readcase 参数来实现的;

首先 echo 显示一下内容要求用户输入:    -n  表示换行符    -e  能够识别特殊字符

echo  -e  "1)    w\n2)   ls\n3)    pwd\4)    quit"

然后再使用 read 来使用;    read   -p   "please   input your  nubmer  "  c                  注释:  c 是一个变量;

脚本如下:

[root@localhost_002 shell100]# cat 42.sh 
#!/bin/bash
echo -e "1) w\n2) ls\n3) pwd\n4) quit"
read -p "Please input you number: " c
case $c in 
     1)
        w
       ;;
     2)
       ls
       ;;
     3)
      pwd
       ;;
     4)
      exit
      ;;
     *) 
      echo "bash is error"
     ;;
esac
执行命令;
[root@localhost_002 shell100]# sh 42.sh 
1) w
2) ls
3) pwd
4) quit
Please input you number: 2
16.sh  1.txt  22.1.sh  23.sh  28.1.sh  28.sh  30.sh    41.2.sh	42.sh	   stu.txt
17.sh  21.sh  22.sh    25.sh  28.2.sh  2.txt  41.1.sh  41.sh	ls.tar.gz

注释:由于上面是执行后自动退出,当然也可以写成死循环的方式,一直循环下去;用while :   do   done

[root@localhost_002 shell100]# cat 42.sh 
#!/bin/bash
echo -e "1) w\n2) ls\n3) pwd\n4) quit"
while :                                  # 新加 while  循环语句;
do
read -p "Please input you number: " c
case $c in 
     1)
        w
       ;;
     2)
       ls
       ;;
     3)
      pwd
       ;;
     4)
      exit
      ;;
     *) 
      echo "bash is error"
     ;;
esac                                     
done                                        # while 循环语句结束;
执行脚本;
[root@localhost_002 shell100]# sh 42.sh 
1) w
2) ls
3) pwd
4) quit
Please input you number: 1
 22:30:03 up 9 min,  1 user,  load average: 0.02, 0.08, 0.09
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.149.135  22:21    3.00s  0.06s  0.01s w
Please input you number: 2
16.sh  1.txt  22.1.sh  23.sh  28.1.sh  28.sh  30.sh    41.2.sh	42.sh	   stu.txt
17.sh  21.sh  22.sh    25.sh  28.2.sh  2.txt  41.1.sh  41.sh	ls.tar.gz
Please input you number: 3
/root/shell/shell100

注释:如上脚本,也只是新加 while 的语句而已;可以实现不断循环输入;当然要是输入 4 选项,即 exit  还是会退出此脚本;

当然还有一个方法:  可以使用 select  语句,这个语句和for 循环的语法相同,也可以遍历文件;

select  格式如下:           select  i    in   w  ls   pwd   exit   do   case语句    done

注释 select  语句会一直执行下去的,并且左侧以 #? 结尾;用法如下;

[root@localhost_002 shell100]# cat 42.1.sh 
#!/bin/bash

select i in w ls pwd exit
do
    case $i in 
        w)
           w
           ;;
       ls)
          ls
           ;;
      pwd)
          pwd
           ;;
     exit)
         exit
          ;;
      *)
        echo "Please input 1-4."
          ;;
     esac
done
执行命令;
[root@localhost_002 shell100]# sh 42.1.sh 
1) w
2) ls
3) pwd
4) exit
#? 2
16.sh  1.txt  22.1.sh  23.sh  28.1.sh  28.sh  30.sh    41.2.sh	42.1.sh  ls.tar.gz
17.sh  21.sh  22.sh    25.sh  28.2.sh  2.txt  41.1.sh  41.sh	42.sh	 stu.txt
#? 1
 22:38:43 up 18 min,  1 user,  load average: 0.00, 0.03, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.149.135  22:21    3.00s  0.09s  0.00s w
#? 3
/root/shell/shell100

注释:当然 左侧 #? 是可以修改了的,只需要在开头添加如下内容即可;如下;

PS3="Please input  you number(1-4): "

[root@localhost_002 shell100]# cat 42.1.sh 
#!/bin/bash
PS3="Please input you number(1-4): "
select i in w ls pwd exit
do
    case $i in 
        w)
           w
           ;;
       ls)
          ls
           ;;
      pwd)
          pwd
           ;;
     exit)
         exit
          ;;
      *)
        echo "Please input 1-4."
          ;;
     esac
done
执行脚本:
[root@localhost_002 shell100]# sh 42.1.sh 
1) w
2) ls
3) pwd
4) exit
Please input you number(1-4): 2
16.sh  1.txt  22.1.sh  23.sh  28.1.sh  28.sh  30.sh    41.2.sh	42.1.sh  ls.tar.gz
17.sh  21.sh  22.sh    25.sh  28.2.sh  2.txt  41.1.sh  41.sh	42.sh	 stu.txt
Please input you number(1-4): 1
 22:44:12 up 23 min,  1 user,  load average: 0.04, 0.03, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.149.135  22:43    4.00s  0.05s  0.01s w
Please input you number(1-4): 3
/root/shell/shell100
Please input you number(1-4): 

注释:这个脚本会一直不断的循环下去,不会退出的;

3、写一个 shell 脚本,每隔 5 分钟判断指定的用户是否登录系统;        需要指定用户名;

注释:如果先登录root 用户,然后通过root用户去sudo 到 yuanhh 用户, 那么这种情况是查询不到,也是会显示 root;

分析: 如果要判断用户是否登录,\从命令行输入判断可以有两种方式,

1)、脚本本执行时 传递一个参数;通过用  命令查看并打印第一列;

2)、另一种是给它一个用户,通过 read  -p  命令;

首先用第一种脚本传递参数的方式:

[root@localhost_002 shell100]# w
 22:58:45 up 38 min,  1 user,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.149.135  22:43    5.00s  0.07s  0.02s w
[root@localhost_002 shell100]# w|awk '{print $1}'|sed '1,2'd
root

脚本代码如下:

[root@localhost_002 shell100]# cat 43.sh 
#!/bin/bash
while :
do
   if  w|sed '1,2'd|awk '{print $1}' |grep -qw "$1"
   then
       echo "用户$1已经登录系统"
       exit
   fi
   sleep  30
done
执行:
[root@localhost_002 shell100]# sh 43.sh root
用户root已经登录系统

方法二: 当然也可以用 read  -p  给一个用户,然后来判断;

4、先普及一个小常识,我们用ps aux可以查看到进程的PID,而每个PID都会在/proc内产生。如果查看到的pid在proc内是没有的,则进程被人修改了,这就代表系统很有可能已经被入侵过了。 请用上面知识编写一个shell,定期检查下自己的系统是否被人入侵过;

分析:可以把ps aux 列出来的pid做一个遍历,然后过滤到pid,并打印第二行:如下:

ps  aux|grep 'pid'|awk '{print $2}'

然后把列出的行逐一遍历,      使用  while   read  xxx; do  ......    done  这种循环的格式来逐行处理;       赋予变量 pid

echo  -e   "1\n2\3"|while  read  n;do echo $n;done

[root@fenye2019 shell]# echo -e "1\n2\n3"|while read n;do echo $n;done
1
2
3

然后在while语句里,使用find 来查找 pid 相关行;   赋予变量  result                    -maxdepth   1  表示查看的深度为 1;

result=`find    /proc  -type  d   -maxdepth  1  -name "$pid"`

然后在通过判断这个变量是否为空,如果在/proc 目录查找不到$pid,则为空;  if  [  -z  $pid  ]   then   echo  $pid  not  exist;

脚本内容:

[root@fenye2019 shell]# cat 44.sh 
#!/bin/bash
echo $$
ps aux|sed '1'd|awk '{print $2}'|while read pid
do
    result=`find /proc -type d -maxdepth 1 -name "$pid"`
    if [ -z $result ]
    then
        echo "$pid not exist"
    fi
done
执行脚本:
[root@fenye2019 shell]# sh 44.sh 
21101
21102 not exist
21103 not exist
21104 not exist

注释:如上在执行过程中还是会显示出脚本本身的pid和命令的pid进程号;

那么如何解决:只能在执行时过滤掉脚本本身的进程pid才可以,可以通过追踪到父进程PPID的方式, 然后把变量在传递到awk的脚本参数里;

pp=$$   表示脚本本身的pid;  

ps  elf 命令可以追踪到 PPID,   第三列则是PPID ,   第四列则是PID;

把shell变量传递awk 脚本里;      ps  elf |sed '1'd >/tmp/pid.txt

for pid  in `awk   -v  ppn=$pp  '$5!=ppn  {print $4}'`  do   if  !  [ -d $pid ]  then   echo  "$pid  not  exist" fi     down

脚本内容如下:

[root@fenye2019 shell]# cat 44.2.sh 
#!/bin/bash
pp=$$
ps -elf|sed '1'd > /tmp/pid.txt
for pid in `awk -v ppn=$pp '$5!=ppn {print $4}' /tmp/pid.txt`
do
    if ! [ -d /proc/$pid ]
    then
        echo "系统中并没有pid为$pid的目录"
    fi
done
[root@fenye2019 shell]# sh 44.2.sh 

此时脚本才算正确了;

5、想办法把文本里面每三行内容合并到一行 例如:1.txt内容如下:

1
2
3
4
5
6
7

分析:根据要求每三行变成一行,可以想到的是第3行,  第6行,  第9行后面为换行符,其他行后面为空格;

可以用 while  read  line 来做一个遍历,然后用 if 判断是否能被 3 整除,如果能则使用 echo  -n 换行输出,如果不能,则显示当前行;

[root@fenye2019 shell]# cat 45.sh 
#!/bin/bash
n=0
cat $1|while read line
do
    n1=$[$n%3]
    if [ $n1 -eq 0 ]
    then
        echo "$line"
    else
        echo -n "$lne\n"
    fi
    n=$[$n+1]
done
[root@fenye2019 shell]# sh 45.sh 1.txt
1 2 3
4 5 6
ada  1231 

 

转载于:https://my.oschina.net/yuanhaohao/blog/3001479

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值