From 2ee2430329b25c88173bde7ee2d1724fc9f64a53 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Tue, 20 Dec 2022 21:35:16 -0800 Subject: [PATCH 01/26] Script to list the top 5 CPU, memory, input/output (I/O), and network consuming processes in Centos and Ubuntu --- performance_tuning/performance-monitoring.sh | 122 +++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 performance_tuning/performance-monitoring.sh diff --git a/performance_tuning/performance-monitoring.sh b/performance_tuning/performance-monitoring.sh new file mode 100644 index 0000000..3ed29b9 --- /dev/null +++ b/performance_tuning/performance-monitoring.sh @@ -0,0 +1,122 @@ +#!/bin/bash +# This script list the top 5 CPU, memory, input/output (I/O), and network consuming processes +# This script should work on both CentOS and macOS +# Author: Prashant Lakhera(laprashant@gmail.com) + +# Check if top command is present +if command -v top >/dev/null 2>&1; then + echo "top command is present" +else + echo "top command is not present. Installing..." + # Install top command + if [ -f /etc/centos-release ]; then + # CentOS + sudo yum install -y procps-ng + elif [ -f /etc/lsb-release ]; then + # Ubuntu + sudo apt-get update + sudo apt-get install -y top + else + # Unsupported OS + echo "Unsupported operating system" + exit 1 + fi +fi + +# Function to list top 5 CPU consuming process +list_top_cpu_consuming_processes() { + # Get the top 5 processes by CPU usage + top_five_cpu_processes=$(ps -eo pcpu,pid,user,args | sort -k 1 -r | head -n 5) + + # Print the results + echo "###############################################################################" + echo "Top 5 CPU consuming processes:" + echo "$top_five_cpu_processes" +} + +# Function to list the top 5 processes by memory usage +list_top_memory_consuming_processes() { + # Get the top 5 processes by memory usage + top_five_memory_processes=$(ps -eo pmem,pid,user,args | sort -k 1 -r | head -n 5) + + # Print the results + echo "###############################################################################" + echo "Top 5 memory consuming processes:" + echo "$top_five_memory_processes" +} + +# Check if iotop command is present +if command -v iotop >/dev/null 2>&1; then + echo "iotop command is present" +else + echo "iotop command is not present. Installing..." + # Install top command + if [ -f /etc/centos-release ]; then + # CentOS + sudo yum install -y epel-release + sudo yum install -y iotop + elif [ -f /etc/lsb-release ]; then + # Ubuntu + sudo apt-get update + sudo apt-get install -y iotop + else + # Unsupported OS + echo "Unsupported operating system" + exit 1 + fi +fi + +# Function to list the top 5 processes by I/O usage +list_top_io_consuming_processes() { + # Get the top 5 processes by I/O usage + top_five_io_processes=$(sudo iotop -o -b -n 5) + + # Print the results + echo "###############################################################################" + echo "Top 5 I/O consuming processes:" + echo "$top_five_io_processes" +} + +# Check if iftop command is present +if command -v iftop >/dev/null 2>&1; then + echo "iftop command is present" +else + echo "iftop command is not present. Installing..." + # Install top command + if [ -f /etc/centos-release ]; then + # CentOS + sudo yum install -y iftop + elif [ -f /etc/lsb-release ]; then + # Ubuntu + sudo apt-get update + sudo apt-get install -y iftop + else + # Unsupported OS + echo "Unsupported operating system" + exit 1 + fi +fi + + +# Function to list the top 5 processes by network usage +list_top_network_consuming_processes() { + # Get the top 5 processes by network usage + top_five_network_processes=$(sudo iftop -P -n -t -s 5) + + # Print the results + echo "###############################################################################" + echo "Top 5 network consuming processes:" + echo "$top_five_network_processes" +} + + +# Main function +main() { + list_top_cpu_consuming_processes + list_top_memory_consuming_processes + list_top_io_consuming_processes + list_top_network_consuming_processes +} + +# Run the main function +main \ No newline at end of file From d030fa7e72d2dea64b34977d81c6f226373345c5 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Tue, 20 Dec 2022 21:43:23 -0800 Subject: [PATCH 02/26] Create main.yml --- .github/workflows/main.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..09e8e0c --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,17 @@ +name: Validate Shell Script + +on: [push] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Validate Shell Script + run: | + # Install shellcheck + sudo apt-get update + sudo apt-get install -y shellcheck + # Run shellcheck on the script + shellcheck environment_setup.sh + shellcheck performance-monitoring.sh From 8acdba716b704e962f6c4f8c3edf13869bb27f16 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Tue, 20 Dec 2022 22:32:26 -0800 Subject: [PATCH 03/26] adding ContainerCreating CreateContainerConfigError and select script to choose different kubernetes error --- .../container_creating_error.sh | 25 +++++++++++++++ kubernetes_debugging/crash_loopback_error.sh | 31 ++++++++++++++++++ .../create_container_config.sh | 24 ++++++++++++++ .../kubernetes_debugging_select.sh | 31 ++++++++++++++++++ kubernetes_debugging/pod_image_pull_error.sh | 32 +++++++++++++++++++ 5 files changed, 143 insertions(+) create mode 100755 kubernetes_debugging/container_creating_error.sh create mode 100755 kubernetes_debugging/crash_loopback_error.sh create mode 100755 kubernetes_debugging/create_container_config.sh create mode 100755 kubernetes_debugging/kubernetes_debugging_select.sh create mode 100755 kubernetes_debugging/pod_image_pull_error.sh diff --git a/kubernetes_debugging/container_creating_error.sh b/kubernetes_debugging/container_creating_error.sh new file mode 100755 index 0000000..468338a --- /dev/null +++ b/kubernetes_debugging/container_creating_error.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Script to check ContainerCreating error in Kubernetes pods +# Author: Prashant Lakhera(laprashant@gmail.com) + +# Set the namespace which we use to query the pods +namespace="default" + +# Query for the pods using the namespace +pods=$(kubectl get pods -n "$namespace" -o json | jq -r '.items[].metadata.name') + +# Iterate through the list of pods +for pod in $pods; do + # Get the status of the current pod + status=$(kubectl get pod "$pod" -n "$namespace" -o json | jq -r '.status.containerStatuses[].state.waiting.reason') + # Check if the status is "ContainerCreating" + if [ "$status" == "ContainerCreating" ]; then + # Print an error message + echo "ERROR: Pod $pod is in a ContainerCreating state!" + exit 1 + # In some cases this is helpful,try to delete the pod to allow it to be rescheduled + # kubectl delete pod "$pod" -n "$namespace" + fi +done + + diff --git a/kubernetes_debugging/crash_loopback_error.sh b/kubernetes_debugging/crash_loopback_error.sh new file mode 100755 index 0000000..6841637 --- /dev/null +++ b/kubernetes_debugging/crash_loopback_error.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Script to check Crashloopbackoff error in Kubernetes pods +# Author: Prashant Lakhera(laprashant@gmail.com) + +# Set the namespace which we use to query the pods +namespace="default" + +# Query for the pods using the namespace +pods=$(kubectl get pods -n "$namespace" -o json | jq -r '.items[].metadata.name') + +# Iterate through the list of pods +for pod in $pods; do + # Get the status of the current pod + status=$(kubectl describe pod "$pod" -n "$namespace"| grep "CrashLoopBackOff" |awk '{print $2}') + + # If the status is "CrashLoopBackOff", handle the error + for state in status + do + if [ "$status" == "CrashLoopBackOff" ]; then + # Print an error message + echo "ERROR: Pod $pod is in a CrashLoopBackOff state!" + exit 1 + + # Try to delete the pod to allow it to be rescheduled + #kubectl delete pod "$pod" -n "$namespace" + + # Print a message indicating that the pod was deleted + #echo "INFO: Deleted pod $pod to allow it to be rescheduled." + fi + done +done diff --git a/kubernetes_debugging/create_container_config.sh b/kubernetes_debugging/create_container_config.sh new file mode 100755 index 0000000..fdc2a3d --- /dev/null +++ b/kubernetes_debugging/create_container_config.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Script to check ContainerCreating error in Kubernetes pods +# Author: Prashant Lakhera(laprashant@gmail.com) + +# Set the namespace which we use to query the pods +namespace="default" + +# Query for the pods using the namespace +pods=$(kubectl get pods -n "$namespace" -o json | jq -r '.items[].metadata.name') + +# Iterate through the list of pods +for pod in $pods; do + # Get the status of the current pod + status=$(kubectl describe pod "$pod" -n "$namespace" | grep "CreateContainerConfigError" | awk '{print $2}') + # If the status of the pod contains the "CreateContainerConfig" error + if [[ "$status" = "CreateContainerConfigError" ]]; then + # Print an error message + echo "ERROR: Pod $pod has a CreateContainerConfig error!" + exit 1 + + # In some cases,Try to delete the pod to allow it to be rescheduled + # kubectl delete pod "$pod" -n "$namespace" + fi +done \ No newline at end of file diff --git a/kubernetes_debugging/kubernetes_debugging_select.sh b/kubernetes_debugging/kubernetes_debugging_select.sh new file mode 100755 index 0000000..ec77de5 --- /dev/null +++ b/kubernetes_debugging/kubernetes_debugging_select.sh @@ -0,0 +1,31 @@ +# Create a list of options for Kubernetes Debugging +options=("CrashLoopBackOff" "ImagePullBackOff" "ContainerCreating" "CreateContainerConfigError" "Quit") + +# Display the menu and prompt the user to select an option +echo "Please select from the following Kubernetes Debugging option" +PS3="Please select an option: " +select opt in "${options[@]}"; do + # Process the user's selection + case $opt in + "CrashLoopBackOff") + # Execute crash_loopback_error.sh + source crash_loopback_error.sh + ;; + "ImagePullBackOff") + # Execute pod_image_pull_error.sh + source pod_image_pull_error.sh + ;; + "ContainerCreating") + # Execute container_creating_error.sh + source container_creating_error.sh + ;; + "CreateContainerConfigError") + # Execute create_container_config.sh + source create_container_config.sh + ;; + "Quit") + break + ;; + *) echo "Invalid option. Please try again.";; + esac +done diff --git a/kubernetes_debugging/pod_image_pull_error.sh b/kubernetes_debugging/pod_image_pull_error.sh new file mode 100755 index 0000000..630eabd --- /dev/null +++ b/kubernetes_debugging/pod_image_pull_error.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Script to check image pull error in Kubernetes pods +# Author: Prashant Lakhera(laprashant@gmail.com) + +# Set the namespace which we use to query the pods +NAMESPACE=default + +# Query for the pods using the namespace and label selector +PODS=$(kubectl get pods -n $NAMESPACE -o json) + +# Verify if the query return any pods +if [ -z "$PODS" ]; then + echo "No pods found" + exit 0 +fi + +# Parse the JSON output to get the list of pod names +POD_NAMES=$(echo $PODS | jq -r '.items[].metadata.name') + +# Iterate over the list of pod names +for POD_NAME in $POD_NAMES; do + # Check for image pull errors in the pod + IMAGE_PULL_ERRORS=$(kubectl describe pod $POD_NAME -n $NAMESPACE | grep -c "ImagePullBackOff") + + # If there is a image pull errors, print an error message and exit with an error code + if [ "$IMAGE_PULL_ERRORS" -gt 0 ]; then + echo "There were image pull errors in pod $POD_NAME" + fi +done + +# If there is no image pull error and all the pods are running, exit with a zero status code +exit 0 \ No newline at end of file From 3969c0533ab8dadd5086d16bc7eb2e841dc933ae Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Wed, 21 Dec 2022 10:11:26 -0800 Subject: [PATCH 04/26] Update performance-monitoring.sh --- performance_tuning/performance-monitoring.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/performance_tuning/performance-monitoring.sh b/performance_tuning/performance-monitoring.sh index 3ed29b9..efd6e4f 100644 --- a/performance_tuning/performance-monitoring.sh +++ b/performance_tuning/performance-monitoring.sh @@ -15,7 +15,7 @@ else elif [ -f /etc/lsb-release ]; then # Ubuntu sudo apt-get update - sudo apt-get install -y top + sudo apt-get install -y procps else # Unsupported OS echo "Unsupported operating system" @@ -119,4 +119,4 @@ main() { } # Run the main function -main \ No newline at end of file +main From 89a6b25afad30c433d1fdac1072de4436647b551 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Wed, 21 Dec 2022 10:13:03 -0800 Subject: [PATCH 05/26] Update performance-monitoring.sh --- performance_tuning/performance-monitoring.sh | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/performance_tuning/performance-monitoring.sh b/performance_tuning/performance-monitoring.sh index efd6e4f..4964cf8 100644 --- a/performance_tuning/performance-monitoring.sh +++ b/performance_tuning/performance-monitoring.sh @@ -3,25 +3,6 @@ # This script should work on both CentOS and macOS # Author: Prashant Lakhera(laprashant@gmail.com) -# Check if top command is present -if command -v top >/dev/null 2>&1; then - echo "top command is present" -else - echo "top command is not present. Installing..." - # Install top command - if [ -f /etc/centos-release ]; then - # CentOS - sudo yum install -y procps-ng - elif [ -f /etc/lsb-release ]; then - # Ubuntu - sudo apt-get update - sudo apt-get install -y procps - else - # Unsupported OS - echo "Unsupported operating system" - exit 1 - fi -fi # Function to list top 5 CPU consuming process list_top_cpu_consuming_processes() { From 5f272238389d0b378f15d1a41cbfab9df90dc1d4 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Tue, 3 Jan 2023 17:39:05 +0000 Subject: [PATCH 06/26] adding version2 after removing header and displaying top 5 process along with header --- .../performance-monitoring-v2.sh | 103 ++++++++++++++++++ performance_tuning/performance-monitoring.sh | 8 +- 2 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 performance_tuning/performance-monitoring-v2.sh diff --git a/performance_tuning/performance-monitoring-v2.sh b/performance_tuning/performance-monitoring-v2.sh new file mode 100644 index 0000000..c76b204 --- /dev/null +++ b/performance_tuning/performance-monitoring-v2.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# This script list the top 5 CPU, memory, input/output (I/O), and network consuming processes +# This script should work on both CentOS and macOS +# Author: Prashant Lakhera(laprashant@gmail.com) + + +# Function to list top 5 CPU consuming process +list_top_cpu_consuming_processes() { + # Get the top 5 processes by CPU usage + top_five_cpu_processes=$(ps -eo pcpu,pid,user,args --no-headers | sort -k 1 -r | head -n 5) + + # Print the results + echo "###############################################################################" + echo "Top 5 CPU consuming processes:" + echo "$top_five_cpu_processes" +} + +# Function to list the top 5 processes by memory usage +list_top_memory_consuming_processes() { + # Get the top 5 processes by memory usage + top_five_memory_processes=$(ps -eo pmem,pid,user,args --no-headers | sort -k 1 -r | head -n 5) + + # Print the results + echo "###############################################################################" + echo "Top 5 memory consuming processes:" + echo "$top_five_memory_processes" +} + +# Check if iotop command is present +if command -v iotop >/dev/null 2>&1; then + echo "iotop command is present" +else + echo "iotop command is not present. Installing..." + # Install top command + if [ -f /etc/centos-release ]; then + # CentOS + sudo yum install -y epel-release + sudo yum install -y iotop + elif [ -f /etc/lsb-release ]; then + # Ubuntu + sudo apt-get update + sudo apt-get install -y iotop + else + # Unsupported OS + echo "Unsupported operating system" + exit 1 + fi +fi + +# Function to list the top 5 processes by I/O usage +list_top_io_consuming_processes() { + # Get the top 5 processes by I/O usage + top_five_io_processes=$(sudo iotop -o -b -n 5) + + # Print the results + echo "###############################################################################" + echo "Top 5 I/O consuming processes:" + echo "$top_five_io_processes" +} + +# Check if iftop command is present +if command -v iftop >/dev/null 2>&1; then + echo "iftop command is present" +else + echo "iftop command is not present. Installing..." + # Install top command + if [ -f /etc/centos-release ]; then + # CentOS + sudo yum install -y iftop + elif [ -f /etc/lsb-release ]; then + # Ubuntu + sudo apt-get update + sudo apt-get install -y iftop + else + # Unsupported OS + echo "Unsupported operating system" + exit 1 + fi +fi + + +# Function to list the top 5 processes by network usage +list_top_network_consuming_processes() { + # Get the top 5 processes by network usage + top_five_network_processes=$(sudo iftop -P -n -t -s 5) + + # Print the results + echo "###############################################################################" + echo "Top 5 network consuming processes:" + echo "$top_five_network_processes" +} + + +# Main function +main() { + list_top_cpu_consuming_processes + list_top_memory_consuming_processes + list_top_io_consuming_processes + list_top_network_consuming_processes +} + +# Run the main function +main diff --git a/performance_tuning/performance-monitoring.sh b/performance_tuning/performance-monitoring.sh index 4964cf8..7d74976 100644 --- a/performance_tuning/performance-monitoring.sh +++ b/performance_tuning/performance-monitoring.sh @@ -7,7 +7,7 @@ # Function to list top 5 CPU consuming process list_top_cpu_consuming_processes() { # Get the top 5 processes by CPU usage - top_five_cpu_processes=$(ps -eo pcpu,pid,user,args | sort -k 1 -r | head -n 5) + top_five_cpu_processes=$(ps -eo pcpu,pid,user,args | sort -k 1 -r | head -n 6) # Print the results echo "###############################################################################" @@ -18,7 +18,7 @@ list_top_cpu_consuming_processes() { # Function to list the top 5 processes by memory usage list_top_memory_consuming_processes() { # Get the top 5 processes by memory usage - top_five_memory_processes=$(ps -eo pmem,pid,user,args | sort -k 1 -r | head -n 5) + top_five_memory_processes=$(ps -eo pmem,pid,user,args | sort -k 1 -r | head -n 6) # Print the results echo "###############################################################################" @@ -50,7 +50,7 @@ fi # Function to list the top 5 processes by I/O usage list_top_io_consuming_processes() { # Get the top 5 processes by I/O usage - top_five_io_processes=$(sudo iotop -o -b -n 5) + top_five_io_processes=$(sudo iotop -o -b -n 6) # Print the results echo "###############################################################################" @@ -82,7 +82,7 @@ fi # Function to list the top 5 processes by network usage list_top_network_consuming_processes() { # Get the top 5 processes by network usage - top_five_network_processes=$(sudo iftop -P -n -t -s 5) + top_five_network_processes=$(sudo iftop -P -n -t -s 6) # Print the results echo "###############################################################################" From eb7e919ad0c397fde305fcb749f582fd5250d070 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Tue, 3 Jan 2023 10:24:46 -0800 Subject: [PATCH 07/26] performance monitoring simplified shell script --- .../performance-monitoring-simplified.sh | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 performance_tuning/performance-monitoring-simplified.sh diff --git a/performance_tuning/performance-monitoring-simplified.sh b/performance_tuning/performance-monitoring-simplified.sh new file mode 100644 index 0000000..d2fae80 --- /dev/null +++ b/performance_tuning/performance-monitoring-simplified.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# This script is the quick check to detect whether the performance issue is due to CPU, Memory, Input/Output (I/O), and network error +# This script should work on both CentOS and macOS +# Author: Prashant Lakhera(laprashant@gmail.com) + + +# Check if the load average is greater than 70% of the CPU cores +load_avg=$(w | head -n 1 | awk '{print $9}' |cut -f1 -d",") +num_cores=$(nproc) +max_load=$(echo "0.7 * $num_cores" | bc) + +if [[ $(echo "$load_avg > $max_load" | bc) -eq 1 ]]; then + #Print a message if the load average is too high + echo -e "\033[1;31m CPU load average is currently $load_avg, which is higher than the maximum of $max_load \033[0m" >&2 +else + # Print a message if the load average is within the acceptable range + echo -e "\033[1;32m CPU load average is currently $load_avg, which is within the acceptable range.\033[0m" +fi + +# Set the memory average threshold +THRESHOLD=90 + +# Get the total memory and used memory in bytes +total_memory=$(grep 'MemTotal' /proc/meminfo | awk '{print $2}') +available_memory=$(grep 'MemAvailable' /proc/meminfo | awk '{print $2}') + +# Calculate the actual memory utilization as a percentage +memory_utilization=$(echo "scale=2; ($total_memory - $available_memory)/$total_memory * 100" | bc) + +# Compare the memory utilization with the threshold +if (( $(echo "$memory_utilization > $THRESHOLD" | bc -l) )) +then + echo -e "\033[1;32m Memory utilization is above the threshold!!! Memory utilization is: $utilization% \033[0m" +else + echo -e "\033[1;32m Memory utilizationis currently $memory_utilization, which is within the acceptable range.\033[0m" +fi + +# Check the I/O wait state + +iowait_state=$(top -b -n 1 | head -n +3|awk '{print $10}'|tail -1 |bc) +if [[ $(echo "$iowait_state > 1" | bc) -eq 1 ]]; then + #Print a message IOWAIT is too high + echo -e "\033[1;31m IOWAIT is currently $iowait_state, which is higher than the acceptable range \033[0m" >&2 +else + # Print a message IOWAIT is within the acceptable range + echo -e "\033[1;32m IOWAIT is currently $iowait_state, which is within the acceptable range.\033[0m" +fi + +# Check if ifconfig command is present +if command -v ifconfig >/dev/null 2>&1; then + echo "ifconfig command is present" +else + echo "ifconfig command is not present. Installing..." + # Install ifconfig command + if [ -f /etc/centos-release ]; then + # CentOS + sudo yum install -y net-tools + elif [ -f /etc/lsb-release ]; then + # Ubuntu + sudo apt-get update + sudo apt-get install -y net-tools + else + # Unsupported OS + echo "Unsupported operating system" + exit 1 + fi +fi + +#Get the network interface name or ask input from the user +#interface=$1 +interface=$(ifconfig |head -1|awk '{print $1}' |cut -f1 -d:) + +# Get the RX error count +rx_error_count=$(ifconfig $interface | grep "RX errors" |awk '{print $3}') + +# Get the TX error count +tx_error_count=$(ifconfig $interface | grep "TX errors" |awk '{print $3}') + +# Check if either error count is greater than zero +if [[ $rx_error_count -gt 0 || $tx_error_count -gt 0 ]]; then + #Print a message Network error count is too high + echo -e "\033[1;31m Network Error is currently for Revieve Error: $rx_error_count and Transmit Error: $tx_error_count, which is higher than the acceptable range \033[0m" >&2 +else + # Print a message Network error count is within the acceptable range + echo -e "\033[1;32m Network Error is currently for Revieve Error: $rx_error_count and Transmit Error: $tx_error_count, which is within the acceptable range.\033[0m" +fi \ No newline at end of file From 77fdcdda7f9c146d14161e904787541beb2211ef Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Tue, 3 Jan 2023 10:56:12 -0800 Subject: [PATCH 08/26] performance monitoring simplified shell script with an update on network reset counter --- performance_tuning/performance-monitoring-simplified.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/performance_tuning/performance-monitoring-simplified.sh b/performance_tuning/performance-monitoring-simplified.sh index d2fae80..7984f04 100644 --- a/performance_tuning/performance-monitoring-simplified.sh +++ b/performance_tuning/performance-monitoring-simplified.sh @@ -77,6 +77,7 @@ rx_error_count=$(ifconfig $interface | grep "RX errors" |awk '{print $3}') tx_error_count=$(ifconfig $interface | grep "TX errors" |awk '{print $3}') # Check if either error count is greater than zero +# Remember these counter only get reset after reboot, so you may get some false alarm. Check this thread for more reference https://unix.stackexchange.com/questions/164057/how-can-i-manually-reset-rx-tx-counters-in-ifconfig-output-without-impacting-d if [[ $rx_error_count -gt 0 || $tx_error_count -gt 0 ]]; then #Print a message Network error count is too high echo -e "\033[1;31m Network Error is currently for Revieve Error: $rx_error_count and Transmit Error: $tx_error_count, which is higher than the acceptable range \033[0m" >&2 From 5c796f4ba420eba7ddfb20908cb733950723c5ea Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Tue, 3 Jan 2023 15:53:18 -0800 Subject: [PATCH 09/26] adding the environment setup script --- environment_setup/environment_setup.sh | 64 ++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 environment_setup/environment_setup.sh diff --git a/environment_setup/environment_setup.sh b/environment_setup/environment_setup.sh new file mode 100644 index 0000000..a4651b0 --- /dev/null +++ b/environment_setup/environment_setup.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# This shell script that checks if the required python modules (pip3, boto3, and awscli) +# the terraform package are installed, and installs them if they are missing. +# This script should work on both CentOS and macOS +# Check the terraform release page to use the latest terraform package https://releases.hashicorp.com/terraform/ +# Author: Prashant Lakhera(laprashant@gmail.com) + +# Check if pip3 is installed +if ! type "pip3" &> /dev/null +then + echo "pip3 is not installed. Installing now ..." + # Install pip3 + # Checking for Mac + if [ "$(uname)" == "Darwin" ] + then + brew install python3 + # Checking for Centos + elif [ -f /etc/centos-release ] + then + sudo yum -y update + sudo yum -y install python3-pip -y + fi +fi + +# Check if boto3 is installed +if python3 -c "import boto3" &> /dev/null; then + echo "Boto3 is already installed" +else + echo "Boto3 is not installed. Installing now...." + pip3 install boto3 --user +fi + +# Check if awscli is installed +if ! type "aws" > /dev/null +then + echo "awscli is not installed. Installing now..." + pip3 install awscli --user +else + echo "awscli is already installed" +fi + +# Check if terraform is installed +if ! type "terraform" > /dev/null +then + echo "terraform is not installed installing now..." + # Install terraform + #Checking for Mac + if [ "$(uname)" == "Darwin" ] + then + brew install terraform + # Checking for Centos + elif [ -f /etc/centos-release ] + then + sudo yum install -y unzip + sudo wget https://releases.hashicorp.com/terraform/1.3.6/terraform_1.3.6_linux_amd64.zip + sudo unzip terraform_1.3.6_linux_amd64.zip + sudo mv terraform /usr/local/bin/ + sudo chmod +x /usr/local/bin/terraform + sudo rm terraform_1.3.6_linux_amd64.zip + fi +else + echo "Terraform is already installed" + +fi \ No newline at end of file From be455a8d1825b1c9d89b78a5299a8370260d87d8 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Fri, 20 Jan 2023 11:18:34 -0800 Subject: [PATCH 10/26] adding code for ec2 instance conversion and ebs volume conversion --- ebs_volume_conversion/README.md | 35 ++++++++++++ .../ebs_volume_conversion.py | 54 +++++++++++++++++++ ec2_instance_conversion/README.md | 35 ++++++++++++ .../ec2_instance_conversion.py | 43 +++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 ebs_volume_conversion/README.md create mode 100644 ebs_volume_conversion/ebs_volume_conversion.py create mode 100644 ec2_instance_conversion/README.md create mode 100644 ec2_instance_conversion/ec2_instance_conversion.py diff --git a/ebs_volume_conversion/README.md b/ebs_volume_conversion/README.md new file mode 100644 index 0000000..d487bde --- /dev/null +++ b/ebs_volume_conversion/README.md @@ -0,0 +1,35 @@ +# Python script to convert EBS Volume + +Python script to convert EBS volume from gp2 to gp3 or from io1 to io2 and read input from csv file with a format volume_id,volume_type + +## Usage + +```python3 ebs_volume_conversion.py -h +usage: ebs_volume_conversion.py [-h] [-f FILE] volume_id volume_type + +positional arguments: + volume_id The EBS volume id of the Volume to be convert + volume_type The new EBS volume type to be converted gp3 or io2 + +optional arguments: + -h, --help show this help message and exit + -f FILE, --file FILE A csv file containing ebs volume id and volume type to convert +``` + +# Example + +1. To convert an ebs volume from gp2 to gp3 + +``` +python3 ebs_volume_conversion.py -volume_id -volume_type gp3 +``` + +2. To convert an ebs volume from io1 to io2 +``` +python3 ebs_volume_conversion.py -volume_id -volume_type io2 +``` + +3. You can pass a csv file containing ebs volume id and volume type to convert +``` +python3 ebs_volume_conversion.py -f ebs_volume.csv +``` diff --git a/ebs_volume_conversion/ebs_volume_conversion.py b/ebs_volume_conversion/ebs_volume_conversion.py new file mode 100644 index 0000000..c9ca367 --- /dev/null +++ b/ebs_volume_conversion/ebs_volume_conversion.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# Python script to convert EBS volume from gp2 to gp3 or from io1 to io2 and read input from csv file with a format volume_id,volume_type + +import boto3 +import argparse +import csv +import sys + +def convert_ebs_vol(volume_id,volume_type): + # Create an EC2 client + ec2 = boto3.client('ec2') + # Ask user if he want to take the snapshot before volume conversion + snapshot = input(f'Do you want to take the snapshot of the following volume {volume_id} before conversion? (y/n)') + # Take the snapshot if user confirms + if snapshot.lower() == 'y': + try: + snapshot = ec2.create_snapshot(VolumeId=volume_id,Description="Snapshot before converting the EBS volume") + # Wait for the snapshot to be completed + waiter = ec2.get_waiter('snapshot_completed') + waiter.wait(SnapshotIds=[snapshot['SnapshotId']]) + print(f'Sucessfully created the snapshot {snapshot["SnapshotId"]} of volume {volume_id}') + except Exception as e: + print(f'An error occurred while creating the snapshot for volume {volume_id}: {e} ') + exit(1) + try: + # Modify the EBS Volume to the new volume type + ec2.modify_volume(VolumeId=volume_id, VolumeType=volume_type) + print(f'Started converting EBS volume {volume_id} to {volume_type}') + # Wait until the EBS volume is available + ec2.get_waiter('volume_available').wait(VolumeIds=[volume_id]) + print(f'Sucessfully converted EBS volume {volume_id} to {volume_type}') + except Exception as e: + print(f'An error occurred while converting the EBS volume {volume_id}: {e} ') + exit(1) + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("-volume_id", help="The EBS volume id of the Volume to be convert") + parser.add_argument("-volume_type", help="The new EBS volume type to be converted gp3 or io2") + parser.add_argument("-f","--file", help="A csv file containing ebs volume id and volume type to convert") + args = parser.parse_args() + if not any(vars(args).values()): + parser.print_help() + sys.exit() + + if args.file: + with open(args.file, 'r') as f: + reader = csv.reader(f) + for row in reader: + volume_id = row[0] + volume_type = row[1] + convert_ebs_vol(volume_id, volume_type) + else: + convert_ebs_vol(args.volume_id, args.volume_type) diff --git a/ec2_instance_conversion/README.md b/ec2_instance_conversion/README.md new file mode 100644 index 0000000..882e89c --- /dev/null +++ b/ec2_instance_conversion/README.md @@ -0,0 +1,35 @@ +# Python script to convert EC2 instance + +Python script to convert EC2 instance from one type to another and read input from csv file with a format instance_id,instance_type + + +## Usage + +```python3 ec2_instance_conversion.py +usage: ec2_instance_conversion.py [-h] [-instance_id INSTANCE_ID] + [-new_instance_type NEW_INSTANCE_TYPE] [-f FILE] + +Convert an EC2 instance from one type to another + +optional arguments: + -h, --help show this help message and exit + -instance_id INSTANCE_ID + The ID of the EC2 instance to convert + -new_instance_type NEW_INSTANCE_TYPE + The new instance type for the EC2 instance + -f FILE, --file FILE A CSV file containing a list of instances and new instance types +``` + +# Example + +1. To convert an EC2 instance to t2.medium + +``` +python3 ec2_instance_conversion.py -instance_id -new_instance_type t2.medium +``` + + +3. You can pass a csv file containing instance id and instance type to convert +``` +python3 ec2_instance_conversion.py -f ec2_conversion.csv +``` diff --git a/ec2_instance_conversion/ec2_instance_conversion.py b/ec2_instance_conversion/ec2_instance_conversion.py new file mode 100644 index 0000000..c9134f8 --- /dev/null +++ b/ec2_instance_conversion/ec2_instance_conversion.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# Python script to convert EC2 instance from one type to another and read input from csv file with a format instance_id,instance_type + +import argparse +import boto3 +import sys +import csv + +def convert_instance(instance_id, new_instance_type, csv_file=None): + # Create an EC2 client + ec2 = boto3.client('ec2') + + # Check if the instance is in a stopped state + response = ec2.describe_instances(InstanceIds=[instance_id]) + instance_state = response['Reservations'][0]['Instances'][0]['State']['Name'] + if instance_state == 'stopped': + snapshot_response = input("The instance is in a stopped state. Please don't forget to take the ebs snapshot of the instance volume before the conversion y/n") + try: + # Modify the instance + ec2.modify_instance_attribute(InstanceId=instance_id, Attribute='instanceType', Value=new_instance_type) + print("Successfully converted instance", instance_id, "to", new_instance_type) + except Exception as e: + print("Error converting instance:", e) + +if __name__ == '__main__': + # Set up the argument parser + parser = argparse.ArgumentParser(description='Convert an EC2 instance from one type to another') + parser.add_argument('-instance_id', help='The ID of the EC2 instance to convert') + parser.add_argument('-new_instance_type', help='The new instance type for the EC2 instance') + parser.add_argument("-f","--file", help='A CSV file containing a list of instances and new instance types') + args = parser.parse_args() + if not any(vars(args).values()): + parser.print_help() + sys.exit() + if args.file: + with open(args.file, 'r') as f: + reader = csv.reader(f) + for row in reader: + instance_id = row[0] + new_instance_type = row[1] + convert_instance(instance_id, new_instance_type) + else: + convert_instance(args.instance_id, args.new_instance_type) From cfa95d2652616312ec32ccba32b9049c58d1d289 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Mon, 23 Jan 2023 11:17:01 -0800 Subject: [PATCH 11/26] script to delete unused ebs volumes and finding unused volumes --- .../deleting_unused_ebs_volumes.py | 33 +++++++++++++++++ finding_unused_ebs_vol/README.md | 32 ++++++++++++++++ .../finding_unused_ebs_volume.py | 37 +++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 deleting_unused_ebs_vol/deleting_unused_ebs_volumes.py create mode 100644 finding_unused_ebs_vol/README.md create mode 100644 finding_unused_ebs_vol/finding_unused_ebs_volume.py diff --git a/deleting_unused_ebs_vol/deleting_unused_ebs_volumes.py b/deleting_unused_ebs_vol/deleting_unused_ebs_volumes.py new file mode 100644 index 0000000..6fef2a8 --- /dev/null +++ b/deleting_unused_ebs_vol/deleting_unused_ebs_volumes.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# This script is to clean up Amazon Elastic Block Store (EBS) volumes that are in an unused state +# Author: Prashant Lakhera(laprashant@gmail.com) + +import boto3 + +# Create an EC2 client +ec2 = boto3.client('ec2') + +def delete_unused_ebs(): + # Get the list of all EBS Volumes + try: + response = ec2.describe_volumes() + except Exception as e: + print(f'Error getting the list of EBS Volumes: {e}') + return + + # Loop through the list of volumes and check for any unused volumes + for volume in response['Volumes']: + if volume['State'] == 'available' and not volume['Attachments']: + volume_id = volume["VolumeId"] + try: + print(f'Deleting unused EBS Volume: {volume_id}') + ec2.delete_volume(VolumeId=volume_id) + except Exception as e: + print(f'Error deleting EBS volume {volume_id}: {e}') + +def main(): + delete_unused_ebs() + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/finding_unused_ebs_vol/README.md b/finding_unused_ebs_vol/README.md new file mode 100644 index 0000000..fbe54e7 --- /dev/null +++ b/finding_unused_ebs_vol/README.md @@ -0,0 +1,32 @@ +# Python script to find unused EBS Volume + +Python script to find unused EBS volume. + +## Usage + +```python3 finding_unused_ebs_volume.py -h +usage: finding_unused_ebs_volume.py [-h] [-f FILE] + +optional arguments: + -h, --help show this help message and exit + -f FILE, --file FILE File name to write the list of unused volumes +``` + +# Example + +1. To convert an ebs volume from gp2 to gp3 + +``` +python3 ebs_volume_conversion.py -volume_id -volume_type gp3 +``` + +2. To convert an ebs volume from io1 to io2 +``` +python3 ebs_volume_conversion.py -volume_id -volume_type io2 +``` + +3. You can pass a csv file containing ebs volume id and volume type to convert +``` +python3 ebs_volume_conversion.py -f ebs_volume.csv +``` + diff --git a/finding_unused_ebs_vol/finding_unused_ebs_volume.py b/finding_unused_ebs_vol/finding_unused_ebs_volume.py new file mode 100644 index 0000000..6d90e85 --- /dev/null +++ b/finding_unused_ebs_vol/finding_unused_ebs_volume.py @@ -0,0 +1,37 @@ +import boto3 +import argparse + +def find_unused_ebs_vol(file_name=None): + try: + # Connect to EC2 service + client = boto3.client('ec2') + # Finding all the EBS Volumes + volumes = client.describe_volumes()['Volumes'] + # Initialize a list to store unused EBS volumes + unused_volumes = [] + # Iterate over the list of unused EBS Volumes + for vol in volumes: + # Check if the volume is in unused state + if vol['State'] == 'available' and not vol['Attachments']: + print(f'Found unused EBS volume: {vol["VolumeId"]}, Volume Availability Zone: {vol["AvailabilityZone"]}, VolumeType: {vol["VolumeType"]}, Volume Size in GB: {vol["Size"]}') + unused_volumes.append(vol) + + # Check the condition to see if the filename is provided and store the unused volume in a file + + if file_name is not None: + with open(file_name,'w') as f: + for vol in unused_volumes: + vol_id = vol["VolumeId"] + f.write(str(vol_id) + '\n') + # Return the list of unused volumes + return unused_volumes + + except Exception as e: + print("An error occurred while trying to get the EBS volumes:", e) + raise e + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-f','--file',help="File name to write the list of unused volumes") + args = parser.parse_args() + find_unused_ebs_vol(args.file) \ No newline at end of file From f93106efca5b6fd09e443903a41c8d17190ebc0c Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Mon, 23 Jan 2023 11:27:06 -0800 Subject: [PATCH 12/26] script to delete unused ebs volumes and finding unused volumes --- .../deleting_unused_ebs_volume.py | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 deleting_unused_ebs_vol/deleting_unused_ebs_volume.py diff --git a/deleting_unused_ebs_vol/deleting_unused_ebs_volume.py b/deleting_unused_ebs_vol/deleting_unused_ebs_volume.py new file mode 100644 index 0000000..5777eee --- /dev/null +++ b/deleting_unused_ebs_vol/deleting_unused_ebs_volume.py @@ -0,0 +1,59 @@ +import boto3 +import argparse +import datetime +import sys + +# Create an EC2 client +ec2 = boto3.client('ec2') + +def delete_unused_ebs(file_name=None): + # Get the list of all EBS Volumes + try: + response = ec2.describe_volumes() + except Exception as e: + print(f'Error getting the list of EBS Volumes: {e}') + return + + # Loop through the list of volumes and check for any unused volumes + for volume in response['Volumes']: + if volume['State'] == 'available' and not volume['Attachments']: + volume_id = volume["VolumeId"] + try: + snapshot = input(f'Do you want to take a snapshot of volume {volume_id} before deleting? (y/n)') + if snapshot.lower() == 'y': + # Take a EBS snapshot + ec2.create_snapshot(VolumeId=volume_id,Description=f'Snapshot of the volume {volume_id} taken on {datetime.datetime.now()}') + print(f'Creating the Snapshot of volume {volume_id}') + + print(f'Deleting unused EBS Volume: {volume_id}') + ec2.delete_volume(VolumeId=volume_id) + except Exception as e: + print(f'Error deleting EBS volume {volume_id}: {e}') + + # Check the condition to see if the filename is provided and read the ebs volume from the file + + if file_name is not None: + try: + with open(file_name, 'r') as f: + volume_ids = f.read().splitlines() + for volume_id in volume_ids: + snapshot = input(f'Do you want to take a snapshot of volume {volume_id} before deleting? (y/n)') + if snapshot.lower() == 'y': + # Take a EBS snapshot + ec2.create_snapshot(VolumeId=volume_id,Description=f'Snapshot of the volume {volume_id} taken on {datetime.datetime.now()}') + print(f'Creating the Snapshot of volume {volume_id}') + + print(f'Deleting unused EBS Volume: {volume_id}') + ec2.delete_volume(VolumeId=volume_id) + except Exception as e: + print(f'Error deleting EBS volume {volume_id}: {e}') + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--file', help='Name of the file that contains the list of unused volumes') + try: + args = parser.parse_args() + delete_unused_ebs() + sys.exit() + except Exception as e: + print("An error occurred while parsing the arguments:", e) From 2cdc01abe3b448678fec6ec549dc561520f62e01 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Mon, 23 Jan 2023 14:52:34 -0800 Subject: [PATCH 13/26] Delete deleting_unused_ebs_vol directory --- .../deleting_unused_ebs_volume.py | 59 ------------------- .../deleting_unused_ebs_volumes.py | 33 ----------- 2 files changed, 92 deletions(-) delete mode 100644 deleting_unused_ebs_vol/deleting_unused_ebs_volume.py delete mode 100644 deleting_unused_ebs_vol/deleting_unused_ebs_volumes.py diff --git a/deleting_unused_ebs_vol/deleting_unused_ebs_volume.py b/deleting_unused_ebs_vol/deleting_unused_ebs_volume.py deleted file mode 100644 index 5777eee..0000000 --- a/deleting_unused_ebs_vol/deleting_unused_ebs_volume.py +++ /dev/null @@ -1,59 +0,0 @@ -import boto3 -import argparse -import datetime -import sys - -# Create an EC2 client -ec2 = boto3.client('ec2') - -def delete_unused_ebs(file_name=None): - # Get the list of all EBS Volumes - try: - response = ec2.describe_volumes() - except Exception as e: - print(f'Error getting the list of EBS Volumes: {e}') - return - - # Loop through the list of volumes and check for any unused volumes - for volume in response['Volumes']: - if volume['State'] == 'available' and not volume['Attachments']: - volume_id = volume["VolumeId"] - try: - snapshot = input(f'Do you want to take a snapshot of volume {volume_id} before deleting? (y/n)') - if snapshot.lower() == 'y': - # Take a EBS snapshot - ec2.create_snapshot(VolumeId=volume_id,Description=f'Snapshot of the volume {volume_id} taken on {datetime.datetime.now()}') - print(f'Creating the Snapshot of volume {volume_id}') - - print(f'Deleting unused EBS Volume: {volume_id}') - ec2.delete_volume(VolumeId=volume_id) - except Exception as e: - print(f'Error deleting EBS volume {volume_id}: {e}') - - # Check the condition to see if the filename is provided and read the ebs volume from the file - - if file_name is not None: - try: - with open(file_name, 'r') as f: - volume_ids = f.read().splitlines() - for volume_id in volume_ids: - snapshot = input(f'Do you want to take a snapshot of volume {volume_id} before deleting? (y/n)') - if snapshot.lower() == 'y': - # Take a EBS snapshot - ec2.create_snapshot(VolumeId=volume_id,Description=f'Snapshot of the volume {volume_id} taken on {datetime.datetime.now()}') - print(f'Creating the Snapshot of volume {volume_id}') - - print(f'Deleting unused EBS Volume: {volume_id}') - ec2.delete_volume(VolumeId=volume_id) - except Exception as e: - print(f'Error deleting EBS volume {volume_id}: {e}') - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('-f', '--file', help='Name of the file that contains the list of unused volumes') - try: - args = parser.parse_args() - delete_unused_ebs() - sys.exit() - except Exception as e: - print("An error occurred while parsing the arguments:", e) diff --git a/deleting_unused_ebs_vol/deleting_unused_ebs_volumes.py b/deleting_unused_ebs_vol/deleting_unused_ebs_volumes.py deleted file mode 100644 index 6fef2a8..0000000 --- a/deleting_unused_ebs_vol/deleting_unused_ebs_volumes.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -# This script is to clean up Amazon Elastic Block Store (EBS) volumes that are in an unused state -# Author: Prashant Lakhera(laprashant@gmail.com) - -import boto3 - -# Create an EC2 client -ec2 = boto3.client('ec2') - -def delete_unused_ebs(): - # Get the list of all EBS Volumes - try: - response = ec2.describe_volumes() - except Exception as e: - print(f'Error getting the list of EBS Volumes: {e}') - return - - # Loop through the list of volumes and check for any unused volumes - for volume in response['Volumes']: - if volume['State'] == 'available' and not volume['Attachments']: - volume_id = volume["VolumeId"] - try: - print(f'Deleting unused EBS Volume: {volume_id}') - ec2.delete_volume(VolumeId=volume_id) - except Exception as e: - print(f'Error deleting EBS volume {volume_id}: {e}') - -def main(): - delete_unused_ebs() - - -if __name__ == '__main__': - main() \ No newline at end of file From 882e4c41f595c501894fc24f366e47d2b2ecedb9 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Mon, 23 Jan 2023 14:52:43 -0800 Subject: [PATCH 14/26] Delete finding_unused_ebs_vol directory --- finding_unused_ebs_vol/README.md | 32 ---------------- .../finding_unused_ebs_volume.py | 37 ------------------- 2 files changed, 69 deletions(-) delete mode 100644 finding_unused_ebs_vol/README.md delete mode 100644 finding_unused_ebs_vol/finding_unused_ebs_volume.py diff --git a/finding_unused_ebs_vol/README.md b/finding_unused_ebs_vol/README.md deleted file mode 100644 index fbe54e7..0000000 --- a/finding_unused_ebs_vol/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Python script to find unused EBS Volume - -Python script to find unused EBS volume. - -## Usage - -```python3 finding_unused_ebs_volume.py -h -usage: finding_unused_ebs_volume.py [-h] [-f FILE] - -optional arguments: - -h, --help show this help message and exit - -f FILE, --file FILE File name to write the list of unused volumes -``` - -# Example - -1. To convert an ebs volume from gp2 to gp3 - -``` -python3 ebs_volume_conversion.py -volume_id -volume_type gp3 -``` - -2. To convert an ebs volume from io1 to io2 -``` -python3 ebs_volume_conversion.py -volume_id -volume_type io2 -``` - -3. You can pass a csv file containing ebs volume id and volume type to convert -``` -python3 ebs_volume_conversion.py -f ebs_volume.csv -``` - diff --git a/finding_unused_ebs_vol/finding_unused_ebs_volume.py b/finding_unused_ebs_vol/finding_unused_ebs_volume.py deleted file mode 100644 index 6d90e85..0000000 --- a/finding_unused_ebs_vol/finding_unused_ebs_volume.py +++ /dev/null @@ -1,37 +0,0 @@ -import boto3 -import argparse - -def find_unused_ebs_vol(file_name=None): - try: - # Connect to EC2 service - client = boto3.client('ec2') - # Finding all the EBS Volumes - volumes = client.describe_volumes()['Volumes'] - # Initialize a list to store unused EBS volumes - unused_volumes = [] - # Iterate over the list of unused EBS Volumes - for vol in volumes: - # Check if the volume is in unused state - if vol['State'] == 'available' and not vol['Attachments']: - print(f'Found unused EBS volume: {vol["VolumeId"]}, Volume Availability Zone: {vol["AvailabilityZone"]}, VolumeType: {vol["VolumeType"]}, Volume Size in GB: {vol["Size"]}') - unused_volumes.append(vol) - - # Check the condition to see if the filename is provided and store the unused volume in a file - - if file_name is not None: - with open(file_name,'w') as f: - for vol in unused_volumes: - vol_id = vol["VolumeId"] - f.write(str(vol_id) + '\n') - # Return the list of unused volumes - return unused_volumes - - except Exception as e: - print("An error occurred while trying to get the EBS volumes:", e) - raise e - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('-f','--file',help="File name to write the list of unused volumes") - args = parser.parse_args() - find_unused_ebs_vol(args.file) \ No newline at end of file From 77b9768ffc92a307e464ba70344d59347a721c26 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 1 Mar 2023 17:23:53 +0000 Subject: [PATCH 15/26] Performance Monitoring python version --- performance_tuning/performance-monitoring.py | 90 ++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 performance_tuning/performance-monitoring.py diff --git a/performance_tuning/performance-monitoring.py b/performance_tuning/performance-monitoring.py new file mode 100644 index 0000000..7439e5d --- /dev/null +++ b/performance_tuning/performance-monitoring.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +import os + +# Function to list top 5 CPU consuming processes +def list_top_cpu_consuming_processes(): + # Get the top 5 processes by CPU usage + top_five_cpu_processes = os.popen("ps -eo pcpu,pid,user,args | sort -k 1 -r | head -n 6").read() + + # Print the results + print("###############################################################################") + print("Top 5 CPU consuming processes:") + print(top_five_cpu_processes) + +# Function to list the top 5 processes by memory usage +def list_top_memory_consuming_processes(): + # Get the top 5 processes by memory usage + top_five_memory_processes = os.popen("ps -eo pmem,pid,user,args | sort -k 1 -r | head -n 6").read() + + # Print the results + print("###############################################################################") + print("Top 5 memory consuming processes:") + print(top_five_memory_processes) + +# Check if iotop command is present +if os.system("command -v iotop >/dev/null 2>&1") == 0: + print("iotop command is present") +else: + print("iotop command is not present. Installing...") + # Install iotop command + if os.path.isfile("/etc/centos-release"): + # CentOS + os.system("sudo yum install -y epel-release") + os.system("sudo yum install -y iotop") + elif os.path.isfile("/etc/lsb-release"): + # Ubuntu + os.system("sudo apt-get update") + os.system("sudo apt-get install -y iotop") + else: + # Unsupported OS + print("Unsupported operating system") + exit(1) + +# Function to list the top 5 processes by I/O usage +def list_top_io_consuming_processes(): + # Get the top 5 processes by I/O usage + top_five_io_processes = os.popen("sudo iotop -o -b -n 6").read() + + # Print the results + print("###############################################################################") + print("Top 5 I/O consuming processes:") + print(top_five_io_processes) + +# Check if iftop command is present +if os.system("command -v iftop >/dev/null 2>&1") == 0: + print("iftop command is present") +else: + print("iftop command is not present. Installing...") + # Install iftop command + if os.path.isfile("/etc/centos-release"): + # CentOS + os.system("sudo yum install -y iftop") + elif os.path.isfile("/etc/lsb-release"): + # Ubuntu + os.system("sudo apt-get update") + os.system("sudo apt-get install -y iftop") + else: + # Unsupported OS + print("Unsupported operating system") + exit(1) + +# Function to list the top 5 processes by network usage +def list_top_network_consuming_processes(): + # Get the top 5 processes by network usage + top_five_network_processes = os.popen("sudo iftop -P -n -t -s 6").read() + + # Print the results + print("###############################################################################") + print("Top 5 network consuming processes:") + print(top_five_network_processes) + +# Main function +def main(): + list_top_cpu_consuming_processes() + list_top_memory_consuming_processes() + list_top_io_consuming_processes() + list_top_network_consuming_processes() + +# Run the main function +if __name__ == "__main__": + main() From 68be547fa21f9210da56c81d09598ee90499be82 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <100daysofdevops@gmail.com> Date: Wed, 1 Mar 2023 14:36:37 -0800 Subject: [PATCH 16/26] AWS shell script per resource cost notification --- .../aws_billing_per_resource.sh | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 aws_resource_notification/aws_billing_per_resource.sh diff --git a/aws_resource_notification/aws_billing_per_resource.sh b/aws_resource_notification/aws_billing_per_resource.sh new file mode 100644 index 0000000..77db5de --- /dev/null +++ b/aws_resource_notification/aws_billing_per_resource.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Set the start and end dates for the time period of cost report +start_date=$(date +%Y-%m-01) +end_date=$(date -d "$(date +%Y-%m-01) +1 month -1 day" +%Y-%m-%d) + +# Get the cost and usage report by resource,the level of granularity (e.g., hourly, daily, or monthly). Check this doc for more info https://docs.aws.amazon.com/cli/latest/reference/ce/get-cost-and-usage.html +usage_report=$(aws ce get-cost-and-usage --time-period Start=$start_date,End=$end_date --granularity MONTHLY --metrics "BlendedCost" "UnblendedCost" "UsageQuantity" --group-by Type=DIMENSION,Key=SERVICE --query 'ResultsByTime[0].Groups') + +# Verify if the cost and usage report retrieval was successful +if [ -z "$usage_report" ]; then + echo "Error: To retrieve cost and usage information by resource." + exit 1 +fi + +# Format the usage and cost report by resource as a table +report_table=$(echo "$usage_report" | jq -r '.[] | [.Keys[0], .Metrics.BlendedCost.Amount, .Metrics.UnblendedCost.Amount, .Metrics.UsageQuantity.Amount] | @tsv' | column -t -s $'\t' | awk 'BEGIN { print "Resource\tBlendedCost\tUnblendedCost\tUsageQuantity" } { print }') + +# Check if the EC2 or S3 resource usage exceeds $5 +if echo "$report_table" | grep -E '(^AmazonEC2|^AmazonS3)' | awk -F '\t' '$2 > 5 || $3 > 5'; then + # Send an email with the cost and usage report by resource(Don't forget to verify the email address: https://docs.aws.amazon.com/cli/latest/reference/ses/send-email.html) + aws ses send-email --from "sender@example.com" --to "recipient@example.com" --subject "AWS cost and usage report for the month" --text "$(echo "$report_table")" +fi From 78dd06ba8e133dad804276e003156f70f1718220 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Fri, 24 Mar 2023 21:31:09 -0700 Subject: [PATCH 17/26] Create cleanup_old_ami_v2.py --- boto3/cleanup_old_ami/cleanup_old_ami_v2.py | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 boto3/cleanup_old_ami/cleanup_old_ami_v2.py diff --git a/boto3/cleanup_old_ami/cleanup_old_ami_v2.py b/boto3/cleanup_old_ami/cleanup_old_ami_v2.py new file mode 100644 index 0000000..10e5c8f --- /dev/null +++ b/boto3/cleanup_old_ami/cleanup_old_ami_v2.py @@ -0,0 +1,23 @@ +import boto3 +from operator import itemgetter + +# Define the maximum number of AMIs to keep +max_count = 5 + +# Connect to AWS using the default profile +ec2 = boto3.client('ec2') + +# Retrieve a list of all AMIs +response = ec2.describe_images(Owners=['self']) + +# Sort the list of AMIs by creation date in descending order +sorted_images = sorted(response['Images'], key=itemgetter('CreationDate'), reverse=True) + +# Loop through the list of AMIs and delete any that are beyond the max_count threshold +for index, image in enumerate(sorted_images): + if index >= max_count: + ec2.deregister_image(ImageId=image['ImageId']) + print(f"Deregistered AMI {image['ImageId']}") + else: + print(f"Keeping AMI {image['ImageId']}") + break From 65a94f9bccff061519a9e408d8a72fe8b9d74ef2 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Fri, 24 Mar 2023 21:34:34 -0700 Subject: [PATCH 18/26] Create cleanup_old_ami_v3.py --- boto3/cleanup_old_ami/cleanup_old_ami_v3.py | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 boto3/cleanup_old_ami/cleanup_old_ami_v3.py diff --git a/boto3/cleanup_old_ami/cleanup_old_ami_v3.py b/boto3/cleanup_old_ami/cleanup_old_ami_v3.py new file mode 100644 index 0000000..471dbac --- /dev/null +++ b/boto3/cleanup_old_ami/cleanup_old_ami_v3.py @@ -0,0 +1,34 @@ +import boto3 +from datetime import datetime +from dateutil.parser import parse + +# Set the tag key and value to use for filtering AMIs +tag_key = "my-tag-key" +tag_value = "my-tag-value" + +# Set the maximum number of days to keep an AMI +max_age_days = 2 + +# Connect to EC2 using the default profile +client = boto3.client("ec2") + +# Get a list of all the AMIs with the specified tag +my_ami = client.describe_images( + Owners=["self"], + Filters=[ + { + "Name": f"tag:{tag_key}", + "Values": [tag_value] + } + ] +)["Images"] + +# Loop through the list of AMIs and delete any that are older than the maximum age +for ami in my_ami: + creation_date = parse(ami["CreationDate"]).replace(tzinfo=None) + ami_id = ami["ImageId"] + age_in_days = (datetime.now() - creation_date).days + print(f"Checking AMI {ami_id} with age {age_in_days} days") + if age_in_days > max_age_days: + client.deregister_image(ImageId=ami_id) + print(f"Deleted AMI {ami_id} with age {age_in_days} days") From ca337c4e89386e2b947c0fa82523bddaf14166d0 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Fri, 24 Mar 2023 21:36:13 -0700 Subject: [PATCH 19/26] Create cleanup_old_ami_v4.py --- boto3/cleanup_old_ami/cleanup_old_ami_v4.py | 39 +++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 boto3/cleanup_old_ami/cleanup_old_ami_v4.py diff --git a/boto3/cleanup_old_ami/cleanup_old_ami_v4.py b/boto3/cleanup_old_ami/cleanup_old_ami_v4.py new file mode 100644 index 0000000..4fdc493 --- /dev/null +++ b/boto3/cleanup_old_ami/cleanup_old_ami_v4.py @@ -0,0 +1,39 @@ +import boto3 +from datetime import datetime +from dateutil.parser import parse + +# Set the tag key and value to use for filtering AMIs +tag_key = "my-tag-key" +tag_value = "my-tag-value" + +# Set the maximum number of days to keep an AMI +max_age_days = 2 + +# Set the list of regions to clean up AMIs +regions = ["us-west-1", "us-west-2", "us-east-1"] + +# Loop through each region and clean up AMIs +for region in regions: + # Connect to EC2 in the current region using the default profile + client = boto3.client("ec2", region_name=region) + + # Get a list of all the AMIs with the specified tag + my_ami = client.describe_images( + Owners=["self"], + Filters=[ + { + "Name": f"tag:{tag_key}", + "Values": [tag_value] + } + ] + )["Images"] + + # Loop through the list of AMIs and delete any that are older than the maximum age + for ami in my_ami: + creation_date = parse(ami["CreationDate"]).replace(tzinfo=None) + ami_id = ami["ImageId"] + age_in_days = (datetime.now() - creation_date).days + print(f"Checking AMI {ami_id} in region {region} with age {age_in_days} days") + if age_in_days > max_age_days: + client.deregister_image(ImageId=ami_id) + print(f"Deleted AMI {ami_id} in region {region} with age {age_in_days} days") From 8b41a46a6248f04f36572131eb4e6562cff256d9 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Fri, 24 Mar 2023 21:43:04 -0700 Subject: [PATCH 20/26] Create retrieve_information_about_ec2.py --- .../ec2_information/retrieve_information_about_ec2.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 boto3/ec2_information/retrieve_information_about_ec2.py diff --git a/boto3/ec2_information/retrieve_information_about_ec2.py b/boto3/ec2_information/retrieve_information_about_ec2.py new file mode 100644 index 0000000..b4d1577 --- /dev/null +++ b/boto3/ec2_information/retrieve_information_about_ec2.py @@ -0,0 +1,11 @@ +import boto3 +import csv + +ec2 = boto3.resource('ec2') +instances = ec2.instances.all() + +with open('ec2-instances.csv', 'w', newline='') as file: + writer = csv.writer(file) + writer.writerow(["Instance ID", "State", "AMI ID", "Platform", "Instance Type", "Public IPv4 Address"]) + for instance in instances: + writer.writerow([instance.id, instance.state['Name'], instance.image.id, instance.platform, instance.instance_type, instance.public_ip_address]) From 84798f8351322ff53d9405d2688ac9b1a0512d58 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Fri, 24 Mar 2023 21:45:16 -0700 Subject: [PATCH 21/26] Create updating_tags.py --- boto3/ec2_information/updating_tags.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 boto3/ec2_information/updating_tags.py diff --git a/boto3/ec2_information/updating_tags.py b/boto3/ec2_information/updating_tags.py new file mode 100644 index 0000000..b041b07 --- /dev/null +++ b/boto3/ec2_information/updating_tags.py @@ -0,0 +1,25 @@ +import boto3 +import csv + +# Export list of EC2 instances to CSV file +ec2 = boto3.resource('ec2') +instances = ec2.instances.all() + +with open('ec2-instances.csv', 'w', newline='') as file: + writer = csv.writer(file) + writer.writerow(["Instance ID", "Name"]) + for instance in instances: + writer.writerow([instance.id, instance.tags[0]['Value'] if instance.tags else ""]) + +# Manually update CSV file with new tag keys and values + + +# Import updated CSV file and update tags for each EC2 instance +with open('ec2-instances-tags.csv', 'r') as file: + reader = csv.reader(file) + next(reader) # skip header row + for row in reader: + instance_id = row[0] + tag_key = row[2] + tag_value = row[3] + ec2.create_tags(Resources=[instance_id], Tags=[{'Key': tag_key, 'Value': tag_value}]) From 9a68dbf33d976ea89b2cdf2c49e7f548d79a9475 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Fri, 24 Mar 2023 22:00:49 -0700 Subject: [PATCH 22/26] Create downloading_all_repos.py --- github_automation/downloading_all_repos.py | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 github_automation/downloading_all_repos.py diff --git a/github_automation/downloading_all_repos.py b/github_automation/downloading_all_repos.py new file mode 100644 index 0000000..2e55195 --- /dev/null +++ b/github_automation/downloading_all_repos.py @@ -0,0 +1,25 @@ +import requests +import os + +# Replace with your GitHub username and personal access token +username = "your-username" +access_token = "your-access-token" + +# Set the base URL for the GitHub API +base_url = "https://api.github.com" + +# Create a session with the access token to authenticate requests +session = requests.Session() +session.auth = (username, access_token) + +# Get the list of repositories for the authenticated user +repositories_url = f"{base_url}/user/repos" +response = session.get(repositories_url) +repositories = response.json() + +# Loop over the repositories and clone them to a local directory +for repository in repositories: + name = repository["name"] + clone_url = repository["clone_url"] + print(f"Cloning {name} from {clone_url}") + os.system(f"git clone {clone_url}") From 9b779db87c96202364ca5a497a46b78175a13bb3 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Fri, 24 Mar 2023 22:05:07 -0700 Subject: [PATCH 23/26] Create rotate_iam_key_v3.py --- boto3/rotate_iam_keys/rotate_iam_key_v3.py | 41 ++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 boto3/rotate_iam_keys/rotate_iam_key_v3.py diff --git a/boto3/rotate_iam_keys/rotate_iam_key_v3.py b/boto3/rotate_iam_keys/rotate_iam_key_v3.py new file mode 100644 index 0000000..3244e16 --- /dev/null +++ b/boto3/rotate_iam_keys/rotate_iam_key_v3.py @@ -0,0 +1,41 @@ +import boto3 +from datetime import datetime, timezone + +client = boto3.client("iam") +s3 = boto3.client("s3") +paginator = client.get_paginator('list_users') + +max_key_age = 5 +s3_bucket = "my-bucket-name" +s3_key_prefix = "new-keys/" + +def rotate_key(key_creation_date): + current_date = datetime.now(timezone.utc) + age = (current_date - key_creation_date).days + return age + +for response in paginator.paginate(): + for user in response['Users']: + username = user['UserName'] + + # Create a new access key for the user + response = client.create_access_key(UserName=username) + access_key_id = response['AccessKey']['AccessKeyId'] + secret_access_key = response['AccessKey']['SecretAccessKey'] + + # Upload the new access key to an S3 bucket(Please do it at your own risk) + s3_key = f"{s3_key_prefix}{access_key_id}.txt" + s3.put_object( + Bucket=s3_bucket, + Key=s3_key, + Body=f"Access Key ID: {access_key_id}\nSecret Access Key: {secret_access_key}" + ) + + listkey = client.list_access_keys(UserName=username) + for accesskey in listkey['AccessKeyMetadata']: + accesskey_id = accesskey['AccessKeyId'] + key_creation_date = accesskey['CreateDate'] + age = rotate_key(key_creation_date) + if age > max_key_age: + print(f"Deactivating key for the following user: {username}") + client.update_access_key(UserName=username, AccessKeyId=accesskey_id, Status='Inactive') From d3b231dfe3c3e2801d33ec08c08daecbbc31d5bc Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Fri, 24 Mar 2023 22:07:27 -0700 Subject: [PATCH 24/26] Create rotate_iam_keys_v4.py --- boto3/rotate_iam_keys/rotate_iam_keys_v4.py | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 boto3/rotate_iam_keys/rotate_iam_keys_v4.py diff --git a/boto3/rotate_iam_keys/rotate_iam_keys_v4.py b/boto3/rotate_iam_keys/rotate_iam_keys_v4.py new file mode 100644 index 0000000..808d3b7 --- /dev/null +++ b/boto3/rotate_iam_keys/rotate_iam_keys_v4.py @@ -0,0 +1,30 @@ +import boto3 +from datetime import datetime, timezone + +client = boto3.client("iam") +paginator = client.get_paginator('list_users') + +max_key_age = 5 +excluded_users = ["user1", "user2"] # List of usernames to exclude + +def rotate_key(key_creation_date): + current_date = datetime.now(timezone.utc) + age = (current_date - key_creation_date).days + return age + +for response in paginator.paginate(): + for user in response['Users']: + username = user['UserName'] + + if username in excluded_users: + # Skip processing excluded users + continue + + listkey = client.list_access_keys(UserName=username) + for accesskey in listkey['AccessKeyMetadata']: + accesskey_id = accesskey['AccessKeyId'] + key_creation_date = accesskey['CreateDate'] + age = rotate_key(key_creation_date) + if age > max_key_age: + print(f"Deactivating key for the following user: {username}") + client.update_access_key(UserName=username, AccessKeyId=accesskey_id, Status='Inactive') From d7e59857ebb8952dc0652b59cee927b8692f1bda Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Wed, 26 Jul 2023 19:34:42 -0700 Subject: [PATCH 25/26] Create apache_log_parsing_v3.py --- apache_log_parsing/apache_log_parsing_v3.py | 48 +++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 apache_log_parsing/apache_log_parsing_v3.py diff --git a/apache_log_parsing/apache_log_parsing_v3.py b/apache_log_parsing/apache_log_parsing_v3.py new file mode 100644 index 0000000..9246e99 --- /dev/null +++ b/apache_log_parsing/apache_log_parsing_v3.py @@ -0,0 +1,48 @@ +import re +import csv +import argparse +from collections import Counter + +IP_REGEX = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" + +# Create the parser +parser = argparse.ArgumentParser(description='Reading the log and CSV file') +parser.add_argument("--l", "--logfile", + help='Please enter the logfile to parse', + dest="logfile", + type=argparse.FileType('r'), + required=True) + +def extract_ips(logfile): + """Extracts all IP addresses from the given logfile.""" + try: + with open(logfile, 'r') as f: + log = f.read() + except Exception as e: + print(f"Error reading file: {e}") + return [] + return re.findall(IP_REGEX, log) + +def count_ips(ip_list): + """Count the occurrence of each IP address in the list.""" + return Counter(ip_list) + +def write_csv(counter): + """Write the counter data to a CSV file.""" + try: + with open("ip_count.csv", 'w') as f: + writer = csv.DictWriter(f, fieldnames=["IP_Address", "Count"]) + writer.writeheader() + for item, count in counter.items(): + writer.writerow({"IP_Address": item, "Count": count}) + except Exception as e: + print(f"Error writing CSV file: {e}") + +def main(): + args = parser.parse_args() + ip_list = extract_ips(args.logfile) + ip_counter = count_ips(ip_list) + write_csv(ip_counter) + +if __name__ == '__main__': + main() From b50f142a949d714192097fbdda0612518c44eed2 Mon Sep 17 00:00:00 2001 From: 100daysofdevops <47483190+100daysofdevops@users.noreply.github.com> Date: Wed, 14 Feb 2024 10:39:42 -0800 Subject: [PATCH 26/26] Create apache_log_parsing_v4.py --- apache_log_parsing/apache_log_parsing_v4.py | 45 +++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 apache_log_parsing/apache_log_parsing_v4.py diff --git a/apache_log_parsing/apache_log_parsing_v4.py b/apache_log_parsing/apache_log_parsing_v4.py new file mode 100644 index 0000000..211521f --- /dev/null +++ b/apache_log_parsing/apache_log_parsing_v4.py @@ -0,0 +1,45 @@ +import re +import csv +import argparse +from collections import Counter + +IP_REGEX = r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" + +# Create the parser +parser = argparse.ArgumentParser(description='Parse a log file and output IP address occurrences to a CSV file.') +parser.add_argument("--l", "--logfile", + help='Logfile to parse', + dest="logfile", + type=argparse.FileType('r'), + required=True) +parser.add_argument("--o", "--output", + help='Output CSV file name', + dest="outputfile", + type=str, + default="ip_count.csv") + +def extract_ips(logfile): + """Extracts all IP addresses from the given logfile.""" + return re.findall(IP_REGEX, logfile.read()) + +def count_ips(ip_list): + """Count the occurrence of each IP address in the list.""" + return Counter(ip_list) + +def write_csv(counter, filename): + """Write the counter data to a CSV file.""" + with open(filename, 'w', newline='') as f: + writer = csv.DictWriter(f, fieldnames=["IP_Address", "Count"]) + writer.writeheader() + for item, count in counter.items(): + writer.writerow({"IP_Address": item, "Count": count}) + print(f"IP counts written to {filename}") + +def main(): + args = parser.parse_args() + ip_list = extract_ips(args.logfile) + ip_counter = count_ips(ip_list) + write_csv(ip_counter, args.outputfile) + +if __name__ == '__main__': + main()