在最近完成老师布置的做业的时候遇到了如何让shell脚本中的命令自动判断一个用户是否已设置密码的问题,虽然看似不是很难的一个问题,可是在这一功能实现的过程当中却包含了许多细小的而重要的知识。刚开始小编对此非常头疼,虽然咱们查看一个用户是否有密码并非很难,直接cat /etc/shadow这个文件看看密码位是否有加密的字符就好了,可是让命令本身去判断和匹配就不是很顺利了,小编上网查看后,并无获得很好的答案,大多数都是人工查看的答案,并不适用于shell脚本中自动的判断,因此在认真对比/etc/passwd 和/etc/shadow 这两个文件以后,又结合本身的想法,实现了这个自动判断的功能,接下来小编将我这一过程实现中遇到的问题和扩展的知识,罗列出来,以便于给像小编同样没有在网上找到合适答案的童鞋们参考,本文纯属我的思考产物,若有更好方法,请赐教。正则表达式
咱们知道用户的密码是存储到/etc/passwd和/etc/shadow这两个文件中的,为何这么说呢?由于当系统开启了用户的投影密码后,才会把密码映射到shadow这个文件中,若是没有开启投影密码,则用户的密码是保存在passwd 这个文件中的,为了提升系统的安全性,通常这个功能是默认开启的,可是咱们能够手动将其关闭:pwconv开启投影密码,pwunconv关闭投影密码。shell
为了接下来的命令实现,小编在这里将passwd文件和shadow文件的关系进行图形化的详细分析,以便小伙伴们能看懂:安全
若是没有开启影子密码功能,则不会存在shadow这个文件,密码就被保存在了passwd文件的密码位上,此时,建立的用户一直都没有设置密码的状况下,该密码位是两个!!符号,若是用户的密码经过passwd -d username 这个命令给清空的话,该密码位上没有任何东西。ide
若是开启了影子密码功能,passwd中密码位的密码将会投射到shadow中,一样,若是用户还没设置过密码,则密码位为两个!!符号,若是用户的密码经过passwd -d username 清空了的话,在shadow的密码位上为空。测试
有图有真相:加密
存在上述的两种状况啊!针对shell脚本而言,编写的脚本要有较高的准确性和可移植性,因此命令的执行必定要有绝对的把握,若是咱们定义查看匹配shadow文件,那若是有的主机上没有开启影子密码功能,那么找不到shadow这个文件,命令的执行结果就不对了,因此为了保证命令的绝对性,小编采用以下思想:spa
无论系统有没有开启影子投射功能,咱们在进行筛选判断以前,先执行pwconv命令开启影子密码功能。这样一来,咱们就彻底的肯定了密码存在于shadow文件中,咱们就能够针对shadow文件进行一些操做。blog
没有密码的状况有两种,一种是密码位为空,一种是密码位一个!或!!,一个!是由于该用户被锁定了。若是用户有密码的状况是密码位为:“$加密方式编号$salt$密码位” 因此咱们能够将密码位的参数提取出来运用正则表达式进行对比,若是不是“$加密方式编号$salt$密码位”形式的参数,就说明该用户没有密码。字符串
开启影子密码的命令为:pwconvget
提取shadow文件中密码位参数的命令为:getent shadow |grep ^username |cut -d: -f2
这里截取的是一个用户的密码位。
将取出的参数进行匹配,判断出是否有密码:[[ "$(pwconv ;getent shadow |grep ^username |cut -d: -f2)" =~ ^'$'.* ]] && echo true || echo false
该命令中使用到了:
$( ):调用括号中的命令执行的结果
` `:条件测试,能够进行条件测试的还有 [ ],可是咱们使用到了扩展正则表达式,而[ ]不支持引用正则表达式,因此咱们使用双引号的条件测试符。
=~:该符号是进行字符串的测试,含义为:左侧字符串是否可以被右侧的PATTERN所匹配。
&&:根据退出状态而定,命令能够有条件地运行,表明条件性的AND THEN ,根据前一条命令的返回值来判断,返回值为真(0),则执行自身后面的命令。
||:表明条件性的OR ELSE,若前一条命令的返回值为假(非0),则执行自身后面的命令。
命令执行的结果为:(两种结果展现)
咱们能够能够将用户名设置为一个变量,经过传递的用户名参数,实现指定用户的查看,将这个方法用户在shell脚本中,就能够进行有条件的判断了。嘻嘻~