SHELL脚本之进阶脚本实操(教程向)

1 处理脚本参数

一个正常的脚本在处理参数时,应该可以做到:

  • 脚本参数无序也能执行

  • 短选项要支持连写

其实要真的自己写代码去处理这些参数,我估计这工作量比一些普通的脚本都要大得多。。。好在Linux中内置了一个命令getopt,这个命令可以帮我处理这两个问题

[root@localhost ~]# getopt -q adp:s:h -ha -s /bin/nologin -p 123 userlist
 -h -a -s '/bin/nologin' -p '123' -- 'userlist'

在这里,我们将adp:s:h-ha -s /bin/nologin -p 123 userlist 作为 getopt 的两个参数

  • adp:s:h:当下一个参数出现 -a-d-p 参数-s 参数-h时,将会把它们解析成正常的选项+参数的形式,并且带参数的选项放在最后面,短选项支持连写,各个选项可以乱序
    • 选项后面的冒号表示该选项需要参数
    • 如果该选项可以的参数不是必要的话,可以在选项后面加两个冒号

再看输出的结果:getopt 这个命令将我们“复杂乱序”的参数变成了一条格式整齐的参数,其中不带参数的短选项被放在了最前面,其次是带参数的选项,最后由 -- ‘userlist’ 结尾,这表示不带选项的参数将会被放在最后面。值得注意的是,不带选项的参数有且仅有一个且在输入前也需要放在最后面


解决了参数格式的问题,还需要解决的问题是,在传入参数后,脚本怎么知道这些参数第几个是什么选项,有几个选项呢。这就需要用到shell中自带的两个函数setshift

  • set:这个函数用于将指定的字符串替换当前的参数列表
# 用法
set -- $STR
  • shift [N]:这个函数用于弹出指定个数的参数
 # 用法
 shift		# 表示将第一个参数弹出
 shift 2	# 表示将前两个参数弹出

看到这里可能你还是一头雾水,知道这两个函数又有什么用呢?我们再来看一般在脚本中会如何使用这两个函数

#!/bin/bash

# $@表示将脚本的全部参数
# 因getopt这个命令会将各个选项的参数转换成'参数'的形式,并不利于我们直接使用它,所以在解析后先将其用sed命令删去
opt=`getopt -q adp:s:h $@ | sed "s/'//g"`
# 将脚本参数改成格式化后的参数
set -- $opt

# 这里使用了一个死循环,每次都判断第一个参数是什么选项,然后做出对应处理后将其弹出,这样就可以逐个处理选项了
while :; do
	case $1 in
	-a)
		...
		shift
	;;
	-d)
		...
		shift
	;;
	-p)
		# -p是带选项的参数,所以一次要弹出两个参数
		...
		shift 2
	;;
	-s)
		...
		shift 2
	;;
	--)
		# 在遇到--后,表示所有选项都已经处理完了,只剩下最后一个不带选项的参数,这时弹出选项后退出循环,脚本中的$1就变成了这个不带选项的参数
		shift
		break
	;;
	*)
		# 当遇到其他无法解析的选项时,输出错误提示并退出脚本的运行
		echo "Error"
		exit 1
	esac
done

至此,一个脚本的参数就基本能很好的处理完成了

扫描二维码关注公众号,回复: 10298700 查看本文章

2 脚本实战

写一个用户脚本:这个脚本用于批量创建用户,并且可以指定密码和使用的shell

  • 脚本格式:./script_file [ -h | -a | -d | -p PASSWORD | -m | -s SHELL ] USER_LIST_FILE
  • -a :创建用户列表文件中的用户
  • -d:删除用户列表文件中的用户
  • -p PASSWORD:设置用户统一密码
  • -m:使用默认密码redhat
  • -s SHELL:指定用户的默认shell,如不指定默认/bin/bash
  • -h:显示帮助信息
  • USER_LIST_FILE文件内容:每行一个用户名
  • 注意事项:
    • 脚本参数无序也能执行
    • 脚本根据不同情况返回不同的状态码
    • 参数错误能报错
    • 短选项要支持连写
    • 不显示多余的输出信息
    • 用户已存在提示
#!/bin/bash
#./script_file [ -h | -a | -d | -p PASSWORD | -m | -s SHELL ] USER_LIST_FILE

opt=`getopt -q adp:s:h $@ | sed "s/'//g"`
set -- $opt

#默认密码
def_passwd=redhat
#默认shell
def_shell=/bin/bash

#一个参数都没有加:提示用法
if [ $# -eq 1 ]; then
	echo "Usage: ./script_file [-h|-a|-d|-p PASSWORD|-s SHELL] USER_LIST_FILE"
	echo "Try use '-h' to get more information."
	exit 2
fi

#只有一个参数:判断是否为-h,不是则报错
#if [ $# -eq 2 ]; then
#	if [[ $1 = -h ]]; then
#		#调用外部获取帮助脚本
#		/root/get_help.sh
#		exit 2
#	else
#		echo "Error, need at least 1 arg!!!"
#		exit 1
#	fi
#fi

#使用无限循环获取所有参数
while :; do
	case $1 in
	-h)
		#调用外部脚本
		/root/get_help.sh
		shift
	;;
	-a)
		#添加和删除不能同时使用
		if [[ $flag != del ]]; then
			flag=add
			shift
		else
			#报错退出
			echo "Error, '-a' and '-d' can not be used together!!!"
			exit 1
		fi
	;;
	-d)
		#添加和删除不能同时使用
		if [[ $flag != add ]]; then
			flag=del
			shift
		else
			#报错退出
			echo "Error, '-a' and '-d' can not be used together!!!"
			exit 1
		fi
	;;
	-p)	
		def_passwd=$2
		shift 2
	;;
	-s)
		def_shell=$2
		shift 2
	;;
	--)
		shift
		break
	;;
	*)
		#提示选项不支持
		echo "Error, unsupported option '$1' !!!"
		exit 1
	esac
done

#判断参数是否为空
if [ -z $1 ]; then
	echo "Error, need userlist file"
	exit 1
fi
#查询文件是否存在
find $1 > /dev/null 2>&1
if [ $? -ne 0 ]; then
	echo "$1 does not exist!!!"
	exit 1
fi

case $flag in
add)
	while read user; do
		id $user &> /dev/null
		if [ $? -eq 0 ]; then
			echo "$user already exist."
		else
			useradd -s $def_shell $user
			#当添加失败时输出错误信息,shell的类型没加判断可能会出错
			if [ $? -eq 0 ]; then
				echo "user $user added."
				echo $def_passwd | passwd --stdin $user > /dev/null 2>&1
			else
				echo "user $user add failed, please check."
			fi
		fi
	done < $1
;;
del)
	while read user; do
		id $user &> /dev/null
		if [ $? -eq 1 ]; then
			echo "user $user do not exist."
		else
			userdel -r $user
			echo "user $user deleted." 
		fi
	done < $1
;;
*)
	echo "Error, need '-a' or '-d' option to execute this script"
	exit 1
esac
#!/bin/bash

get_help(){
	echo "Descreption: this script is use to manage user"
	echo -e "\t-a\t\tcreate the user"
	echo -e "\t-d\t\tdelete the user"
	echo -e "\t-p PASSWORD\tset the password of user in stand of defualt [redhat]"
	echo -e "\t-s SHELL_TYPE \tset the shell of user in stand of defualt [/bin/bash]"
	echo -e "\t-h\t\tget the help of this script"
}

get_help

忘记写-m,-m与-p不能同时用的判断和-a与-d的判断类似,所以偷个懒就不补了

想试一下脚本调用脚本还有练一下函数的使用,查看帮助的代码写到了另外一个脚本get_help.sh里

测试用例:

  1. 不写参数
[root@localhost ~]# ./script_file.sh 
Usage: ./script_file [-h|-a|-d|-p PASSWORD|-s SHELL] USER_LIST_FILE
Try use '-h' to get more information.
  1. 只写一个参数-h
[root@localhost ~]# ./script_file.sh -h
Descreption: this script is use to manage user
	-a		create the user
	-d		delete the user
	-p PASSWORD	set the password of user in stand of defualt [redhat]
	-s SHELL_TYPE 	set the shell of user in stand of defualt [/bin/bash]
	-h		get the help of this script
  1. 只写一个不为-h的参数
[root@localhost ~]# ./script_file.sh -a
Error, need userlist file
[root@localhost ~]# ./script_file.sh userlist 
Error, need '-a' or '-d' option to execute this script
  1. 默认添加测试
[root@localhost ~]# ./script_file.sh -a userlist 
user k1 added.
user k2 added.
user k3 added.
[root@localhost ~]# ./script_file.sh -a userlist 
k1 already exist.
k2 already exist.
k3 already exist.
[root@localhost ~]# cat /etc/passwd | grep '^k[1-3]'
k1:x:1011:1012::/home/k1:/bin/bash
k2:x:1012:1013::/home/k2:/bin/bash
k3:x:1013:1014::/home/k3:/bin/bash
  1. 指定密码、shell、选项无序、连写测试
[root@localhost ~]# ./script_file.sh -ah -s /bin/nologin -p 123 userlist
Descreption: this script is use to manage user
	-a		create the user
	-d		delete the user
	-p PASSWORD	set the password of user in stand of defualt [redhat]
	-s SHELL_TYPE 	set the shell of user in stand of defualt [/bin/bash]
	-h		get the help of this script
user k1 added.
user k2 added.
user k3 added.
[root@localhost ~]# cat /etc/passwd | grep '^k[1-3]'
k1:x:1011:1012::/home/k1:/bin/nologin
k2:x:1012:1013::/home/k2:/bin/nologin
k3:x:1013:1014::/home/k3:/bin/nologin
  1. 删除测试
[root@localhost ~]# ./script_file.sh -d userlist 
user k1 deleted.
user k2 deleted.
user k3 deleted.
[root@localhost ~]# ./script_file.sh -d userlist 
user k1 do not exist.
user k2 do not exist.
user k3 do not exist.
[root@localhost ~]# ./script_file.sh -ad userlist 
Error, '-a' and '-d' can not be used together!!!
  1. 文件错误提示
[root@localhost ~]# ./script_file.sh -a userlist1
userlist1 does not exist!!!
发布了67 篇原创文章 · 获赞 2 · 访问量 1383

猜你喜欢

转载自blog.csdn.net/weixin_42511320/article/details/105015875