在最近完成老師佈置的做業的時候遇到了如何讓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腳本中,就能夠進行有條件的判斷了。嘻嘻~