10

I have a server hosted on EC2. The server is built on the Linux AMI, based on CentOS. It is dedicated to a client project, and I connect via SSH. Sometimes, I forget to shut down the server when unused, therefore generating unnecessary costs.

How do I make the server shut down automatically on inactivity, for example after 30 min without an SSH connection?

Naturally, I am looking for the simplest solution. A check every hour or so would also be OK, just something that works reliably.

8

As of January 2013 Amazon CloudWatch provides an option to Use Amazon CloudWatch to Detect and Shut Down Unused Amazon EC2 Instances, see the introductory blog post Amazon CloudWatch - Alarm Actions for details on this functionality:

Today we are giving you the ability to stop or terminate your EC2 instances when a CloudWatch alarm is triggered. You can use this as a failsafe (detect an abnormal condition and then act) or as part of your application's processing logic (await an expected condition and then act). [emphasis mine]

Your use case is listed in section Failsafe Ideas specifically:

If you (or your developers) are forgetful, you can detect unused EC2 instances and shut them down. You could do this by detecting a very low load average for an extended period of time. This type of failsafe could be used to reduce your AWS bill by making sure that you are not paying for resources you're not actually using.

As outlined, this depends on being able to heuristically detect the appropriate condition triggering the alarm and stopping the instance - you might take it to the next level by means of Publishing Custom Metrics to CloudWatch based on the logged in SSH user count, idle time or else and gain more control/precision for the desired detection and shutdown process in turn.

1
  • 1
    As a first experiment, I set up an alarm which shuts down the instance when NetworkIn (averaged over 5 minutes) is below 1000 bytes (per minute) for more than 30 minutes. – feklee Mar 25 '13 at 23:26
5

You could create a cron job script right on the instance itself that uses a command like

netstat | grep ssh | grep ESTABLISHED

and if no result is returned write that to file, then the cron tries again and if it returns no results again the script runs this.

/sbin/shutdown -h now
2

If all you're looking for is to keep the server running while you're logged-in, and your session idle for less than n units of time, you can do so via a cron script which you mentioned, by monitoring the output of w(1) which reports IDLE time for logged-in user, which you can use.

8
  • 1
    w does indeed look interesting. To get the idle time in seconds for user ec2-user: w -hs ec2-user | sed -e 's/.* \([0-9]\+\.[0-9]\{2\}\)s .*/\1/' – feklee Mar 24 '13 at 13:02
  • I think he wanted to shut down automatically if nobody was logged in for a certain length of time? – Michael Hampton Mar 24 '13 at 15:28
  • @MichaelHampton I'm the only user. – feklee Mar 24 '13 at 15:39
  • @feklee If you aren't logged in, then "nobody is logged in" :) – Michael Hampton Mar 24 '13 at 15:40
  • 7
    @abbe If nobody logs on, then it's time to format and reinstall. – Michael Hampton Mar 24 '13 at 17:14
2

I also have few EC2 instances that I only use once in a while. Here's a systemd service I made that shuts down instance when there's no SSH activity for some time.

1
  • Seems interesting. Unfortunately the link is broken. – Fernando Correia Apr 28 at 2:36
2

For a self-contained solution that doesn't require setting up other services, and doesn't depend on usage metrics, set this script to run on a schedule:

#!/bin/bash
#
# Shuts down the host on inactivity.
#
# Designed to be executed as root from a cron job.
# It will power off on the 2nd consecutive run without an active ssh session.
# That prevents an undesirable shutdown when the machine was just started, or on a brief disconnect.
#
# To enable, add this entry to /etc/crontab:
# */5 *   * * *   root    /home/ubuntu/dotfiles/bin/shutdown-if-inactive
#
set -o nounset -o errexit -o pipefail

MARKER_FILE="/tmp/ssh-inactivity-flag"

STATUS=$(netstat | grep ssh | grep ESTABLISHED &>/dev/null && echo active || echo inactive)

if [ "$STATUS" == "inactive" ]; then
  if [ -f "$MARKER_FILE" ]; then
    echo "Powering off due to ssh inactivity."
    poweroff  # See https://unix.stackexchange.com/a/196014/56711
  else
    # Create a marker file so that it will shut down if still inactive on the next time this script runs.
    touch "$MARKER_FILE"
  fi
else
  # Delete marker file if it exists
  rm --force "$MARKER_FILE"
fi

To run this script every 5 minutes, shutting down the instance after 10 minutes of inactivity, add this entry to /etc/crontab:

*/5 *   * * *   root    /home/ubuntu/bin/shutdown-if-inactive

Change /home/ubuntu/bin to the path where the script was saved.

This was tested on an EC2 instance running Ubuntu 20.04. See source.

This expands on @dmohr's answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.