I want to terminate my ec2 instance between 1hour and 1h30 min (random interval) after it starts.
How can i achieve this?
Using cron job or at command
Below is the working code, But it will be good if i can do this using crontab instead of sleep command.
sleep $(shuf -i 3600-5400-n 1) && aws ec2 terminate-instances --instance-ids $AWS_INSTANCE_ID --region ${region}
Thanks
When the instance starts, you could run a script (eg via User Data) that:
Sleeps for the desired time period (eg sleep 3600)
Does a shutdown (eg sudo shutdown -h now)
Be sure to set your termination behaviour to Terminate otherwise the instance will simply stop.
Related
I am trying to run a script to start, stop, or restart a bot from my front end webpage.
I have a bot that runs almost 24/7 on a Linux EC2 instance, and a webpage front end that allows for parameter input and shows the current status of the bot. The front end sends a POST request to a lambda function, which writes the parameters to my S3 bucket. The script to start the bot on the EC2 instance pulls the latest parameters from S3 and initializes the bot. When the bot starts up and shuts down, it writes the status ("running", "stopped") to a file in the S3 bucket, which then shows on the front end.
I have looked into SSM Run Command with Lambda, but given that the bot runs for days at a time, I don't believe that's viable. Additionally, it uses an agent to connect, so trying to use the screen command would terminate when the agent terminates.
I have also tried adding the script to my EC2 instance’s User Data, but that does not seem to work. Similarly a cron job for reboot does not work.
I've considered using a trigger file in S3, i.e. having the EC2 instance check at a given time interval for some trigger file in S3 that would indicate a start or stop, but that seems very resource intensive.
What alternatives do I have?
The solution that worked for me was setting up a crontab job that runs on reboot, then starting, stopping, and restarting the EC2 instance with a lambda function.
Steps to resolve this for anyone in the same boat:
SSH into the EC2 instance
crontab -e
add the following line:
#reboot sleep 60 && cd /home/ec2-user/bot_folder/ && /usr/bin/screen -S bot -dm /usr/bin/python3 run_bot.py
(for vim, press i to enter insert mode, paste the line and make changes, then press esc :wq enter to save)
Ensure that the script has all of its paths specified absolutely. In my case, using Selenium, the chromedriver path needed to be specified.
Finally, setup a lambda function to start/stop/reboot your instance as the comment above referenced.
I have the following command in my EC2 User Data:
setsid nohup /root/go/src/prometheus-to-cloudwatch-master/dist/bin/prometheus-to-cloudwatch --cloudwatch_namespace TestBox/Prometheus --cloudwatch_region eu-west-1 --cloudwatch_publish_timeout 5 --prometheus_scrape_interval 30 --prometheus_scrape_url MyScrapeUrl &
This script will take metrics published at the prometheus_scrape_url and push them to CloudWatch. By default this script runs in the foreground and every 30 seconds will output the number of metrics pushed to CloudWatch. I have added setsid nohup to run the script in the background in a new session.
The issue here is that the script doesn't seem to run until I SSH into the box following initialisation and su to the root user (it's like it's queued to be run when I next SSH as the root user).
My expected behaviour is that the script runs as part of the user data and I should never need to SSH into the box.
The script in question is: https://github.com/cloudposse/prometheus-to-cloudwatch
I needed to add a shutdown hooks on my EC2 instances to do some resource clean up stuff.
Moreover, I would also be able to start and stop manually my instance for testing purpose and I wanted the startup and shutdown hooks to be triggered the same way as on the initial bootstrap.
I then decided to install a script as a service on AWS EC2 Ubuntu 16.04 LTS instance via a Cloudformation bash script.
Here is the first naive version of the script:
UserData:
"Fn::Base64":
!Sub
- |
#!/usr/bin/env bash
BOOTSTRAP_SCRIPT_NAME=bootstrap
BOOTSTRAP_SCRIPT_PATH=/etc/init.d/${BOOTSTRAP_SCRIPT_NAME}
cat > /etc/init.d/boostrap <<EOF
### BEGIN INIT INFO
# Provides: ${BOOTSTRAP_SCRIPT_NAME}
# Required-Start: \\\$local_fs \\\$remote_fs \\\$network \\\$syslog \\\$named
# Required-Stop: \\\$local_fs \\\$remote_fs \\\$network \\\$syslog \\\$named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Bootstrap an instance
# Description: Bootstrap an instance
### END INIT INFO
function start() {
echo "STARTUP on $(date)"
}
function stop() {
echo "SHUTDOWN on $(date)"
}
case "\$1" {
start)
start | tee -a /var/log/${BOOTSTRAP_SCRIPT_NAME}.log
;;
stop)
stop | tee -a /var/log/${BOOTSTRAP_SCRIPT_NAME}.log
;;
}
EOF
chmod +x ${BOOTSTRAP_SCRIPT_PATH}
update-rc.d -f ${BOOTSTRAP_SCRIPT_NAME} remove
update-rc.d ${BOOTSTRAP_SCRIPT_NAME} defaults
With this version, the bootstrap script is never started.
I quickly understood that the bootstrap script was installed during the cloud-init phase and by the way during the linux sysv init phase and would not take part of the current init phase ... (If this is wrong tell me ;-))
I then decided to start it manually such as apache2 in cloudformation bash examples. I added the following line at the end of the script.
${BOOTSTRAP_SCRIPT_PATH} start
I tested it again, and saw the "STARTUP on XXX" log in the bootstrap.log file after this fix.
But when I tried to stop the instance in the consol, no "SHUTDOWN on XXX" logs appeared in the bootstrap.log file ...
I log into the instance and try to start/stop the script manually ... all the startup and shutdown logs appeared 8-O. I then supposed that as the boostrap script was not identified as an init script the stop callback would not be called on instance stop or terminate ... (If this is wrong tell me ;-))
I then start and stop several times the instance from the AWS console and both STARTUP and SHUTDOWN messages still appeared in the logs.
This confirmed my hypothesis. The logs are only missing during the first init and shutdown cycle.
So I did something weird and ugly ... I replace the last line start command with this one :
reboot -n
The script now works as I need but I think there should be a cleaner way to enable my script for init or a least for the shutdown phase during cloud-init without rebooting ...
Is anyone has a best solution or more details on the issue ?
PS : I tried init u and telinit u instead of reboot with no success
The reason for this seems to be that the bootstrap is not started as a service the first time. It is run as a normal script. Instead of ${BOOTSTRAP_SCRIPT_PATH} start, try adding the following line to your user-data:
sudo service ${BOOTSTRAP_SCRIPT_NAME} start
I have a script that will
kill all sshd processes
start a new sshd process
I would like to scp this script onto a remote computer and execute it using ssh. After it executes the first step of killing all sshd, will it still get to the 2nd step of running sshd again? I'm worried because I'm running the script using ssh and ssh will die after step 1.
Normal procedure is to stop the main sshd, with e.g. /etc/init.d/sshd stop or your distro's equivalent. This way, the listening daemon shuts down while existing connections go on until the clients disconnect.
If you want to upgrade/replace sshd, change any settings and restart it, this is the way to go.
No need to scp it to server, just try doing this :
while read cmd; do ssh server "bash -c $cmd"; done < script.sh
Why not to use cron for it?
For example:
10 * * * * /path_to_script
minute hour day month dayofweek command
Do not forget to switch it off;)
Is there a way that Amazon Web Services EC2 instances can be self terminating? Does Amazon have anything that allows an instance to terminate itself ("Hara-Kiri") after running for more than say an hour? I could change the scripts on the running instance to do this itself, but that might fail and I don't want to edit the image, so I would like Amazon to kill the instance.
To have an instance terminate itself do both of these steps:
Start the instance with --instance-initiated-shutdown-behavior terminate or the equivalent on the AWS console or API call.
Run shutdown -h now as root. On Ubuntu, you could set this up to happen in 55 minutes using:
echo "sudo halt" | at now + 55 minutes
I wrote an article a while back on other options to accomplish this same "terminate in an hour" goal:
Automatic Termination of Temporary Instances on Amazon EC2
http://alestic.com/2010/09/ec2-instance-termination
The article was originally written before instance-initiated-shutdown-behavior was available, but you'll find updates and other gems in the comments.
You can do this
ec2-terminate-instances $(curl -s http://169.254.169.254/latest/meta-data/instance-id)
The ec2 will get its current instance id and terminate itself.
Hopefully this will work
instanceId=$(curl http://169.254.169.254/latest/meta-data/instance-id/)
region=$(curl http://169.254.169.254/latest/dynamic/instance-identity/document | grep region | awk '{print $3}' | sed 's/"//g'|sed 's/,//g')
/usr/bin/aws ec2 terminate-instances --instance-ids $instanceId --region $region
Hope this help you !!!
Here is my script for Self-Terminating
$ EC2_INSTANCE_ID="`wget -q -O - http://instance-data/latest/meta-data/instance-id || die \"wget instance-id has failed: $?\"`"
$ echo "ec2-terminate-instances $EC2_INSTANCE_ID" | at now + 55 min || die 'cannot obtain instance-id'
If you want to assign it as Self-Stopping on Self-Terminating, you can do it one time only.
In your EC2 Console go to Instance Settings, change Shutdown Behavior to Stop.
Configure /etc/cloud/cloud.cfg, you may refer to how to run a boot script using cloud-init.
Follow answer from Eric Hammond, put the command in a file and locate it in scripts-per-boot path:
$ echo '#!/bin/sh' > per-boot.sh
$ echo 'echo "halt" | at now + 55 min' >> per-boot.sh
$ echo 'echo per-boot: `date` >> /tmp/per-boot.txt' >> per-boot.sh
$ chmod +x per-boot.sh
$ sudo chown -R root per-boot.sh
$ sudo mv -viu per-boot.sh /var/lib/cloud/scripts/per-boot
Reboot your instance, check if the script is executed:
$ cat /tmp/per-boot.txt
per-boot: Mon Jul 4 15:35:42 UTC 2016
If so, just in case you forgot to stop your instance, it will assure you that the instance will do itself termination as stopping when it has run for 55 minutes or whatever time you set in the script.
Broadcast message from root#ip-10-0-0-32
(unknown) at 16:30 ...
The system is going down for halt NOW!
PS: For everyone want to use the Self-Stopping, one thing you should note that not all EC2 types are self recovery on restarting. I recommend to use EC2-VPC/EBS with On/Off Schedule.
I had a similar need, where I had web applications firing up EC2 instances. I could not trust the web application to stop/terminate the instances, so I created a script to run in a separate process, called the "feeder". The feeder owns the responsibility of stopping/terminating the instance. The web application must periodically request that the feeder "feed" the instance. If an instance "starves" (is not fed within a timeout period), the feeder will stop/terminate it. Two feeders can be run simultaneously on different machines to protect against issues with one feeder process. In other words, the instance runs on a pressure switch. When pressure is released, the instance is stopped/terminated. This also allows me to share an instance among multiple users.
To the original question, the feeder, which could be running in the EC2 instance itself, eliminates the need to know a priori how long the task will be running, but it places a burden on the application to provide periodic feedings. If the laptop is closed, the instance will go down.
The feeder lives here: https://github.com/alessandrocomodi/fpga-webserver and has a permissive open-source license.