欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Shell 练习题(二)

程序员文章站 2024-03-15 23:26:12
...

变量

根据变量的生效范围等标准划分下面变量类型:

  • 局部变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效
  • 环境(全局)变量:生效范围为当前shell进程及其子进程
    变量声明、赋值:export name=VALUE,declare -x name=VALUE
    变量引用:$name, ${name}
    显示所有环境变量:env,printenv,export,declare -x
    删除变量:unset name
  • 本地变量:生效范围为当前shell进程中某代码片断,通常指函数
  • 位置变量:$1, $2, …来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数
    $1, $2, …:对应第1、第2等参数,shift [n]换位置
    $0: 命令本身
    $: 传递给脚本的所有参数,全部参数合为一个字符串
    aaa@qq.com: 传递给脚本的所有参数,每个参数为独立字符串
    $#: 传递给脚本的参数的个数
    aaa@qq.com $
    只在被双引号包起来的时候才会有差异
    set – 清空所有位置变量
  • 特殊变量:$?, $0, $*, aaa@qq.com, KaTeX parse error: Expected 'EOF', got '#' at position 1: #̲,$
    $? 变量保存最近的命令退出状态。 0 代表成功,1-255代表失败 echo $?

read

使用read来把输入值分配给一个或多个shell变量
-p 指定要显示的提示
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N -d ‘字符’ 输入结束符
-t N TIMEOUT为N秒
read 从标准输入中读取值,给每个单词分配一个变量
所有剩余单词都被分配给最后一个变量
read -p “Enter a filename: “ FILE

let

 bash中的算术运算:help let
+, -, *, /, %取模(取余), **(乘方)
实现算术运算:
(1) let var=算术表达式
(2) var=$[算术表达式]
(3) var=$((算术表达式))
(4) var=$(expr arg1 arg2 arg3 ...)
(5) declare –i var = 数值
(6) echo ‘算术表达式’ | bc
乘法符号有些场景中需要转义,如*  bash有内建的随机数生成器:$RANDOM(0-32767)
echo $[$RANDOM%50] :0-49之间随机数

 增强型赋值:
+=, -=, *=, /=, %=let varOPERvalue
例如:let count+=3
 自加3后自赋值
 自增,自减:
let var+=1
let var++
let var-=1
let var--

1、编写脚本/root/bin/systeminfo.sh,显示当前主机系统信息,包括主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小

#!/bin/bash
BEGINCOLOR="\e[1;35m"
ENDCOLOR="\e[0m"
 
echo -e "My hostname is ${BEGINCOLOR}`hostname`$ENDCOLOR"
echo -e "IP address is ${BEGINCOLOR}`ifconfig ens33 |grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}'|head -n1`$ENDCOLOR"
echo -e "OS version is ${BEGINCOLOR}`cat /etc/redhat-release`$ENDCOLOR"
echo -e "Kernel version is ${BEGINCOLOR}`uname -r`$ENDCOLOR"
echo -e "CPU type is ${BEGINCOLOR}`lscpu|grep "Model name" |cut -d: -f2 |tr -s " "`$ENDCOLOR"
echo -e "Memtotol is ${BEGINCOLOR}`cat /proc/meminfo |head -n1 |grep -Eo '[0-9]+.*'`$ENDCOLOR"
echo -e "Disk space is ${BEGINCOLOR}`lsblk |grep 'sda\>'|grep -Eo '[0-9]+[[:upper:]]'`$ENDCOLOR"

Shell 练习题(二)

grep
‘[:upper:]’
大写字母类。包括:‘A B C D E F G H I J K L M N O P Q R S T U V W X Y Z’。
-A,–after-context=NUM 输出当前行以及向后数NUM数的所有行
-B,–before-context=NUM 输出当前行以及向前数NUM数的所有行
-C,–context=NUM 输出当前行以及向前向后各数NUM数的所有行
-c,–count 统计每个文件中包含指定字符串的行数
-e,–regexp=PATTERN 用PATTERN来进行匹配操作
-E,–extended-regexp PATTERN是一个可扩展的正则表达式(缩写ERE)
-f<范本文件>,–file=FILE 指定范本文件,其内容有一个或多个范本样式,让grep查找符合范本条件的文件内容,格式为每一行的范本样式
-F,–fixed-strings PATTERN是一个由断行符分隔的定长字符串(取消默认的基本正则表达式)
-h,–no-filename 输出时不显示文件名前缀
-i,–ignore-case 忽略大小写
-l,–files-with-match 只显示包含指定字符串的文件名
-n,–line-number 输出的同时显示行号
-o,–only-matching 只显示匹配到的字符串
-q,–quiet,–silent 静默模式,不输出任何信息
-s,–nomessages 不显示不存在或无法匹配的错误信息
-v,–invert-march 显示不匹配的行
-V,-version 显示版本信息
-w,–word-regexp 匹配整个单词
–color=auto 对匹配到的文本着色显示

2、编写脚本/root/bin/backup.sh,可实现每日将/etc/目录备份到/root/etcyyyy-mm-dd中

#!/bin/bash
cp -a /etc/ /root/etc`date +%F` && echo "备份完成"

3、编写脚本/root/bin/disk.sh,显示当前硬盘分区中空间利用率最大的值

#!/bin/bash
##编写脚本/root/bin/disk.sh,显示当前硬盘分区中空间利 用率最大的值
maxdisk=`df | grep "/dev/sd" | tr -s " " ":" | cut -d : -f5 | sort -nr | head -n1`
maxuse=`df | grep "/dev/sd" | tr -s " " ":" | cut -d : -f1 | sort -nr | head -n1`
echo "磁盘"$maxuse"使用量为:"$maxdisk

4、编写脚本/root/bin/links.sh,显示正连接本主机的每个远程主机的IPv4地址和连接数教并按连接数从大到小排序

#!/bin/bash
##编写脚本/root/bin/links.sh,显示正连接本主机的每个远 程主机的IPv4地址和连接数,并按连接数从大到小排序
echo -e "远程主机连接统计为:\n\t连接数\t远程主机IP"
netstat -nt | tr -s " " | cut -d " " -f5 | cut -d : -f1 | sort -n | uniq -c |tr -s " " "\t"| egrep '([0-9]+.){3}[0-9]+'

————————————————————————————————————————

1、编写脚本/root/bin/sumid.sh,计算/etc/passwd文件中的第10个用户和第20用户的ID之和

#!/bin/bash
user10=`cat /etc/passwd | cut -d: -f3 | sed -n "10p"`
user20=`cat /etc/passwd | cut -d: -f3 | sed -n "20p"`
let Num=$user10+$user20  #如果不用let,就单单只是两个数字的拼接为字符串而已
echo $Num

2、编写脚本/root/bin/sumspace.sh,传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和

#!/bin/bash
File1=$(grep "^$" $1 | wc -l)  # ^代表行首 $代表行尾 ^$意思就是行首之后就是行尾,中间什么也没有 所以代表空行
File2=$(grep "^$" $2 | wc -l)
let Sumlink=$File1+$File2
echo "the sum of $1 and $2 spacelines is $Sumlink"

3、编写脚本/root/bin/sumfile.sh,统计/etc,/var,/usr目录*有多少个一级子目录和文件

#!/bin/bash
##写一个脚本/root/bin/sumfile.sh,统计/etc, /var, /usr目录*有多少个一级子目录和文件
num1=$(ls -l /etc | wc -l)
num2=$(ls -l /var | wc -l)
num3=$(ls -l /usr | wc -l)
let Num=$num1+$num2+$num3
echo $Num

————————————————————————————————————————

1、编写脚本/root/bin/argsnum.sh,接受一个文件路径作为参数;如果参数个数小于1,则提示用户“至少应该给一个参数”,并立即退出;如果参数个数不小于1,则显示第一个参数所指向的文件中的空白行数

#!/bin/bash
[[ $1 == "" ]] && echo "please enter a parameter" || echo $(grep "^$" $1 | wc -l)

Shell 练习题(二)
2、编写脚本/root/bin/hostping.sh,接受一个主机的IPv4地址做为参数,测试是否可连通。如果能ping通,则提示用户“该IP地址可访问”;如果不可ping通,则提示用户“该IP地址不可访问”

#!/bin/bash
# =~:正则匹配,用来判断其左侧的参数是否符合右边的要求
ipaddr='(\<([0-9]|[1-9][0-9]|1[0-9]{2}|2([0-4][0-9]|5[0-5]))\>\.){3}\<([0-9]|[1-9][0-9]|1[0-5][1-9]|2([0-4][0-9]|5[0-4]))\>'
    read -p "please input a IPV4 addr: " ipv4
    if [[ $ipv4 =~ $ipaddr ]];then 
        echo "a legal IP."
        ping $ipv4 -c 4
        echo "这个IP可以正常访问"
    else
        echo "unlegal IP"
        echo "请输入正确的地址"
        exit
    fi

IPV4地址由4个组数字组成,每组数字之间以.分隔,每组数字的取值范围是0-255。
IPV4必须满足以下四条规则:
1、任何一个1位或2位数字,即0-99;
2、任何一个以1开头的3位数字,即100-199;
3、任何一个以2开头、第2位数字是0-4之间的3位数字,即200-249;
4、任何一个以25开头,第3位数字在0-5之间的3位数字,即250-255。

注意正则表达式最后一位IP地址,如果是255的话就是广播地址,这里我特意省略了
如果也要包括的话就在最后改为 2([0-4][0-9]|5[0-5])

Shell 练习题(二)

3、编写脚本/root/bin/checkdisk.sh,检查磁盘分区空间和inode使用率,如果超过80%,就发广播警告空间将满

#!/bin/bash
a="`df |grep ^/dev/sd |tr -s " " ":"|cut -d: -f5 |cut -d% -f1 |sort -nr`"
if [ $a -gt 80 ]
then
    echo "WARING!!!"
else
    echo "Nothing.."
fi

Shell 练习题(二)————————————————————————————————————————

存在性测试

存在性测试
-a FILE:同-e
-e FILE: 文件存在性测试,存在为真,否则为假

存在性及类别测试
-b FILE:是否存在且为块设备文件
-c FILE:是否存在且为字符设备文件
-d FILE:是否存在且为目录文件
-f FILE:是否存在且为普通文件
-h FILE 或 -L FILE:存在且为符号链接文件
-p FILE:是否存在且为命名管道文件
-S FILE:是否存在且为套接字文件

文件权限测试:
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行

文件特殊权限测试:
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限

文件大小测试:
-s FILE: 是否存在且非空

文件是否打开:
-t fd: fd 文件描述符是否在某终端已经打开
-N FILE:文件自从上一次被读取之后是否被修改过
-O FILE:当前有效用户是否为文件属主
-G FILE:当前有效用户是否为文件属组

双目测试:
FILE1 -ef FILE2: FILE1是否是FILE2的硬链接
FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2: FILE1是否旧于FILE2
 
=~:正则匹配,用来判断其左侧的参数是否符合右边的要求

1、编写脚本/bin/per.sh,判断当前用户对指定的参数文件,是否不可读并且不可写

#!/bin/bash
##chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判断当前用户对/tmp/fiile1>文件 是否不可读且不可写 ?
flie1=/home/soft/zuoye/file
[ -r $file1 ]
arg1=$(echo $?)
echo $arg1
[[ $arg1 -eq 0 ]] && echo "该用户对此文件有读的权限" || echo "该用户对此文件没有
读的权限"
[ -w $file1 ]
arg2=$(echo $?)
echo $arg2
[[ $arg2 -eq 0 ]] && echo "该用户对此文件有写的权限" || echo "该用户对此文件没有
写的权限"

2、编写脚本/root/bin/excute.sh,判断参数文件是否为sh后缀的普通文件,如果是,添加所有人可执行权限,否则提示用户非脚本文件

#!/bin/bash
# =~:正则匹配,用来判断其左侧的参数是否符合右边的要求
read -p "Please input a filename: " file
if [[ $file =~ .*sh$ ]] ; then
        if [ -f $file ] ; then
                chmod a+x $file
                echo "success"
        fi
else
        echo '非脚本文件' 
fi

3、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和允许普通用户登录系统

tr命令详解

#!/bin/bash
# tr将空白转为@,
read -p "请输入禁止的用户:" user
uid=$( id $user |tr " " @ |cut aaa@qq.com -f1 |grep -o "[0-9]\{3,\}" )
#  $( id $user  | cut -d" " -f1 |grep -o "[0-9]\{3,\}"  )

[ $uid -ge 500 ] && usermod -s /bin/nologin $user || echo '该用户为系统用户,无法禁止!'
echo '该用户已禁止登陆'
#!/bin/bash
read -p "请输入允许登录的用户:" user
uid=$( id $user |tr " " @ |cut aaa@qq.com -f1 |grep -o "[0-9]\{3,\}" )
[ $uid -ge 500 ] && usermod -s /bin/bash $user || echo '该用户为系统用户'
echo '该用户已允许登陆'

cut [OPTION]… [FILE]…
cut 命令并不直接操作于源文件,而是操作输出缓冲。
-d:指定字段分隔符,默认是空格 -d:
-f: filed 指定要显示的字段列表 eg:-f1 显示第一个字段 -f1,3 显示一三字段 -f1-3显示一到三字段,
字段从左到右 依次增大,从1开始。

————————————————————————————————————————

1、让所有用户的PATH环境变量的值多出一个路径,例如:
/usr/local/apache/bin

echo "PATH=$PATH:/usr/local/apache/bin">>/etc/profile.d/path.sh
vim /etc/profile.d/env.sh
export PATH=/usr/local/apache/bin:$PATH
source /etc/profile.d/env.sh

2、用户root登录时,将命令指示符变成红色,并自动启用如下别名:
rm=‘rm –i’
cdnet=‘cd /etc/sysconfig/network-scripts/’
editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eth0’
editnet=‘vim /etc/sysconfig/network-scripts/ifcfgeno16777736 或 ifcfg-ens33 ’ (如果系统是CentOS7)

命令符红色 和 定义别名:

在 ~/.bashrc中将放入以下命令:
PS1='\[\e[1;31m\][\aaa@qq.com\h \w]\$\[\e[0m\]'
alias rm='rm –i'
alias cdnet='cd /etc/sysconfig/network-scripts/'
alias editnet='vim /etc/sysconfig/network-scripts/ifcfg-eth0'
alias editnet='vim /etc/sysconfig/network-scriptsifcfg-ens33'

这里注意要su切换
Shell 练习题(二)
Shell 练习题(二)
3、任意用户登录系统时,显示红色字体的警示提醒信息
“Hi,dangerous!”

在/etc/profile.d/env.sh 中添加
echo -e "\e[1;31mHi,dangerous ! \e[0m"

4、编写生成脚本基本格式的脚本,包括作者,联系方式,版本,时间,描述等

vim ~/.vimrc

set nu "show line
set ts=4 "TAB 4 chars
syntax on "grammar light
set cursorline
"set mouse=a
set ai
autocmd BufNewFile *.sh exec ":call SetTitle()"
func SetTitle()
     if expand("%:e")=='sh'
             call setline(1,"#!/bin/bash")
             call setline(2,"#")
             call setline(3,"#**************")
             call setline(4,"#author:果子哥")
             call setline(5,"#QQ:xxxxxxxx")
             call setline(6,"#email:aaa@qq.com")
             call setline(7,"#version:x.0")
             call setline(8,"#date: ".strftime("%Y-%m-%d"))
             call setline(9,"#description: script")
             call setline(10,"#*************************************")
     endif
endfunc
autocmd BufNewFile * normal G   #自动将光标定位到末尾

5、编写用户的环境初始化脚本reset.sh,包括别名,登录提示符,vim的设置,环境变量等

vim reset.sh
...
cat >> ~/.bash_profile << EOF
PS1='\[\e[1;8;$[RANDOM%6+41]m\][\aaa@qq.com\h \w]\$\[\e[0m\]'
export REGEX_IP='(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])[.]){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])'
EOF

#config bashrc
cat >> ~/.bashrc << EOF
alias cdnet='cd /etc/sysconfig/network-scripts/'
EOF

#config vimrc
cat >> ~/.vimrc << EOF
set nu "show line
set ts=4 "TAB 4 chars
syntax on "grammar light
set cursorline
"set mouse=a
set ai
autocmd BufNewFile *.sh exec ":call SetTitle()"
func SetTitle()
     if expand("%:e")=='sh'
             call setline(1,"#!/bin/bash")
             call setline(2,"#")
             call setline(3,"     #*************************************")
             call setline(4,"     #author:果子哥")
             call setline(5,"     #QQ:123456")
             call setline(6,"     #email:aaa@qq.com")
             call setline(7,"     #version:x.0")
             call setline(8,"     #date: ".strftime("%Y-%m-%d"))
             call setline(9,"     #description: script")
             call setline(10,"     #*************************************")
     endif
endfunc
autocmd BufNewFile * normal G   #自动将光标定位到末尾
EOF

Shell 练习题(二)

————————————————————————————————————————

1、编写脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息

#!/bin/bash
 if [ $# -eq 0 ];then
     echo "one argument (username) is required!" 
     exit
 elif [ $# -gt 1 ];then
     echo "required 1 argument, but $# arguments were supplied!"
     exit
 fi  

useradd $1 &> /dev/nul
USER_EXIT=$?
[ $USER_EXIT  -eq 9 ] && echo "createuser.sh: user $1 already exists" && exit 9
[ ! $USER_EXIT -eq 0 ] && echo "createuser.sh: ERROR"

id $1

Shell 练习题(二)

2、编写脚本/root/bin/yesorno.sh,提示用户输入yes或no,并判断用户输入的是yes还是no,或是其它信息

#!/bin/bash
read -p "Please input [Yes/No]:" YESORNO
case $YESORNO in
[Yy][Ee][Ss]|[Yy])
echo "you choose yesyes"
;;
[Nn][Oo]|[Nn])
echo "you choose no"
;;
*)
echo "you choose other"
esac

3、编写脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)

#!/bin/bash
[ $# -lt 1 ] && echo "Please input unless one argument!" && exit
for count in `seq 1 $#`
do
CHAR=$(eval ls -dl \$$count | cut -c 1)
CO="\e[1;32m"
LOR="\e[0m"
case $CHAR in
-)
        echo -e "The file type is \e[1;32mnormal file\e[0m"
        ;;
l)
        echo -e "The file type is $CO link file $LOR"
        ;;
d)
        echo -e "The file type is $CO directory $LOR"
        ;;
*)
        echo "sorry,I still don't know the file type "
esac
done

4、编写脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数

#!/bin/bash
[ $# -lt 1 ] && echo "Please intput unless one argument" && exit
[ $# -gt 1 ] && echo "I just can understand one argument" && exit
[[ $1 =~ ^[0-9]*$ ]] && echo "your argument is a positive integer" || echo "your argument isn't a INT"
相关标签: # Shell shell