I’ve been using on-demand machines (similar to AWS EC2 and Google Cloud VM instances) to perform large computations. Those machines are both pay-as-you go and pretty expensive, so you want to terminate them as soon as your computations are done.
I’m sure there’s some fancy way, using tools provided by the cloud machine provider, to automatically shut down a machine that’s idle. But I thought, rather than looking for each vendor-specific, complicated (and likely billable) solution, I’d come up with a bash script. And here it goes:
while : do load5M=$(uptime | awk -F'[a-z]:' '{ print $2}' | cut -d, -f1) threshold=0.5 echo $load5M if (( $(echo "$load5M < $threshold" | bc -l) )); then sudo shutdown now break fi sleep 5 done
It's an infinite loop, with a 5 seconds pause, which gets the load average over the last 5 minutes, displays it, and if it's lower than the defined threshold of 0.5 (that's half a CPU core), immediately stops the machine. Simple enough, apart from the 2 magic lines needed to get the load average and to do a comparison between 2 floats (I found that surprisingly tougher than comparing 2 integers!)
A little warning though: be sure to test it, to check that your provider doesn't automatically restarts a terminated machine. That's quite unlikely, but it would be a shame ^^
Update 2021-10-04
I recently tried that on Debian, and I had an error about "bc not found", so I had to sudo apt-get install bc
.
I'm still getting a weird 0: not found
on the same line... And it doesn't work. So, turns out it might be Ubuntu-only somehow (I'm using it on Ubuntu 20.04 LTS, in case the version matters too)
Thank you very much for sharing it! It is precisely what I was looking for!!
Hello & another ‘Thank You’!
After testing the seemingly only readily available tool (‘autopoweroff’), which did not work for me, I found your script and managed to adapt it to european systems, where ‘uptime’ returns processor loads as comma separated floats with decimal commas instead of decimal points…
Works flawlessly (if there are mistakes, please let me know) on two headless systems I built: a small WebDav server, which starts up when addressed from the internet (I didn’t want it to run idle 99.9% of time, also for security concerns) and a small multimedia server (…don’t want to get up from the sofa to turn it off when finished watching movies :-)).
I’m not a programmer and far from being a Linux expert, so I’m a little proud of it.
Here’s how I did it:
Nice!
I’m pretty sure I did try that
if [ $stuff -gt $otherstuff ]
in my attempts to get the comparison working, but in my case it didn’t work. Bash is so mysterious to me…It seems that comparing integers is much simpler than comparing floats…
I was literally forced to do it that way because the output before piping to ‘sed’ was like this:
0,89, 0,54, 1,44. ‘cut’ takes the commas as separators, therefore the -f option did not work. I had to eliminate all commas, which led to three integers. The 5min load value was then cut by the position of the three characters because ‘cut -f’ does not interpret the blanks between the numbers as separators…
Think it would have been more complicated, if the output of ‘uptime’ had been like this:
0.45, 0.76, 0.67 – with commas AND decimal points….
I’m happy with the result!