PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /usr/libexec/pcp/bin
Viewing File: /usr/libexec/pcp/bin/pmlogger_daily
#! /bin/sh # # Copyright (c) 2013-2016,2018,2020 Red Hat. # Copyright (c) 1995-2000,2003 Silicon Graphics, Inc. All Rights Reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # Daily administrative script for PCP archive logs # . $PCP_DIR/etc/pcp.env . $PCP_SHARE_DIR/lib/rc-proc.sh . $PCP_SHARE_DIR/lib/utilproc.sh # error messages should go to stderr, not the GUI notifiers # unset PCP_STDERR # constant setup # tmp=`mktemp -d "$PCP_TMPFILE_DIR/pmlogger_daily.XXXXXXXXX"` || exit 1 status=0 echo >$tmp/lock prog=`basename $0` PROGLOG=$PCP_LOG_DIR/pmlogger/$prog.log MYPROGLOG=$PROGLOG.$$ USE_SYSLOG=true # optional begin logging to $PCP_LOG_DIR/NOTICES # if $PCP_LOG_RC_SCRIPTS then logmsg="begin pid:$$ $prog args:$*" if which pstree >/dev/null 2>&1 then logmsg="$logmsg [`pstree -lps $$`]" logmsg="`echo "$logmsg" | sed -e 's/---pstree([^)]*)//'`" fi $PCP_BINADM_DIR/pmpost "$logmsg" fi _cleanup() { if [ -s "$MYPROGLOG" ] then rm -f "$PROGLOG" mv "$MYPROGLOG" "$PROGLOG" else rm -f "$MYPROGLOG" fi $USE_SYSLOG && [ $status -ne 0 ] && \ $PCP_SYSLOG_PROG -p daemon.error "$prog failed - see $PROGLOG" if $SHOWME then : no pid file created else rm -f "$PCP_RUN_DIR/pmlogger_daily.pid" fi lockfile=`cat $tmp/lock 2>/dev/null` [ -n "$lockfile" ] && rm -f "$lockfile" rm -rf $tmp $VERY_VERBOSE && echo >&2 "End: `date '+%F %T.%N'`" } trap "_cleanup; exit \$status" 0 1 2 3 15 # pretty format a find-filter timespec # _timespec() { echo "$1" | sed -e 's/:/ /g' \ | while read _d _h _m do case "$_d:$_h:$_m" in 0::) echo "0 days" ;; 0::1) echo "1 minute" ;; 0::*) echo "$_m minutes" ;; 0:1:) echo "1 hour" ;; 0:*:) echo "$_h hours" ;; 0:1:1) echo "1 hour and 1 minute" ;; 0:1:*) echo "1 hour and $_m minutes" ;; 0:*:*) echo "$_h hours and $_m minutes" ;; 1::) echo "1 day" ;; 1::1) echo "1 day and 1 minute" ;; 1::*) echo "1 day and $_m minutes" ;; 1:1:) echo "1 day and 1 hour" ;; 1:*:) echo "1 day and $_h hours" ;; 1:1:1) echo "1 day, 1 hour and 1 minute" ;; 1:1:*) echo "1 day, 1 hour and $_m minutes" ;; 1:*:1) echo "1 day, $_h hours and 1 minute" ;; 1:*:*) echo "1 day, $_h hours and $_m minutes" ;; *::) echo "$_d days" ;; *::1) echo "$_d days and 1 minute" ;; *::*) echo "$_d days and $_m minutes" ;; *:1:) echo "$_d days and 1 hour" ;; *:*:) echo "$_d days and $_h hours" ;; *:1:1) echo "$_d days, 1 hour and 1 minute" ;; *:1:*) echo "$_d days, 1 hour and $_m minutes" ;; *:*:1) echo "$_d days, $_h hours and 1 minute" ;; *:*:*) echo "$_d days, $_h hours and $_m minutes" ;; esac done } if is_chkconfig_on pmlogger then PMLOGGER_CTL=on else PMLOGGER_CTL=off fi # control files for pmlogger administration ... edit the entries in this # file (and optional directory) to reflect your local configuration; see # also -c option below. # CONTROL=$PCP_PMLOGGERCONTROL_PATH CONTROLDIR=$PCP_PMLOGGERCONTROL_PATH.d # default number of days to keep archive logs # CULLAFTER=14 # default compression program and days until starting compression and # filename suffix pattern for file files to NOT compress # COMPRESS="" COMPRESS_CMDLINE="" if which xz >/dev/null 2>&1 then if xz -0 --block-size=10MiB </dev/null >/dev/null 2>&1 then # want minimal overheads, -0 is the same as --fast COMPRESS_DEFAULT="xz -0 --block-size=10MiB" else COMPRESS_DEFAULT=xz fi else # overridden by $PCP_COMPRESS or if not set, no compression COMPRESS_DEFAULT="" fi COMPRESSAFTER_CMDLINE="" eval `pmconfig -L -s transparent_decompress` if $transparent_decompress then COMPRESSAFTER_DEFAULT=0 else COMPRESSAFTER_DEFAULT="never" fi if [ -n "$PCP_COMPRESSAFTER" ] then $PCP_BINADM_DIR/find-filter </dev/null >/dev/null 2>&1 mtime "+$PCP_COMPRESSAFTER" if [ $? != 0 -a X"$PCP_COMPRESSAFTER" != Xforever -a X"$PCP_COMPRESSAFTER" != Xnever ] then echo "Error: \$PCP_COMPRESSAFTER value ($PCP_COMPRESSAFTER) must be number, time, \"forever\" or \"never\"" status=1 exit fi fi COMPRESSREGEX="" COMPRESSREGEX_CMDLINE="" COMPRESSREGEX_DEFAULT="\.(index|Z|gz|bz2|zip|xz|lzma|lzo|lz4)$" # threshold size to roll $PCP_LOG_DIR/NOTICES # NOTICES=$PCP_LOG_DIR/NOTICES ROLLNOTICES=20480 # mail addresses to send daily NOTICES summary to # MAILME="" MAILFILE=$PCP_LOG_DIR/NOTICES.daily # search for your mail agent of choice ... # MAIL='' for try in Mail mail email do if which $try >/dev/null 2>&1 then MAIL=$try break fi done # determine path for pwd command to override shell built-in PWDCMND=`which pwd 2>/dev/null | $PCP_AWK_PROG ' BEGIN { i = 0 } / not in / { i = 1 } / aliased to / { i = 1 } { if ( i == 0 ) print } '` [ -z "$PWDCMND" ] && PWDCMND=/bin/pwd eval $PWDCMND -P >/dev/null 2>&1 [ $? -eq 0 ] && PWDCMND="$PWDCMND -P" here=`$PWDCMND` echo > $tmp/usage cat >> $tmp/usage <<EOF Options: -c=FILE,--control=FILE pmlogger control file -E,--expunge expunge metrics with metadata inconsistencies when merging archives -f,--force force actions (intended for QA, not production) -k=TIME,--discard=TIME remove archives after TIME (format DD[:HH[:MM]]) -K compress, but no other changes -l=FILE,--logfile=FILE send important diagnostic messages to FILE -m=ADDRs,--mail=ADDRs send daily NOTICES entries to email addresses -M do not rewrite, merge or rename archives -N,--showme perform a dry run, showing what would be done -o merge yesterdays logs only (old form, default is all) -p poll and exit if processing already done for today -r,--norewrite do not process archives with pmlogrewrite(1) -R,--rewriteall check and rewrite all archives -s=SIZE,--rotate=SIZE rotate NOTICES file after reaching SIZE bytes -t=WANT implies -VV, keep verbose output trace for WANT days -V,--verbose verbose output (multiple times for very verbose) -x=TIME,--compress-after=TIME compress archive data files after TIME (format DD[:HH[:MM]]) -X=PROGRAM,--compressor=PROGRAM use PROGRAM for archive data file compression -Y=REGEX,--regex=REGEX egrep filter when compressing files ["$COMPRESSREGEX_DEFAULT"] --help EOF _usage() { pmgetopt --progname=$prog --config=$tmp/usage --usage status=1 exit } # option parsing # SHOWME=false VERBOSE=false VERY_VERBOSE=false MYARGS="" COMPRESSONLY=false OFLAG=false PFLAG=false TRACE=0 RFLAG=false REWRITEALL=false MFLAG=false EXPUNGE="" FORCE=false KILL=pmsignal ARGS=`pmgetopt --progname=$prog --config=$tmp/usage -- "$@"` [ $? != 0 ] && exit 1 eval set -- "$ARGS" while [ $# -gt 0 ] do case "$1" in -c) CONTROL="$2" CONTROLDIR="$2.d" shift ;; -E) EXPUNGE="-E" ;; -f) FORCE=true ;; -k) CULLAFTER="$2" shift $PCP_BINADM_DIR/find-filter </dev/null >/dev/null 2>&1 mtime "+$CULLAFTER" if [ $? != 0 -a X"$CULLAFTER" != Xforever -a X"$CULLAFTER" != Xnever ] then echo "Error: -k value ($CULLAFTER) must be number, time, \"forever\" or \"never\"" status=1 exit fi ;; -K) if $PFLAG then echo "Error: -p and -K are mutually exclusive" status=1 exit fi COMPRESSONLY=true PROGLOG=$PCP_LOG_DIR/pmlogger/$prog-K.log MYPROGLOG=$PROGLOG.$$ ;; -l) PROGLOG="$2" MYPROGLOG=$PROGLOG.$$ USE_SYSLOG=false shift ;; -m) MAILME="$2" shift ;; -M) if $REWRITEALL then echo "Error: -R and -M are mutually exclusive" status=1 exit fi MFLAG=true RFLAG=true ;; -N) SHOWME=true USE_SYSLOG=false MYARGS="$MYARGS -N" ;; -o) OFLAG=true ;; -p) if $COMPRESSONLY then echo "Error: -K and -p are mutually exclusive" status=1 exit fi PFLAG=true ;; -r) if $REWRITEALL then echo "Error: -R and -r are mutually exclusive" status=1 exit fi RFLAG=true ;; -R) if $RFLAG then echo "Error: -r and -R are mutually exclusive" status=1 exit fi REWRITEALL=true ;; -s) ROLLNOTICES="$2" shift check=`echo "$ROLLNOTICES" | sed -e 's/[0-9]//g'` if [ ! -z "$check" ] then echo "Error: -s value ($ROLLNOTICES) must be numeric" status=1 exit fi ;; -t) TRACE="$2" shift # send all stdout and stderr output (after argument parsing) to # $PCP_LOG_DIR/pmlogger/daily.<date>.trace # PROGLOG=$PCP_LOG_DIR/pmlogger/daily.`date "+%Y%m%d.%H.%M"`.trace MYPROGLOG=$PROGLOG.$$ VERBOSE=true VERY_VERBOSE=true MYARGS="$MYARGS -V -V" ;; -V) if $VERBOSE then VERY_VERBOSE=true else VERBOSE=true fi MYARGS="$MYARGS -V" ;; -x) COMPRESSAFTER_CMDLINE="$2" shift if [ -n "$PCP_COMPRESSAFTER" -a "$PCP_COMPRESSAFTER" != "$COMPRESSAFTER_CMDLINE" ] then echo "Warning: -x value ($COMPRESSAFTER_CMDLINE) ignored because \$PCP_COMPRESSAFTER ($PCP_COMPRESSAFTER) set in environment" COMPRESSAFTER_CMDLINE="" continue fi $PCP_BINADM_DIR/find-filter </dev/null >/dev/null 2>&1 mtime "+$COMPRESSAFTER_CMDLINE" if [ $? != 0 -a X"$COMPRESSAFTER_CMDLINE" != Xforever -a X"$COMPRESSAFTER_CMDLINE" != Xnever ] then echo "Error: -x value ($COMPRESSAFTER_CMDLINE) must be number, time, \"forever\" or \"never\"" status=1 exit fi ;; -X) COMPRESS_CMDLINE="$2" shift if [ -n "$PCP_COMPRESS" -a "$PCP_COMPRESS" != "$COMPRESS_CMDLINE" ] then echo "Warning: -X value ($COMPRESS_CMDLINE) ignored because \$PCP_COMPRESS ($PCP_COMPRESS) set in environment" COMPRESS_CMDLINE="" continue fi ;; -Y) COMPRESSREGEX_CMDLINE="$2" shift if [ -n "$PCP_COMPRESSREGEX" -a "$PCP_COMPRESSREGEX" != "$COMPRESSREGEX_CMDLINE" ] then echo "Warning: -Y value ($COMPRESSREGEX_CMDLINE) ignored because \$PCP_COMPRESSREGEX ($PCP_COMPRESSREGEX) set in environment" COMPRESSREGEX_CMDLINE="" continue fi ;; --) shift break ;; -\?) _usage ;; esac shift done [ $# -ne 0 ] && _usage if $PFLAG then rm -f $tmp/ok if [ -f $PCP_LOG_DIR/pmlogger/pmlogger_daily.stamp ] then last_stamp=`sed -e '/^#/d' <$PCP_LOG_DIR/pmlogger/pmlogger_daily.stamp` if [ -n "$last_stamp" ] then # Polling happens every 60 mins, so if pmlogger_daily was last # run more than 23.5 hours ago, we need to do it again, otherwise # exit quietly # now_stamp=`pmdate %s` check=`expr $now_stamp - \( 23 \* 3600 \) - 1800` if [ "$last_stamp" -ge "$check" ] then $SHOWME && echo "-p stamp $last_stamp now $now_stamp check $check do nothing" exit fi $SHOWME && echo "-p stamp $last_stamp now $now_stamp check $check do work" touch $tmp/ok fi fi if [ ! -f $tmp/ok ] then # special start up logic when pmlogger_daily.stamp does not exist # ... by convention, archive files are stored in per-host directories # below $PCP_ARCHIVE_DIR # find "$PCP_ARCHIVE_DIR" -name "`pmdate -1d %Y%m%d`.index" >$tmp/tmp if [ -s $tmp/tmp ] then $SHOWME && echo "-p start up already run heuristic match, do nothing" exit fi $SHOWME && echo "-p start up do work" fi fi # write date-and-timestamp to be checked by -p polling # if $SHOWME then echo "+ date-and-timestamp `pmdate '%Y-%m-%d %H:%M:%S %s'`" elif $COMPRESSONLY then # no date-and-timestamp update with -K : else # doing the whole shootin' match ... # if _save_prev_file $PCP_LOG_DIR/pmlogger/pmlogger_daily.stamp then : else echo "Warning: cannot save previous date-and-timestamp" fi # only update date-and-timestamp if we can write the file # pmdate '# %Y-%m-%d %H:%M:%S %s' >$tmp/stamp if cp $tmp/stamp $PCP_LOG_DIR/pmlogger/pmlogger_daily.stamp then : else echo "Warning: cannot install new date-and-timestamp" fi fi if $SHOWME then : else # Salt away previous log, if any ... # _save_prev_file "$PROGLOG" # After argument checking, everything must be logged to ensure no mail is # accidentally sent from cron. Close stdout and stderr, then open stdout # as our logfile and redirect stderr there too. Create the log file with # correct ownership first. # # Exception ($SHOWME, above) is for -N where we want to see the output. # touch "$MYPROGLOG" chown $PCP_USER:$PCP_GROUP "$MYPROGLOG" >/dev/null 2>&1 exec 1>"$MYPROGLOG" 2>&1 fi if $VERY_VERBOSE then echo >&2 "Start: `date '+%F %T.%N'`" if which pstree >/dev/null 2>&1 then if pstree -spa $$ >$tmp/tmp 2>&1 then echo >&2 "Called from:" cat >&2 $tmp/tmp else # pstree not functional for us ... -s not supported in older # versions : fi fi fi # if SaveLogs exists in the $PCP_LOG_DIR/pmlogger directory then save # $MYPROGLOG there as well with a unique name that contains the date and time # when we're run ... skip if -N (showme) # if $SHOWME then : else if [ -d $PCP_LOG_DIR/pmlogger/SaveLogs ] then now="`date '+%Y%m%d.%H.%M.%S'`" link=`echo $MYPROGLOG | sed -e "s/$prog/SaveLogs\/$prog.$now/"` if [ ! -f "$link" ] then if $SHOWME then echo "+ ln $MYPROGLOG $link" else ln $MYPROGLOG $link fi fi fi fi if [ ! -f "$CONTROL" ] then echo "$prog: Error: cannot find control file ($CONTROL)" status=1 exit fi _error() { echo "$prog: [$filename:$line]" echo "Error: $@" echo "... logging for host \"$host\" unchanged" touch $tmp/err } _warning() { echo "$prog: [$filename:$line]" echo "Warning: $@" } _skipping() { echo "$prog: Warning: $@" echo "[$filename:$line] ... skip log merging and compressing for host \"$host\"" touch $tmp/skip } _lock() { if [ ! -w $1 ] then _warning "no write access in $1 skip lock file processing" else # demand mutual exclusion # rm -f $tmp/stamp $tmp/out delay=200 # tenths of a second while [ $delay -gt 0 ] do if pmlock -v "$1/lock" >>$tmp/out 2>&1 then echo "$1/lock" >$tmp/lock break else [ -f $tmp/stamp ] || touch -t `pmdate -30M %Y%m%d%H%M` $tmp/stamp find $tmp/stamp -newer "$1/lock" -print 2>/dev/null >$tmp/tmp if [ -s $tmp/tmp ] then if [ -f "$1/lock" ] then _warning "removing lock file older than 30 minutes" LC_TIME=POSIX ls -l "$1/lock" rm -f "$1/lock" else # there is a small timing window here where pmlock # might fail, but the lock file has been removed by # the time we get here, so just keep trying # : fi fi fi pmsleep 0.1 delay=`expr $delay - 1` done if [ $delay -eq 0 ] then # failed to gain mutex lock # if [ -f "$1/lock" ] then _warning "is another PCP cron job running concurrently?" LC_TIME=POSIX ls -l "$1/lock" else echo "$prog: `cat $tmp/out`" fi _error "failed to acquire exclusive lock ($1/lock) ..." return 1 fi fi return 0 } _unlock() { rm -f "$1/lock" echo >$tmp/lock } # filter file names to leave those that look like PCP archives # managed by pmlogger_check and pmlogger_daily, namely they begin # with a datestamp # # need to handle both the year 2000 and the old name formats, and # possible ./ prefix (from find .) # _filter_filename() { sed -n \ -e 's/^\.\///' \ -e '/^[12][0-9][0-9][0-9][0-1][0-9][0-3][0-9][-.]/p' \ -e '/^[0-9][0-9][0-1][0-9][0-3][0-9][-.]/p' } _get_primary_logger_pid() { pidfile="$PCP_TMP_DIR/pmlogger/primary" if [ ! -L "$pidfile" ] then pid='' elif which realpath >/dev/null 2>&1 then pri=`readlink $pidfile` pid=`basename "$pri"` else pri=`ls -l "$pidfile" | sed -e 's/.*-> //'` pid=`basename "$pri"` fi echo "$pid" } # mails out any entries for the previous 24hrs from the PCP notices file # if [ ! -z "$MAILME" ] then # get start time of NOTICES entries we want - all earlier are discarded # args=`pmdate -1d '-v yy=%Y -v my=%b -v dy=%d'` args=`pmdate -1d '-v Hy=%H -v My=%M'`" $args" args=`pmdate '-v yt=%Y -v mt=%b -v dt=%d'`" $args" # # Basic algorithm: # from NOTICES head, look for a DATE: entry for yesterday or today; # if its yesterday, find all HH:MM timestamps which are in the window, # until the end of yesterday is reached; # copy out the remainder of the file (todays entries). # # initially, entries have one of three forms: # DATE: weekday mon day HH:MM:SS year # Started by pmlogger_daily: weekday mon day HH:MM:SS TZ year # HH:MM message # # preprocess to provide a common date separator - if new date stamps are # ever introduced into the NOTICES file, massage them first... # rm -f $tmp/pcp $PCP_AWK_PROG ' /^Started/ { print "DATE:",$4,$5,$6,$7,$9; next } { print } ' $NOTICES | \ $PCP_AWK_PROG -F ':[ \t]*|[ \t]+' $args ' $1 == "DATE" && $3 == mt && $4 == dt && $8 == yt { tday = 1; print; next } $1 == "DATE" && $3 == my && $4 == dy && $8 == yy { yday = 1; print; next } { if ( tday || (yday && $1 > Hy) || (yday && $1 == Hy && $2 >= My) ) print }' >$tmp/pcp if [ -s $tmp/pcp ] then if [ ! -z "$MAIL" ] then $MAIL -s "PCP NOTICES summary for `hostname`" $MAILME <$tmp/pcp else # when run from cron, this will still likely end up as an email echo "$prog: Warning: cannot find a mail agent to send mail ..." echo "PCP NOTICES summary for `hostname`" cat $tmp/pcp fi [ -w `dirname "$NOTICES"` ] && mv -f $tmp/pcp "$MAILFILE" fi fi # Roll $PCP_LOG_DIR/NOTICES -> $PCP_LOG_DIR/NOTICES.old if larger # that 10 Kbytes, and you can write in $PCP_LOG_DIR # if [ -s "$NOTICES" -a -w `dirname "$NOTICES"` ] then if [ "`wc -c <"$NOTICES"`" -ge $ROLLNOTICES ] then if $VERBOSE then echo "Roll $NOTICES -> $NOTICES.old" echo "Start new $NOTICES" fi if $SHOWME then echo "+ mv -f $NOTICES $NOTICES.old" echo "+ touch $NOTICES" else echo >>"$NOTICES" echo "*** rotated by $prog: `date`" >>"$NOTICES" mv -f "$NOTICES" "$NOTICES.old" echo "Started by $prog: `date`" >"$NOTICES" chown $PCP_USER:$PCP_GROUP "$NOTICES" >/dev/null 2>&1 fi fi fi # Keep our pid in $PCP_RUN_DIR/pmlogger_daily.pid ... this is checked # by pmlogger_check when it fails to obtain the lock should it be run # while pmlogger_daily is running # # For most packages, $PCP_RUN_DIR is included in the package, # but for Debian and cases where /var/run is a mounted filesystem # it may not exist, so create it here before it is used to create # any pid/lock files # # $PCP_RUN_DIR creation is also done in other daemons startup, but we # have no guarantee any other daemons are running on this system. # # Skip all of this if -N (showme) # if $SHOWME then : else if [ ! -d "$PCP_RUN_DIR" ] then mkdir -p -m 775 "$PCP_RUN_DIR" 2>/dev/null # might be running from cron as unprivileged user [ $? -ne 0 -a "$PMLOGGER_CTL" = "off" ] && exit 0 chown $PCP_USER:$PCP_GROUP "$PCP_RUN_DIR" >/dev/null 2>&1 if which restorecon >/dev/null 2>&1 then restorecon -r "$PCP_RUN_DIR" fi fi echo $$ >"$PCP_RUN_DIR/pmlogger_daily.pid" fi # note on control file format version # 1.0 was shipped as part of PCPWEB beta, and did not include the # socks field [this is the default for backwards compatibility] # 1.1 is the first production release, and the version is set in # the control file with a $version=1.1 line (see below) # version='' # if this file exists at the end, we encountered a serious error # rm -f $tmp/err # root around in PCP_TMP_DIR/pmlogger looking for files like: # 8193: # 4330 # bozo # /var/log/pcp/pmlogger/bozo/20180313.08.53 # pmlogger_daily # if the directory containing the archive matches, then the name # of the file is the pid. # # The pid(s) (if any) appear on stdout, so be careful to send any # diagnostics to stderr. # _get_non_primary_logger_pid() { pid='' for log in $PCP_TMP_DIR/pmlogger/[0-9]* do [ "$log" = "$PCP_TMP_DIR/pmlogger/[0-9]*" ] && continue if $VERY_VERBOSE then _host=`sed -n 2p <$log` _arch=`sed -n 3p <$log` $PCP_ECHO_PROG >&2 $PCP_ECHO_N "... try $log host=$_host arch=$_arch: ""$PCP_ECHO_C" fi # throw away stderr in case $log has been removed by now match=`sed -e '3s@/[^/]*$@@' $log 2>/dev/null | \ $PCP_AWK_PROG ' BEGIN { m = 0 } NR == 3 && $0 == "'$dir'" { m = 2; next } END { print m }'` $VERY_VERBOSE && $PCP_ECHO_PROG >&2 $PCP_ECHO_N "match=$match ""$PCP_ECHO_C" if [ "$match" = 2 ] then pid=`echo $log | sed -e 's,.*/,,'` if _get_pids_by_name pmlogger | grep "^$pid\$" >/dev/null then $VERY_VERBOSE && echo >&2 "pmlogger process $pid identified, OK" break fi $VERY_VERBOSE && echo >&2 "pmlogger process $pid not running, skip" pid='' else $VERY_VERBOSE && echo >&2 "different directory, skip" fi done echo "$pid" } _parse_control() { controlfile="$1" line=0 # strip leading directories from pathname to get useful filename # dirname=`dirname $PCP_PMLOGGERCONTROL_PATH` filename=`echo "$controlfile" | sed -e "s@$dirname/@@"` if echo "$controlfile" | grep -q -e '\.rpmsave$' -e '\.rpmnew$' -e '\.rpmorig$' -e '\.dpkg-dist$' -e '\.dpkg-old$' -e '\.dpkg-new$' then echo "Warning: ignoring backup control file \"$controlfile\"" return fi sed \ -e "s;PCP_ARCHIVE_DIR;$PCP_ARCHIVE_DIR;g" \ -e "s;PCP_LOG_DIR;$PCP_LOG_DIR;g" \ $controlfile | \ while read host primary socks dir args do # start in one place for each iteration (beware of relative paths) cd "$here" line=`expr $line + 1` if $VERY_VERBOSE then case "$host" in \#!#*) # stopped by pmlogctl ... we'll be checking this one echo >&2 "[$filename:$line] host=\"$host\" primary=\"$primary\" socks=\"$socks\" dir=\"$dir\" args=\"$args\"" ;; \#*|'') # comment or empty ;; *) echo >&2 "[$filename:$line] host=\"$host\" primary=\"$primary\" socks=\"$socks\" dir=\"$dir\" args=\"$args\"" ;; esac fi case "$host" in \#!#*) # stopped by pmlogctl ... need to check this one host=`echo "$host" | sed -e 's/^#!#//'` ;; \#*|'') # comment or empty continue ;; \$*) # in-line variable assignment $SHOWME && echo "# $host $primary $socks $dir $args" cmd=`echo "$host $primary $socks $dir $args" \ | sed -n \ -e "/='/s/\(='[^']*'\).*/\1/" \ -e '/="/s/\(="[^"]*"\).*/\1/' \ -e '/=[^"'"'"']/s/[;&<>|].*$//' \ -e '/^\\$[A-Za-z][A-Za-z0-9_]*=/{ s/^\\$// s/^\([A-Za-z][A-Za-z0-9_]*\)=/export \1; \1=/p }'` if [ -z "$cmd" ] then # in-line command, not a variable assignment _warning "in-line command is not a variable assignment, line ignored" else rm -f $tmp/cmd case "$cmd" in 'export PATH;'*) _warning "cannot change \$PATH, line ignored" ;; 'export IFS;'*) _warning "cannot change \$IFS, line ignored" ;; 'export PCP_COMPRESS;'*) old_value="$PCP_COMPRESS" $SHOWME && echo "+ $cmd" echo eval $cmd >>$tmp/cmd eval $cmd if [ -n "$old_value" ] then _warning "\$PCP_COMPRESS ($PCP_COMPRESS) reset from control file, previous value ($old_value) ignored" fi if [ -n "$PCP_COMPRESS" -a -n "$COMPRESS_CMDLINE" -a "$PCP_COMPRESS" != "$COMPRESS_CMDLINE" ] then _warning "\$PCP_COMPRESS ($PCP_COMPRESS) reset from control file, -X value ($COMPRESS_CMDLINE) ignored" COMPRESS_CMDLINE="" fi ;; 'export PCP_COMPRESSAFTER;'*) old_value="$PCP_COMPRESSAFTER" check=`echo "$cmd" | sed -e 's/.*=//' -e 's/ *$//'` $PCP_BINADM_DIR/find-filter </dev/null >/dev/null 2>&1 mtime "+$check" if [ $? != 0 -a -n "$check" -a X"$check" != Xforever -a X"$check" != Xnever ] then _error "\$PCP_COMPRESSAFTER value ($check) must be number, time, \"forever\" or \"never\"" else $SHOWME && echo "+ $cmd" echo eval $cmd >>$tmp/cmd eval $cmd if [ -n "$old_value" ] then _warning "\$PCP_COMPRESSAFTER ($PCP_COMPRESSAFTER) reset from control file, previous value ($old_value) ignored" fi if [ -n "$PCP_COMPRESSAFTER" -a -n "$COMPRESSAFTER_CMDLINE" -a "$PCP_COMPRESSAFTER" != "$COMPRESSAFTER_CMDLINE" ] then _warning "\$PCP_COMPRESSAFTER ($PCP_COMPRESSAFTER) reset from control file, -x value ($COMPRESSAFTER_CMDLINE) ignored" COMPRESSAFTER_CMDLINE="" fi fi ;; 'export PCP_COMPRESSREGEX;'*) old_value="$PCP_COMPRESSREGEX" $SHOWME && echo "+ $cmd" echo eval $cmd >>$tmp/cmd eval $cmd if [ -n "$old_value" ] then _warning "\$PCP_COMPRESSREGEX ($PCP_COMPRESSREGEX) reset from control file, previous value ($old_value) ignored" fi if [ -n "$PCP_COMPRESSREGEX" -a -n "$COMPRESSREGEX_CMDLINE" -a "$PCP_COMPRESSREGEX" != "$COMPRESSREGEX_CMDLINE" ] then _warning "\$PCP_COMPRESSREGEX ($PCP_COMPRESSREGEX) reset from control file, -Y value ($COMPRESSREGEX_CMDLINE) ignored" COMPRESSREGEX_CMDLINE="" fi ;; *) $SHOWME && echo "+ $cmd" echo eval $cmd >>$tmp/cmd eval $cmd ;; esac fi continue ;; esac # set the version and other global variables # [ -f $tmp/cmd ] && . $tmp/cmd if [ -z "$version" -o "$version" = "1.0" ] then if [ -z "$version" ] then _warning "processing default version 1.0 control format" version=1.0 fi args="$dir $args" dir="$socks" socks=n fi # do shell expansion of $dir if needed # _do_dir_and_args if [ -z "$primary" -o -z "$socks" -o -z "$dir" -o -z "$args" ] then _error "insufficient fields in control file record" continue fi # substitute LOCALHOSTNAME marker in this config line # (differently for directory and pcp -h HOST arguments) # dirhostname=`hostname || echo localhost` dir=`echo $dir | sed -e "s;LOCALHOSTNAME;$dirhostname;"` [ $primary = y -o "x$host" = xLOCALHOSTNAME ] && host=local: if $VERBOSE then echo if $COMPRESSONLY then echo "=== compressing PCP archives for host $host ===" else echo "=== daily maintenance of PCP archives for host $host ===" fi echo fi if $VERY_VERBOSE then pflag='' [ $primary = y ] && pflag=' -P' echo >&2 "Check pmlogger$pflag -h $host ... in $dir ..." fi # make sure output directory hierarchy exists and $PCP_USER # user can write there # if [ ! -d "$dir" ] then mkdir_and_chown "$dir" 755 $PCP_USER:$PCP_GROUP >$tmp/tmp 2>&1 if [ ! -d "$dir" ] then cat $tmp/tmp _error "cannot create directory ($dir) for PCP archive files" continue else _warning "creating directory ($dir) for PCP archive files" fi fi cd $dir dir=`$PWDCMND` $SHOWME && echo "+ cd $dir" if $SHOWME then echo "+ get mutex lock" else if _lock "$dir" then : else # fatal error, reported in _lock() # continue fi fi # For archive rewriting (to make metadata consistent across # archives) find the rules as follows: # - if pmlogrewrite exists (as a file, directory or symlink) # in the current archive directory use that # - else use $PCP_VAR_DIR/config/pmlogrewrite # rewrite='' for type in -f -d -L do if [ $type "./pmlogrewrite" ] then rewrite="$rewrite -c `pwd`/pmlogrewrite" break fi done [ -z "$rewrite" ] && rewrite='-c $PCP_VAR_DIR/config/pmlogrewrite' if $REWRITEALL then # Do the pmlogrewrite -qi thing (using pmlogger_rewrite) for # all archives in this directory # rewrite_args="$rewrite" if $VERBOSE then echo "Info: pmlogrewrite all archives in $dir" rewrite_args="$rewrite_args -V" fi $VERY_VERBOSE && rewrite_args="$rewrite_args -V" if $SHOWME then echo "+ $PCP_BINADM_DIR/pmlogger_rewrite $rewrite_args $dir" else if eval $PCP_BINADM_DIR/pmlogger_rewrite $rewrite_args $dir then : else _error "pmlogger_rewrite failed in $dir" fi fi fi pid='' if [ X"$primary" = Xy ] then if test -e "$PCP_TMP_DIR/pmlogger/primary" then _host=`sed -n 2p <"$PCP_TMP_DIR/pmlogger/primary"` _arch=`sed -n 3p <"$PCP_TMP_DIR/pmlogger/primary"` $VERY_VERBOSE && echo >&2 "... try $PCP_TMP_DIR/pmlogger/primary: host=$_host arch=$_arch" pid=`_get_primary_logger_pid` fi if [ -z "$pid" ] then if $VERY_VERBOSE then echo >&2 "primary pmlogger process PID not found" ls >&2 -l "$PCP_TMP_DIR/pmlogger" $PCP_PS_PROG $PCP_PS_ALL_FLAGS | egrep >&2 '[P]ID|[p]mlogger' fi elif _get_pids_by_name pmlogger | grep "^$pid\$" >/dev/null then $VERY_VERBOSE && echo >&2 "primary pmlogger process $pid identified, OK" else $VERY_VERBOSE && echo >&2 "primary pmlogger process $pid not running" pid='' fi else # pid(s) on stdout, diagnostics on stderr # pid=`_get_non_primary_logger_pid` if $VERY_VERBOSE then if [ -z "$pid" ] then $VERY_VERBOSE && echo >&2 "No non-primary pmlogger process(es) found" else $VERY_VERBOSE && echo >&2 "non-primary pmlogger process(es) $pid identified, OK" fi fi fi if [ -z "$pid" ] then if [ "$PMLOGGER_CTL" = "on" ] then _error "no pmlogger instance running for host \"$host\"" else _warning "no pmlogger instance running for host \"$host\"" fi _warning "skipping log rotation because we don't know which pmlogger to signal" elif ! $COMPRESSONLY then # send pmlogger a SIGUSR2 to "roll the archive logs" # if $SHOWME then echo "+ $KILL -s USR2 $pid" else $VERY_VERBOSE && echo >&2 "Sending SIGUSR2 to $pid" $KILL -s USR2 "$pid" if $VERY_VERBOSE then # We have seen in qa/793, but never in a "real" # deployment, cases where the pmlogger process # vanishes a short time after the SIGUSR2 has been # sent and caught, the process has called exec() and # main() has restarted. This check is intended # detect and report when this happens if -VV is # in play. # sleep 1 if $PCP_PS_PROG -p "$pid" 2>&1 | grep "^$pid[ ]" >/dev/null then : still alive else echo >&2 "Error: pmlogger process $pid has vanished" fi fi fi fi if ! $COMPRESSONLY then # Cull any old archives. # # We now do this first, so that if the archives are bad for # any reason we don't want failures to merge or rewrite to # prevent removing old files as this can lead to full # filesystems if left unattended. # if [ X"$CULLAFTER" != Xforever -a X"$CULLAFTER" != Xnever ] then # *BSD semantics for find(1) -mtime +N are "rounded up to # the next full 24-hour period", compared to GNU/Linux # semantics "any fractional part is ignored". So, these are # almost always off by one day in terms of the files selected. # # For GNU/Linux reduce the number of days by one (opens up # the window). # # The real filtering is done by find-filter, we just want to # be sure that we include all of the candidate files in the # find(1) part. # CULLDAYS=`echo $CULLAFTER | sed -e 's/:.*//'` if [ "$PCP_PLATFORM" = freebsd -o "$PCP_PLATFORM" = netbsd -o "$PCP_PLATFORM" = openbsd ] then : else # decrement, unless already zero # [ "$CULLDAYS" -gt 0 ] && CULLDAYS=`expr "$CULLDAYS" - 1` fi if [ "$CULLDAYS" -gt 0 ] then find . -type f -mtime +$CULLDAYS else find . -type f fi \ | $PCP_BINADM_DIR/find-filter mtime +$CULLAFTER \ | _filter_filename \ | sort >$tmp/list if [ -n "$pid" ] then # pmlogger is running, make sure we don't cull the current # archive # if [ -f "$PCP_TMP_DIR/pmlogger/$pid" ] then current_base=`sed -n -e '3s;.*/;;p' <"$PCP_TMP_DIR/pmlogger/$pid"` if [ -n "$current_base" ] then $VERY_VERBOSE && echo >&2 "[$filename:$line] skip cull for current $current_base archive" sed -e "/^$current_base/d" <$tmp/list >$tmp/tmp mv $tmp/tmp $tmp/list fi fi fi if [ -s $tmp/list ] then if $VERBOSE then echo "Archive files older than `_timespec $CULLAFTER` being removed ..." fmt <$tmp/list | sed -e 's/^/ /' fi if $SHOWME then cat $tmp/list | xargs echo + rm -f else cat $tmp/list | xargs rm -f fi else $VERY_VERBOSE && echo >&2 "Warning: no archive files found to cull" fi fi # Merge archive logs. # # Will work for new style YYYYMMDD.HH.MM[-NN] archives and old style # YYMMDD.HH.MM[-NN] archives. # Note: we need to handle duplicate-breaking forms like # YYYYMMDD.HH.MM-seq# (even though pmlogger_merge already picks most # of these up) in case the base YYYYMMDD.HH.MM archive is for some # reason missing here # # Assume if the .meta or .meta.* file is present then other # archive components are also present (if not the case it # is a serious process botch, and pmlogger_merge will fail below) # # Find all candidate input archives, remove any that contain today's # date and group the remainder by date. # TODAY=`date +%Y%m%d` find *.meta* \ \( -name "*.[0-2][0-9].[0-5][0-9].meta*" \ -o -name "*.[0-2][0-9].[0-5][0-9]-[0-9][0-9].meta*" \ \) \ -print 2>/dev/null \ | sed \ -e "/^$TODAY\./d" \ -e 's/\.meta\..*//' \ -e 's/\.meta//' \ | sort -n \ | $PCP_AWK_PROG ' { if (lastdate != "" && match($1, "^" lastdate "\\.") == 1) { # same date as previous one inlist = inlist " " $1 next } else { # different date as previous one if (inlist != "") print lastdate,inlist inlist = $1 lastdate = $1 sub(/\..*/, "", lastdate) } } END { if (inlist != "") print lastdate,inlist }' >$tmp/list if $OFLAG then # -o option, preserve the old semantics, and only process the # previous day's archives ... aim for a time close to midday # yesterday and report that date # now_hr=`pmdate %H` hr=`expr 12 + $now_hr` grep "^[0-9]*`pmdate -${hr}H %y%m%d` " $tmp/list >$tmp/tmp mv $tmp/tmp $tmp/list fi rm -f $tmp/skip if $MFLAG then # -M don't rewrite, merge or rename # : else if [ ! -s $tmp/list ] then if $SHOWME then : else if $VERBOSE then echo "Warning: no archives found to merge" $VERY_VERBOSE && ls >&2 -l fi fi else cat $tmp/list \ | while read outfile inlist do if [ -f $outfile.0 -o -f $outfile.index -o -f $outfile.meta ] then _skipping "output archive ($outfile) already exists" continue else $VERY_VERBOSE && echo >&2 "Rewriting input archives using $rewrite" if $RFLAG then : else for arch in $inlist do if $SHOWME then echo "+ pmlogrewrite -iq $rewrite $arch" else if eval pmlogrewrite -iq $rewrite $arch then : else _skipping "rewrite for $arch failed using $rewrite failed" continue fi fi done fi [ -f $tmp/skip ] && continue if $VERY_VERBOSE then for arch in $inlist do echo >&2 "Input archive $arch ..." if $SHOWME then echo "+ pmdumplog -L $arch" else pmdumplog >&2 -L $arch fi done fi narch=`echo $inlist | wc -w | sed -e 's/ //g'` if [ "$narch" = 1 ] then # optimization - rename, don't merge, for one input archive # if $SHOWME then echo "+ pmlogmv$MYARGS $inlist $outfile" elif pmlogmv$MYARGS $inlist $outfile then if $VERY_VERBOSE then echo >&2 "Renamed output archive $outfile ..." pmdumplog >&2 -L $outfile fi else _error "problems executing pmlogmv for host \"$host\"" fi else # more than one input archive, merge away # if $SHOWME then echo "+ pmlogger_merge$MYARGS $EXPUNGE -f $inlist $outfile" elif pmlogger_merge$MYARGS $EXPUNGE -f $inlist $outfile then if $VERY_VERBOSE then echo >&2 "Merged output archive $outfile ..." pmdumplog >&2 -L $outfile fi else _error "problems executing pmlogger_merge for host \"$host\"" fi fi fi done fi fi fi # and compress old archive data files # (after cull - don't compress unnecessarily) # COMPRESSAFTER="$PCP_COMPRESSAFTER" [ -z "$COMPRESSAFTER" ] && COMPRESSAFTER="$COMPRESSAFTER_CMDLINE" [ -z "$COMPRESSAFTER" ] && COMPRESSAFTER="$COMPRESSAFTER_DEFAULT" $VERY_VERBOSE && echo >&2 "COMPRESSAFTER=$COMPRESSAFTER" if [ -n "$COMPRESSAFTER" -a X"$COMPRESSAFTER" != Xforever -a X"$COMPRESSAFTER" != Xnever ] then # may have some compression to do ... # COMPRESS="$PCP_COMPRESS" [ -z "$COMPRESS" ] && COMPRESS="$COMPRESS_CMDLINE" [ -z "$COMPRESS" ] && COMPRESS="$COMPRESS_DEFAULT" # $COMPRESS may have args, e.g. -0 --block-size=10MiB so # extract executable command name # COMPRESS_PROG=`echo "$COMPRESS" | sed -e 's/[ ].*//'` if [ -n "$COMPRESS_PROG" ] && which "$COMPRESS_PROG" >/dev/null 2>&1 then current_vol='' if [ -n "$pid" ] then # pmlogger running, need to avoid the current volume # # may need to wait for pmlogger to get going ... logic here # is based on _wait_for_pmlogger() in qa/common.check # i=1 while true do # pmlc may race with pmlogger starting up here - a timeout is required # to avoid pmlc blocking forever and hanging pmlogger_daily. RHBZ#1892326 [ -z "$PMLOGGER_REQUEST_TIMEOUT" ] && export PMLOGGER_REQUEST_TIMEOUT=2 if pmlc "$pid" </dev/null 2>&1 | tee $tmp/out \ | grep "^Connected to .*pmlogger" >/dev/null then # pmlogger socket has been set up ... break else [ $i -eq 20 ] && break i=`expr $i + 1` sleep 1 fi done echo status | pmlc "$pid" >$tmp/out 2>&1 current_vol=`sed -n <$tmp/out -e '/^log volume/s/.*[^0-9]\([0-9][0-9]*\)$/\1/p'` if [ -z "$current_vol" ] then _warning "cannot get current volume for pmlogger PID=$pid (after $i attempts)" cat $tmp/out else pminfo -f pmcd.pmlogger.archive >$tmp/out current_base=`sed -n <$tmp/out -e '/ or "'$pid'"]/{ s/.*\/// s/"// p }'` if [ -z "$current_base" ] then _warning "cannot get archive basename pmlogger PID=$pid" cat $tmp/out fi fi fi if $FORCE || [ -n "$current_vol" -a -n "$current_base" ] then COMPRESSREGEX="$PCP_COMPRESSREGEX" [ -z "$COMPRESSREGEX" ] && COMPRESSREGEX="$COMPRESSREGEX_CMDLINE" [ -z "$COMPRESSREGEX" ] && COMPRESSREGEX="$COMPRESSREGEX_DEFAULT" if [ "$COMPRESSAFTER" -eq 0 ] then # compress all possible files immediately # find . -type f else # compress files last modified more than $COMPRESSSAFTER # days ago # if [ "$PCP_PLATFORM" = freebsd -o "$PCP_PLATFORM" = netbsd -o "$PCP_PLATFORM" = openbsd ] then # See note above re. find(1) on FreeBSD/NetBSD/OpenBSD # mtime=`expr $COMPRESSAFTER - 1` else mtime=$COMPRESSAFTER fi find . -type f -mtime +$mtime fi \ | _filter_filename \ | egrep -v "$COMPRESSREGEX" \ | sort >$tmp/list if [ -s $tmp/list -a -n "$current_base" -a -n "$current_vol" ] then # don't compress current volume (or later ones, if # pmlogger has moved onto a new volume since # $current_vol was determined), and don't compress # either the current index or the current metadata # files # $VERY_VERBOSE && echo >&2 "[$filename:$line] skip compress for current $current_base.$current_vol volume" rm -f $tmp/out touch $tmp/out # need to handle both the year 2000 and the old name # formats, the ...DDMM and ...DDMM.HH.MM, and the # ...DDMM.HH.MM-seq# variants to get the base name # separated from the other part of the file name, but # on the upside compressed file names were stripped out # above by the egrep -v "$COMPRESSREGEX" # sed -n <$tmp/list \ -e '/\./s/\.\([^.][^.]*\)$/ \1/p' \ | while read base other do if [ "$base" != "$current_base" ] then echo "$base.$other" >>$tmp/out else case "$other" in .index*|.meta*) # don't do these ones ;; [0-9]*) # data volume if [ "$other" -lt "$current_vol" ] then echo "$base.$other" >>$tmp/out fi ;; esac fi done mv $tmp/out $tmp/list fi if [ -s $tmp/list ] then if $VERBOSE then if [ "$COMPRESSAFTER" -eq 0 ] then echo "Archive files being compressed ..." else echo "Archive files older than $COMPRESSAFTER days being compressed ..." fi fmt <$tmp/list | sed -e 's/^/ /' fi if $SHOWME then cat $tmp/list | xargs echo + $COMPRESS else cat $tmp/list | xargs $COMPRESS fi else $VERY_VERBOSE && echo >&2 "Warning: no archive files found to compress" fi elif [ -z "$COMPRESSAFTER" -o X"$COMPRESSAFTER" = Xforever -o X"$COMPRESSAFTER" = Xnever ] then # never going to do compression, so don't warn ... : else _warning "current volume of current pmlogger not known, compression skipped" fi else _error "$COMPRESS_PROG: compression program not found" fi fi # and cull old trace files (from -t option) # if [ "$TRACE" -gt 0 ] && ! $COMPRESSONLY then if [ "$PCP_PLATFORM" = freebsd -o "$PCP_PLATFORM" = netbsd -o "$PCP_PLATFORM" = openbsd ] then # See note above re. find(1) on FreeBSD/NetBSD/OpenBSD # mtime=`expr $TRACE - 1` else mtime=$TRACE fi find "$PCP_ARCHIVE_DIR" -type f -mtime +$mtime \ | sed -n -e '/pmlogger\/daily\..*\.trace/p' \ | sort >$tmp/list if [ -s $tmp/list ] then if $VERBOSE then echo "Trace files older than $TRACE days being removed ..." fmt <$tmp/list | sed -e 's/^/ /' fi if $SHOWME then cat $tmp/list | xargs echo + rm -f else cat $tmp/list | xargs rm -f fi else $VERY_VERBOSE && echo >&2 "Warning: no trace files found to cull" fi fi _unlock "$dir" done } # .NeedRewrite in $PCP_LOG_DIR/pmlogger is just like -R, but needs # only be done once, e.g. after software upgrade with new pmlogrewrite(1) # configuration files # if ! $COMPRESSONLY && [ -f $PCP_LOG_DIR/pmlogger/.NeedRewrite ] then REWRITEALL=true $VERBOSE && echo "Info: found .NeedRewrite => rewrite all archives" fi _parse_control $CONTROL append=`ls $CONTROLDIR 2>/dev/null | LC_COLLATE=POSIX sort` for extra in $append do _parse_control $CONTROLDIR/$extra done if [ -f $tmp/err ] then # serious errors # status=1 fi # if need be, remove .NeedRewrite so we don't trigger -R processing # next time # if ! $COMPRESSONLY && [ -f $PCP_LOG_DIR/pmlogger/.NeedRewrite ] then if $SHOWME then echo + rm -f $PCP_LOG_DIR/pmlogger/.NeedRewrite else rm -f $PCP_LOG_DIR/pmlogger/.NeedRewrite fi fi # optional end logging to $PCP_LOG_DIR/NOTICES # if $PCP_LOG_RC_SCRIPTS then $PCP_BINADM_DIR/pmpost "end pid:$$ $prog status=$status" fi exit