Last active
December 22, 2021 19:41
-
-
Save Coopeh/4ab987e5b8210e4222a82c2581aed861 to your computer and use it in GitHub Desktop.
SSH Idle Session Kicker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
### | |
# | |
# SSH Inactive Session Killer | |
# | |
### | |
# Set idle time in hours - default is 12 | |
idle_time="12" | |
# Where to store session file for logging - default is /var/ssh-session | |
session_directory="/var/ssh-session" | |
############# | |
# If idle_time is left empty, set to default of 12 hours | |
if [[ -z $idle_time ]]; then | |
idle_time="12" | |
fi | |
# If session directory is left empty, set to default of /var/ssh-session | |
if [[ -z $session_directory ]]; then | |
session_directory="/var/ssh-session" | |
fi | |
# Exit on script error - https://vaneyckt.io/posts/safer_bash_scripts_with_set_euxo_pipefail/ | |
set -uo pipefail | |
# Warning and disconnect timing variables in hours | |
warning_time=$( date -d "$((idle_time - 1)) hours ago" +%s ) | |
disconnect_time=$(date -d "$idle_time hours ago" +%s) | |
# Create the sessions directory | |
if [ ! -d "$session_directory" ]; then | |
mkdir -p "$session_directory" | |
fi | |
# Create arrays from new lines | |
IFS=$'\n'; | |
# Function to create array of user session info | |
user_info() { | |
who -s | awk '{ print $2 }' | (cd /dev && xargs stat -c '%n %U %X') | awk '{print $1" "$2" "$3}' | grep -v "root|grep" | sort -k 3,3 | |
} | |
user_sessions=$(user_info) | |
# Remove non-idle session files | |
for f in "$session_directory"/*; do | |
# Check that this is definitely a file | |
test -f "$f" || continue | |
# Create reusable variables for checking session and idle time for arithmetic later | |
session_check=$(echo "${user_sessions[*]}" | grep "pts/${f##*/}") | |
session_idle_time=$(echo "${user_sessions[*]}" | grep "pts/${f##*/}" | awk '{print $3}') | |
# Check if the file exists but there's no longer a session | |
if [[ -z $session_check ]]; then | |
rm "$f" | |
echo "pts/${f##*/} no longer connected, removing session file" | |
continue | |
# Check if the file exists, but is no longer an inactive session | |
elif [[ ! -z $session_check ]] && [[ $session_idle_time > $warning_time ]]; then | |
rm "$f" | |
echo "pts/${f##*/} no longer an inactive session, removing session file" | |
continue | |
fi | |
done | |
# Loop through the current connected users | |
for i in ${user_sessions[*]}; do | |
# Create pts, user and session variables from the connected user data | |
pts=$(echo "$i" | awk '{print $1}' | cut -d '/' -f2) | |
user=$(echo "$i" | awk '{print $2}') | |
session=$(echo "$i" | awk '{print $3}') | |
# If the session is idle for over the idle cut off time | |
if [[ $session < $warning_time ]]; then | |
# If the session file doesn't exist, create it and warn the user that they will be disconnected | |
if [[ ! -f "$session_directory/$pts" ]]; then | |
touch "$session_directory/$pts" | |
echo "Hi $user. Your SSH session has been inactive for $((idle_time - 1)) hours, it will be closed in 1 hour at $(date -d '1 hour') if no activity is detected." | write "$user" "pts/$pts" | |
continue | |
# If the session file exists, check it hasn't been there for the idle cut off time | |
# Kill the session if over idle cut off time | |
elif [[ -f "$session_directory/$pts" && $session < $disconnect_time ]]; then | |
pkill -9 -t "pts/$pts" | |
rm "$session_directory/$pts" | |
fi | |
fi | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment