Set a time- limit on a process or application
With a small background script, you can set a time- limit on a process or application.
As long as your user does not know the administrator's password, it is not surpassed too easily.
The solution below
Is such a small background script. It limits the usage per day to a defined number of minutes, to set in the head of the script. Once set up (which is not too difficult) it runs very easy, and no additional action is needed afterwards.
The script
#!/usr/bin/python3
import subprocess
import os
import sys
import time
#--- set the time limit below (minutes)
minutes = 1
#--- set the process name to limit below
app = "gedit"
uselog = "/opt/limit/uselog"
datefile = "/opt/limit/currdate"
def read(f):
try:
return int(open(f).read().strip())
except FileNotFoundError:
pass
currday1 = read(datefile)
while True:
time.sleep(10)
currday2 = int(time.strftime("%d"))
# check if the day has changed, to reset the used quantum
if currday1 != currday2:
open(datefile, "wt").write(str(currday2))
try:
os.remove(uselog)
except FileNotFoundError:
pass
try:
# if the pid of the targeted process exists, add a "tick" to the used quantum
pid = subprocess.check_output(["pgrep", app]).decode("utf-8").strip()
n = read(uselog)
n = n + 1 if n != None else 0
# when time exceeds the permitted amount, kill the process
if n > minutes*6:
subprocess.Popen(["kill", pid])
open(uselog, "wt").write(str(n))
except subprocess.CalledProcessError:
pass
currday1 = currday2
How to use
- On your desktop (or anywhere else), create a folder named:
limit
- Copy the script into an empty file, save it as
limit_use
(no extension) inside the folder and make it executable
Edit in the head of the script the process name to limit, and the maximum number of allowed minutes. In the example:
#--- set the time limit below (minutes)
minutes = 1
#--- set the process name to limit below
app = "gedit"
Copy the folder to the directory /opt
:
cp -r /path/to/limit /opt
Now edit /etc/rc.local
to make the script run it as root
on startup:
sudo -i gedit /etc/rc.local
Just before the line
exit 0
another line:
/opt/limit/limit_use &
That's it
When someone tries to kill the background script:
(action not allowed)
Explanation; how it works
- Once per 10 seconds, the script looks if the targeted process is running. If so, it "adds" one "point" to a total usage, to be recorded in a file (
/opt/limit/uselog
). If the dayly limit is reached, the script no longer allows the process to run, killing it if it exists.
- On the day change (the date is recorded in a file, so reboot won't help), the log file is deleted, allowing a new amount of usage time to build up.
- Since the script runs on boot up, from
rc.local
only user(s) with sudo privileges can stop the script, even then only if the user knows the process name.
Stop the script
In case you'd like to stop the script, use the command:
sudo kill "$(pgrep limit_use)"
But again, you'd need the sudo password to do so.
EDIT
Although the script above should provide a reasonably secure way of limiting an application's usage, as mentioned by @Bytecommander, it can be surpassed, although not very easily. The combination with the measure below will make it very unlikely that this will happen, unless your son knows the setup, and is quite experienced with Linux/Ubuntu.
Additional measure
A bit further from a "simple solution", but still not too difficult to set up is the additional measure below. If our suspected delinquent would find out the script is called from /etc/rc.local
, would manage to become root, and remove the line in /etc/rc.local
, or would be able to stop the script that way, we can confront him with the next problem: the screen blacks out after log in. Additionally, the solution checks if the background script is running after 5 minutes after restart, blacking out if not.
The extra measure is a startup- check if the line /opt/limit/limit_use &
is present in /etc/rc.local
, and a check after 5 minutes if the script still runs. Since the script runs from a (hidden from Startup Applications) launcher in /etc/xdg/autostart
it will be quite difficult to find out what is happening, unless you know how it is done. The combination of these two measures makes it unlikely your son will find out, and if he does, probably nothing will stop him.
How to set up
Two simple steps are involved:
Copy the code below into an empty file, save it as blackout.desktop
on your desktop:
[Desktop Entry]
Name=not allowed
Exec=/bin/bash -c "sleep 15 && /usr/local/bin/blackout.py"
Type=Application
Terminal=false
NoDisplay=true
Copy the file to /etc/xdg/autostart
:
sudo cp /path/to/blackout.desktop /etc/xdg/autostart
Copy the script below into an empty file, save it as blackout.py
on your desktop, make it executable and copy it to /usr/local/bin
:
cp /path/to/blackout.py /usr/local/bin
The script
#!/usr/bin/env python3
import subprocess
import time
def dim_screen():
screen = [
l.split()[0] for l in subprocess.check_output(["xrandr"]).decode("utf-8").splitlines()\
if " connected" in l
]
for scr in screen:
subprocess.Popen(["xrandr", "--output", scr, "--brightness", "0"])
if not "/opt/limit/limit_use &" in open("/etc/rc.local").read():
dim_screen()
time.sleep(300)
try:
pid = subprocess.check_output(["pgrep", "limit_use"]).decode("utf-8").strip()
except subprocess.CalledProcessError:
dim_screen()
Explanation
Launchers in /etc/xdg/autostart
will launch an application (in this case the extra security check- up) for all users. This could be overwritten locally, but you have to know the check up runs. By putting the line NoDisplay=true
into our launcher, it will not appear locally in Startup Applications
, so without knowing it exists, it is unlikely to be discovered.
Furthermore, your son has only 15 seconds to find out (then the screen is blacked out) so he would have a serious problem, unless he is a genious, has a lot of experience with Ubuntu and a creative mind.