第八章、bash脚本编程(中)
07_02_bash脚本编程之六 使用脚本选项及组合条件测试(39 - $)
10. 写一个脚本:
1、添加10个用户user1到user10,密码同用户名;但要求只有用户不存在的情况下才能添加;
2. 扩展: - 答案为adminusers.sh
接受一个参数:
add: 添加用户user1..user10
del: 删除用户user1..user10
其它:退出
3. 参数指定 添加/删除 多个用户 - 答案为adminusers2.sh
adminusers --add user1,user2,user3,hello,hi
11. 写一个脚本:
计算100以内所有能被3整除的正整数的和;
取模,取余:%
3%2=1
100%55=45
12. 写一个脚本:
计算100以内所有奇数的和以及所有偶数的和;分别显示之;
let I=$[$I+1]
SUM=$[$SUM+$I]
let SUM+=$I
let I+=1 相当于 let I++
-=
let I-=1 相当于 let I--
++I, --I
*=
/=
%=
13. 写一个脚本:
分别显示当前系统上所有默认shell为bash的用户和默认shell为/sbin/nologin的用户,并统计各类shell下的用户总数。显示结果形如:
BASH,3users,they are:
root,redhat,gentoo
NOLOGIN, 2users, they are:
bin,ftp
#!/bin/bash
#
NUMBASH=`grep "bash$" /etc/passwd | wc -l`
BASHUSERS=`grep "bash$" /etc/passwd | cut -d: -f1`
BASHUSERS=`echo $BASHUSERS | sed 's@[[:space:]]@,@g'`
echo "BASH, $NUMBASH users, they are:"
echo "$BASHUSERS
组合测试条件
-a: 与关系
-o: 或关系
!:非关系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
练习: - 答案为 quit.sh
判断参数是不是在:q, Q, quit, Quit中。
08_01_facl及用户及Linux终端(65 - $)
生成随机数
RANDOM 系统内置环境变量可以生成随机数,范围: 0-32768
随机数生成器:熵池,保存很多随机数,可能取空
/dev/random: 熵池空时,阻塞,更安全
/dev/urandom: 熵池空时,软件模拟生成,
08_02_bash脚本编程之七 case语句及脚本选项进阶
练习:
写一个脚本,利用RANDOM生成10个随机数,并找出其中的最大值,和最小值;答案为random.sh
#!/bin/bash
#
declare -i MAX=0
declare -i MIN=0
for I in {1..10}; do
MYRAND=$RANDOM
[ $I -eq 1 ] && MIN=$MYRAND
if [ $I -le 9 ]; then
echo -n "$MYRAND,"
else
echo "$MYRAND"
fi
[ $MYRAND -gt $MAX ] && MAX=$MYRAND
[ $MYRAND -lt $MIN ] && MIN=$MYRAND
done
echo $MAX, $MIN
#!/bin/bash
#
for i in {1..10}; do
NUMS+=$RANDOM" "
done
MAXNUM=`echo $NUMS | cut -d' ' -f1`
MINNUM=$MAXNUM
for i in $NUMS; do
[ $i -gt $MAXNUM ] && MAXNUM=$i
[ $i -lt $MINNUM ] && MINNUM=$i
done
echo $NUMS
echo "max: $MAXNUM"
echo "min: $MINNUM"
面向过程的控制结构包括:
顺序结构
选择结构
循环结构
选择结构:fi和case语句
if: 单分支、双分支、多分支
if CONDITION; then
statement
...
fi
if CONDITION; then
statement
...
else
statement
...
fi
if CONDITION1; then
statement
...
elif CONDITION2; then
statement
...
esle
statement
...
fi
case语句:选择结构
case SWITCH in
value1)
statement
...
;;
value2)
statement
...
;;
*)
statement
...
;;
esac
value可以使用: - 例如case.sh
a-z
A-Z
0-9
[abc]
写debug.sh练习case的使用
练习:写一个脚本,实现功能:添加删除用户,显示详细信息 - 答案为adminusers3.sh
#!/bin/bash
#
DEBUG=0
ADD=0
DEL=0
for I in `seq 0 $#`; do
if [ $# -gt 0 ]; then
case $1 in
-v|--verbose)
DEBUG=1
shift ;;
-h|--help)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 0
;;
--add)
ADD=1
ADDUSERS=$2
shift 2
;;
--del)
DEL=1
DELUSERS=$2
shift 2
;;
*)
echo "Usage: `basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
exit 7
;;
esac
fi
done
if [ $ADD -eq 1 ]; then
for USER in `echo $ADDUSERS | sed 's@,@ @g'`; do
if id $USER &> /dev/null; then
[ $DEBUG -eq 1 ] && echo "$USER exists."
else
useradd $USER
[ $DEBUG -eq 1 ] && echo "Add user $USER finished."
fi
done
fi
if [ $DEL -eq 1 ]; then
for USER in `echo $DELUSERS | sed 's@,@ @g'`; do
if id $USER &> /dev/null; then
userdel -r $USER
[ $DEBUG -eq 1 ] && echo "Delete $USER finished."
else
[ $DEBUG -eq 1 ] && echo "$USER not exist."
fi
done
fi
08_03_磁盘及文件系统管理详解之一(^-15)
练习:写一个脚本showlogged.sh,其用法格式为:
showlogged.sh -v -c -h|--help
其中,-h选项只能单独使用,用于显示帮助信息;-c选项时,显示当前系统上登录的所有用户数;如果同时使用了-v选项,则既显示同时登录的用户数,又显示登录的用户的相关信息;如
Logged users: 4.
They are:
root tty2 Feb 18 02:41
root pts/1 Mar 8 08:36 (172.16.100.177)
root pts/5 Mar 8 07:56 (172.16.100.177)
hadoop pts/6 Mar 8 09:16 (172.16.100.177)
#!/bin/bash
#
declare -i SHOWNUM=0
declare -i SHOWUSERS=0
for I in `seq 1 $#`; do
if [ $# -gt 0 ]; then
case $1 in
-h|--help)
echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
exit 0 ;;
-v|--verbose)
let SHOWUSERS=1
shift ;;
-c|--count)
let SHOWNUM=1
shift ;;
*)
echo "Usage: `basename $0` -h|--help -c|--count -v|--verbose"
exit 8 ;;
esac
fi
done
if [ $SHOWNUM -eq 1 ]; then
echo "Logged users: `who | wc -l`."
if [ $SHOWUSERS -eq 1 ]; then
echo "They are:"
who
fi
fi
终端类型:
console: 控制台
pty: 物理终端 (VGA)
tty#: 虚拟终端 (VGA)
ttyS#: 串行终端
pts/#: 伪终端
练习:写一个脚本
通过命令行传递一个文件路径参数给脚本:
如果参数多了或少了,报错;
如果参数指定的路径对应的是目录而不是文件,报错;
而后,检查路径指定的文件是否为空或不存在,如果是,则新建此文件,并在文件中生成如下内容
#!/bin/bash
#
而后,使用vim编辑器打开此文件,并让光标处于这个文件的最后一行;
#!/bin/bash
if [ ! $# -eq 1 ]; then
echo "Usage: `basename $0` filepath"
exit 1
fi
if [ -d $1 ]; then
echo $?
echo "The file path is directory!"
exit 2
fi
if [ ! -e $1 ]; then
echo -e "#!/bin/bash\n#" > $1
vim $1
exit 3
fi
if grep "[^[:space:]]" $1 &>/dev/null; then
vim + $1
exit 4
else
echo -e "#!/bin/bash\n#" > $1
vim $1
exit 3
fi
写个脚本,按如下方式执行:
mkscript.sh -v|--version VERSION -a|--author AUTHOR -t|--time DATETIME -d|--description DESCRIPTION -f|--file /PATH/TO/FILE -h|--help
1、此脚本能创建或打开-f选项指向的文件/PATH/TO/FILE;如果其为空文件,能自动为其生成第一行;如果文件不空,且第一行不是#!/bin/bash,则中止此脚本,并报错“The file is not a bash script.";否则,则直接使用vim 打开此文件;
提示:/PATH/TO/FILE,要判断其目录是否存在;如果不存在,则报错;
2、如果为空文件,自动生成的第一行内容为:
#!/bin/bash
3、如果为空文件,且使用了-a选项,则在文件中添加“# Author: -a选项的参数”,比如:
# Author: Jerry
4、如果为空文件,且使用了-t选项,则在文件中添加“# Date: 脚本执行-t选项后指定的时间”,比如:
# Date: 2013-03-08 18:05
5、如果为空文件,且使用了-d选项,则在文件中添加“# Description: -d选项的内容”,比如:
# Description: Create a bash script file head.
6、如果为空文件,且使用了-v选项,则在文件添加“# Version: -v后跟的参数”,比如:
# Version: 0.1
7、-h选项只能单独使用,用于显示使用帮助;
8、其它选项,显示帮助信息;
说明:
这是一个用于创建脚本的脚本,它可以自动帮助创建一个bash脚本的文件头,这样,以后使用此脚本来创建其它脚本将变得比较高效。比如:
#!/bin/bash
# Author: Jerry(jerry@magedu.com)
# Date: 2013-03-08 18:05
# Description: Create a bash script file head.
# Version: 0.1
#
#!/bin/bash
#
print_help()
{
echo "Usage: `basename $0` [options]"
echo "Options:"
echo -e "\t -t|--time"
echo -e "\t -a|--author AUTHOR"
echo -e "\t -v|--version VERSION"
echo -e "\t -f|--file /PATH/TO/FILE"
echo -e "\t -d|--description DESCRIPTION"
echo -e "\t -h|--help"
exit 1
}
[ $# -eq 0 ] && print_help
while [ $# -gt 0 ]; do
case $1 in
-f|--file)
FILE=$2
shift 2;;
-a|--author)
AUTHOR=$2
shift 2;;
-t|--time)
DATE=`date "+%F %T"`
shift;;
-d|--description)
DESCRIPTION=$2
shift 2;;
-v|--version)
VERSION=$2
shift 2;;
-h|--help)
print_help
exit 1;;
*)
print_help
exit 1;;
esac
done
if [ -f $FILE ]; then
if grep "[^[:space:]]" $FILE &>/dev/null; then
if [ `head -1 $FILE` != "#!/bin/bash" ]; then
echo "The file is not a bash script."
exit 3
else
vim + $FILE
exit 2
fi
fi
fi
if [ -d $FILE ]; then
echo "$FILE is a directory."
exit 3
fi
echo "#!/bin/bash" >> $FILE
[ -n "$AUTHOR" ] && echo "# Author: $AUTHOR" >> $FILE
[ -n "$DATE" ] && echo "# Date: $DATE" >> $FILE
[ -n "$DESCRIPTION" ] && echo "# Description: $DESCRIPTION" >> $FILE
[ -n "$VERSION" ] && echo "# Version: $VERSION" >> $FILE
echo "#" >> $FILE
vim + $FILE
bss: Block Started by Symbol
readelf -h
readelf -S
objdump -h
ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度、段的数量。
09_04_Linux压缩及归档 (66分钟-$)
脚本编程3种控制结构:
1. 顺序结构
2. 选择结构
if
case
3. 循环结构
for
while
until
while循环:适用于循环次数未知的场景,要有退出条件
语法:
while CONDITION; do
statement
...
done
练习:计算100以内所有正整数的和
#!/bin/bash
declare -i I=1
declare -i SUM=0
while [ $I -le 100 ]; do
let SUM+=$I
let I++
done
echo $SUM
练习:转换用户输入的字符为大写,除了quit:
#!/bin/bash
#
read -p "Input something: " STRING
while [ $STRING != 'quit' ]; do
echo $STRING | tr 'a-z' 'A-Z'
read -p "Input something: " STRING
done
练习:每隔5秒查看hadoop用户是否登录,如果登录,显示其登录并退出;否则,显示当前时间,并说明hadoop尚未登录:
#!/bin/bash
#
who | grep "hadoop" &> /dev/null
RETVAL=$?
while [ $RETVAL -ne 0 ]; do
echo "`date`, hadoop is not log."
sleep 5
who | grep "hadoop" &> /dev/null
RETVAL=$?
done
echo "hadoop is logged in."
10_01_Raid及mdadm命令之一 (^ - 17)
写一个脚本:
1) 显示一个菜单给用户:
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
2) 当用户给定选项后显示相应的内容;
扩展:
当用户选择完成,显示相应信息后,不退出;而让用户再一次选择,再次显示相应内容;除了用户使用quit;
#!/bin/bash
#
cat << EOF
d|D) show disk usages.
m|M) show memory usages.
s|S) show swap usages.
*) quit.
EOF
read -p "Your choice: " CHOICE
while [ $CHOICE != 'quit' ];do
case $CHOICE in
d|D)
echo "Disk usage: "
df -Ph ;;
m|M)
echo "Memory usage: "
free -m | grep "Mem" ;;
s|S)
echo "Swap usage: "
free -m | grep "Swap" ;;
*)
echo "Unknown.." ;;
esac
read -p "Again, your choice: " CHOICE
done
控制echo显示文字的颜色以及显示效果
echo -e "\033[1;31;41mHello\033[0m,world"
[31m: 两位数字控制颜色,第一位表示控制前/背景色,3-前景色,4-背景色,
[1m: 一位数字控制字体,加粗,闪烁,下划线等,1为加粗
\033 - ctrl键
echo显示字体颜色