14

I am looking for a script or a tool which I can turn on, when needed, which shuts down my computer if there is e.g. no network traffic for say 10 minutes, or below 100kb for example.

Would be really handy for automatic downloading. I know there are downsides to this, internet connection is hanging, download program is hanging, so if you have a better idea, please tell me.

Thanks in advance.

2 Answers 2

16

There are a few ways to go about this, I have written a very simple bash script that you can use to monitor the speed in KB p/s for a desired interface, when the download speed drops below the minimum (which you can set), then your computer will be shutdown.

Some things to keep in mind here are:

  • This is a bash script that I put together quickly, there are many different techniques to achieve the same result, however this is an easy one to understand and implement.

  • You will need to execute the bash script from cron as root, that means you need to open cron as the root user and add a cronjob as desired. The reason it needs to be in root's cron is that you will not be able to shutdown your computer from the command line without being root, and you cannot use sudo while you are away from keyboard. There are ways to get around it but I am trying to keep it as simple as possible.

  • I use a linux tool called ifstat, so you will need to install this otherwise the script will not work:

    sudo apt-get install ifstat
    
  • There are 2 options that you can modify in the script below, the INTERFACE and MIN_SPEED. The INTERFACE needs to be set to the interface you are using to download, either eth0 for your wired device or wlan0 for you wireless device, you can use the command ifconfig from the command line to see what interfaces you have available. The MIN_SPEED is set as desired, in my example I set it to the number 5, which means that if my download speed is less than 5 KB per second then my computer will shutdown.

  • Lastly, to improve on the script we could use a while loop and check the download speed over a specified period of time and if the average is less than the minimum we would shutdown, as well as run the script as a service, this is a more accurate way of approaching the problem and I will be happy to help you with that if this is the route you would like to follow.

Copy and paste the below code into a file in a directory of your choice on your computer, example i_speed.sh, then, very important, make the file executable, to do this from the command line, if your file was called i_speed.sh as follows:

    chmod +x i_speed.sh 

Now you can sudo -i to root and setup your cronjob to call the script at time intervals that you desire.

Code to copy and paste into a file called i_speed.sh:

#!/bin/bash

# Bash script to determine a network interfaces current transfer speed and 
  shutdown the computer if the current transfer speed is less than MIN_SPEED

# Set INTERFACE to the network interface you would like to monitor
INTERFACE='wlan0'

# Set MIN_SPEED in KB per second that network interface (INTERFACE) speed 
  must be larger than, if speed falls below this number then computer will shutdown.
MIN_SPEED=5


# This is where the work get's done:
CURRENT_SPEED=`ifstat -i $INTERFACE 1 1 | awk '{print $1}' | sed -n '3p'`
INT=${CURRENT_SPEED/\.*}

if [ $INT -lt $MIN_SPEED ]; then
    shutdown -h now
else
    exit
fi

UPDATE

I wrote a small python program as an update to the bash script above which allows you to set additional variables such as retries and interval to get an average min speed over a specified period of time. Further updates will include a GUI for this program. Just copy and paste the code below into a file, example download_monitor.py then run it as follows sudo python download_monitor.py

## Download Monitor v0.1 - March 2012

# Set the interface you wish to monitor, eg: eth0, wlan0, usb0
INTERFACE = "eth0"

# Set the minimum download speed in KB/s that must be achieved.
MINIMUM_SPEED = 15

# Set the number of retries to test for the average minimum speed. If the average speed is less
# than the minimum speed for x number of retries, then shutdown.
RETRIES = 5

# Set the interval (in seconds), between retries to test for the minimum speed.
INTERVAL = 10


import os, time
from commands import getoutput

def worker ():
    RETRIES_COUNT = RETRIES
    while True:
        SPEED = int(float(getoutput("ifstat -i %s 1 1 | awk '{print $1}' | sed -n '3p'" % INTERFACE)))
        if (SPEED < MINIMUM_SPEED and RETRIES_COUNT <= 0):
            os.system("shutdown -h now")
        elif SPEED < MINIMUM_SPEED:
            RETRIES_COUNT -= 1
            time.sleep(INTERVAL)
        else:
            RETRIES_COUNT = RETRIES
            time.sleep(INTERVAL)

worker()
6
  • THANKS! Thats exactly what i wanted! I will try this tomorrow, Got the missus over right now and she wants some linuxfree time... But thats the script I was looking for. Thanks
    – cirkator
    Feb 19, 2012 at 18:10
  • Hey man : ) sorry that i didn't reply earlier but i found no time to test it. But it is WORKING : ) I thought some more about the script, would it be possible to program it so it behaves a little bit different? It would be great if the script starts at startup, then shows a little window on the desktop, which says: "You have 3 minutes to enter e.g. "NO" if you want to stop the script, otherwise it will shutdown the pc if there is no network traffic (or below something) for e.g. a period of 5 minutes."
    – cirkator
    Feb 25, 2012 at 9:48
  • This way i could start the script via cron on every startup but if i am physically at the pc and i dont want the script to run i could easily disable it. And if its a scheduled autostart lets say at 3.a.m. just for downloading, it would count down 3 minutes and then set the script in "Go and monitor-mode". Also is it possible to have the script running all the time, and keep on checking or can i only run it e.g. every minute with cron and let it check for no network traffic? THANKS AGAIN YOU ARE THE MAN :)
    – cirkator
    Feb 25, 2012 at 9:55
  • @cirkator I'm glad it's working for you. Sure, all those options are possible and possibly the correct way to go about doing it. I will be happy to write a more official program but it will take a bit longer. Once I have something in place I'll let you test.
    – kingmilo
    Feb 25, 2012 at 20:59
  • Take all the time in the world, i´m just happy at the thought that you are coding something for us in your freetime. Very much appreciated! : )
    – cirkator
    Feb 27, 2012 at 22:25
4

I found this topic very helpful. With no Python knowledge I've updated the above script to get average network speed and go into long sleep if average speed is more than minimum speed. After long sleep calculations are reset and average speed is calculated again.

## Download Monitor v0.2 - June 2017

# Set the interface you wish to monitor, eg: eth0, wlan0, usb0
INTERFACE = "enp4s0"

# Set the minimum download speed in KB/s that must be achieved.
MINIMUM_SPEED = 10

# Set the number of retries to test for the average minimum speed.
RETRIES = 5

# Set the interval (in seconds), between retries to calculate average speed.
INTERVAL = 5

# Set the interval (in seconds), between recalculating average speed
LONG_INTERVAL = 600

import os, time
from commands import getoutput

def worker ():
    RETRIES_COUNT = 1
    SPEED = 0
    while True:
        # Sum downstream and upstream and add with previous speed value
        # {print $1} use just downstream
        # {print $2} use just upstream
        # {print $1+$2} use sum of downstream and upstream
        SPEED += int(float(getoutput("ifstat -i %s 1 1 | awk '{print $1+$2}' | sed -n '3p'" % INTERFACE)))

        if RETRIES_COUNT > RETRIES:
            # Calculate average speed from all retries
            AVG_SPEED = int(float(SPEED) / float(RETRIES_COUNT))

            # If average speed is below minimum speed - suspend
            if AVG_SPEED < MINIMUM_SPEED:
                os.system("shutdown -h now")
            # Else reset calculations and wait for longer to retry calculation
            else:
                RETRIES_COUNT = 1
                SPEED = 0
                time.sleep(LONG_INTERVAL)
        else:
            RETRIES_COUNT += 1
            time.sleep(INTERVAL)

worker()
1
  • Awesome. So this means this cronjob has to be started only once, right?
    – bomben
    Jan 25, 2020 at 19:12

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