#!/bin/bash# History# 2011-12-2 SM Created# 2011-12-4 AS Add functions to get info about the system/applications# 2012-02-3 AS Add functions to collect php/php-fpm/mysql/apache/nginx configuration# 2012-02-6 AS Reformat mysql output and other minor changes# 2012-06-4 AS Get pci devices information# Start scriptOUTPUT_FILE=$(pwd)/nc_sales_audit.txtVERSION="20120604"if [ $EUID -ne 0 ]; thenecho "[ERROR]: Please run this script with root privileges."exit 1fiif [ ! -f /etc/redhat-release ]; thenecho "[ERROR]: Sorry, this script is for CentOS/RHEL only."# exit 1finame_val() {printf "%20s | %s\n" "$1" "$(echo $2)"}header() {HEADER="$1"echo "------------------------------"echo ">>>>> $HEADER"echo "------------------------------"}section () {echoecho "$1" | awk '{l=sprintf("#_%-88s", $0 "_"); print l}' | sed -e 's/ /#/g' -e 's/_/ /g'}group_concat () {sed -e '{H; $!d}' -e 'x' -e 's/\n[[:space:]]*\([[:digit:]]*\)[[:space:]]*/, \1x/g' -e 's/[[:space:]][[:space:]]*/ /g' -e 's/, //' ${1}}# START# Get basic system statusget_basic_info() {> $OUTPUT_FILEecho "------------------- ChinaNetCloud Sales Audit Script Start ------------------- " | tee -a $OUTPUT_FILE 1>&2echo "+ Results Output File: $OUTPUT_FILE" >&2echo "------------------------------------------------------------------------------" | tee -a $OUTPUT_FILE 1>&2section "System_Summary_For_$(hostname)"name_val "Script Version" "$VERSION"name_val "Hostname" "$(hostname)"name_val "Date" "`date -u +'%F %T UTC'` (local TZ: `date +'%Z %z'`)"name_val "Uptime" "$(uptime | awk '{print substr($0, index($0, "up") + 3)}')"if which dmidecode &> /dev/null; thenvendor="$(dmidecode -s system-manufacturer 2>/dev/null | sed 's/ *$//g')"product="$(dmidecode -s system-product-name 2>/dev/null | sed 's/ *$//g')"name_val "System" "${vendor} - ${product}";fiif which lsb_release &>/dev/null; thenrelease=$(lsb_release -a 2>/dev/null|awk -F: '/Description/ {print $2}')elif [ -e /etc/redhat-release ]; thenrelease=$(cat /etc/redhat-release);elif [ -e /etc/debian_version ]; thenrelease="Debian-based version $(cat /etc/debian_version)";elserelease="-"finame_val Release "$release"name_val Kernel "$(uname -r)"CPU_ARCH='32-bit'OS_ARCH='32-bit'if grep -q ' lm ' /proc/cpuinfo; thenCPU_ARCH='64-bit'fiif file /bin/bash 2>/dev/null | grep -q '64-bit'; thenOS_ARCH='64-bit'finame_val "Architecture" "CPU = $CPU_ARCH, OS = $OS_ARCH"if getenforce >/dev/null 2>&1; thengetenforce="$(getenforce 2>&1)";finame_val "SELinux" "${getenforce:-No SELinux detected}";DMESG="/var/log/dmesg"if grep -qi -e vmware -e vmxnet $DMESG; thenVIRT="VMWare";elif grep -q -e 'Xen virtual console' -e 'Xen version' $DMESG; thenVIRT="Xen";elif grep -q -e QEMU -e 'paravirtualized kernel on KVM' $DMESG; thenVIRT="KVM/QEMU";elif grep -q VBOX $DMESG; thenVIRT="VirtualBox";fiif [ -n "$VIRT" ]; thenname_val "Virtualized" "${VIRT}";fiechoname_val "LANGUAGE" "$LANG"if which gcc &>/dev/null; thenname_val "GCC Version" "$(gcc -dumpversion)"elsename_val "GCC Version" "Not Installed"finame_val "Max open files" "$(ulimit -n)"}parse_proc_cpuinfo () {section "CPU"header "CPU - Information"# Physical processors are indicated by distinct 'physical id'. Virtual CPUs# are indicated by paragraphs -- one per paragraph. We assume that all# processors are identical, i.e. that there are not some processors with dual# cores and some with quad cores.CPU_FILE=/proc/cpuinfocat /proc/cpuinfo > /tmp/aspersavirtual=$(grep -c ^processor $CPU_FILE);physical=$(grep 'physical id' $CPU_FILE | sort -u | wc -l);cores=$(grep 'cpu cores' $CPU_FILE | head -n 1 | cut -d: -f2);# Older kernel won't have 'physical id' or 'cpu cores'.if [ "${physical}" = "0" ]; then physical=${virtual}; fiif [ -z "${cores}" ]; then cores=0; fi# Test for HTT; cannot trust the 'ht' flag. If physical * cores < virtual,# then hyperthreading is in use.cores=$((${cores} * ${physical}));if [ ${cores} -gt 0 -a $cores -lt $virtual ]; then htt=yes; else htt=no; finame_val "Processors" "physical = ${physical}, cores = ${cores}, virtual = ${virtual}, hyperthreading = ${htt}"awk -F: '/cpu MHz/{print $2}' /tmp/aspersa | sort | uniq -c > /tmp/aspersa2name_val "Speeds" "$(group_concat /tmp/aspersa2)"awk -F: '/model name/{print $2}' /tmp/aspersa | sort | uniq -c > /tmp/aspersa2name_val "Models" "$(group_concat /tmp/aspersa2)"awk -F: '/cache size/{print $2}' /tmp/aspersa | sort | uniq -c > /tmp/aspersa2name_val "Caches" "$(group_concat /tmp/aspersa2)"header "CPU - TOP 30"echo " PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND"top -b -n1|grep -E "^\s?[0-9]+"|sort -k9 -g|tail -30}parse_disk() {section "DISK"header "Fdisk"fdisk -l 2>/dev/nullheader "File Systems"df -h -P 2>/dev/null | while read a b c d e f; doprintf "%-40s %-5s %-5s %-5s %-5s %-5s\n" "$a" "$b" "$c" "$d" "$e" "$f"doneechoheader "/etc/fstab"while read a b c d e f; doprintf "%-30s %-20s %-6s %-30s %-2s %-2s\n" "$a" "$b" "$c" "$d" "$e" "$f"done < /etc/fstabheader "PV Information"pvs 2>/dev/nullheader "VG Information"vgs 2>/dev/nullheader "LV Information"lvs 2>/dev/nullheader "iostat"iostat -Ndx 2 5 2>/dev/nullheader "vmstat"vmstat 2 5 2>/dev/nullsection "Disk_Schedulers_And_Queue_Size"echo "" > /tmp/aspersafor disk in $(ls /sys/block/ | grep -v -e ram -e loop -e 'fd[0-9]'); doif [ -e "/sys/block/${disk}/queue/scheduler" ]; thenname_val "${disk}" "$(cat /sys/block/${disk}/queue/scheduler | grep -o '\[.*\]') $(cat /sys/block/${disk}/queue/nr_requests)"fdisk -l "/dev/${disk}" >> /tmp/aspersa 2>/dev/nullfidone}parse_memory() {section "MEMORY"header "Free and used memory"free -mheader "MEMORY - TOP 30"echo " PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND"top -b -n1|grep -E "^\s?[0-9]+"|sort -k10 -g|tail -30}parse_software() {section "SOFTWARE"if [ -f /etc/redhat-release ]; thenheader "RPM Packages: (Total: $(rpm -qa|wc -l))"rpm -qa|grep -Ei "^(php|mysql|nginx|httpd|apache|redis|memcache|mongo|postgre|tomcat|resin|haproxy|varnish|vsftp|gcc)"|sortfiheader "Version Information:"if which java &>/dev/null ; thenBIN_JAVA=$(which java)VERSION_JAVA=$(java -version 2>&1|head -n 1|awk -F'"' '{print $2}')name_val "Java Version" "$VERSION_JAVA ($BIN_JAVA)"fiif which perl &>/dev/null ; thenBIN_PERL=$(which perl)VERSION_PERL=$(perl -V|perl -ne 'if (/.*revision (\d+) version (\d+) subversion (\d+)/) {print "$1.$2.$3\n"}')name_val "Perl Version" "$VERSION_PERL ($BIN_PERL)"fiif which python &>/dev/null ; thenBIN_PYTHON=$(which python)VERSION_PYTHON=$(python -V 2>&1 | awk '{print $2}')name_val "Python Version" "$VERSION_PYTHON ($BIN_PYTHON)"fiif which httpd &>/dev/null ; thenBIN_APACHE=$(which httpd)VERSION_APACHE=$(httpd -v| head -n 1|perl -pi -e 's/.*(\d+\.\d+.\d).*/$1/')name_val "Apache Version" "$VERSION_APACHE ($BIN_APACHE)"fiif which nginx &>/dev/null ; thenBIN_NGINX=$(which nginx)VERSION_NGINX=$(nginx -v 2>&1 | perl -pi -e 's/.*(\d+\.\d+.\d).*/$1/')name_val "Nginx Version" "$VERSION_NGINX ($BIN_NGINX)"fiif which lighttpd &>/dev/null ; thenBIN_LIGHTTPD=$(which lighttpd)VERSION_LIGHTTPD=$(lighttpd -v| head -n 1| perl -pi -e 's/.*(\d+\.\d+.\d).*/$1/')name_val "Lighttpd Version" "$VERSION_LIGHTTPD ($BIN_LIGHTTPD)"fiif which vsftpd &>/dev/null ; thenBIN_VSFTPD=$(which vsftpd)VERSION_VSFTPD=$(vsftpd -v 0>&1|perl -pi -e 's/.*(\d+\.\d+.\d).*/$1/')name_val "Vsftpd Version" "$VERSION_VSFTPD ($BIN_VSFTPD)"fiif which php &>/dev/null ; thenBIN_PHP=$(which php)VERSION_PHP=$(php -v 2>/dev/null | head -n 1 | perl -pi -e 's/.*(\d+\.\d+.\d).*/$1/')name_val "PHP Version" "$VERSION_PHP ($BIN_PHP)"fiif which memcached &>/dev/null ; thenBIN_MEMCACHED=$(which memcached)VERSION_MEMCACHED=$(memcached -h|head -n 1|awk '{print $2}')name_val "Memcached Version" "$VERSION_MEMCACHED ($BIN_MEMCACHED)"fiif [ -n "$CATALINA_HOME" ]; thenVERSION_TOMCAT=$($CATALINA_HOME/bin/version.sh 2>/dev/null | awk -F: '/version/ {print $2}')name_val "Tomcat Version" "$VERSION_TOMCAT ($CATALINA_HOME)"fiif which mysql &>/dev/null ; thenBIN_MYSQL_CLIENT=$(which mysql)VERSION_MYSQL_CLIENT=$(mysql -V | perl -pi -e 's/.*(\d+\.\d+.\d).*/$1/')name_val "MySQL Client Version" "$VERSION_MYSQL_CLIENT ($BIN_MYSQL_CLIENT)"fiif which mongod &>/dev/null; thenVERSION_MONGOD=$(/usr/bin/mongod --version|awk -F"(,| )" '/db version/ {print substr($3,2)}')BIN_MONGOD=$(which mongod)name_val "MongoDB Version" "$VERSION_MONGOD ($BIN_MONGOD)"fiif which psql &>/dev/null ; thenBIN_PSQL=$(which psql)VERSION_PSQL=$(psql -V | head -n 1 | perl -pi -e 's/.*(\d+\.\d+.\d).*/$1/')name_val "PostgreSQL Version" "$VERSION_PSQL ($BIN_PSQL)"fiecho}parse_iptables() {section iptablesheader "Iptables Rules"iptables -nvLecho}# GET INFORMATION ABOUT CRONTABparse_cron() {section CRONTABfor USER_LINE in `cat /etc/passwd | cut -d: -f1`; doUSER_CRON=$(crontab -l -u $USER_LINE 2>/dev/null)if [ -n "$USER_CRON" ]; thenecho ">>>>> crontab for $USER_LINE" ;crontab -l -u $USER_LINEecho "-------------------------------"fidone}parse_network() {section Network_Connectionsheader "Listening ports"netstat -ntlpuheader "IP Address"ifconfigheader "Ethernet Settings - eth0"ethtool eth0 2>/dev/nullheader "Ethernet Settings - eth1"ethtool eth1 2>/dev/nullheader "Ethernet Settings - eth2"ethtool eth2 2>/dev/nullheader "IP Routing"route -nif which ss &>/dev/null; thenheader "Socket statistics"ss -sechofi}parse_others() {section "PCI DEVICES"lspci -tv 2>/dev/nullsection "PROCESSES"ps aux|sort -r -k10section "KERNEL_PARAMETERS"sysctl -a 2>/dev/null | grep -E "(somaxconn|backlog|file-max|ip_forward|tcp_tw|keepalive|tcp_fin|swappiness|tcp_syn)"|sortsection "USER_LOGIN"header "Current Users"/usr/bin/wheader "last logged in users"last -10header "Last bad login attempts"lastb -10}# Apache sectionget_httpd_info() {section "APACHE"header "Apache configuration"for APACHE_INCLUDE_CONF in $(find /etc/httpd/ /etc/apache2/ /usr/local/apache2/ /usr/local/httpd/ -type f -name '*.conf' 2>/dev/null); doif [ -s $APACHE_INCLUDE_CONF ]; thenheader "Apache configuration - $APACHE_INCLUDE_CONF"cat $APACHE_INCLUDE_CONF|sed -e '/^\s*$/d;/^\s*#/d;'fidone}# Nginx sectionget_nginx_info() {section "NGINX"for NGINX_INCLUDE_CONF in $(find /etc/nginx /usr/local/nginx* -name '*.conf' 2>/dev/null); doif [ -s $NGINX_INCLUDE_CONF ]; thenheader "Nginx configuration - $NGINX_INCLUDE_CONF"cat $NGINX_INCLUDE_CONF | sed -e '/^\s*$/d;/^\s*#/d;'fidone}# MySQL sectionget_mysql_info() {# Function - check and display config filemysql_config_get() {if [ -f "$1" ]; thenheader "MySQL Configuration File - $1"cat $1fi}section "MYSQL"# get options from running MySQL processesheader "MySQL Startup Options"MYSQLD_BASEDIR=$(ps aux | grep -w '[m]ysqld' | perl -ne 'if ( /.*mysqld\s+.*--basedir=(.*?)\s+.*/ ) {print $1."\n"}')if [ -n "$MYSQLD_BASEDIR" ]; thenecho "MySQL basedir: $MYSQLD_BASEDIR"fiMYSQLD_DATADIR=$(ps aux | grep -w '[m]ysqld' | perl -ne 'if ( /.*mysqld\s+.*--datadir=(.*?)\s+.*/ ) {print $1."\n"}')if [ -n "$MYSQLD_DATADIR" ]; thenecho "MySQL datadir: $MYSQLD_DATADIR"fiMYSQLD_LOG_ERROR=$(ps aux | grep -w '[m]ysqld' | perl -ne 'if ( /.*mysqld\s+.*--log-error=(.*?)\s+.*/ ) {print $1."\n"}')if [ -n "$MYSQLD_LOG_ERROR" ]; thenecho "MySQL error file: $MYSQLD_LOG_ERROR"fiMYSQLD_SOCKET=$(ps aux | grep -w '[m]ysqld' | perl -ne 'if ( /.*mysqld\s+.*--socket=(.*?)\s+.*/ ) {print $1."\n"}')if [ -n "$MYSQLD_SOCKET" ]; thenecho "MySQL socket: $MYSQLD_SOCKET"fi# get MySQL configuration filemysql_config_get /etc/my.cnfmysql_config_get $MYSQLD_BASEDIR/my.cnfMYSQLD_EXTRA_FILE=$(ps aux | grep -w '[m]ysqld' | perl -ne 'if ( /.*mysqld\s+.*--defaults-extra-file=(.*?)\s+.*/ ) {print $1."\n"}')if [ -n "MYSQLD_EXTRA_FILE" ]; thenmysql_config_get $MYSQLD_EXTRA_FILEfi# get MySQL global variables / global status, etcecho "Going to collect MySQL global variables and status,which are really helpful for tuning and optimization." >&2MYSQL_RETRY_COUNT=1MYSQL_OK="NO"# skip if customer failed to provide valid user/passwdwhile [ $MYSQL_RETRY_COUNT -lt 5 -a $MYSQL_OK != "YES" ]; doecho -n "MySQL user name (root as default): " >&2read MYSQL_USERecho -n "MySQL password: " >&2read -s MYSQL_PASSWDif [ -z "$MYSQL_USER" ]; thenMYSQL_USER=rootfiechomysql -u$MYSQL_USER -p$MYSQL_PASSWD -e "select now();" &>/dev/nullif [ $? -ne 0 ]; thenecho "MySQL - Access denied, please check your username and password" >&2MYSQL_RETRY_COUNT=$((MYSQL_RETRY_COUNT+1))elseMYSQL_OK="YES"fidoneif [ $MYSQL_OK != "YES" ]; thenecho "MySQL - Customer failed to provide valid username/password. Skipping .."elseif [ -z "$MYSQLD_DATADIR" ]; thenMYSQLD_DATADIR=$(echo "show global variables like 'datadir';" | mysql -uroot -p$MYSQL_PASSWD | awk '/datadir/ {print $2}')fiif [ -z "$MYSQLD_LOG_ERROR" ]; thenMYSQLD_LOG_ERROR=$(echo "show global variables like 'log_error';" | mysql -uroot -p$MYSQL_PASSWD | awk '/log_error/ {print $2}')fiif [ -z "$MYSQLD_SLOW_LOG" ]; thenMYSQLD_SLOW_LOG=$(echo "show global variables like 'slow_query_log_file';" | mysql -uroot -p$MYSQL_PASSWD | awk '/slow_query_log_file/ {print $2}')fiheader "MySQL - global status"mysql -u$MYSQL_USER -p$MYSQL_PASSWD -e "show global status;" | perl -ne 'my ($a,$b)=split /\s+/,$_; printf ("| %-40s | %-12s |\n",$a,$b)'header "MySQL - global variables"mysql -u$MYSQL_USER -p$MYSQL_PASSWD -e "show global variables;" | perl -ne 'my ($a,$b)=split /\s+/,$_; printf ("| %-40s | %-36s |\n",$a,$b)'header "MySQL - innodb status"mysql -u$MYSQL_USER -p$MYSQL_PASSWD -e "show innodb status\G"fi# list files under mysql datadirif [ -n "$MYSQLD_DATADIR" ]; thenheader "Files under $MYSQLD_DATADIR"ls -l $MYSQLD_DATADIR# database size summaryheader "Database size"find $MYSQLD_DATADIR -maxdepth 1 -type d -exec du -sh {} \;fi# MySQL error logsif [ -s "$MYSQLD_LOG_ERROR" ]; thenheader "MySQL - error logs"tail -100 $MYSQLD_LOG_ERRORfi# MySQL slow logsif [ -s "$MYSQLD_SLOW_LOG" ]; thenheader "MySQL - slow logs"tail -100 $MYSQLD_SLOW_LOGelif [ -s "$MYSQLD_DATADIR/slow.log" ]; thenheader "MySQL - slow logs"tail -100 $MYSQLD_DATADIR/slow.logfi# MySQL historyheader "MySQL_History"for USER_HOME in `awk -F: '{print $6}' /etc/passwd|sort|uniq`; doif [ -s "$USER_HOME/.mysql_history" ]; thenecho ">>>>> MySQL history under $USER_HOME"cat $USER_HOME/.mysql_historyecho "-------------------------------"fidone}get_php_info() {section "PHP/PHP-FPM"# php module informationfor PHP_INI_CONF in $(find /usr/local/php* /etc/php* -type f -name '*.ini' 2>/dev/null); doheader "PHP - Configuration file $PHP_INI_CONF"cat $PHP_INI_CONF|sed -e '/^\s*$/d;/^\s*;/d;'donePHP_CGI_CONF=$(ps aux|perl -ne 'if ( /.*--fpm-config\s(.*?)$/ ) {print $1."\n"}'|uniq)# php-fpm version 5.2if [ -s "$PHP_CGI_CONF" ]; thenheader "PHP_FPM - Configuration file $PHP_CGI_CONF"echo "listen_address: " $(perl -ne 'if (/^\s*(\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "user: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "group:" $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "style: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "StartServers: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "MinSpareServers: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "MaxSpareServers: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "request_terminate_timeout: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "request_slowlog_timeout: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "rlimit_files: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)echo "max_requests: " $(perl -ne 'if (/^\s* (\S+)<\/value>/) {print $1}' $PHP_CGI_CONF)fi# php-fpm version 5.3+for PHP_FPM_CONF in $(find /usr/local/php* /etc/php* -type f -name '*.conf' 2>/dev/null); doheader "PHP_FPM - Configuration file - $PHP_FPM_CONF"cat $PHP_FPM_CONF|sed -e '/^\s*$/d;/^\s*;/d;'done}# main functionmain() {get_basic_infoparse_proc_cpuinfoparse_memoryparse_diskparse_softwareparse_iptablesparse_cronparse_networkparse_othersif [ $(ps aux|grep -E "[h]ttpd|[a]pache2"|wc -l) -gt 0 ]; thenget_httpd_infofiif [ $(ps aux|grep [n]ginx|wc -l) -gt 0 ]; thenget_nginx_infofiget_php_infoif [ $(ps aux|grep [m]ysql|wc -l) -gt 0 ]; thenget_mysql_infofi/bin/rm -f /tmp/aspersa /tmp/aspersa2}main >> $OUTPUT_FILE## Email resultsecho "------------------------------------------------------------------------------Done. Please send this file to ChinaNetCloud - sales_audit@chinanetcloud.com$OUTPUT_FILE------------------------------------------------------------------------------"