PNG  IHDRQgAMA a cHRMz&u0`:pQ<bKGDgmIDATxwUﹻ& ^CX(J I@ "% (** BX +*i"]j(IH{~R)[~>h{}gy)I$Ij .I$I$ʊy@}x.: $I$Ii}VZPC)I$IF ^0ʐJ$I$Q^}{"r=OzI$gRZeC.IOvH eKX $IMpxsk.쒷/&r[޳<v| .I~)@$updYRa$I |M.e JaֶpSYR6j>h%IRز if&uJ)M$I vLi=H;7UJ,],X$I1AҒJ$ XY XzI@GNҥRT)E@;]K*Mw;#5_wOn~\ DC&$(A5 RRFkvIR}l!RytRl;~^ǷJj اy뷦BZJr&ӥ8Pjw~vnv X^(I;4R=P[3]J,]ȏ~:3?[ a&e)`e*P[4]T=Cq6R[ ~ޤrXR Հg(t_HZ-Hg M$ãmL5R uk*`%C-E6/%[t X.{8P9Z.vkXŐKjgKZHg(aK9ڦmKjѺm_ \#$5,)-  61eJ,5m| r'= &ڡd%-]J on Xm|{ RҞe $eڧY XYrԮ-a7RK6h>n$5AVڴi*ֆK)mѦtmr1p| q:흺,)Oi*ֺK)ܬ֦K-5r3>0ԔHjJئEZj,%re~/z%jVMڸmrt)3]J,T K֦OvԒgii*bKiNO~%PW0=dii2tJ9Jݕ{7"I P9JKTbu,%r"6RKU}Ij2HKZXJ,妝 XYrP ެ24c%i^IK|.H,%rb:XRl1X4Pe/`x&P8Pj28Mzsx2r\zRPz4J}yP[g=L) .Q[6RjWgp FIH*-`IMRaK9TXcq*I y[jE>cw%gLRԕiFCj-ďa`#e~I j,%r,)?[gp FI˨mnWX#>mʔ XA DZf9,nKҲzIZXJ,L#kiPz4JZF,I,`61%2s $,VOϚ2/UFJfy7K> X+6 STXIeJILzMfKm LRaK9%|4p9LwJI!`NsiazĔ)%- XMq>pk$-$Q2x#N ؎-QR}ᶦHZډ)J,l#i@yn3LN`;nڔ XuX5pF)m|^0(>BHF9(cզEerJI rg7 4I@z0\JIi䵙RR0s;$s6eJ,`n 䂦0a)S)A 1eJ,堌#635RIgpNHuTH_SԕqVe ` &S)>p;S$魁eKIuX`I4춒o}`m$1":PI<[v9^\pTJjriRŭ P{#{R2,`)e-`mgj~1ϣLKam7&U\j/3mJ,`F;M'䱀 .KR#)yhTq;pcK9(q!w?uRR,n.yw*UXj#\]ɱ(qv2=RqfB#iJmmL<]Y͙#$5 uTU7ӦXR+q,`I}qL'`6Kͷ6r,]0S$- [RKR3oiRE|nӦXR.(i:LDLTJjY%o:)6rxzҒqTJjh㞦I.$YR.ʼnGZ\ֿf:%55 I˼!6dKxm4E"mG_ s? .e*?LRfK9%q#uh$)i3ULRfK9yxm܌bj84$i1U^@Wbm4uJ,ҪA>_Ij?1v32[gLRD96oTaR׿N7%L2 NT,`)7&ƝL*꽙yp_$M2#AS,`)7$rkTA29_Iye"|/0t)$n XT2`YJ;6Jx".e<`$) PI$5V4]29SRI>~=@j]lp2`K9Jaai^" Ԋ29ORI%:XV5]JmN9]H;1UC39NI%Xe78t)a;Oi Ҙ>Xt"~G>_mn:%|~ޅ_+]$o)@ǀ{hgN;IK6G&rp)T2i୦KJuv*T=TOSV>(~D>dm,I*Ɛ:R#ۙNI%D>G.n$o;+#RR!.eU˽TRI28t)1LWϚ>IJa3oFbu&:tJ*(F7y0ZR ^p'Ii L24x| XRI%ۄ>S1]Jy[zL$adB7.eh4%%누>WETf+3IR:I3Xה)3אOۦSRO'ٺ)S}"qOr[B7ϙ.edG)^ETR"RtRݜh0}LFVӦDB^k_JDj\=LS(Iv─aTeZ%eUAM-0;~˃@i|l @S4y72>sX-vA}ϛBI!ݎߨWl*)3{'Y|iSlEڻ(5KtSI$Uv02,~ԩ~x;P4ցCrO%tyn425:KMlD ^4JRxSهF_}شJTS6uj+ﷸk$eZO%G*^V2u3EMj3k%)okI]dT)URKDS 7~m@TJR~荪fT"֛L \sM -0T KfJz+nإKr L&j()[E&I ߴ>e FW_kJR|!O:5/2跌3T-'|zX ryp0JS ~^F>-2< `*%ZFP)bSn"L :)+pʷf(pO3TMW$~>@~ū:TAIsV1}S2<%ޟM?@iT ,Eūoz%i~g|`wS(]oȤ8)$ ntu`өe`6yPl IzMI{ʣzʨ )IZ2= ld:5+請M$-ї;U>_gsY$ÁN5WzWfIZ)-yuXIfp~S*IZdt;t>KūKR|$#LcԀ+2\;kJ`]YǔM1B)UbG"IRߊ<xܾӔJ0Z='Y嵤 Leveg)$znV-º^3Ւof#0Tfk^Zs[*I꯳3{)ˬW4Ւ4 OdpbZRS|*I 55#"&-IvT&/윚Ye:i$ 9{LkuRe[I~_\ؠ%>GL$iY8 9ܕ"S`kS.IlC;Ҏ4x&>u_0JLr<J2(^$5L s=MgV ~,Iju> 7r2)^=G$1:3G< `J3~&IR% 6Tx/rIj3O< ʔ&#f_yXJiގNSz; Tx(i8%#4 ~AS+IjerIUrIj362v885+IjAhK__5X%nV%Iͳ-y|7XV2v4fzo_68"S/I-qbf; LkF)KSM$ Ms>K WNV}^`-큧32ŒVؙGdu,^^m%6~Nn&͓3ŒVZMsRpfEW%IwdǀLm[7W&bIRL@Q|)* i ImsIMmKmyV`i$G+R 0tV'!V)֏28vU7͒vHꦼtxꗞT ;S}7Mf+fIRHNZUkUx5SAJㄌ9MqμAIRi|j5)o*^'<$TwI1hEU^c_j?Е$%d`z cyf,XO IJnTgA UXRD }{H}^S,P5V2\Xx`pZ|Yk:$e ~ @nWL.j+ϝYb퇪bZ BVu)u/IJ_ 1[p.p60bC >|X91P:N\!5qUB}5a5ja `ubcVxYt1N0Zzl4]7­gKj]?4ϻ *[bg$)+À*x쳀ogO$~,5 زUS9 lq3+5mgw@np1sso Ӻ=|N6 /g(Wv7U;zωM=wk,0uTg_`_P`uz?2yI!b`kĸSo+Qx%!\οe|އԁKS-s6pu_(ֿ$i++T8=eY; צP+phxWQv*|p1. ά. XRkIQYP,drZ | B%wP|S5`~́@i޾ E;Չaw{o'Q?%iL{u D?N1BD!owPHReFZ* k_-~{E9b-~P`fE{AܶBJAFO wx6Rox5 K5=WwehS8 (JClJ~ p+Fi;ŗo+:bD#g(C"wA^ r.F8L;dzdIHUX݆ϞXg )IFqem%I4dj&ppT{'{HOx( Rk6^C٫O.)3:s(۳(Z?~ٻ89zmT"PLtw䥈5&b<8GZ-Y&K?e8,`I6e(֍xb83 `rzXj)F=l($Ij 2*(F?h(/9ik:I`m#p3MgLaKjc/U#n5S# m(^)=y=đx8ŬI[U]~SцA4p$-F i(R,7Cx;X=cI>{Km\ o(Tv2vx2qiiDJN,Ҏ!1f 5quBj1!8 rDFd(!WQl,gSkL1Bxg''՞^ǘ;pQ P(c_ IRujg(Wz bs#P­rz> k c&nB=q+ؔXn#r5)co*Ũ+G?7< |PQӣ'G`uOd>%Mctz# Ԫڞ&7CaQ~N'-P.W`Oedp03C!IZcIAMPUۀ5J<\u~+{9(FbbyAeBhOSܳ1 bÈT#ŠyDžs,`5}DC-`̞%r&ڙa87QWWp6e7 Rϫ/oY ꇅ Nܶըtc!LA T7V4Jsū I-0Pxz7QNF_iZgúWkG83 0eWr9 X]㾮݁#Jˢ C}0=3ݱtBi]_ &{{[/o[~ \q鯜00٩|cD3=4B_b RYb$óBRsf&lLX#M*C_L܄:gx)WΘsGSbuL rF$9';\4Ɍq'n[%p.Q`u hNb`eCQyQ|l_C>Lb꟟3hSb #xNxSs^ 88|Mz)}:](vbۢamŖ࿥ 0)Q7@0=?^k(*J}3ibkFn HjB׻NO z x}7p 0tfDX.lwgȔhԾŲ }6g E |LkLZteu+=q\Iv0쮑)QٵpH8/2?Σo>Jvppho~f>%bMM}\//":PTc(v9v!gոQ )UfVG+! 35{=x\2+ki,y$~A1iC6#)vC5^>+gǵ@1Hy٪7u;p psϰu/S <aʸGu'tD1ԝI<pg|6j'p:tպhX{o(7v],*}6a_ wXRk,O]Lܳ~Vo45rp"N5k;m{rZbΦ${#)`(Ŵg,;j%6j.pyYT?}-kBDc3qA`NWQū20/^AZW%NQ MI.X#P#,^Ebc&?XR tAV|Y.1!؅⨉ccww>ivl(JT~ u`ٵDm q)+Ri x/x8cyFO!/*!/&,7<.N,YDŽ&ܑQF1Bz)FPʛ?5d 6`kQձ λc؎%582Y&nD_$Je4>a?! ͨ|ȎWZSsv8 j(I&yj Jb5m?HWp=g}G3#|I,5v珿] H~R3@B[☉9Ox~oMy=J;xUVoj bUsl_35t-(ՃɼRB7U!qc+x4H_Qo֮$[GO<4`&č\GOc[.[*Af%mG/ ňM/r W/Nw~B1U3J?P&Y )`ѓZ1p]^l“W#)lWZilUQu`-m|xĐ,_ƪ|9i:_{*(3Gѧ}UoD+>m_?VPۅ15&}2|/pIOʵ> GZ9cmíتmnz)yߐbD >e}:) r|@R5qVSA10C%E_'^8cR7O;6[eKePGϦX7jb}OTGO^jn*媓7nGMC t,k31Rb (vyܴʭ!iTh8~ZYZp(qsRL ?b}cŨʊGO^!rPJO15MJ[c&~Z`"ѓޔH1C&^|Ш|rʼ,AwĴ?b5)tLU)F| &g٣O]oqSUjy(x<Ϳ3 .FSkoYg2 \_#wj{u'rQ>o;%n|F*O_L"e9umDds?.fuuQbIWz |4\0 sb;OvxOSs; G%T4gFRurj(֍ڑb uԖKDu1MK{1^ q; C=6\8FR艇!%\YÔU| 88m)֓NcLve C6z;o&X x59:q61Z(T7>C?gcļxѐ Z oo-08jہ x,`' ҔOcRlf~`jj".Nv+sM_]Zk g( UOPyεx%pUh2(@il0ݽQXxppx-NS( WO+轾 nFߢ3M<;z)FBZjciu/QoF 7R¥ ZFLF~#ȣߨ^<쩡ݛкvџ))ME>ώx4m#!-m!L;vv#~Y[đKmx9.[,UFS CVkZ +ߟrY٧IZd/ioi$%͝ب_ֶX3ܫhNU ZZgk=]=bbJS[wjU()*I =ώ:}-蹞lUj:1}MWm=̛ _ ¾,8{__m{_PVK^n3esw5ӫh#$-q=A̟> ,^I}P^J$qY~Q[ Xq9{#&T.^GVj__RKpn,b=`żY@^՝;z{paVKkQXj/)y TIc&F;FBG7wg ZZDG!x r_tƢ!}i/V=M/#nB8 XxЫ ^@CR<{䤭YCN)eKOSƟa $&g[i3.C6xrOc8TI;o hH6P&L{@q6[ Gzp^71j(l`J}]e6X☉#͕ ׈$AB1Vjh㭦IRsqFBjwQ_7Xk>y"N=MB0 ,C #o6MRc0|$)ف"1!ixY<B9mx `,tA>)5ػQ?jQ?cn>YZe Tisvh# GMމȇp:ԴVuږ8ɼH]C.5C!UV;F`mbBk LTMvPʍϤj?ԯ/Qr1NB`9s"s TYsz &9S%U԰> {<ؿSMxB|H\3@!U| k']$U+> |HHMLޢ?V9iD!-@x TIî%6Z*9X@HMW#?nN ,oe6?tQwڱ.]-y':mW0#!J82qFjH -`ѓ&M0u Uγmxϵ^-_\])@0Rt.8/?ٰCY]x}=sD3ojަЫNuS%U}ԤwHH>ڗjܷ_3gN q7[q2la*ArǓԖ+p8/RGM ]jacd(JhWko6ڎbj]i5Bj3+3!\j1UZLsLTv8HHmup<>gKMJj0@H%,W΃7R) ">c, xixј^ aܖ>H[i.UIHc U1=yW\=S*GR~)AF=`&2h`DzT󑓶J+?W+}C%P:|0H܆}-<;OC[~o.$~i}~HQ TvXΈr=b}$vizL4:ȰT|4~*!oXQR6Lk+#t/g lԁߖ[Jڶ_N$k*". xsxX7jRVbAAʯKҎU3)zSNN _'s?f)6X!%ssAkʱ>qƷb hg %n ~p1REGMHH=BJiy[<5 ǁJҖgKR*倳e~HUy)Ag,K)`Vw6bRR:qL#\rclK/$sh*$ 6덤 KԖc 3Z9=Ɣ=o>X Ώ"1 )a`SJJ6k(<c e{%kϊP+SL'TcMJWRm ŏ"w)qc ef꒵i?b7b('"2r%~HUS1\<(`1Wx9=8HY9m:X18bgD1u ~|H;K-Uep,, C1 RV.MR5άh,tWO8WC$ XRVsQS]3GJ|12 [vM :k#~tH30Rf-HYݺ-`I9%lIDTm\ S{]9gOڒMNCV\G*2JRŨ;Rҏ^ڽ̱mq1Eu?To3I)y^#jJw^Ńj^vvlB_⋌P4x>0$c>K†Aļ9s_VjTt0l#m>E-,,x,-W)سo&96RE XR.6bXw+)GAEvL)͞K4$p=Ũi_ѱOjb HY/+@θH9޼]Nԥ%n{ &zjT? Ty) s^ULlb,PiTf^<À] 62R^V7)S!nllS6~͝V}-=%* ʻ>G DnK<y&>LPy7'r=Hj 9V`[c"*^8HpcO8bnU`4JȪAƋ#1_\ XϘHPRgik(~G~0DAA_2p|J묭a2\NCr]M_0 ^T%e#vD^%xy-n}-E\3aS%yN!r_{ )sAw ڼp1pEAk~v<:`'ӭ^5 ArXOI驻T (dk)_\ PuA*BY]yB"l\ey hH*tbK)3 IKZ򹞋XjN n *n>k]X_d!ryBH ]*R 0(#'7 %es9??ښFC,ՁQPjARJ\Ρw K#jahgw;2$l*) %Xq5!U᢯6Re] |0[__64ch&_}iL8KEgҎ7 M/\`|.p,~`a=BR?xܐrQ8K XR2M8f ?`sgWS%" Ԉ 7R%$ N}?QL1|-эټwIZ%pvL3Hk>,ImgW7{E xPHx73RA @RS CC !\ȟ5IXR^ZxHл$Q[ŝ40 (>+ _C >BRt<,TrT {O/H+˟Pl6 I B)/VC<6a2~(XwV4gnXR ϱ5ǀHٻ?tw똤Eyxp{#WK qG%5],(0ӈH HZ])ג=K1j&G(FbM@)%I` XRg ʔ KZG(vP,<`[ Kn^ SJRsAʠ5xՅF`0&RbV tx:EaUE/{fi2;.IAwW8/tTxAGOoN?G}l L(n`Zv?pB8K_gI+ܗ #i?ޙ.) p$utc ~DžfՈEo3l/)I-U?aԅ^jxArA ΧX}DmZ@QLےbTXGd.^|xKHR{|ΕW_h] IJ`[G9{).y) 0X YA1]qp?p_k+J*Y@HI>^?gt.06Rn ,` ?);p pSF9ZXLBJPWjgQ|&)7! HjQt<| ؅W5 x W HIzYoVMGP Hjn`+\(dNW)F+IrS[|/a`K|ͻ0Hj{R,Q=\ (F}\WR)AgSG`IsnAR=|8$}G(vC$)s FBJ?]_u XRvύ6z ŨG[36-T9HzpW̞ú Xg큽=7CufzI$)ki^qk-) 0H*N` QZkk]/tnnsI^Gu't=7$ Z;{8^jB% IItRQS7[ϭ3 $_OQJ`7!]W"W,)Iy W AJA;KWG`IY{8k$I$^%9.^(`N|LJ%@$I}ֽp=FB*xN=gI?Q{٥4B)mw $Igc~dZ@G9K X?7)aK%݅K$IZ-`IpC U6$I\0>!9k} Xa IIS0H$I H ?1R.Чj:4~Rw@p$IrA*u}WjWFPJ$I➓/6#! LӾ+ X36x8J |+L;v$Io4301R20M I$-E}@,pS^ޟR[/s¹'0H$IKyfŸfVOπFT*a$I>He~VY/3R/)>d$I>28`Cjw,n@FU*9ttf$I~<;=/4RD~@ X-ѕzἱI$: ԍR a@b X{+Qxuq$IЛzo /~3\8ڒ4BN7$IҀj V]n18H$IYFBj3̵̚ja pp $Is/3R Ӻ-Yj+L;.0ŔI$Av? #!5"aʄj}UKmɽH$IjCYs?h$IDl843.v}m7UiI=&=0Lg0$I4: embe` eQbm0u? $IT!Sƍ'-sv)s#C0:XB2a w I$zbww{."pPzO =Ɔ\[ o($Iaw]`E).Kvi:L*#gР7[$IyGPI=@R 4yR~̮´cg I$I/<tPͽ hDgo 94Z^k盇΄8I56^W$I^0̜N?4*H`237}g+hxoq)SJ@p|` $I%>-hO0eO>\ԣNߌZD6R=K ~n($I$y3D>o4b#px2$yڪtzW~a $I~?x'BwwpH$IZݑnC㧄Pc_9sO gwJ=l1:mKB>Ab<4Lp$Ib o1ZQ@85b̍ S'F,Fe,^I$IjEdù{l4 8Ys_s Z8.x m"+{~?q,Z D!I$ϻ'|XhB)=…']M>5 rgotԎ 獽PH$IjIPhh)n#cÔqA'ug5qwU&rF|1E%I$%]!'3AFD/;Ck_`9 v!ٴtPV;x`'*bQa w I$Ix5 FC3D_~A_#O݆DvV?<qw+I$I{=Z8".#RIYyjǪ=fDl9%M,a8$I$Ywi[7ݍFe$s1ՋBVA?`]#!oz4zjLJo8$I$%@3jAa4(o ;p,,dya=F9ً[LSPH$IJYЉ+3> 5"39aZ<ñh!{TpBGkj}Sp $IlvF.F$I z< '\K*qq.f<2Y!S"-\I$IYwčjF$ w9 \ߪB.1v!Ʊ?+r:^!I$BϹB H"B;L'G[ 4U#5>੐)|#o0aڱ$I>}k&1`U#V?YsV x>{t1[I~D&(I$I/{H0fw"q"y%4 IXyE~M3 8XψL}qE$I[> nD?~sf ]o΁ cT6"?'_Ἣ $I>~.f|'!N?⟩0G KkXZE]ޡ;/&?k OۘH$IRۀwXӨ<7@PnS04aӶp.:@\IWQJ6sS%I$e5ڑv`3:x';wq_vpgHyXZ 3gЂ7{{EuԹn±}$I$8t;b|591nءQ"P6O5i }iR̈́%Q̄p!I䮢]O{H$IRϻ9s֧ a=`- aB\X0"+5"C1Hb?߮3x3&gşggl_hZ^,`5?ߎvĸ%̀M!OZC2#0x LJ0 Gw$I$I}<{Eb+y;iI,`ܚF:5ܛA8-O-|8K7s|#Z8a&><a&/VtbtLʌI$I$I$I$I$I$IRjDD%tEXtdate:create2022-05-31T04:40:26+00:00!Î%tEXtdate:modify2022-05-31T04:40:26+00:00|{2IENDB`Mini Shell

HOME


Mini Shell 1.0
DIR:/proc/self/root/opt/cloudlinux/venv/lib/python3.11/site-packages/clwpos/
Upload File :
Current File : //proc/self/root/opt/cloudlinux/venv/lib/python3.11/site-packages/clwpos/daemon_redis_lib.py
# coding=utf-8
#
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENCE.TXT
#

# Redis manipulation library for Cloudlinux AccelerateWP daemon

# pylint: disable=no-absolute-import
import json
import logging
import pwd
import os
import subprocess
import signal
import psutil
import time
from logging import Logger
from typing import List, Optional, Tuple

from clcommon.clpwd import drop_privileges
from clcommon.utils import (
    run_command,
    ExternalProgramFailed,
    is_user_present,
    demote
)
from clcommon.cpapi import cpusers
from clcommon.const import Feature
from clcommon.cpapi import is_panel_feature_supported, get_main_username_by_uid
from clcommon.clpwd import ClPwd
from clwpos.constants import REDIS_SERVER_BIN_FILE

from clwpos.cl_wpos_exceptions import WposError
from clwpos.utils import (
    USER_WPOS_DIR,
    is_run_under_user,
    drop_permissions_if_needed,
    run_in_cagefs_if_needed
)
from clcommon.cpapi.cpapiexceptions import NoPackage
from clwpos import gettext as _


logger = logging.getLogger(__name__)

_REDIS_CLI_BIN_FILE = '/opt/alt/redis/bin/redis-cli'


def _get_pids_for_file(file_path: str) -> List[int]:
    """
    Retrieves list of PID list processes, which uses file (using fuser utility)
    This can find any process (for example php), not only redis service process
    :param file_path: Filename to check
    :return: PID list
    """
    # in most cases this is correct path
    fuser_binary = '/usr/bin/fuser'
    # fallback to prev approach
    if not os.path.exists(fuser_binary):
        fuser_binary = '/sbin/fuser'

    try:
        # # /usr/sbin/fuser /home/cltest1/.clwpos/redis.sock
        # /home/cltest1/.clwpos/redis.sock: 55882 [105766 251507]
        std_out = run_command([fuser_binary, file_path], return_full_output=False)
        lines_list = std_out.split('\n')
        # Get PID list from output
        s_pid_list = lines_list[0].split(':')[1].strip()
        pid_list = []
        for s_pid in s_pid_list.split(' '):
            try:
                pid_list.append(int(s_pid.strip()))
            except ValueError:
                pass
        return pid_list
    except (ExternalProgramFailed, IndexError):
        pass
    return []


def _get_user_pids(username: str) -> List[int]:
    """
    Update PID list in cache for user using /bin/ps utility
    :param: username: Username to scan
    :return: None
    """
    # /bin/ps -o"pid" -u cltest1
    # PID
    # 1608661
    # 1638657
    # ......
    # Get user's PID list
    try:
        std_out = run_command(['/bin/ps', '-o', 'pid', '-u', username], return_full_output=False)
    except ExternalProgramFailed:
        return []
    lines_list = std_out.split('\n')
    if len(lines_list) < 2:
        return []
    # Remove header line
    user_pid_list = []
    lines_list = lines_list[1:]
    for line in lines_list:
        line = line.strip()
        if line:
            try:
                user_pid_list.append(int(line.strip()))
            except ValueError:
                pass
    return user_pid_list


def _get_user_redis_pids(username: str, home_dir: str) -> List[int]:
    """
    Get redis PID list for user
    :param username: user name
    :param home_dir: User's  homedir
    :return: PID list or [] if user has no redis
    """
    redis_socket_file = os.path.join(home_dir, USER_WPOS_DIR, 'redis.sock')
    pid_list_sock = _get_pids_for_file(redis_socket_file)
    user_pids = _get_user_pids(username)
    pid_list = []
    for pid in pid_list_sock:
        if pid in user_pids:
            pid_list.append(pid)
    return pid_list


def kill_process_by_pid(_logger: Logger, pid: int):
    """
    Kill process by pid
    :param _logger: Logger to log errors
    :param pid: Process pid to kill
    """
    if not is_run_under_user():
        raise WposError("Internal error! Trying to kill process with root privileges")

    try:
        os.kill(pid, signal.SIGTERM)  # 15
        time.sleep(5)
        try:
            os.kill(pid, signal.SIGKILL)  # 9
        except OSError:
            pass
    except OSError as e:
        _logger.warning("Can't kill redis process, pid %s; error: %s", pid, str(e))

    _logger.info('Killed process with pid=%s', str(pid))


def _kill_all_redises_for_user(logger: Logger, username: str):
    """
    Kill all user's redice processes
    :param logger: Logger to log errors
    :param username: User name
    """
    if not is_user_present(username):
        return
    user_pwd = pwd.getpwnam(username)
    redis_pid_list = _get_user_redis_pids(user_pwd.pw_name, user_pwd.pw_dir)
    logger.info('Killing redis with pid=%s for user=%s', str(redis_pid_list), username)

    with drop_privileges(username):
        for redis_pid in redis_pid_list:
            kill_process_by_pid(logger, redis_pid)



def kill_all_users_redises(logger: Logger):
    """
    Find and kill lost redices for all panel users
    :param logger: Daemon's logger
    """
    try:
        users = cpusers()
    except (OSError, IOError, IndexError, NoPackage) as e:
        logger.warning("Can't get user list from panel: %s", str(e))
        return
    for username in users:
        _kill_all_redises_for_user(logger, username)

def redis_socket_health_check(uid: int) -> bool:
    """
    /opt/alt/redis/bin/redis-cli -s /home/cltest1/.clwpos/redis.sock ping
    Could not connect to Redis at /home/cltest1/.clwpos/redis.sock: No such file or directory
    echo $?
    1
    /opt/alt/redis/bin/redis-cli -s /home/cltest1/.clwpos/redis.sock ping
    PONG
    echo $?
    0
    """
    try:
        username = get_main_username_by_uid(uid)
        user_pwd = pwd.getpwnam(username)
    except KeyError:
        logger.warning("Redis check error for user %s. No user with such uid", str(uid))
        return False

    redis_socket_path = os.path.join(user_pwd.pw_dir, USER_WPOS_DIR, 'redis.sock')
    redis_ping_cmd = [_REDIS_CLI_BIN_FILE, '-s', redis_socket_path, 'ping']
    with drop_permissions_if_needed(username):
        output = run_in_cagefs_if_needed(redis_ping_cmd)
        logger.info('Redis health check for user=%s, return code=%s, stdout=%s, stderr=%s',
                    username,
                    str(output.returncode),
                    str(output.stdout),
                    str(output.stderr))
    return output.returncode == 0

def is_user_redis_alive(user_id: int) -> Tuple[bool, bool, dict]:
    """
    Check user's redis is alive
    :param user_id: uid to check sockets
    return True/False - redis alive/not alive
    :return: Tuple: (redis is working/not working, is user present, errors dict)
      error  - (False, False {"result": "error", "context": "..."})
    """
    try:
        user_pwd = pwd.getpwuid(user_id)
        username = user_pwd.pw_name
    except KeyError:
        logger.warning("Redis check error for user %s. No user with such uid", str(user_id))
        return False, False, {"result": _("Redis check error for user with uid %(uid)s. No such user"),
                              "context": {"uid": str(user_id)}}

    try:
        is_redis_alive = redis_socket_health_check(user_id)
    except Exception as e:
        logger.warning("Redis check error for user %s. Error is: %s", username, str(e))
        return False, True, { "result": _("Redis CLI start error %(error)s for user %(user)s"),
                              "context": { "error": str(e), "user": username } }

    if not is_redis_alive:
        # Process start error
        return False, True, {"result": _("Redis CLI check error %(error)s for user %(user)s"),
                             "context": {"error": "Redis is not pingable for user, most likely it is not started",
                                         "user": username}}
    return True, True, {"result": "success"}


def _get_redis_pid_from_pid_file_with_wait(redis_pid_filename: str) -> Optional[int]:
    """
    Get redis process PID from redis pid file. Wait up to 10 seconds
    :param redis_pid_filename: Redis PID filename
    :return: Redis PID or None on error (pid file absent/invalid or redis not started)
    """
    for i in range(100):
        try:
            with open(redis_pid_filename, 'r') as f:
                pid = int(f.read().strip())
                os.kill(pid, 0)
                return pid
        except (OSError, IOError, ValueError):
            # Error, PID file absent/invalid or redis still absent
            time.sleep(0.1)
    # Error, redis not started or pid file read/parse error
    return None


def reload_redis_for_user_thread(username: str,
                                 old_redis_pid: Optional[int],
                                 force_reload: str = 'no') -> Tuple[Optional[int], dict]:
    """
    Reloads redis for supplied user via helper script. Should be trun in thread
    :param username: Username to setup redis
    :param old_redis_pid: Old Redis PID for kill
    :param force_reload: reload redis w/o checks
    :return: Tuple:
      If redis was started for user - (PID of new redis process, {"result": "success"})
      else - redis was not started  - (None, {"result": "error", "context": ""})
    """
    try:
        user_pwd = pwd.getpwnam(username)
    except (KeyError, OSError, ):
        logger.debug("Can't reload redis for user '%s'. User not found.", username)
        return None, {"result": _("Can't reload redis for user '%(user)s'. User not found."),
                      "context": {"user": username}}
    logger.info('Calling redis_reloader with parameters: username: %s, old redis pid: %s, force reload: %s',
                 username,
                str(old_redis_pid),
                force_reload)
    try:
        # Run redis_reloader_script
        proc = subprocess.Popen(['/usr/share/cloudlinux/wpos/redis_reloader.py', username,
                                 str(old_redis_pid), force_reload],
                                shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        stdout, stderr = proc.communicate()
    except (OSError, IOError,) as e:
        logger.warning("Reload redis error for user '%s'. Error is %s", username, str(e))
        return None, {"result": _("Reload redis error for user '%(user)s'. Error is %(msg)s"),
                      "context": {"user": username, "msg": str(e)}}
    try:
        reload_result_dict = json.loads(stdout)
        if reload_result_dict['result'] != 'success':
            return None, reload_result_dict
    except (KeyError, json.JSONDecodeError, TypeError):
        return None, {"result": _("Reload redis for user '%(user)s' decode error: %(error_msg)s"),
                      "context": {"user": username, "error_msg": stdout}}
    # Redis was started, get PID
    pidfile_path = os.path.join(user_pwd.pw_dir, USER_WPOS_DIR, 'redis.pid')
    redis_pid = None
    if reload_result_dict.get('redis_enabled', True):
        redis_pid = _get_redis_pid_from_pid_file_with_wait(pidfile_path)
    return redis_pid, {"result": "success"}


def parse_redises() -> List[Tuple[int, int]]:
    """
    Get redis process by parsing psutil.process_iter
    Return list of tuples: [(user_uid, process_pid)]
    """
    res = []
    for proc in psutil.process_iter(['name']):
        if proc.info['name'] == 'redis-server':
            res.append(_validate_redis_proc(proc))
    return list(filter(None, res))


def _validate_redis_proc(p: psutil.Process) -> Optional[Tuple[int, int]]:
    """
    Ensure that redis process is ours:
        1. Right binary (alt-redis)
        2. Right socket
    """
    redis_bin = REDIS_SERVER_BIN_FILE

    uid = p.uids().real

    username = get_main_username_by_uid(uid)
    pw = pwd.getpwnam(username)
    user_home = pw.pw_dir

    sock_abspath = f'unixsocket:{user_home}/.clwpos/redis.sock'
    cmd = ' '.join(p.cmdline())
    if cmd.startswith(redis_bin) and sock_abspath in cmd:
        return uid, p.pid
    return None