用 shell 脚本批量生成强密码

2024-08-08 08:23:46 浏览数 (2)

        Linux 上可以使用一行命令批量生成随机字符串:

代码语言:javascript复制
cat /dev/urandom | LC_ALL=C tr -dc "[:graph:]" | fold -w 16 |head -100

        这个命令组合主要用于生成一个随机的、包含可打印字符(不包括空格)的字符串列表,每个字符串长度为16个字符,总共生成100个这样的字符串。下面是对命令各部分的详细解析:

  1. cat /dev/urandom:
    • cat 命令用于读取文件内容并将其输出到标准输出。
    • /dev/urandom 是一个特殊的设备文件,提供了无限长度的伪随机数据流。与 /dev/random 相比,/dev/urandom 不会因缺少熵(随机性)而阻塞输出,但它可能包含较少的随机性。
  2. | LC_ALL=C tr -dc "[:graph:]" |:
    • 管道符号 | 用于将前一个命令的输出作为后一个命令的输入。
    • LC_ALL=C 设置环境变量 LC_ALL 为 C,这通常用于确保命令的行为在不同的语言环境中保持一致。特别是,它影响字符分类(如哪些字符是“可打印的”)。
    • tr -dc "[:graph:]" 使用 tr(translate 或 delete/complement)命令。-d 选项删除(实际上是忽略)输入中不匹配给定集合的字符,-c 选项是取补集的意思,即删除集合外的所有字符。[:graph:] 是一个字符类,表示所有可打印字符(除了空格)。因此,这个命令的作用是从 /dev/urandom 的输出中筛选出所有可打印字符(不包括空格)。
  3. | fold -w 16 |:
    • 再次使用管道将前一个命令的输出作为输入。
    • fold -w 16 命令用于将输入文本折叠成每行宽度为16个字符的段落。在这个上下文中,它确保每个生成的随机字符串长度为16个字符。
  4. head -100:
    • 最后,head -100 命令从折叠后的输出中取出前100行。由于每行都是一个长度为16的随机字符串,因此最终结果是100个这样的字符串。

        综上所述,这个命令组合的作用是生成一个包含100个随机字符串的列表,每个字符串由16个随机选择的可打印字符(不包括空格)组成。这样的字符串可以用于各种需要随机标识符的场合,如密码生成、测试数据生成等。

但是,如果要求密码中必须包含数字、大小写字母、特殊字符,那么这条命令的结果并不是每次都符合要求。创建内容如下的脚本文件 GenerateStrongPassword.sh:

代码语言:javascript复制
#!/bin/bash
if [ ! -n "$1" ] ;then
    echo "执行方式:GenerateStrongPassword.sh 密码个数"
    exit
fi

is_positive_integer() {
    # 正则表达式判断是否为正整数
    regex='^[0-9] $'
    if [[ $1 =~ $regex ]] && [ "$1" -ge 0 ]; then
        return 0
    else
        return 1
    fi
}
 
# 调用函数检查参数是否为正整数
if !(is_positive_integer "$1") then
    echo "参数必须是正整数"
    exit
fi

num=1 
password=`cat /dev/urandom | LC_ALL=C tr -dc "[:graph:]" | fold -w 16 | head -$1`
regexp_str='^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9]).{16}$'

for i in $password
do
    if grep -oP $regexp_str <<< $i; then
          :
    else
        echo "$i	$((num  ))"
    fi
done

        执行脚本生成 100 个密码,结果如下:

代码语言:javascript复制
[root@vvml-yz-hbase-test~]#./GenerateStrongPassword.sh 100
6t&)KjX&'v/]6OgF
@evZ^G{5,}&e,j.
!X&VG.YYi6eXzuSj
P3q=P2u_%:G$"uY8
LiQ|`1iYF!,;:t%i
v(CiR[,]PNY}z<D5
2D=J0N,]fac_@Zs
H!:k*Kvj WbzqVng	1
*^(Lt `vY0 #jpG,
w03dsuQx4dRK1-F4
dG^|Y[:Mp?L/(fG=	2
gZLm,:>=e&q4nrJe
9a rx&e_TO;)BzW/
Q}yQY%gS-}T9T<<2
$sbs*i1q?tm`EcmE
ua!blnpcER"d7F[_
$K.z/MDf=<~J3V!F
Cs'pYR%|5%aXm4Ja
V)!x0qU.ORtB#vDH
OD5;^Sl@ruqZ9!(U
}P`X9F^13YxR(hL
p@?>acOQ~WY=E!$	3
bt7s[N?{E_!zy.L-
ZPwTb#]0j/VC%N4@
p3j X86d|u>$#aTM
RjYUcJ8%{l4&>ST|
vA|=WgfljDhi?clg	4
COjkZYDww16r9CHS	5
YDhf:B%L [7E|O]]
yj@p$O`M4$G6yvnQ
=_`p!MLXF7]nm>v'
@ao]vsizFQ'D[ q	6
Ck!]IA'>o-$`2ye(
`^(V{iTRNzBB20C
U]<ayX6J'}G(!Lkk
U=yx*rb4oWKa|o&x
zVHZ5TG{2JH>Q1e
m1)&^}A_[@Z_=sA[
fH!(>SX"j#^54w N
,5y@`q# &Bduw$=
w}XS;RA.zvg$X961
Otv8#?mI^Q P<k[p
!~~ 5{~OV1$[=mY6
g|8*X ej1kSTLSrp
T<vt%[P!>}cD(sG=	7
&lWpH~e.s'(A)xjd	8
DlSM>h.vOVNR!uq	9
cUg0~u?WLzFl!}]'
* mnW=XE<eexuxMt	10
324]zMD:0`cKH6_Q
d@)YW}%:et2{qWPr
IKil*my<MLkS6$H7
v0Qh|pSWDQUrhQ9H
M2g9aZCM?;<B68|*
6C?nD?[S(0S-r3o=
oML/&z41b3yTP$`5
bd4]b/{2eS(RTylU
<g24mIW;$uuIdz=/
G|ro,?JKHNBsvJqZ	11
P)lv[V{{<y91odt{
J[H3R)<x^u9]>nL$
W`f6yB|'WAlPpy&P
C>*yDPvN^uwr(Hun	12
Q!~GP|,PY`Cu1h!G
a(HA3.WTiHd|)Sw?
I-nrZn{Kuo<]Jqer	13
K~h5LlM.^/8``o6s
)^TUjQBb P&ehF_T	14
P_3YF%'GcHM"4IG1
YDHSP?pL x[t]w)e	15
}iiF6VL?aLPPipOf
){FOr03.O,2y4sRC
QN>#RF(VEZ9}e$Ki
/C#t^/vXZ0~IiQ.
z7 7:*uivHuh ,%k
.Px~gxZUE|G"7*l
Os<fc.WZ=i*fTZe#	16
�abpNq#WP#v6&
Y%p'y9N:M30Bh;G^
rlu=LeuKZ.9oyuRJ
~L"V33aBXF@76Gp6
=pKJ:tvg'|teoUJ9
>RL.))?Rax@lTq#	17
lE ^s;NiS(z3|wIe
U,ss]R7`dJ<}w$YG
Mq'nMF6 Rn~UN:A.
7=AAZ6To=,=cQdD#
BhF}Adl/9qlNk=,a
*HvGQ$[Se]-)o(Sy	18
O9-4quTrWt@f)bSI
-Iz(W">_s xjy<mY	19
,EU0YBHWE]^5xoG}
">W<jy,Z,Ia_F9d
EnK{CPA]8|ETY'0
k!WbYe~18qwr"s%M
PCb'/y3Q?W>jSk@
Mx%D?2XcF5C$wGCx
Kl ~htGD&5Rp!O.s
qy5ZV("I7>*K2.Ux
qD<&h()(%N[X1Z%
[root@vvml-yz-hbase-test~]#

        脚本中使用正则表达式对生成的密码进行判断。

  • 正则表达式说明:
    • ^ 代表开始。
    • (?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9]) 用四个肯定顺序环视零宽断言对字符进行判定。
    • (?=.*[a-z]) 判断小写字母是否存在。
    • (?=.*[A-Z]) 判断大写字母是否存在。
    • (?=.*[0-9]) 判断数字是否存在。
    • (?=.*[^a-zA-Z0-9]) 判断特殊字符是否存在。
    • .{16} 代表任意 16 个字符。
    • $ 代表结尾。

        可以看到,有 19 个密码不满足要求,其中 18 个不包含数字,一个不包含特殊字符(第5个)。经过多次测试,约有 10% - 20% 会出现这种情况。下面修改脚本,批量生成强密码,具体需求如下:

  • 批量生成 100 个密码。
  • 密码长度统一为 16 个字符。
  • 密码中包含数字、大小写字母、特殊字符。

        主要做的修改是:当判断生成的密码不符合要求时重新生成一个,继续判断,直到满足要求为止。修改后的脚本内容如下:

代码语言:javascript复制
#!/bin/bash
if [ ! -n "$1" ] ;then
    echo "执行方式:GenerateStrongPassword.sh 密码个数"
    exit
fi

is_positive_integer() {
    # 正则表达式判断是否为正整数
    regex='^[0-9] $'
    if [[ $1 =~ $regex ]] && [ "$1" -ge 0 ]; then
        return 0
    else
        return 1
    fi
}
 
# 调用函数检查参数是否为正整数
if !(is_positive_integer "$1") then
    echo "参数必须是正整数"
    exit
fi

num=1 
password=`cat /dev/urandom | LC_ALL=C tr -dc "[:graph:]" | fold -w 16 | head -$1`
regexp_str='^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[^a-zA-Z0-9]).{16}$'

for i in $password
do
    if grep -oP $regexp_str <<< $i > /dev/null ; then
        echo "$i	强密码"
    else
        a=`cat /dev/urandom | LC_ALL=C tr -dc "[:graph:]" | fold -w 16 | head -1`
        until echo "$a" | grep -oP $regexp_str > /dev/null
        do
            a=`cat /dev/urandom | LC_ALL=C tr -dc "[:graph:]" | fold -w 16 | head -1`
        done
        echo "$a	重新生成的强密码    $((num  ))"
    fi
done

        执行脚本结果如下:

代码语言:javascript复制
[root@vvml-yz-hbase-test~]#./GenerateStrongPassword.sh 100
)qW.(|`mzr'/1wk*	强密码
h7lT$4BDnYV=_/q	强密码
K5GiC8fZl.,QLfus	强密码
rQ7B6%ldF}aoS {Q	重新生成的强密码    1
-t6{IFi6/6YmXzV%	重新生成的强密码    2
iOt?ywH/y5}**/3E	强密码
|<t*VF(0zh~H;jr1	强密码
f0]1)2]>^|t<Z1;:	强密码
W[Z?)7$Ip=|O2GH=	强密码
)cs,6Em3L,R]Mu7?	强密码
Wb1_Vw`^3${EmUQ"	强密码
:g4)/%/,"N0=WEn*	强密码
 0^6Z*,{gX[NF'"'	强密码
]aY/F/"5biKU'=S:	强密码
$Kb.=yJvgcb/a2,-	强密码
2WtnW1Drfp**.iMT	强密码
@60Y'Z]4ZVFPVKDf	强密码
/{S--By-D{`h5p~	强密码
Jg<>5pyww:eg}Z"&	重新生成的强密码    3
cLV]/}T8g#|PuyE^	强密码
,<Nf:1eU>i$Swug#	强密码
&XVMc^|el86XB8:M	强密码
d=X?[W( M)e0lQ&6	强密码
Z,{:@32uPe,]8S:*	重新生成的强密码    4
m/A]qIG{/9[gHm	强密码
kv~}t8-Y4s 0u[CA	强密码
c1z#V_buM6{/.8r5	强密码
(u)3?S"V'Ng8MW#v	强密码
9}:g3?(Y0=ivOAV0	强密码
rbGS_]7Lb-P|P]e]	重新生成的强密码    5
.&$d&#@:EnNPb*|8	强密码
gQfUazBph|xHJ0%&	强密码
ek`*Oz'HNS_8ro}!	强密码
V{@%}6]0eXU=*s	强密码
<6[lc:&j ")D('xJ	强密码
a4)Py>L.`4b(xX/Q	强密码
x^C4eaYDa^o-^~n-	强密码
4zG }!eDsq%nrvo%	强密码
{wS?ItnVQ7YI|]H"	强密码
="HqM|6c(im4/H-	强密码
v6p O^NVem~Q~^5l	重新生成的强密码    6
2^Q.i3$brBFcR79x	强密码
INQpz`t ;EiR7..	强密码
Q^4^x$ll(h!*!OjH	强密码
bUPN%Jx1m<dMnGN)	强密码
I0dEQi_jFS /]|8"	强密码
B5!^i>0X2zI$kWg4	强密码
dRqpS[ow6>W@e.F)	强密码
")~#1#hr<:hp.W>c	强密码
jDFQ{D)$hDxr3W-9	强密码
ed]@SPda`Q0J@Ynx	重新生成的强密码    7
p/GONw@PD7$O]Z^-	重新生成的强密码    8
sUbyi<U)dq|?t~?4	强密码
CqU!8#I86i6gT yO	强密码
@~p=h5UkbKDv^:s8	强密码
(Q3UeMpVXD!PR2,s	重新生成的强密码    9
7|R,gHV3A?xAtl0_	强密码
D.w7hL*6_^|C~;$	强密码
31KT%|?tWCLB/$l	强密码
l[X(t4hzS![Kk9yM	强密码
~~Q-mrw#;mTeU0e	强密码
{NAb=M"b#3_-]xbL	强密码
] 'd*$}?f7tyE"Y5	强密码
.50 9_iC``@P&H3	强密码
yiwK*!5m0;!ii#R[	强密码
ht@_<mYRSb7;Cb3u	强密码
GMos-d/9fVdl{sUS	强密码
9o<tr^jhgd|J9FER	强密码
,~V&A-er|7L8)bcY	强密码
_b(l5Bnv^c|8RC'*	强密码
x4.-&Y,^T(<)1P!D	强密码
Q#zC4/Tc')E`@Yb	强密码
V<qf*Xbrhl&Hw1TV	强密码
p55p=N3S!,oae5A	重新生成的强密码    10
~%z*T~K&mg1$OmEG	强密码
Ye~BY?2T?BFH5j%	强密码
!:-Q%-']T/$8Fax0	强密码
YDSdM1LHy4.&//K_	强密码
4V.Fl?>w46G;oCs	强密码
(E/eMOZB 9wCy[t	强密码
U8myJslO.;:4vVvg	强密码
*8bdJ19pUh&8=C=I	强密码
>[18S|~gOdSx4M	强密码
$yOX6vW;[xONUtgL	强密码
WMrO/I@15t1TPc~D	强密码
,|z.uoN(l #b29w	强密码
Rt8;JCv_T6G,;[$9	强密码
=[!`OBMW*$71Lvo	强密码
~,C_K$'-R6%v"%S(	强密码
ku4u>2P0Dj"XAjEo	强密码
6`/rR3O`'0jgv^eF	重新生成的强密码    11
~l`O72Pa/k=}sXck	强密码
3Jd4)`Q9X3:.$yl[	强密码
?}!jt%*1lKjVL9}v	重新生成的强密码    12
^c5QF;Z4`C#,4hxV	重新生成的强密码    13
4)(x~"F4?"NMNGma	强密码
3qrje;f2D.*wii2P	强密码
k`_)tAI_/,#9(%J1	强密码
b](6)1z.G=RYfvu	重新生成的强密码    14
}5M%n}a;Dq'|R ]#	强密码
[root@vvml-yz-hbase-test~]#

        可以看到,所有 100 个密码都为强密码,完全满足需求。因为不满足需求的情况不到 20%,所以不用担心循环陷入无休止的迭代中。当然必须指出,这版实现使用的是“判错重来”方式,会有不到 20% 的密码生成是做了无用功。

0 人点赞