Automate EC2 Instances With Python Boto3 — Start, Stop, and Monitor | Part 2
Save money and time by automating your EC2 instances with just a few lines of Python.
Automate EC2 Instances With Python Boto3 — Start, Stop, and Monitor | Part 2

Save money and time by automating your EC2 instances with just a few lines of Python.
Quick Recap of Part 1
In Part 1 we learned what boto3 is and how to set it up. If you haven’t read it yet — read that first, then come back here.
In this article we’re going to do something really practical — automate EC2 instances with Python.
By the end of this article you’ll have a working Python script that can:
- ✅ Start your EC2 instance automatically
- ✅ Stop your EC2 instance automatically
- ✅ Check the status of your instance
- ✅ Save you money by not running EC2 when you don’t need it
Let’s build it. 🚀
Why Automate EC2?
Here’s a real problem I faced.
When I was learning AWS I kept forgetting to stop my EC2 instance after I was done working. I’d close my laptop and go to sleep — and the instance would keep running all night.
AWS charges you for every hour your instance runs. Even on free tier there are limits. After free tier — it costs real money.
The solution? Automate it.
Write a script once. It handles starting and stopping for you. You never forget again. 💡
This is also exactly the kind of automation script companies want their DevOps and Cloud engineers to write.
What You Need Before Starting
- ✅ Boto3 installed (
pip install boto3) - ✅ AWS credentials configured (
aws configure) - ✅ At least one EC2 instance created in your AWS account
- ✅ Your EC2 Instance ID (find it in AWS Console → EC2 → Instances)
Your Instance ID looks like this: i-0abc123def456789
Part 1 — Check EC2 Instance Status
Before starting or stopping anything — let’s check what state our instance is in.
import boto3
def check_instance_status(instance_id):
# Create EC2 client
ec2 = boto3.client('ec2', region_name='ap-south-1')
# Get instance details
response = ec2.describe_instances(
InstanceIds=[instance_id]
)
# Extract instance information
instance = response['Reservations'][0]['Instances'][0]
state = instance['State']['Name']
instance_type = instance['InstanceType']
public_ip = instance.get('PublicIpAddress', 'No IP assigned')
print(f"Instance ID: {instance_id}")
print(f"Instance Type: {instance_type}")
print(f"Current State: {state}")
print(f"Public IP: {public_ip}")
return state
# Run it
instance_id = 'i-0abc123def456789' # Replace with your instance ID
check_instance_status(instance_id)
Output will look like:
Instance ID: i-0abc123def456789
Instance Type: t2.micro
Current State: stopped
Public IP: No IP assigned
Part 2 — Start Your EC2 Instance
import boto3
import time
def start_instance(instance_id):
ec2 = boto3.client('ec2', region_name='ap-south-1')
print(f"Starting instance {instance_id}...")
# Start the instance
response = ec2.start_instances(
InstanceIds=[instance_id]
)
# Get the new state
new_state = response['StartingInstances'][0]['CurrentState']['Name']
print(f"Instance state: {new_state}")
# Wait until instance is fully running
print("Waiting for instance to be running...")
waiter = ec2.get_waiter('instance_running')
waiter.wait(InstanceIds=[instance_id])
# Get public IP after starting
response = ec2.describe_instances(InstanceIds=[instance_id])
instance = response['Reservations'][0]['Instances'][0]
public_ip = instance.get('PublicIpAddress', 'No IP')
print(f"Instance is now RUNNING!")
print(f"Public IP: {public_ip}")
print(f"You can SSH with: ssh -i your-key.pem ubuntu@{public_ip}")
return public_ip
# Run it
instance_id = 'i-0abc123def456789' # Replace with your instance ID
start_instance(instance_id)
Output will look like:
Starting instance i-0abc123def456789...
Instance state: pending
Waiting for instance to be running...
Instance is now RUNNING!
Public IP: 13.233.45.67
You can SSH with: ssh -i your-key.pem ubuntu@13.233.45.67
Part 3 — Stop Your EC2 Instance
import boto3
def stop_instance(instance_id):
ec2 = boto3.client('ec2', region_name='ap-south-1')
print(f"Stopping instance {instance_id}...")
# Stop the instance
response = ec2.stop_instances(
InstanceIds=[instance_id]
)
new_state = response['StoppingInstances'][0]['CurrentState']['Name']
print(f"Instance state: {new_state}")
# Wait until fully stopped
print("Waiting for instance to stop completely...")
waiter = ec2.get_waiter('instance_stopped')
waiter.wait(InstanceIds=[instance_id])
print("Instance is now STOPPED!")
print("You are no longer being charged for compute. ✅")
# Run it
instance_id = 'i-0abc123def456789' # Replace with your instance ID
stop_instance(instance_id)
Part 4 — The Complete Automation Script
Now let’s put it all together into one clean, complete script:
import boto3
import sys
def get_ec2_client():
return boto3.client('ec2', region_name='ap-south-1')
def check_status(instance_id):
ec2 = get_ec2_client()
response = ec2.describe_instances(InstanceIds=[instance_id])
instance = response['Reservations'][0]['Instances'][0]
state = instance['State']['Name']
public_ip = instance.get('PublicIpAddress', 'No IP assigned')
instance_type = instance['InstanceType']
print(f"\n{'='*40}")
print(f"Instance ID : {instance_id}")
print(f"Instance Type : {instance_type}")
print(f"State : {state.upper()}")
print(f"Public IP : {public_ip}")
print(f"{'='*40}\n")
return state
def start_instance(instance_id):
ec2 = get_ec2_client()
state = check_status(instance_id)
if state == 'running':
print("Instance is already running! Nothing to do.")
return
if state == 'pending':
print("Instance is already starting up. Please wait.")
return
print(f"Starting instance {instance_id}...")
ec2.start_instances(InstanceIds=[instance_id])
print("Waiting for instance to be running...")
waiter = ec2.get_waiter('instance_running')
waiter.wait(InstanceIds=[instance_id])
# Get updated IP
response = ec2.describe_instances(InstanceIds=[instance_id])
instance = response['Reservations'][0]['Instances'][0]
public_ip = instance.get('PublicIpAddress', 'No IP')
print(f"✅ Instance STARTED successfully!")
print(f"Public IP: {public_ip}")
def stop_instance(instance_id):
ec2 = get_ec2_client()
state = check_status(instance_id)
if state == 'stopped':
print("Instance is already stopped! Nothing to do.")
return
if state == 'stopping':
print("Instance is already stopping. Please wait.")
return
print(f"Stopping instance {instance_id}...")
ec2.stop_instances(InstanceIds=[instance_id])
print("Waiting for instance to stop...")
waiter = ec2.get_waiter('instance_stopped')
waiter.wait(InstanceIds=[instance_id])
print("✅ Instance STOPPED successfully!")
print("You are no longer being charged for compute.")
def main():
# Replace with your actual instance ID
INSTANCE_ID = 'i-0abc123def456789'
if len(sys.argv) < 2:
print("Usage: python ec2_automation.py [start|stop|status]")
return
action = sys.argv[1].lower()
if action == 'start':
start_instance(INSTANCE_ID)
elif action == 'stop':
stop_instance(INSTANCE_ID)
elif action == 'status':
check_status(INSTANCE_ID)
else:
print("Invalid action. Use: start, stop, or status")
if __name__ == '__main__':
main()
How to use it:
python ec2_automation.py status # Check status
python ec2_automation.py start # Start instance
python ec2_automation.py stop # Stop instance
Bonus — Schedule Auto Stop at Night
Want your EC2 to automatically stop every night at 10pm so you never forget?
On Linux/Mac add this to your crontab:
crontab -e
Add this line:
0 22 * * * /usr/bin/python3 /home/ubuntu/ec2_automation.py stop
This runs the stop script every day at 10pm automatically. 🎉
Common Errors and Fixes
Error 1 — InvalidInstanceID
botocore.exceptions.ClientError: InvalidInstanceID.NotFound
Fix: Double check your instance ID. It should look like i-0abc123def456789
Error 2 — UnauthorizedOperation
botocore.exceptions.ClientError: UnauthorizedOperation
Fix: Your IAM user needs EC2 permissions. Go to AWS Console → IAM → your user → attach AmazonEC2FullAccess policy.
Error 3 — Wrong Region
Getting “instance not found” even with correct ID? Fix: Make sure your region matches. Mumbai = ap-south-1
What I Learned Building This
- Always check instance state BEFORE starting or stopping — avoid errors
- Waiters are your best friend — they pause your script until AWS finishes the action
- Never hardcode credentials — always use environment variables or IAM roles
- Small automation scripts like this are exactly what DevOps interviews ask you to build
Real World Use Cases
Companies use EC2 automation scripts like this for:
- Dev environments — start at 9am, stop at 6pm automatically
- Batch processing — start instance, run job, stop instance
- Cost optimization — never pay for idle instances
- Disaster recovery — automatically restart failed instances
This is not just a learning exercise — this is production-level thinking. 💪
Quick Summary
Function What it does check_status() Shows instance state and IP start_instance() Starts EC2 and waits until running stop_instance() Stops EC2 and waits until stopped crontab schedule Automates stop every night
What’s Coming in Part 3
Next we’re going to build something even more useful —
“Build an Automatic S3 Backup System With Python Boto3”
We’ll write a Python script that automatically backs up your important files to S3 every day. Never lose your data again.
Follow LearnWithPrashik so you don’t miss it! 🙌
Final Thoughts
You just built a real EC2 automation tool with Python.
This is the kind of script that saves companies thousands of rupees every month in wasted EC2 costs. And now you know how to build it.
Put this on your GitHub. Mention it in interviews. It’s a real project that shows real skill. 💪
Follow LearnWithPrashik for the complete AWS + Python automation series.
Connect with me: LinkedIn: linkedin.com/in/prashik-besekar GitHub: github.com/prashikBesekar
메타데이터
- post_id
- 06e4b3bd939a
- slug
- automate-ec2-instances-with-python-boto3-start-stop-and-monitor-part-2-06e4b3bd939a
- url
- https://awstip.com/automate-ec2-instances-with-python-boto3-start-stop-and-monitor-part-2-06e4b3bd939a
- canonical_url
- https://awstip.com/automate-ec2-instances-with-python-boto3-start-stop-and-monitor-part-2-06e4b3bd939a
- author_url
- https://medium.com/@LearnWithPrashik
- status
- ok
- fetched_at
- 2026-06-22 18:00:48