#!/bin/bash
Check if required commands are installed
check_dependencies() {
local missing_commands=()
for command in ps grep awk cut read; do
if ! command -v “$command” &> /dev/null; then
missing_commands+=(“$command”)
fi
done
if [ ${#missing_commands[@]} -gt 0 ]; then
echo "The following commands are required but not found in your PATH:"
for command in "${missing_commands[@]}"; do
echo "- $command"
done
echo "Please install the missing commands and try again."
exit 1
fi
}
Function to find near matches for a process name
find_near_matches() {
local process_name=“$1”
local near_matches=$(ps -eo comm | grep -i “$process_name” | awk ‘!seen[$0]++’ | tr ‘\n’ ‘\n’)
echo “$near_matches”
}
Function to get process information by PID
get_process_info() {
local pid=“$1”
local process_info=$(ps -p “$pid” -o comm,cmd --no-headers | head -n 1)
local process_name=$(echo “$process_info” | awk ‘{print $1}’)
local process_path=$(echo “$process_info” | awk ‘{for(i=2;i<=NF;i++) if($i ~ /^//) {print $i; exit}}’)
echo “$process_name” “$process_path”
}
Function to send signal to a process group
send_signal_to_process_group() {
local pids=“$1”
local signal=“$2”
for pid in $pids; do
kill “-$signal” “$pid”
done
}
Function to handle process termination
handle_process_termination() {
local pids=“$1”
local signal=“$2”
local wait_time=“$3”
send_signal_to_process_group "$pids" "$signal"
echo "Signal $signal sent to process group with PIDs: $pids"
# Wait for the specified time to allow signal to be processed
echo "Waiting for $wait_time seconds to allow signal to be processed..."
sleep "$wait_time"
# Check if processes are still running after signal
local still_running_pids=""
for pid in $pids; do
if ps -p "$pid" -o comm,cmd > /dev/null; then
still_running_pids+="$pid "
fi
done
if [ -n "$still_running_pids" ]; then
echo "The following processes are still running after $wait_time seconds: $still_running_pids"
echo "Do you want to send a HARD KILL (SIGKILL 9) to these processes? (y/n)"
read kill_9_signal
if [ "$kill_9_signal" == "y" ]; then
send_signal_to_process_group "$still_running_pids" 9
echo "HARD KILL (SIGKILL 9) sent to process group with PIDs: $still_running_pids"
echo "Waiting for 2 seconds to allow SIGKILL to be processed..."
sleep 2
fi
else
echo "All processes have terminated successfully."
fi
}
Function to list processes by user
list_processes_by_user() {
local username=“$1”
local processes=$(ps -u “$username” -o pid,user,comm --no-headers)
if [ -n “$processes” ]; then
echo “Processes for user ‘$username’:”
echo “$processes”
else
echo “No processes found for user ‘$username’.”
fi
}
Function to list all users
list_all_users() {
local users=$(cut -d: -f1 /etc/passwd)
echo “Available users:”
counter=1
for user in $users; do
echo “$counter) $user”
counter=$((counter + 1))
done
}
Function to prompt user for kill signal
prompt_kill_signal() {
echo “Do you want to send:”
echo " (y) Soft Kill (SIGTERM 15)"
echo " (k) HARD KILL (SIGKILL 9)"
echo " (c) Cancel"
read -r kill_signal
}
Function to list top 10 processes by CPU usage
list_top_cpu_processes() {
echo “Observing processes for CPU usage…”
top_cpu_processes=$(ps -eo pid,user,comm,%cpu,cmd --sort=-%cpu | head -n 11)
echo “Top 10 processes by CPU usage:”
echo “No. PID USER COMMAND %CPU PATH”
echo “$top_cpu_processes” | awk ‘NR>1 {printf “%2d) %-8s %-10s %-20s %5s %s\n”, NR-1, $1, $2, $3, $4, $5}’
# Allow user to select a process
echo "Enter the number corresponding to the desired process (or 'q' to cancel):"
read -r selection
if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le 10 ]; then
selected_pid=$(echo "$top_cpu_processes" | awk -v sel="$selection" 'NR==sel+1 {print $1}')
handle_selected_process "$selected_pid"
fi
}
Function to list top 10 processes by memory usage
list_top_memory_processes() {
echo “Observing processes for memory usage…”
top_memory_processes=$(ps -eo pid,user,comm,%mem,cmd --sort=-%mem | head -n 11)
echo “Top 10 processes by memory usage:”
echo “No. PID USER COMMAND %MEM PATH”
echo “$top_memory_processes” | awk ‘NR>1 {printf “%2d) %-8s %-10s %-20s %5s %s\n”, NR-1, $1, $2, $3, $4, $5}’
# Allow user to select a process
echo "Enter the number corresponding to the desired process (or 'q' to cancel):"
read -r selection
if [[ "$selection" =~ ^[0-9]+$ ]] && [ "$selection" -ge 1 ] && [ "$selection" -le 10 ]; then
selected_pid=$(echo "$top_memory_processes" | awk -v sel="$selection" 'NR==sel+1 {print $1}')
handle_selected_process "$selected_pid"
fi
}
Function to handle the selected process
handle_selected_process() {
local pid=“$1”
if ps -p “$pid” -o comm,cmd > /dev/null; then
# Get the process name and path
IFS=" " read -ra process_info <<< “$(get_process_info “$pid”)”
process_name=“${process_info[0]}”
process_path=“${process_info[1]}”
echo "Process with PID $pid is running:"
echo "Name: $process_name"
echo "Path: $process_path"
prompt_kill_signal
if [ "$kill_signal" == "y" ]; then
echo "Enter the number of seconds to wait for the process to terminate (default is 5):"
read -r wait_time
if [ -z "$wait_time" ]; then
wait_time=5
fi
handle_process_termination "$pid" 15 "$wait_time"
elif [ "$kill_signal" == "k" ]; then
handle_process_termination "$pid" 9 2
fi
else
echo "Process with PID $pid is not running"
fi
}
Check dependencies before running the script
check_dependencies
Prompt the user to enter the PID or process name to check
while true; do
echo “Enter one of the following options:”
echo " - PID: Enter a specific PID to check the process."
echo " - Process Name: Enter a process name to check."
echo " - ‘user’: List processes by user."
echo " - ‘cpu’: List top 10 CPU consuming processes."
echo " - ‘mem’: List top 10 memory consuming processes."
echo " - ‘q’: Quit the program."
read -e input
if [ "$input" == "q" ]; then
echo "Exiting..."
break
elif [ "$input" == "user" ]; then
list_all_users
echo "Enter the number corresponding to the desired user (or 'q' to cancel):"
read selection
if [ "$selection" == "q" ]; then
continue
fi
selected_user=$(cut -d: -f1 /etc/passwd | awk -v sel="$selection" 'NR == sel')
list_processes_by_user "$selected_user"
elif [ "$input" == "cpu" ]; then
list_top_cpu_processes
elif [ "$input" == "mem" ]; then
list_top_memory_processes
else
# Check if the input is a PID or a process name
if [[ "$input" =~ ^[0-9]+$ ]]; then
# Input is a PID
pid="$input"
if ps -p "$pid" -o comm,cmd > /dev/null; then
# Get the process name and path
IFS=" " read -ra process_info <<< "$(get_process_info "$pid")"
process_name="${process_info[0]}"
process_path="${process_info[1]}"
echo "Process with PID $pid is running:"
echo "Name: $process_name"
echo "Path: $process_path"
prompt_kill_signal
if [ "$kill_signal" == "y" ]; then
echo "Enter the number of seconds to wait for the process to terminate (default is 5):"
read -r wait_time
if [ -z "$wait_time" ]; then
wait_time=5
fi
handle_process_termination "$pid" 15 "$wait_time"
elif [ "$kill_signal" == "k" ]; then
handle_process_termination "$pid" 9 2
fi
else
echo "Process with PID $pid is not running"
fi
else
# Input is a process name
process_name="$input"
pids=$(ps -C "$process_name" -o pid= | xargs)
if [ -n "$pids" ]; then
# Get the process path for the main thread
IFS=" " read -ra process_info <<< "$(get_process_info "$(echo "$pids" | head -n 1)")"
process_path="${process_info[1]}"
echo "Process with name '$process_name' (PID: $pids) is running:"
echo "Path: $process_path"
prompt_kill_signal
if [ "$kill_signal" == "y" ]; then
echo "Enter the number of seconds to wait for the process to terminate (default is 5):"
read -r wait_time
if [ -z "$wait_time" ]; then
wait_time=5
fi
handle_process_termination "$pids" 15 "$wait_time"
elif [ "$kill_signal" == "k" ]; then
handle_process_termination "$pids" 9 2
fi
else
# Find near matches for the process name
near_matches=$(find_near_matches "$process_name")
while true; do
if [ -n "$near_matches" ]; then
echo "No exact match found for '$process_name'. Near matches:"
counter=1
while read -r match; do
echo "$counter) $match"
counter=$((counter + 1))
done <<< "$near_matches"
echo "Enter the number corresponding to the desired process name (or 'q' to quit, 'n' for a new search):"
read -r selection
if [ "$selection" == "q" ]; then
echo "Exiting..."
break
elif [ "$selection" == "n" ]; then
break
else
selected_process=$(echo "$near_matches" | awk -v sel="$selection" '{if (NR == sel) print $0}')
if [ -n "$selected_process" ]; then
pids=$(ps -C "$selected_process" -o pid= | xargs)
if [ -n "$pids" ]; then
IFS=" " read -ra process_info <<< "$(get_process_info "$(echo "$pids" | head -n 1)")"
process_path="${process_info[1]}"
echo "Process with name '$selected_process' (PID: $pids) is running:"
echo "Path: $process_path"
prompt_kill_signal
if [ "$kill_signal" == "y" ]; then
echo "Enter the number of seconds to wait for the process to terminate (default is 5):"
read -r wait_time
if [ -z "$wait_time" ]; then
wait_time=5
fi
handle_process_termination "$pids" 15 "$wait_time"
elif [ "$kill_signal" == "k" ]; then
handle_process_termination "$pids" 9 2
fi
break
else
near_matches=$(find_near_matches "$process_name")
fi
else
echo "Invalid selection"
fi
fi
else
near_matches=$(find_near_matches "$process_name")
if [ -n "$near_matches" ]; then
continue
else
echo "Process with name '$process_name' is not running"
break
fi
fi
done
fi
fi
fi