Linux 上可以使用一行命令批量生成随机字符串:
代码语言:javascript复制cat /dev/urandom | LC_ALL=C tr -dc "[:graph:]" | fold -w 16 |head -100
这个命令组合主要用于生成一个随机的、包含可打印字符(不包括空格)的字符串列表,每个字符串长度为16个字符,总共生成100个这样的字符串。下面是对命令各部分的详细解析:
- cat /dev/urandom:
- cat 命令用于读取文件内容并将其输出到标准输出。
- /dev/urandom 是一个特殊的设备文件,提供了无限长度的伪随机数据流。与 /dev/random 相比,/dev/urandom 不会因缺少熵(随机性)而阻塞输出,但它可能包含较少的随机性。
- | LC_ALL=C tr -dc "[:graph:]" |:
- 管道符号 | 用于将前一个命令的输出作为后一个命令的输入。
- LC_ALL=C 设置环境变量 LC_ALL 为 C,这通常用于确保命令的行为在不同的语言环境中保持一致。特别是,它影响字符分类(如哪些字符是“可打印的”)。
- tr -dc "[:graph:]" 使用 tr(translate 或 delete/complement)命令。-d 选项删除(实际上是忽略)输入中不匹配给定集合的字符,-c 选项是取补集的意思,即删除集合外的所有字符。[:graph:] 是一个字符类,表示所有可打印字符(除了空格)。因此,这个命令的作用是从 /dev/urandom 的输出中筛选出所有可打印字符(不包括空格)。
- | fold -w 16 |:
- 再次使用管道将前一个命令的输出作为输入。
- fold -w 16 命令用于将输入文本折叠成每行宽度为16个字符的段落。在这个上下文中,它确保每个生成的随机字符串长度为16个字符。
- 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% 的密码生成是做了无用功。