Commit b382bfa3aa3f8ef3b35d06c286b09bf9b19a5793
1 parent
dee510b3
add system information gathering, in cfengine speek this will create our hard classes
Showing
1 changed file
with
315 additions
and
0 deletions
system_information.sh
0 → 100755
| 1 | +#!/bin/dash | |
| 2 | + | |
| 3 | +## | |
| 4 | +# This is a first test what static informations I can gather from a | |
| 5 | +# system. The minimal requirement are the IP addresses because | |
| 6 | +# on these I build up my classes. | |
| 7 | +# The system type is also important...we might need to be running | |
| 8 | +# on variuous UNIX flavours. (But for now we focus on various linux | |
| 9 | +# flavours and maybe FreeBSD. | |
| 10 | +# | |
| 11 | + | |
| 12 | + | |
| 13 | +# Function calculates number of bit in a netmask | |
| 14 | +# | |
| 15 | +mask2cidr() { | |
| 16 | + local NBITS=0 | |
| 17 | + local OLDIFS="${IFS}" | |
| 18 | + IFS=. | |
| 19 | + | |
| 20 | + for DEC in $1 | |
| 21 | + do | |
| 22 | + case ${DEC} in | |
| 23 | + 255) NBITS=$((NBITS+8));; | |
| 24 | + 254) NBITS=$((NBITS+7));; | |
| 25 | + 252) NBITS=$((NBITS+6));; | |
| 26 | + 248) NBITS=$((NBITS+5));; | |
| 27 | + 240) NBITS=$((NBITS+4));; | |
| 28 | + 224) NBITS=$((NBITS+3));; | |
| 29 | + 192) NBITS=$((NBITS+2));; | |
| 30 | + 128) NBITS=$((NBITS+1));; | |
| 31 | + 0);; | |
| 32 | + *) NBITS=0; IFS="${OLDIFS}"; return 1 | |
| 33 | + esac | |
| 34 | + done | |
| 35 | + IFS="${OLDIFS}" | |
| 36 | + ${ECHO} "${NBITS}" | |
| 37 | +} | |
| 38 | + | |
| 39 | +cidr2mask() { | |
| 40 | + local MASK="" | |
| 41 | + local FULL_OCTETS=$((${1}/8)) | |
| 42 | + local PARTIAL_OCTET=$((${1}%8)) | |
| 43 | + | |
| 44 | + for I in 0 1 2 3 | |
| 45 | + do | |
| 46 | + if [ ${I} -lt ${FULL_OCTETS} ] | |
| 47 | + then | |
| 48 | + MASK="${MASK}255" | |
| 49 | + elif [ ${I} -eq ${FULL_OCTETS} ] | |
| 50 | + then | |
| 51 | + MASK="${MASK}$((256-(1<<(8-${PARTIAL_OCTET}))))" | |
| 52 | + else | |
| 53 | + MASK="${MASK}0" | |
| 54 | + fi | |
| 55 | + ${TEST} ${I} -lt 3 && MASK="${MASK}." | |
| 56 | + done | |
| 57 | + | |
| 58 | + ${ECHO} ${MASK} | |
| 59 | +} | |
| 60 | + | |
| 61 | +## | |
| 62 | +# retrieve interfaces. I prefer using ip if it is | |
| 63 | +# available, else I fallback to ifconfig... don't know | |
| 64 | +# how to retrieve this information on other systems. | |
| 65 | +# | |
| 66 | +get_if_data() { | |
| 67 | + if [ ${IP} ] | |
| 68 | + then | |
| 69 | + eval $(${IP} -o link | ${AWK} '{ | |
| 70 | + sub(/:/,"",$1); | |
| 71 | + no=$1; | |
| 72 | + sub(/:/,"",$2); | |
| 73 | + name=$2; | |
| 74 | + for (i=3; i<NF; i++) { | |
| 75 | + if ($i == "state") { | |
| 76 | + i++; state=$i | |
| 77 | + } | |
| 78 | + if ($i ~ /link/) { | |
| 79 | + i++; mac=$i; | |
| 80 | + classes=classes mac " " | |
| 81 | + } | |
| 82 | + } | |
| 83 | + print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";"; | |
| 84 | + if ("UP" == state) classes=classes mac " " | |
| 85 | + } | |
| 86 | + BEGIN { | |
| 87 | + classes="" | |
| 88 | + } | |
| 89 | + END { | |
| 90 | + print "CLASSES=\"${CLASSES}" classes " \";"; | |
| 91 | + print "NINTERFACES=" FNR ";" | |
| 92 | + }') | |
| 93 | + | |
| 94 | + eval $(${IP} -o addr | ${AWK} '{ | |
| 95 | + sub(/:/,"",$1); | |
| 96 | + no=$1; | |
| 97 | + if ($3 == "inet") { | |
| 98 | + sub(/[\/%].*/,"",$4); | |
| 99 | + print "IF" no "_IPV4=\"${IF" no "_IPV4}" $4 " \";"; | |
| 100 | + classes=classes $4 " " | |
| 101 | + } | |
| 102 | + if ($3 == "inet6") { | |
| 103 | + sub(/[\/%].*/,"",$4); | |
| 104 | + print "IF" no "_IPV6=\"${IF" no "_IPV6}" $4 " \";"; | |
| 105 | + classes=classes $4 " " | |
| 106 | + } | |
| 107 | + } | |
| 108 | + BEGIN { | |
| 109 | + classes="" | |
| 110 | + } | |
| 111 | + END { | |
| 112 | + print "CLASSES=\"${CLASSES}" classes " \";" | |
| 113 | + }') | |
| 114 | + else | |
| 115 | + if [ ${IFCONFIG} ] | |
| 116 | + then | |
| 117 | + #eval $(${IFCONFIG} -a | ${AWK} '{ | |
| 118 | + eval $(ifconfig -a | awk ' | |
| 119 | + /ether/ { mac=$2 } | |
| 120 | + /inet / { ipv4=ipv4 $2 " " } | |
| 121 | + /inet6/ { ipv6=ipv6 $2 " " } | |
| 122 | + /^[^ \t]/ { | |
| 123 | + if ("" != ipv4 || "" != ipv6) state="UP"; else state="DOWN"; | |
| 124 | + if ("" != name) { | |
| 125 | + print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";" \ | |
| 126 | + "IF" no "_IPV4=\"${IF" no "_IPV4}" ipv4 " \";" \ | |
| 127 | + "IF" no "_IPV6=\"${IF" no "_IPV6}" ipv6 " \";"; | |
| 128 | + no++; | |
| 129 | + } | |
| 130 | + ipv4=ipv6=""; | |
| 131 | + sub(/:/,"",$1); | |
| 132 | + name=$1 | |
| 133 | + } | |
| 134 | + BEGIN { | |
| 135 | + no=1; | |
| 136 | + } | |
| 137 | + END { | |
| 138 | + if ("" != ipv4 || "" != ipv6) state="UP"; else state="DOWN"; | |
| 139 | + print "IF" no "_NAME=" name ";IF" no "_STATE=" state ";IF" no "_MAC=" mac ";" \ | |
| 140 | + "IF" no "_IPV4=\"${IF" no "_IPV4}" ipv4 " \";" \ | |
| 141 | + "IF" no "_IPV6=\"${IF" no "_IPV6}" ipv6 " \";"; | |
| 142 | + print "NINTERFACES=" no | |
| 143 | + }') | |
| 144 | + else | |
| 145 | + ${LOGGER} -p local0.warn 'Found no way to retrieve interface information.' | |
| 146 | + fi | |
| 147 | + fi | |
| 148 | +} | |
| 149 | + | |
| 150 | +## | |
| 151 | +# start guessing the system type | |
| 152 | +# 1. get informations via uname | |
| 153 | +# | |
| 154 | +get_host_info() { | |
| 155 | + OS="$(${UNAME} -o)" | |
| 156 | + KERNEL="$(${UNAME} -s)" | |
| 157 | + VERSION="$(${UNAME} -r)" | |
| 158 | + PLATFORM="$(${UNAME} -m)" | |
| 159 | + HOSTNAME="$(${UNAME} -n)" | |
| 160 | + CLASSES="$(${ECHO} -e "${OS}\n${KERNEL}\n${VERSION}\n${PLATFORM}\n${HOSTNAME}" |\ | |
| 161 | + ${SORT} -u | ${TR} "\n" " ")" | |
| 162 | +} | |
| 163 | + | |
| 164 | +## | |
| 165 | +# if we are on a linux try to figure out wich distribution we are | |
| 166 | +# running. | |
| 167 | +# First look what kind of realease file we have: | |
| 168 | +# | |
| 169 | +# 00 01 - Novell SuSE ---> /etc/SuSE-release | |
| 170 | +# 00 02 - Red Hat ---> /etc/redhat-release, /etc/redhat_version | |
| 171 | +# 00 04 - Fedora ---> /etc/fedora-release | |
| 172 | +# 00 08 - Slackware ---> /etc/slackware-release, /etc/slackware-version | |
| 173 | +# 00 10 - Debian ---> /etc/debian_release, /etc/debian_version | |
| 174 | +# 00 20 - Mandrake ---> /etc/mandrake-release | |
| 175 | +# 00 40 - Yellow dog ---> /etc/yellowdog-release | |
| 176 | +# 00 80 - Sun JDS ---> /etc/sun-release | |
| 177 | +# 01 00 - Solaris/Sparc ---> /etc/release | |
| 178 | +# 02 00 - Gentoo ---> /etc/gentoo-release | |
| 179 | +# | |
| 180 | +# Here I follow a pessimistic way because I prefere to have no | |
| 181 | +# identification at all over a wrong one...so I check for all these files. | |
| 182 | +# If I can't find any or find multiple of them I assume this system | |
| 183 | +# as unidentified. Anyway when I found one I still check the content... | |
| 184 | +# Here I need some help as I don't know the valid content of these files. | |
| 185 | +# For now I assume that at least the name of the distribution is in | |
| 186 | +# the file. | |
| 187 | +# | |
| 188 | +get_dist_info() { | |
| 189 | + if [ -z "${KERNEL}" ] | |
| 190 | + then | |
| 191 | + get_host_info | |
| 192 | + fi | |
| 193 | + | |
| 194 | + if [ "Linux" = "${KERNEL}" ] | |
| 195 | + then | |
| 196 | + local SUSE=1 | |
| 197 | + local REDHAT=2 | |
| 198 | + local FEDORA=4 | |
| 199 | + local SLACKWARE=8 | |
| 200 | + local DEBIAN=16 | |
| 201 | + local MANDRAKE=32 | |
| 202 | + local YELLOWDOG=64 | |
| 203 | + local SUNJDS=128 | |
| 204 | + local GENTOO=256 | |
| 205 | + local SOLARIS=512 | |
| 206 | + | |
| 207 | + local LAST=${SOLARIS} | |
| 208 | + | |
| 209 | + local CHK=$((SUSE|REDHAT|FEDORA|SLACKWARE|DEBIAN|MANDRAKE|\ | |
| 210 | + YELLOWDOG|SUNJDS|GENTOO|SOLARIS)) | |
| 211 | + | |
| 212 | + eval local FILES_${SUSE}=\'/etc/SuSE-release\' | |
| 213 | + eval local FILES_${REDHAT}=\'/etc/redhat-release /etc/redhat_version\' | |
| 214 | + eval local FILES_${FEDORA}=\'/etc/fedora-release\' | |
| 215 | + eval local FILES_${SLACKWARE}=\'/etc/slackware-release /etc/slackware-version\' | |
| 216 | + eval local FILES_${DEBIAN}=\'/etc/debian_release /etc/debian_version\' | |
| 217 | + eval local FILES_${MANDRAKE}=\'/etc/mandrake-release\' | |
| 218 | + eval local FILES_${YELLOWDOG}=\'/etc/yellowdog-release\' | |
| 219 | + eval local FILES_${SUNJDS}=\'/etc/sun-release\' | |
| 220 | + eval local FILES_${GENTOO}=\'/etc/gentoo-release\' | |
| 221 | + eval local FILES_${SOLARIS}=\'/etc/release\' | |
| 222 | + | |
| 223 | + local CUR=1 | |
| 224 | + while [ ${CUR} -le ${LAST} ] | |
| 225 | + do | |
| 226 | + local DIR | |
| 227 | + | |
| 228 | + eval local FILES=\"\${FILES_${CUR}}\" | |
| 229 | + | |
| 230 | + for DIR in ${FILES} | |
| 231 | + do | |
| 232 | + ${TEST} -f ${DIR} || CHK=$((CHK&~CUR)) | |
| 233 | + done | |
| 234 | + | |
| 235 | + CUR=$((CUR*2)) | |
| 236 | + done | |
| 237 | + | |
| 238 | + DIST="Unknown" | |
| 239 | + | |
| 240 | + ${TEST} ${CHK} -eq ${SUSE} && DIST="Suse" | |
| 241 | + ${TEST} ${CHK} -eq ${REDHAT} && DIST="Redhat" | |
| 242 | + ${TEST} ${CHK} -eq ${FEDORA} && DIST="Fedora" | |
| 243 | + ${TEST} ${CHK} -eq ${SLACKWARE} && DIST="Slakware" | |
| 244 | + ${TEST} ${CHK} -eq ${DEBIAN} && DIST="Debian" | |
| 245 | + ${TEST} ${CHK} -eq ${MANDRAKE} && DIST="Mandrake" | |
| 246 | + ${TEST} ${CHK} -eq ${YELLOWDOG} && DIST="Yellowdog" | |
| 247 | + ${TEST} ${CHK} -eq ${SUNJDS} && DIST="Sun" | |
| 248 | + ${TEST} ${CHK} -eq ${GENTOO} && DIST="Gentoo" | |
| 249 | + ${TEST} ${CHK} -eq ${SOLARIS} && DIST="Solaris" | |
| 250 | + | |
| 251 | + if [ 'Unknown' != "${DIST}" ] | |
| 252 | + then | |
| 253 | + eval ${GREP} -iq ${DIST} \${FILES_${CHK}} || DIST="Unknown" | |
| 254 | + fi | |
| 255 | + | |
| 256 | + CLASSES="${CLASSES}${DIST} " | |
| 257 | + else | |
| 258 | + DIST="${OS}" | |
| 259 | + fi | |
| 260 | +} | |
| 261 | + | |
| 262 | +## | |
| 263 | +# Here now starts the usage of the functions defined above. | |
| 264 | +# | |
| 265 | + | |
| 266 | +## | |
| 267 | +# first specify some programs | |
| 268 | +# | |
| 269 | +WHICH="/usr/bin/which" | |
| 270 | +UNAME="$(${WHICH} uname)" | |
| 271 | +TEST="$(${WHICH} test)" | |
| 272 | +GREP="$(${WHICH} grep)" | |
| 273 | +AWK="$(${WHICH} awk)" | |
| 274 | +ECHO="$(${WHICH} echo)" | |
| 275 | +SORT="$(${WHICH} sort)" | |
| 276 | +TR="$(${WHICH} tr)" | |
| 277 | +PRINTF="$(${WHICH} printf)" | |
| 278 | +LOGGER="$(${WHICH} logger)" | |
| 279 | +IP="$(${WHICH} ip)" | |
| 280 | +IFCONFIG="$(${WHICH} ifconfig)" | |
| 281 | + | |
| 282 | +get_dist_info | |
| 283 | +get_if_data | |
| 284 | + | |
| 285 | +## | |
| 286 | +# report everysthing | |
| 287 | +# | |
| 288 | + | |
| 289 | +${PRINTF} "%15s : %s\n" "OS" "${OS}" | |
| 290 | +${PRINTF} "%15s : %s\n" "KERNEL" "${KERNEL}" | |
| 291 | +${PRINTF} "%15s : %s\n" "VERSION" "${VERSION}" | |
| 292 | +${PRINTF} "%15s : %s\n" "PLATFORM" "${PLATFORM}" | |
| 293 | +${PRINTF} "%15s : %s\n" "DIST" "${DIST}" | |
| 294 | +${PRINTF} "%15s : %s\n" "HOSTNAME" "${HOSTNAME}" | |
| 295 | +${PRINTF} "%15s : %s\n" "# INTERFACES" "${NINTERFACES}" | |
| 296 | + | |
| 297 | +NO=1 | |
| 298 | +while [ ${NO} -le ${NINTERFACES:=0} ] | |
| 299 | +do | |
| 300 | + eval printf \"%15s : %s\\\n\" \"IF${NO}_NAME\" \"\${IF${NO}_NAME}\" | |
| 301 | + eval printf \"%15s : %s\\\n\" \"IF${NO}_MAC\" \"\${IF${NO}_MAC}\" | |
| 302 | + eval printf \"%15s : %s\\\n\" \"IF${NO}_STATE\" \"\${IF${NO}_STATE}\" | |
| 303 | + eval printf \"%15s : %s\\\n\" \"IF${NO}_IPV4\" \"\${IF${NO}_IPV4}\" | |
| 304 | + eval printf \"%15s : %s\\\n\" \"IF${NO}_IPV6\" \"\${IF${NO}_IPV6}\" | |
| 305 | + NO=$((NO+1)) | |
| 306 | +done | |
| 307 | + | |
| 308 | +${PRINTF} "%15s : %s\n" "CLASSES" "${CLASSES}" | |
| 309 | + | |
| 310 | +echo | |
| 311 | +echo $(mask2cidr 255.255.128.0) | |
| 312 | +echo $(cidr2mask 17) | |
| 313 | +eval echo \$\(cidr2mask $(mask2cidr 255.255.128.0)\) | |
| 314 | + | |
| 315 | +# vim: set ts=4 sw=4: | ... | ... |
Please
register
or
login
to post a comment