├── .gitignore ├── CNAME ├── README.md ├── services-list.txt └── system-check.sh /.gitignore: -------------------------------------------------------------------------------- 1 | report.txt 2 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | system-checks.org -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## System Checker script 2 | 3 | Works on this time only CentOS / Fedora / Debian. 4 | 5 | * this script does not make any changes to your system 6 | * during operation, temporary files can be created in `/tmp` catalog 7 | 8 | ## Features list 9 | 10 | * System info 11 | * Hostname 12 | * Distributive 13 | * Lical IP 14 | * External IP 15 | * SELinux status 16 | * Kernel / Architecture 17 | * Load average 18 | * Active user 19 | * CPU 20 | * Model name 21 | * Vendor 22 | * Cores / MHz 23 | * Hypervizor vendor 24 | * CPU usage 25 | * Memory usage 26 | * Total / Usage 27 | * Swap total / Usage 28 | * Boot information 29 | * Last boot 30 | * Uptime 31 | * Active user 32 | * Last 3 reboot 33 | * Last logons info 34 | * Disk Usage 35 | * Mount information 36 | * Disk utilization 37 | * Disc IO speed (Read / Write) 38 | * Show read-only mounted devices 39 | * Average information 40 | * Top 5 memory usage processes 41 | * Top 5 CPU usage processes 42 | * Speedtest 43 | * Washington, D.C. (east) 44 | * San Jose, California (west) 45 | * Frankfurt, DE, JP 46 | * Checking systemd services status 47 | * You can define services list 48 | * Show information form default list (nginx, mongo, rsyslog and etc) 49 | * Bash users 50 | * Who logged 51 | * Listen ports 52 | * Unowned files 53 | * User list from processes 54 | 55 | ## Parameters 56 | 57 | * `-sn` - Skip speedtest 58 | * `-sd` - Skip disk test 59 | * `-ss` - Show all running services 60 | * `-e` - Extra info (Bash users, Who logged, All running services, Listen ports, UnOwned files, User list from processes) 61 | 62 | ## Usage 63 | You can use this script with several parameters: 64 | ``` 65 | ./system-check.sh -sn -sd -e 66 | ``` 67 | ``` 68 | ./system-check.sh -ss 69 | ``` 70 | 71 | ## How to run? 72 | 73 | You can run script directly: 74 | ```bash 75 | wget -O - https://raw.githubusercontent.com/m0zgen/system-checks/master/system-check.sh | bash 76 | ``` 77 | 78 | Or you can clone repository: 79 | 80 | ```bash 81 | git clone https://github.com/m0zgen/system-checks.git 82 | ``` 83 | 84 | After clone go to folder and run script: 85 | ```bash 86 | cd system-checks && ./system-check.sh 87 | ``` 88 | 89 | ## Repository 90 | 91 | * [https://github.com/m0zgen/system-checks](https://github.com/m0zgen/system-checks) 92 | 93 | ## Description 94 | 95 | * [https://sys-adm.in/sections/os-nix/881-bash-sbor-informatsii-o-sisteme.html](https://sys-adm.in/sections/os-nix/881-bash-sbor-informatsii-o-sisteme.html) 96 | 97 | ## Thanks 98 | 99 | * [https://github.com/SimplyLinuxFAQ/health-check-script](https://github.com/SimplyLinuxFAQ/health-check-script) 100 | 101 | 102 | -------------------------------------------------------------------------------- /services-list.txt: -------------------------------------------------------------------------------- 1 | # Common services 2 | auditd 3 | chronyd 4 | crond 5 | firewalld 6 | rsyslog 7 | postfix 8 | sshd 9 | systemd-journald 10 | NetworkManager 11 | 12 | # Additional services 13 | docker 14 | nginx 15 | php-fpm 16 | httpd 17 | mariadb 18 | nscd 19 | 20 | # 21 | openvpn@server 22 | wg-quick@wg0-server 23 | 24 | -------------------------------------------------------------------------------- /system-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Author: Yevgeniy Goncharov aka xck, http://sys-adm.in 3 | # Collect & Check Linux server status 4 | 5 | # Sys env / paths / etc 6 | # -------------------------------------------------------------------------------------------\ 7 | PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin 8 | SCRIPT_PATH=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd) 9 | 10 | # Initial variables 11 | # ---------------------------------------------------\ 12 | HOSTNAME=`hostname` 13 | SERVER_IP=`hostname -I` 14 | MOUNT=$(mount|egrep -iw "ext4|ext3|xfs|gfs|gfs2|btrfs"|grep -v "loop"|sort -u -t' ' -k1,2) 15 | FS_USAGE=$(df -PTh|egrep -iw "ext4|ext3|xfs|gfs|gfs2|btrfs"|grep -v "loop"|sort -k6n|awk '!seen[$1]++') 16 | SERVICES="$SCRIPT_PATH/services-list.txt" 17 | TESTFILE="$SCRIPT_PATH/tempfile" 18 | TOTALMEM=$(free -m | awk '$1=="Mem:" {print $2}') 19 | EBPF_STATUS=$(sysctl kernel.unprivileged_bpf_disabled | awk '{ print $3}') 20 | DEBUG=false 21 | 22 | # Colored styles 23 | on_success="DONE" 24 | on_fail="FAIL" 25 | white="\e[1;37m" 26 | green="\e[1;32m" 27 | red="\e[1;31m" 28 | purple="\033[1;35m" 29 | nc="\e[0m" 30 | 31 | SuccessMark="\e[47;32m ------ OK \e[0m" 32 | WarningMark="\e[43;31m ------ WARNING \e[0m" 33 | CriticalMark="\e[47;31m ------ CRITICAL \e[0m" 34 | d="-------------------------------------" 35 | 36 | Info() { 37 | echo -en "${1}${green}${2}${nc}\n" 38 | } 39 | 40 | Warn() { 41 | echo -en "${1}${purple}${2}${nc}\n" 42 | } 43 | 44 | Success() { 45 | echo -en "${1}${green}${2}${nc}\n" 46 | } 47 | 48 | Error () { 49 | echo -en "${1}${red}${2}${nc}\n" 50 | } 51 | 52 | Splash() { 53 | echo -en "${white}${1}${nc}\n" 54 | } 55 | 56 | space() { 57 | echo -e "" 58 | } 59 | 60 | # Help information 61 | usage() { 62 | 63 | Info "" "\nParameters:\n" 64 | echo -e "-sn - Skip speedtest\n 65 | -sd - Skip disk test\n 66 | -ss - Show all running services\n 67 | -e - Extra info (Bash users, Who logged, All running services, Listen ports, UnOwned files, User list from processes) 68 | " 69 | 70 | Info "" "Usage:" 71 | echo -e "You can use this script with several parameters:" 72 | echo -e "./system-check.sh -sn -sd -e" 73 | echo -e "./system-check.sh -ss" 74 | exit 1 75 | 76 | } 77 | 78 | # Checks arguments 79 | while [[ "$#" -gt 0 ]]; do 80 | case $1 in 81 | -sn|--skip-network) SKIPNET=1; ;; 82 | -ss|--skip-services) SKIPSERVICES=1; ;; 83 | -sd|--skip-disk) SKIPDISK=1 ;; 84 | -e|--extra) EXTRA=1 ;; 85 | -h|--help) usage ;; 86 | *) echo "Unknown parameter passed: $1"; exit 1 ;; 87 | esac 88 | shift 89 | done 90 | 91 | # Functions 92 | # ------------------------------------------------------------------------------------------------------\ 93 | 94 | ## Service functions 95 | 96 | # Yes / No confirmation 97 | confirm() { 98 | # call with a prompt string or use a default 99 | read -r -p "${1:-Are you sure? [y/N]} " response 100 | case "$response" in 101 | [yY][eE][sS]|[yY]) 102 | true 103 | ;; 104 | *) 105 | false 106 | ;; 107 | esac 108 | } 109 | 110 | # Check is current user is root 111 | isRoot() { 112 | if [ $(id -u) -ne 0 ]; then 113 | Error "You must be root user to continue" 114 | exit 1 115 | fi 116 | RID=$(id -u root 2>/dev/null) 117 | if [ $? -ne 0 ]; then 118 | Error "User root no found. You should create it to continue" 119 | exit 1 120 | fi 121 | if [ $RID -ne 0 ]; then 122 | Error "User root UID not equals 0. User root must have UID 0" 123 | exit 1 124 | fi 125 | } 126 | 127 | # Checks supporting distros 128 | checkDistro() { 129 | # Checking distro 130 | if [ -e /etc/centos-release ]; then 131 | DISTRO=`cat /etc/redhat-release | awk '{print $1,$4}'` 132 | RPM=1 133 | elif [ -e /etc/fedora-release ]; then 134 | DISTRO=`cat /etc/fedora-release | awk '{print ($1,$3~/^[0-9]/?$3:$4)}'` 135 | RPM=1 136 | elif [ -e /etc/os-release ]; then 137 | DISTRO=`lsb_release -d | awk -F"\t" '{print $2}'` 138 | RPM=0 139 | else 140 | Error "Your distribution is not supported (yet)" 141 | exit 1 142 | fi 143 | } 144 | 145 | # get Actual date 146 | getDate() { 147 | date '+%d-%m-%Y_%H-%M-%S' 148 | } 149 | 150 | # SELinux status 151 | isSELinux() { 152 | 153 | if [[ "$RPM" -eq "1" ]]; then 154 | selinuxenabled 155 | if [ $? -ne 0 ] 156 | then 157 | Error "SELinux:\t\t" "DISABLED" 158 | else 159 | Info "SELinux:\t\t" "ENABLED" 160 | fi 161 | fi 162 | 163 | } 164 | 165 | isEBPF() { 166 | local stat=$(sysctl kernel.unprivileged_bpf_disabled | awk '{ print $3}') 167 | 168 | if [[ "$stat" -eq "0" ]]; then 169 | echo "Enabled (0)" 170 | elif [[ "$stat" -eq "1" ]]; then 171 | echo "1-Disabled until next reboot (1)" 172 | elif [[ "$stat" -eq "2" ]]; then 173 | echo "Disabled but can be re-enabled without reboot (2)" 174 | else 175 | echo "Unknown" 176 | fi 177 | } 178 | 179 | # If file exist true / false 180 | chk_fileExist() { 181 | PASSED=$1 182 | 183 | if [[ -d $PASSED ]]; then 184 | # echo "$PASSED is a directory" 185 | return 1 186 | elif [[ -f $PASSED ]]; then 187 | # echo "$PASSED is a file" 188 | return 1 189 | else 190 | # echo "$PASSED is not valid" 191 | return 0 192 | 193 | fi 194 | } 195 | 196 | # Unit services status 197 | chk_SvsStatus() { 198 | systemctl is-active --quiet $1 && Info "$1: " "Running" || Error "$1: " "Stopped" 199 | } 200 | 201 | chk_SvcExist() { 202 | local n=$1 203 | # systemctl list-units --all -t service | awk {'print $1'} | grep $n.service 204 | if [[ $(systemctl list-unit-files --type service | awk {'print $1'} | grep $n.service) == $n.service ]]; then 205 | return 0 206 | else 207 | return 1 208 | fi 209 | } 210 | 211 | ## Functional / Test functions 212 | 213 | # Collect CPU information 214 | cpu_info() { 215 | echo -en "Model name:\t\t${green}$(lscpu | grep -oP 'Model name:\s*\K.+')${nc}\n" 216 | echo -en "Vendor ID:\t\t${green}$(lscpu | grep -oP 'Vendor ID:\s*\K.+')${nc}\n" 217 | Info "CPU Cores\t\t" `awk -F: '/model name/ {core++} END {print core}' /proc/cpuinfo` 218 | # Info "CPU MHz:\t\t" `lscpu | grep -oP 'CPU MHz:\s*\K.+'` 219 | Info "CPU MHz:\t\t" `cat /proc/cpuinfo | grep "MHz" | head -1 | awk '{print $4}'` 220 | Info "Hypervisor vendor:\t" `lscpu | grep -oP 'Hypervisor vendor:\s*\K.+'` 221 | if [[ "$RPM" -eq 1 ]]; then 222 | Info "Virtualization:\t\t" `lscpu | grep -oP 'Virtualization:\s*\K.+'` 223 | fi 224 | Info "CPU Usage:\t\t" `cat /proc/stat | awk '/cpu/{printf("%.2f%%\n"), ($2+$4)*100/($2+$4+$5)}' | awk '{print $0}' | head -1` 225 | } 226 | 227 | # Test HDD 228 | test_disk() { 229 | 230 | if [[ "$SKIPDISK" -eq "1" ]]; then 231 | Info "" "Disk test was skipped" 232 | else 233 | echo -en "Write (1st):\t\t${green}$(dd if=/dev/zero of=$TESTFILE bs=1M count=1024 |& awk '/copied/ {print $0}' | sed 's:.*,::')${nc}\n" 234 | echo -en "Write (2nd):\t\t${green}$(dd if=/dev/zero of=$TESTFILE bs=1M count=1024 |& awk '/copied/ {print $0}' | sed 's:.*,::')${nc}\n" 235 | echo -en "Write (3nd):\t\t${green}$(dd if=/dev/zero of=$TESTFILE bs=1M count=1024 |& awk '/copied/ {print $0}' | sed 's:.*,::')${nc}\n" 236 | echo "" 237 | echo -en "Read (1st):\t\t${green}$(dd if=$TESTFILE of=/dev/null bs=1M count=1024 |& awk '/copied/ {print $0}' | sed 's:.*,::')${nc}\n" 238 | echo -en "Read (2nd):\t\t${green}$(dd if=$TESTFILE of=/dev/null bs=1M count=1024 |& awk '/copied/ {print $0}' | sed 's:.*,::')${nc}\n" 239 | echo -en "Read (3nd):\t\t${green}$(dd if=$TESTFILE of=/dev/null bs=1M count=1024 |& awk '/copied/ {print $0}' | sed 's:.*,::')${nc}\n" 240 | rm -rf $TESTFILE 241 | fi 242 | 243 | } 244 | 245 | # HDD usage 246 | disk_usage() { 247 | echo -e "( 0-90% = OK/HEALTHY, 90-95% = WARNING, 95-100% = CRITICAL )" 248 | echo -e "$d$d" 249 | echo -e "Mounted File System[s] Utilization (Percentage Used):\n" 250 | 251 | COL1=$(echo "$FS_USAGE"|awk '{print $1 " "$7}') 252 | COL2=$(echo "$FS_USAGE"|awk '{print $6}'|sed -e 's/%//g') 253 | 254 | for i in $(echo "$COL2"); do 255 | { 256 | if [ $i -ge 95 ]; then 257 | COL3="$(echo -e $i"% $CriticalMark\n$COL3")" 258 | elif [[ $i -ge 90 && $i -lt 95 ]]; then 259 | COL3="$(echo -e $i"% $WarningMark\n$COL3")" 260 | else 261 | COL3="$(echo -e $i"% $SuccessMark\n$COL3")" 262 | fi 263 | } 264 | done 265 | COL3=$(echo "$COL3"|sort -k1n) 266 | paste <(echo "$COL1") <(echo "$COL3") -d' '|column -t 267 | 268 | # https://unix.stackexchange.com/questions/43875/sending-the-output-from-dd-to-awk-sed-grep 269 | # https://www.shellhacks.com/disk-speed-test-read-write-hdd-ssd-perfomance-linux/ 270 | } 271 | 272 | # IPv4 speed tests 273 | speedtest_v4() { 274 | local res=$(wget -4O /dev/null -T200 $1 2>&1 | awk '/\/dev\/null/ {speed=$3 $4} END {gsub(/\(|\)/,"",speed); print speed}') 275 | local region=$2 276 | echo -en "$2\t\t${green}$res${nc}\n" 277 | } 278 | 279 | test_v4() { 280 | 281 | if [[ "$SKIPNET" -eq "1" ]]; then 282 | Info "" "Network test was skipped" 283 | else 284 | Info "Status\t\t\t" "Started..." 285 | speedtest_v4 "http://speedtest.wdc01.softlayer.com/downloads/test10.zip" "Washington, D.C. (east)\t" 286 | speedtest_v4 "http://speedtest.sjc01.softlayer.com/downloads/test10.zip" "San Jose, California (west)" 287 | speedtest_v4 "http://speedtest.frankfurt.linode.com/100MB-frankfurt.bin" "Frankfurt, DE, JP\t" 288 | fi 289 | } 290 | 291 | # General system information 292 | system_info() { 293 | checkDistro 294 | Info "Hostname:\t\t" $HOSTNAME 295 | Info "Distro:\t\t\t" "${DISTRO}" 296 | Info "IP:\t\t\t" $SERVER_IP 297 | Info "External IP:\t\t" $(curl -s -4 icanhazip.com) 298 | 299 | isRoot 300 | isSELinux 301 | 302 | Info "Kernel:\t\t\t" `uname -r` 303 | echo -en "eBPF:\t\t\t${green}$(isEBPF)${nc}\n" 304 | Info "Architecture:\t\t" `arch` 305 | Info "Active User:\t\t" `w | cut -d ' ' -f1 | grep -v USER | xargs -n1` 306 | Info "Locale:\t\t\t" `locale | head -1 | sed 's/^[^=:]*[=:]//'` 307 | echo -en "Current Load Average:\t${green}$(uptime|grep -o "load average.*"|awk '{print $3" " $4" " $5}')${nc}" 308 | } 309 | 310 | # Memory info 311 | mem_info() { 312 | Info "Total memory:\t\t" "${TOTALMEM}Mb" 313 | Info "Memory Usage:\t\t" `free | awk '/Mem/{printf("%.2f%%"), $3/$2*100}'` 314 | space 315 | if free | awk '/^Swap:/ {exit !$2}'; then 316 | TOTALSWAP=$(free -m | awk '$1=="Swap:" {print $2}') 317 | Info "Total swap:\t\t" "${TOTALSWAP}Mb" 318 | Info "Swap Usage:\t\t" `free | awk '/Swap/{printf("%.2f%%"), $3/$2*100}'` 319 | else 320 | Error "Swap Usage:\t\t" "swap does not exist" 321 | fi 322 | } 323 | 324 | # Boot info 325 | boot_info() { 326 | Info "Active User:\t\t" `w | cut -d ' ' -f1 | grep -v USER | xargs -n1` 327 | echo -en "Last Reboot:\t\t${green}$(who -b | awk '{print $3,$4,$5}')${nc}" 328 | echo -en "\nUptime:\t\t\t${green}`awk '{a=$1/86400;b=($1%86400)/3600;c=($1%3600)/60} {printf("%d days, %d hour %d min\n",a,b,c)}' /proc/uptime`${nc}" 329 | } 330 | 331 | # Actions 332 | # ------------------------------------------------------------------------------------------------------\ 333 | 334 | space 335 | Splash "-------------------------------\t\tSystem Information\t----------------------------" 336 | 337 | system_info 338 | 339 | Splash "\n\n-------------------------------\t\tCPU Information\t\t------------------------------" 340 | 341 | cpu_info 342 | 343 | Splash "\n\n-------------------------------\t\tMemory Information\t\t------------------------------" 344 | 345 | mem_info 346 | 347 | Splash "\n\n-------------------------------\t\tBoot Information\t------------------------------" 348 | 349 | boot_info 350 | 351 | Splash "\n\n-------------------------------\t\tLast 3 Reboot Info\t------------------------------" 352 | last reboot | head -3 353 | 354 | Splash "\n\n-------------------------------\t\tLast info\t------------------------------" 355 | last | head -9 356 | 357 | Splash "\n\n-------------------------------\t\tMount Information\t------------------------------" 358 | echo -en "$MOUNT"|column -t 359 | 360 | Splash "\n\n-------------------------------\t\tDisk usage\t\t------------------------------" 361 | 362 | disk_usage 363 | 364 | Splash "\n\n-------------------------------\t\tTest disk IO\t------------------------------" 365 | 366 | test_disk 367 | 368 | Splash "\n\n-------------------------------\t\tRead-only mounted\t------------------------------" 369 | echo "$MOUNT"|grep -w \(ro\) && Info "\n.....Read Only file system[s] found"|| Info "No read-only file system[s] found. " 370 | 371 | Splash "\n\n-------------------------------\t\tTop 5 memory usage\t------------------------------" 372 | ps -eo pmem,pcpu,pid,ppid,user,stat,args | sort -k 1 -r | head -6 373 | 374 | Splash "\n\n-------------------------------\t\tTop 5 CPU usage\t\t------------------------------" 375 | ps -eo pcpu,pmem,pid,ppid,user,stat,args | sort -k 1 -r | head -6 376 | 377 | 378 | Splash "\n\n-------------------------------\t\tSpeedtest\t------------------------------" 379 | # Debug clean 380 | if ( ! $DEBUG ); then 381 | test_v4 382 | else 383 | echo "Debug is enabled!" 384 | fi 385 | 386 | 387 | if [[ -f $SERVICES ]]; then 388 | 389 | Splash "\n\n-------------------------------\t\tServices state\t\t------------------------------" 390 | 391 | # Read data from list.txt 392 | while read -r service; do 393 | 394 | # Cut comment lines 395 | if [[ -n "$service" && "$service" != [[:blank:]#]* ]]; then 396 | if chk_SvcExist $service; then 397 | chk_SvsStatus $service 398 | else 399 | Warn "$service " "Not installed" 400 | fi 401 | fi 402 | 403 | done < $SERVICES 404 | 405 | fi 406 | 407 | if [[ "$SKIPSERVICES" -eq "1" ]]; then 408 | if confirm "List all running services? (y/n or enter)"; then 409 | Splash "\n\n-------------------------------Running services------------------------------" 410 | space 411 | systemctl list-units | grep running 412 | fi 413 | fi 414 | 415 | 416 | 417 | if [[ "$EXTRA" -eq "1" ]]; then 418 | 419 | Splash "\n\n-------------------------------\t\tBash users\t------------------------------" 420 | space 421 | cat /etc/passwd | grep bash | awk -F: '{ print $1}' 422 | 423 | Splash "\n\n-------------------------------\t\tUsers from processes\t------------------------------" 424 | space 425 | ps -ef | awk '{print $1}' | sort | uniq | grep -v 'UID' 426 | 427 | Splash "\n\n-------------------------------\t\tLogged users\t------------------------------" 428 | space 429 | w -h 430 | 431 | Splash "\n\n-------------------------------\t\tListen ports\t------------------------------" 432 | space 433 | if ! command -v netstat &> /dev/null 434 | then 435 | Warn "" "NETSTAT could not be found" 436 | else 437 | netstat -tulpn | grep 'LISTEN' 438 | fi 439 | 440 | Splash "\n\n-------------------------------\t\tAll running services\t----------------------" 441 | space 442 | systemctl list-units | grep running 443 | 444 | Splash "\n\n-------------------------------\t\tAll running processes\t----------------------" 445 | space 446 | # ps -A | awk '{print $4}' | grep -v 'CMD' | uniq | sort 447 | # as tree 448 | # ps -ejH 449 | ps axjf 450 | 451 | Splash "\n\n-------------------------------\t\tUnowned files\t----------------------" 452 | space 453 | Info "Status\t\t\t" "Find..." 454 | # find / -nouser -o -nogroup -exec ls -l {} \; 455 | find / -xdev -nouser -o -nogroup -exec ls {} \; > /tmp/find_res.log 456 | 457 | if [ -s /tmp/find_res.log ] 458 | then 459 | cat /tmp/find_res.log | grep -v '/' -A 1 460 | else 461 | Info "Status:\t\t\t" "OK. Not found." 462 | fi 463 | 464 | fi 465 | 466 | 467 | 468 | --------------------------------------------------------------------------------