Revision $Id: webjob-harvest-system_info.base,v 1.16 2006/02/06 05:02:33 klm Exp $ Purpose This recipe demonstrates how to setup and configure a basic harvest/reporting scheme that can be used within a WebJob framework to harvest system_info data, load it into MySQL, and generate a browsable set of indexed CSV- and HTML-reports. Motivation The motivation for this recipe was the need to have a browsable repository of host-based information (backed by CSV files) that can be viewed online or packaged up and disseminated as an archive (e.g., tar ball). Such a repository would be most useful in situations where you want to quickly retrieve information about a given host or set of hosts. As the number of systems in your network(s) grow and evolve, it will be necessary to periodically harvest system information and process it. This recipe provides a simple, convenient mechanism for doing just that. Requirements Cooking with this recipe requires an operational WebJob server. If you do not have one of those, refer to the instructions provided in the README.INSTALL file that comes with the source distribution. The latest source distribution is available here: http://sourceforge.net/project/showfiles.php?group_id=40788 Each client must be running UNIX and have basic system utilities and WebJob (1.5.0 or higher) installed. The server must be running UNIX and have basic system utilities, Apache, MySQL, and WebJob (1.5.0 or higher) installed. The commands presented throughout this recipe were designed to be executed within a Bourne shell (i.e., sh or bash). Solution The solution is to install and configure the build tree, create a custom nph-webjob.cfg config file to handle system_info data, schedule a job (s_hdc_system_info) to harvest system_info data, and generate a set of reports by running make in the build tree. The following steps describe how to implement this solution. 1. Set WEBJOB_BASE_DIR as appropriate for your server. Then, extract build.tgz.uu from this recipe (Appendix 1), uudecode it, and unpack its contents in a suitable location. # WEBJOB_BASE_DIR=/var/webjob # sed -e '1,/^--- build.tgz.uu ---$/d; /^--- build.tgz.uu ---$/,$d' webjob-harvest-system_info.txt > build.tgz.uu # uudecode build.tgz.uu # tar -C ${WEBJOB_BASE_DIR} -zxf build.tgz If you don't have uudecode on your system, try the following: # perl -ne 'next if (/^begin/); last if (/^end/); chomp; print unpack("u",$_);' < build.tgz.uu > build.tgz At this point, you should have a tree that looks like this: build/Makefile build/Mk/common-loader.mk build/Mk/common-macros.mk build/Mk/common-slicer-column-value.mk build/Mk/common-slicer-column.mk build/Mk/common-slicer.mk build/Mk/common-subdir.mk build/Mk/custom-macros.mk build/Mk/custom-slicer-column-value.mk.template build/Mk/custom-slicer-column.mk.template build/MkClients build/MkScripts/data_prep build/MkScripts/data_yank build/MkScripts/make_raw_index build/MkScripts/make_raw_list build/MkScripts/make_raw_report build/MkScripts/make_web_index_for_system_info build/MkScripts/make_web_report_for_system_info build/client/Makefile build/client/loader/Makefile build/system_info/Makefile build/system_info/loader/Makefile build/system_info/slicer/Makefile 2. Edit ${WEBJOB_BASE_DIR}/build/Mk/custom-macros.mk and set the WEBJOB_BASE_DIR and PROJECT_DB macros. By default, these macros are set to '/var/webjob' and 'webjob', respectively. If your server's BaseDirectory is in a different location, modify WEBJOB_BASE_DIR as appropriate. Likewise, if you want to create/use a different database, then modify PROJECT_DB as well. Going forward, this recipe assumes that you've used the default values. # vi ${WEBJOB_BASE_DIR}/build/Mk/custom-macros.mk Various build tree components use WEBJOB_BASE_DIR to determine where the raw (i.e., harvested) system_info data resides, and the PROJECT_DB macro specifies the MySQL database that should be created/used when inserting/querying the data. 3. Edit ${WEBJOB_BASE_DIR}/build/MkClients and insert a record for each WebJob client. The records in this file have the following format: client_id|hostname|ip For example, if you had two hosts, host1 and host2, your MkClients file might look something like this: --- MkClients --- client_id|hostname|ip client_host1|host1|192.168.1.1 client_host2|host2|192.168.1.2 --- MkClients --- One way to create this list is to extract client_id and IP information from the log file (nph-webjob.log). Depending on your naming convention, you may be able to recover hostnames as well. In the example shown above, each hostname can be derived from the corresponding client_id. Thus, the following command (or some variation of it) could be used to build MkClients: # WEBJOB_LOG_FILE=${WEBJOB_BASE_DIR}/logfiles/nph-webjob.log # tail -10000 ${WEBJOB_LOG_FILE} | egrep ' GET .* Success$' | awk '{print $4"|"$4"|"$5}' | sed 's/[|]client_/|/; s/[|]server_/|/;' | sort -u If you want to build a list specific to this data type, then add the target command name to your egrep statement like so: # tail -10000 ${WEBJOB_LOG_FILE} | egrep ' GET .* s_hdc_system_info .* Success$' | awk '{print $4"|"$4"|"$5}' | sed 's/[|]client_/|/; s/[|]server_/|/;' | sort -u 4. Next, you need to create a nph-webjob.cfg file to customize the way system_info data will be stored as it is uploaded to the server. If this file already exists, you'll need to manually edit it and set OverwriteExistingFiles and PutNameFormat to 'Y' and '%CMD/%CMD_%CID', respectively. The purpose of this custom config file is to override the default CGI behavior. Refer to the comments associated with ConfigSearchOrder in nph-webjob.cgi to get all the details. # mkdir -p ${WEBJOB_BASE_DIR}/config/nph-webjob/commands/s_hdc_system_info # vi ${WEBJOB_BASE_DIR}/config/nph-webjob/commands/s_hdc_system_info/nph-webjob.cfg At this point, your custom nph-webjob.cfg file should look like this: --- nph-webjob.cfg --- OverwriteExistingFiles=Y PutNameFormat=custom/system_info/system_info_%CID --- nph-webjob.cfg --- Note that the PutNameFormat specified here is guaranteed to produce filename collisions provided that a given client uploads system_info data more than once. This was done for two reasons: 1) with this particular application, there is no requirement to maintain a history of system_info data (i.e., we only need to maintain the most current information for each client) and 2) it dramatically simplifies server-side processing by creating predictable filenames for all WebJob clients in a single output directory. However, the default CGI configuration will reject any upload that attempts to overwrite existing files. This is why OverwriteExistingFiles must also be disabled, but only for this particular command. 5. Set WEBJOB_CLIENT and WEBJOB_COMMANDS as appropriate for your server. Next, extract s_hdc_system_info from this recipe (Appendix 2), and install it in the specified commands directory. Once the file is in place, set its ownership and permissions to 0:0 and mode 644, respectively. # WEBJOB_CLIENT=common # WEBJOB_COMMANDS=${WEBJOB_BASE_DIR}/profiles/${WEBJOB_CLIENT}/commands # sed -e '1,/^--- s_hdc_system_info ---$/d; /^--- s_hdc_system_info ---$/,$d' webjob-harvest-system_info.txt > s_hdc_system_info # cp s_hdc_system_info ${WEBJOB_COMMANDS}/ # chmod 644 ${WEBJOB_COMMANDS}/s_hdc_system_info # chown 0:0 ${WEBJOB_COMMANDS}/s_hdc_system_info The s_hdc_system_info script is designed to harvest system information and format it as follows: nodename|os|os_release|os_version|machine|processor|platform The 's_hdc' name prefix indicates that this is a "standard harvest downloaded command" script. 6. Schedule s_hdc_system_info to run on your WebJob clients. If you don't have a established/preferred way of doing that, take a look at this recipe: http://webjob.sourceforge.net/Files/Recipes/webjob-run-periodic.txt If you are using the hourly script, drop the following command into the script -- e.g., as a one-shot or periodic job. ${WEBJOB_HOME}/bin/webjob -e -f ${WEBJOB_HOME}/etc/upload.cfg s_hdc_system_info Now, sit back and wait for the data to roll in. 7. Once all the system_info data has been harvested, you'll need to process it. This can be done on the server as follows: # cd ${WEBJOB_BASE_DIR}/build && make Before you tackle this step, make sure that MySQL is running and your account has access to it. If you need to use credentials to access MySQL, you'll need to put them in your ~/.my.cnf because the current build scripts are unable to handle credentials for you. If the make process completes successfully, you'll have a new directory under ${WEBJOB_BASE_DIR}/build called ${PROJECT_DB}_reports. This directory can be explored with a web browser, or it can be packaged as a dated tar ball using 'make dtar'. Alternatively, you could make the reports accessible to remote users via Apache by copying or linking the reports tree into the server's web tree. Here's what an example build would look like with two hosts such as those used in step 3 (i.e., host1 and host2): ===> client ===> loader yank... ---> client.out prep... ---> client.out load... ---> client.out.sql ===> system_info ===> loader yank... ---> system_info_client_host1.out ---> system_info_client_host2.out prep... ---> client_host1_system_info.out ---> client_host2_system_info.out load... ---> client_host1_system_info.out.sql ---> client_host2_system_info.out.sql ===> slicer ===> client_id ===> c0/da/6d/client_id_c0da6d00bda11671cd359f0df20bb385 ===> 77/d4/80/client_id_77d4805ea5ee6d36720391cb32ecf78b ===> os ===> a3/dc/63/os_a3dc630729e463135f4e608954fa6e19 ===> os_release ===> 6d/bc/dd/os_release_6dbcdd54896178633c0e754921a491ef ===> fe/93/f9/os_release_fe93f9e525180fe2cd676bfc9425fd1b ===> os_version ===> 6a/7b/42/os_version_6a7b4244eb9f3237a41758fe9ffe2ae3 ===> machine ===> 30/5f/2c/machine_305f2c2be1993430e0808181e5be473e ===> processor ===> 30/5f/2c/processor_305f2c2be1993430e0808181e5be473e ===> platform ===> 6c/3e/22/platform_6c3e226b4d4795d518ab341b0824ec29 8. To automatically process system_info on a nightly basis, you'll need to create a cron job that does the following: # cd ${WEBJOB_BASE_DIR}/build && make clean all The clean target resets the build environment by removing temporary output files and deletes tables from the database (i.e., ${PROJECT_DB}). Closing Remarks The build tree presented in this recipe can be adapted/extended to process other/multiple data types. However, the web-based reports do not scale well beyond a few thousand entries per column. This effectively restricts the usefulness of this recipe to small- or medium-sized data types. This limitation could be fixed by splitting the web-based reports in to pieces with next/previous links as needed. The make tree could be better. It shouldn't be necessary to clean out the database and rebuild everything each time new data needs to be processed. Th harvest script in this recipe was originally designed to collect system_info data from Solaris and/or FreeBSD systems. Some, but not enough, effort has been made to support other UNIXes. Also, the processing scripts in this recipe were originally designed to work on FreeBSD and Linux. In other words, your mileage may vary. In particular, you may find that the head and tail utilities used in the various components may cause problems for certain platforms. Credits This recipe was brought to you by Klayton Monroe. Appendix 1 --- build.tgz.uu --- begin 644 build.tgz M'XL(`!?$Z$,``^P]^V/:.-+]-?P56I+FH*1I8TH]%H7I+EBY'1ZV:>K#1EL_GL M;J$`W]FLDL\'OGEZHF1SNZJ25[/JSI.LDMTIY)^0PFK18FED.YI%R).;7G]! M.=VRUX'0>M,%'?_CFU6RP)>/OZ*JN;68RQ.@.*E^'I(XUHX.C=.1-31MO4@.*"KD M6+O1+XV>3BY-BS"\2->P](YC6H9NIZ.#'C,&G=ZHJY/X_?'/[=-&];#VVUA, MK+[6L4P;*!*+';]O5\JMG]:'=/2 MK?+^4946];*U7J](NQ.+=7JZ-@#2XY?L:!<]/;;UVNH3^9(\3YLC!SZ[%P9\ MVA][I/V\W34'.J\ETV;HIV>Q+>.2_$XDCX;2;Z1$I$[/T`<.7'^` M%IQK?0`EMP9:7R^Q.Y2`7MLGY>/JF#;'VCN_[1"YY^O0P5&M>M)JM@]KT!WH MB'9[0Q+W0\L8."0>5\:)X2U0_N7U412WTQSD$]?3W,JWLC+93KMZ^(*]'_8_G/55(0P%MA_JK*S0^T_A3H`!6;_ M[6SLOW6DB$R?L/WGLA&U_PJ>_9=JB1"`?*,3V689[>/R0:/>+&WQVO%[=C$6%Z*9,2_? M?+YY)!E^94K']$D'.I6C\@@AQ-VYH_D[R\^O$AEAEKG)BD=/)>V@`0,::?;\']-A2;Y-$"NM_NV=T=$ON MF+U1?R!_TGHC_9N-@07Z'[1]-A3_V=F%KXW^7T.*2!6&]?]T-J+&@/K=!(-> M4KQ>/7(TB$9@P($3<1SP0T##E\Z'MUWT'N!.T*]`]7_.HQ(LR`.9\',\+:0# M^47F9S'-S/1P,#1"E@9'Z54Z[V@.:=/K<^JMQ._]RG\<\@C][B"]/J@?O3L^ MH<$)VLB8O!)=H,UA/(/_G,0\-I%5#/4F%,KP%_6B&?T;&'30=U/*8(SC[Z.A MYLK_B-S`!?(_GU5WF?]7R.?5?!;*%W9492/_UY$B$G9SY;^0_'E/\N^0;*Y8 M*!05]7$D/T/LL46_\*\\H4B=J335!J[#YKM+O3-V>X':P%XR\WXRCM7E0:Q` MTV?/O6@6RO^@%N">`I/W6S?Z7>F<^A1P"XMAH-O6NT0"YR'0:B:S)_%*=L]T MO%K0Q-AS.XB,CLR?*C)EQ_NU7%JT>_T\VUP/\`95N%_;GLO(6!1 M=$N(.$"EWC)#TPO;09G@H/+R:PM=>+-#+]SC` MJ,7H6`;57_LYZC):`*L('\I-#%&]2[D)<)+L[=?]NS8-0K_>]A%^^VI/ M(J%23#3Q8AS>M'*(%93BZ'DEIKG>T\WQ-"ZV]31'9P88HIYQQ23M`X\;"$-- M\A5D!J!O!DPW-4,FGV`L$%;#T+P(&F%H!V[$V:.)L\_3_9 M7'YR_\_NQOY?1XK(XIUN_W]_^W\87H^__V?FCIYKI]^;9M*'56#\G@GOYEAH MN?59M0(RU_FX48#`+'+LJ9&F+^B"WY`2?1"V%%EH1TTQH=QFOL`\FC2,>!LA MVV@Y>C(ZXJ@R;XV9SM.(0"8&,DS,S*RAG;$-9U;=)3;ES%N_N]4O^/I=&P"W M_;LX'/_(S=Q!(_80+0)"O=T0#&8$!^',Z:OG,5.W9IF":1PLW]A1SB[&8LCF M=%O<9W#1;6[Z2&>*<8$E]B MH2P11(X"@KSB?BRYZSRT63VDFM57)-/5/V4&HUZ//("BMD9_V9"()_]#FW0B MA+%(_BN*RI__RNWDL[M4_N_E-4 MPOL_B0;NT2?-,M")C%3Z3]LA7_(D2Z->;X$/><,>]+"]\JXNB-__6MW_5WV_ MO5]N5IDF`(UB]HW!%9^>ODK[)7"1_F->>%D^"WX";$#`<>_-AX+/_YJ"<;-C M&4,L'D*OE`$Z9@0:C\W)F_0U*2S_%ZP4?16,A?(_OQ/<_Z%F"SL;^;^6%)'P M"\O_!6P4U@IKW`[BJ@,WQN?%A3-B7TAFQ5L#_1*VM)5.9R;^P$L0+H3?1Q`B MV0LBE[:\D"C-96N5+)L'0FF^7SWX#-Y@/,P+7`76NS/N@O-\)V?ZL&]TP_>; MYLK_;Y;\+"V2_]G";FC];S>_L]G_MY84D42;*_\G)/_C;`%?2O*O5^(_NI3_ M`G&^$>1_Q<3E/Y\:JX&QZ/G?W"[*?U7-%?*[.7K^CYK+;>3_6E)$\LV5_X*3 M/#E?R&3S(.J)LE,LP-_*Y/R!.;RSC*MK!X'F981,?NYI=PZN`9@#R]2W2;G7 M(PTL8Y.&#@/Z2>]&*.2G:QM4,B'1OD+%LE"CM.JG/&S>+&W1XT-H/(KNLKBS M036VC<&E^45/+RV(Y_L@KG!M(AHHRZQ/?"LDWTZ::>J9/$\[5W_&4+/;'WM: MMP]`91F0Z.BD:YG#I18K-!!J8(RA:.O"!_0.,Z#1\%[8J2A@K^F!%I+8:=KN MC"P+3\,!U"3:%6Q:_K-SZ9TQX^Y*A;Z+?;'T3BS6_5+H73#/2N?X2:07S][+ MS_KRLZXT!2_B4P%NC_+)[YI["@7S:O M**C_-_[?FA*3_FVC^W!MV@[.B@=CN)D6?YLDYC]?XUG),:!??OZG6MC=G/^Y MEA0>?_?4KPAAH/R?/?Z*`C?Y_J_`%FK#$Z.-B M?,0NX9M&^=AO:&?/8[%WMG:E)U.Q^QAA9K#RZD=57$OT;I&9Y%A[3'Z7'4(C MCA_P!$!F*,CT?$JY0KH7>+:?S:2&3#<2MPC=5RY?TKWH4J!Y: MLGT2[)`I26+;XO;%%=T\P:_Y[@3QDP5$Q8_WI^SZ]AJ=[2O=,0$A(AT4*\7+ M8K/8*CI%B=1/6[7Z"776`(L.DEV*W[/0>I."#D#!BM%BY\68LT=M[ M>_!5<8LBPM-*7+HE6$>FE6FZ9=P.3BO6'>7G5ZWN<^$%$VO0P?!4-W>%Z9JZ30:F0^B6?0(SVV"_+5WKXNQ))Z0`^ZL4C]-?*RS`P-B^YNX6 M^K4RSO@]9$&(GBL8W2,P<#J;R,@+!XUJN57%!DO3-TRR MHGN465AA7H3=H/E)^DF(ZTC@YBI0*9IUE]S)IR@I,#:QS",Q5,,9>3]VDFSVFBQ/A[5RQ6"NZT@%\E$$IQ[&?7' M"Y)X@#IO3NJ-*E'(4>VDVIQ. MDW#GO5Z&\0V^'E)[",#'/P MT-W;=-ZP&4V4'9]*<1M`68"?CNIMP3/^8.07\-?`LUP,5\1 MTYY[4W1M?B'>Z3F%.#GFE'`)-:\,)^'<9OX'IX(8)X^DDR,P2>X0;2<(&:9: MD`9/R8GI@)'3N@89#7_V4.\8ET8'#]H&P4_85D;Y6@-KT'9D'RN"-.\80SV- M?,Q41JU2FB9YB>]9-?I07:!&_-Z]ED>#FX%Y.T"2OJTW6_1`RG/]"@]Q9[Z!X&3#$2?U]OE288' MLD-[/I)Y)/#1[.D$S5"4(\5XH$\ZP))E39,1IA$Z8I&VJ* MSK2Q:H-/6@\$/74GDAYOI"9-*=H:-6'])J&G:M#ZU'BN)_^"LP&;HC89GFLG MB[$19M:8O'Q)JO7#2/U3L`T=W74!MW'P!SI*,!#C47J"7,^BH,=-VR%5*VSW MO5B4G6OJ#M$ZCO')ZV"477K7K*X(<3XJU.5=W9`$N#-2_/='O1OZ1A"JRY#V MT>+MFS^Q&,Z(S3+!_WZ:&O_%MU1$"&-^_#>;R^TJ?/_GCI++9FG\M[!Y_]-: MTHKCO\A)X4>`H8C-3TZ/#<@_):& MA+_3@/!;MXS;X17'C5<7$EXF`CPE`+QL_/>TW'I;"C17!`:&S/'W$^(5>%S. M\.GF^#_#$0>=]*JFYN%Q->IIUGPT9KF6DVC\JED#8W`U&Q$`J_>'SEV:!0'Z MVATB@U^(S85.M`&4L4<>81"1_>G./_/XI\>J*7^>B&,6[_=]!S-Z)=FIC*$8 M`L[JH1],_/YD['<7'UOQ?B@NK524*TEJ"F@(A782A>Z]![=*_)R;NC(_;R#CL=,O,F M`J@#'(=*=?_=FU"4E)L)+'SJ*O5@MG>>#COBSK^:>>9D1*@8@\N(4S"ZS'-\ MP63,R>!KI1Y;2OYUTTS]C^9O1#`6Z/]=5-8Z(/NB87?!GJ*]I7I(N?!N#CN,*Z^@L!.!?8CN6T7'V MZ'7%N-)MIU@\KA3(Q]MDOUMH7^N?4^SF(;A\Q>(^MR58WAL:22D6FTXWVG67 M8\T8D`;X;,9`C[##A$32#C2#_V$`!YUK?``,SX^Z,E'%WIK635H4B`(6M-._ M`U?;/K7,*TOKPVA`EOL33!)AWB7;U*UMMUF12*"+GL)`D_K0,/;OF MC3/4P>I(_L"C=,E$I]@M.L7$-CGSBJ$Y=>_%J0+D(60<>?_+OH79A-P%9,"V MLO2/(\-"L;"*\:Y=OKIF'M$CT62T_@27]W1+.N1GU\LI'T]$OP^@R' MWB`ZAEJC)BI2P.YH/$0ZLSIH*\ZU!K?,4:]+[@P=/E'KV-`? M;*6O?09R#JZ:2P'/9>:W]R3:C#G4 M!\GC]^"L;A.)NJYG$FWZS.>[H@Q^D%+X,'77P+"$&+`BX/9#ZFP@N?,%'>P2 M47`@V7)3$CH0MX]PVV>)O*207GD,(.[\%SS9E8%?M$>(2MBR`6,5$8A1G@E6EO/Q2Y"0\\>7?C:O?>4*FCQ%%#D=5OH M5EQ^I<1/_OX'2;?IRY?^3Y/_E#^D,C:ET&52>O;L65;]#`0:#>@+L!,'B6U\ MQ77&UJ_V0NV0S(N,?46;MW1G!!.)W=W#%: M+9A+#9=+@IDB(NB:J'*7/AK$GQS"%]4QE3:U-L_$`&%225&B/;8__'=+,^,_ M[(S82&`L7/_)[H;C/[OJ)OZSEK2&]1_&29O`CW\!B-%DS2M`^:57@`CYI7ST M#K+SW[`8Q,S)14M"5+LUCN2NCNJ;FI?LW%"XPY`0J__TU\2JP@M0PC9=,WA& M7Z>HR9=E^9"^3C'CZF]";2:AQ!."+I)H5/H-;4M<;H`K'Y$.ZB>5&NX)*KF+ M5MY2$ZDUZ@_HZ&//UO[HKWO_H._][=[/_ M=SUI7>L_,UF*V@7_6.=1X`&[(/>]V`7^APTIH3;+/]_2'F)4R\9HBY?9F,Q\=LW\>=[<_IL#LV=::"T\[=`DN?=.+?W2 M^(RWTE+TJS*;]:=O;7^9]:?'7GO"33TUG/TM^HK.GG:UML44%RR&!EN&XZVL M>`A%M+KB-K@,?;%N`(?_DLP?KDT;SQC^^"K%&Z<@W\1=J[BA33#2IS9EVK/: MJ#>7J"R>59_="&@06F*9QOAC[G,:^X656-@8?T)^5DO'[/;"9MPGZVT(FE*IC;@X1#-(<@GS@$7Y0KUJT>9]GJ)5'6OF[GZ/_?WK4W MIVT$\?SM3Z%0VIH$(UZVFP28<1R[N(V+!^.99&R7(4!L:HP8@]O)N/2S]]X/ M/9"$=3))=B>3!.FT=WM[>[>GW9_N#J_5#C(!I"P./$A\"4`C;(C&/EVR#TG, MA@JM#$G?55Z&6K!C1",M[\A+BTVQ*E*.>>0!('\FD\NQITC8Z:B)KM=H"26Z MA'_BD8O_%8,V^UR.45+E41,M^\1,+EX<-94;+>4&,H[668?5R0,^O$"FAL\U M;M0^.8,O#<'\!)' M/50:1]=$KS1P9V98+;*$7Y1-=?QFTS&R?IR4FA=/Y:VM$A/[?C*['GV>;XI' MD/K&:,KLDKS:3&#GS.^L3U=]/'[J.+C(QA(2A#70-0!Q;%7605.'Z3CD2Q\M M0Z9067_6SK%"O+!O6ZXM-/E=35!+^F@R&:)F!#3NI\FGV?1-S9Y?\W;2*9', MDG0>3JXR)I-?;8N`7K7G=^Z1@*.;/`1;I%S\@K!RF.B=NRP8:ZGL7[YDM2Z? M&BQM`Z$/+LQ+&5KJX&KSP:74F!,LJ?&3I4L(&<4E0A.J_Y=]W6K,DOW-P\]R M9"'7#1'R]&B$?S/+FWC.JKRDWI[G,O+X,G089=[P5N.^Q$?2 MUD7!O*:Q&L#/9S?73!&I2"#Y6"+MA_XF_;(FW<5%71 M[3E)O17N/+OZ!T[/J,MD3BH^8[K(O=%+GXX=O,6ACRF=QFZ@_4O^3Y+ZL+=U MV-OZ3%(?PGX77N2S)3M;MK.5O-(ZSX93V520(XV6;3I(`5T4"VVPN#IRHA;9 M1Y;H(KRAJO6LZ[OA9]+_]`V$+?C;5%QYH9NQ"KPK"_2%2P&_X<`:PW=<#2G@ M/61/*E/:I6*9BN#8F_:5F+C9)D1U9EQ&Y!68%DZZJ@%"*KZL&6%Y!8K0[(IY MX85?&"2\=!P-"<\J4(1G5PP++YPP7\FEBV9";,:=R\Q^&A98\75\159](1-" M"_Y<;''!M.#"K?"76WH=1L1F[(74['>R0@_#FN;BY\>&++'[P_%X#[^[[/2N ML-9FT"U!#O0$F*R44&HS8RB@`^GL=`;T"#"U"SYP/O MV]@E[T9E,;]"^&5[O#?_I,RAX\S=94@@*,_2*P+?A-LDUE"S2>!!OKRE&!/Q M6M90/&D?'^=X/^7I$M?.[3#I4!+&QB2:$L15DC#00_*58`^ORB52AN3"_/I^ M-+F96?4-_@UWQHBZWFV=1K^$'="?![F@?QP)GPQ]V/"`O@A3/CJZ.'``O_&P"(,T&3^%Q#@/1G?S.,Z`QG M^F/'&\0Q0Q,/+#%)$5H,3 M[N4O#U:$KKRA8!%MV!.TB#)L`2ZB6VE]Z@R2[I$V/A-Q1#]WIN.F*QN]?^W< M3GFHA_@=6A*YR`G)XMH?LKWSXB7^I(3^RC.GAH#8I[R:3`'U_OW\.P3ML&&W M`G*'E_Z/G&:IF#8&"6@WNQPV@`>"6/V(GDBQ1O]6.S5H%'K68*H"/^9EH''_%5@:J'`([T]])B`"SA6&EL4B7D$(.* MFT'_?A[`@.*7/*"7?T:#^36Z\.J7'S$$)BJ\*0%3(6SHWPK^XS$G=ZLL$S'E M)3`N:43\OMMNED&[8H&[HL*[4LD4C`3STG,+T\]-Y-\ M'B7]7-ER/U\Y_USOL*?,05>7W;`\=+?H\1+18\J<:#)Z%"G=">E>:5?)2(\M MM<&L]$B]X,I,]^F%%5+3X_>"N?3T\%YPI:B[NV"%'/68\AO*4P^7W).K[I9] MI63UF-(;3%B/T`.NI'5/!ZR0M1Y7?E.9ZQ[IAU&:&)C!KK/SRRH/R"-7'PS) M)0__*,`Z)YY!XS@WSJTL\IXL^9)Y# MYCEDGD=@"9GG0*L3S?^F6K8-U5$L5I>=_X.)Y'^72]5RL;SSK%@JERKE9]:V MH?9H])WG?VOZ'SLX3)KX,(BO_TH570+]IT!^^C_NW0SQE)U4'1C_L>/2NZK_ MTJX\_[U4(>=_%:L5P'^D0?C_2>_"8BO_VIU!_9_J5"@_A/T!4+7?W;^GUS_=TIE./\O%7J$_Z\, M>3(!_BEQ:V5ACV"&M#7OM/?A,0:O_;;ONO[NR4P/[3H%#_7S/<9#X$G):_]4*4_M_^UN@_^7!@7J/T7_K[+M?O^#_MF%^3\-2LK_XS.[/&S> MF2DGX"B'K_"C/^2Q$^+,`\*[?7#2:G=.79ZD&2 echo "Usage: ${PROGRAM} [-H]" 1>&2 echo 1>&2 exit 1 } Main() { #################################################################### # # Punch in and go to work. # #################################################################### output_list=" nodename os os_release os_version machine processor platform " count=1 for field_name in ${output_list} ; do eval ${field_name}="" count=`expr ${count} + 1` done field_separator="|" #################################################################### # # Process command line arguments. # #################################################################### while getopts "H" OPTION ; do case "${OPTION}" in H) print_header=1 ;; *) Usage ;; esac done if [ ${OPTIND} -le $# ] ; then Usage fi #################################################################### # # Harvest raw data. # #################################################################### os=`uname -s 2> /dev/null` case "${os}" in FreeBSD) machine=`uname -m 2> /dev/null` nodename=`uname -n 2> /dev/null | cut -f1 -d.` os_release=`uname -r 2> /dev/null` os_version=`uname -v 2> /dev/null | sed 's/ *$//; s/^.*\(\#[0-9]\{1,\}\).*\/\([^\/]\{1,\}\)$/\2 \1/;'` platform="" processor=`uname -p 2> /dev/null` ;; Darwin) machine=`uname -m 2> /dev/null` nodename=`uname -n 2> /dev/null | cut -f1 -d.` os_release=`uname -r 2> /dev/null` os_version=`uname -v 2> /dev/null | sed 's/ *$//; s/^.*\/\([^\/]\{1,\}\)$/\1/;'` platform="" processor=`uname -p 2> /dev/null` ;; Linux) machine=`uname -m 2> /dev/null` nodename=`uname -n 2> /dev/null | cut -f1 -d.` os_release=`uname -r 2> /dev/null` os_version=`uname -v 2> /dev/null | sed 's/\(\#[0-9]\{1,\}\( SMP\)\{0,1\}\).*$/\1/;'` platform=`uname -i 2> /dev/null` processor=`uname -p 2> /dev/null` ;; OpenBSD) machine=`uname -m 2> /dev/null` nodename=`uname -n 2> /dev/null | cut -f1 -d.` os_release=`uname -r 2> /dev/null` os_version=`uname -v 2> /dev/null | sed 's/ *$//; s/\(\#[0-9]\{1,\}\).*$/ \1/;'` platform="" processor=`uname -p 2> /dev/null` ;; NetBSD) machine=`uname -m 2> /dev/null` nodename=`uname -n 2> /dev/null | cut -f1 -d.` os_release=`uname -r 2> /dev/null` os_version=`uname -v 2> /dev/null | sed 's/ *$//; s/^.*\(\#[0-9]\{1,\}\).*\/\([^\/]\{1,\}\)$/\2 \1/;'` platform="" processor=`uname -p 2> /dev/null` ;; SunOS) machine=`uname -m 2> /dev/null` nodename=`uname -n 2> /dev/null | cut -f1 -d.` os_release=`uname -r 2> /dev/null` os_version=`uname -v 2> /dev/null` platform=`uname -i 2> /dev/null` processor=`uname -p 2> /dev/null` ;; *) echo "${PROGRAM}: Unsupported OS (${os})." 1>&2 exit 2 ;; esac #################################################################### # # Print report. # #################################################################### count=1 header="" for field_name in ${output_list} ; do header=`AddListItem "${header}" "${field_name}" "${count}" "${field_separator}"` count=`expr ${count} + 1` done count=1 output="" for field_name in ${output_list} ; do eval field_data=\$${field_name} output=`AddListItem "${output}" "${field_data}" "${count}" "${field_separator}"` count=`expr ${count} + 1` done if [ ${print_header-0} -eq 1 ] ; then echo "${header}" fi echo "${output}" } Main $* --- s_hdc_system_info ---