How do I start & kill a process at a given time of day?

Hi FOSS Community,

I have 2 noob shell script questions:

  1. I have a process running on my Ubuntu PC and I want to stop it for a few hours in order to run a different application. But I want the process to startup again at a certain time of day.
    For example: I want the application that is already running to get killed (or suspended) at 2pm each day and then start at 5pm. Can this be done via a bash script?

  2. Building on the above question, if I wanted the above to occur, but set a different pair of time interval for weekends.
    For example: On Saturdays & Sundays the process would stop at 3pm and then startup automatically at 4pm, what would the bash script look like in this case?

Thanks in advance.

cron / crontab is your friend :

# Weekdays : 
00 14 * * 1-5 path/to/shellscript stop 2>&1
00 17 * * 1-5 path/to/shellscript start 2>&1
# Weekends : 
00 15 * * 0,6 path/to/shellscript stop 2>&1
00 16 * * 0,6 path/to/shellscript start 2>&1

You can either run it under your username - “crontab -e”… or as root :

sudo -i
crontab -e

Note - some distros won’t let “ordinary” users run cronjobs, debian doesn’t do that, you can, by default, run a cronjob as a user… some distros enforce group membership (i.e. /etc/group), some want you to have entry for the user account in /etc/cron.allow. Note also - Sunday can alternately be day “0” or day “7”… I always go for zero myself :smiley:

Is your “running thing” part of systemd? Do you start / stop it with “service” or “systemctl” commands? Does it run as “you” or root?

If not - then you might have to run some kill commands in your shell script to stop it…

As an example - here’s a shellscript I wrote some time ago to stop / start a VirtualBox VM :

#! /bin/sh
# /etc/init.d/StartVM
#

#Edit these variables!
VMUSER=x
VMLIST="bumt2-00"

case "$1" in
  start)
        echo "Starting VirtualBox VMs..."
        for VMNAME in $VMLIST ; do
#          sudo -H -b -u $VMUSER /usr/bin/VBoxVRDP -s "$VMNAME"
           sudo -H -b -u $VMUSER /usr/bin/VBoxHeadless --startvm "$VMNAME"
        done
        ;;
  stop)
        echo "Saving state of Virtualbox VMs..."
        for VMNAME in $VMLIST ; do
           sudo -H -u  $VMUSER /usr/bin/VBoxManage controlvm "$VMNAME" savestate
        done

        ;;
*)
        echo "Usage: /etc/init.d/StartVM {start|stop}"
        exit 1
        ;;
esac

exit 0

Edit : note - my $VMLIST can be a list of VM’s if necessary… You probably won’t need a for loop in your use case… Note also - I started that VM “headless”, but had configured the VM to also run a console on an RDP port so I can rdesktop or remmina to its console…

1 Like

Yes.

I would recommend looking at the previous post and answering the questions asked there.

There are many possibilities and solution methods to your problem, which is why it would be helpful if you would elaborate precisely, what your goal is and what you want to do. For example, what application do you want to stop and then run again? What does it do? What is it for? How critical is it? How exactly timed does the re-run have to be? Why does it need to be stopped in the first place? Et cetera.

It would be great, if you could elaborate as precisely as possible on all these open questions, to be able to recommend the best solution to you.

Otherwise, it’s hard to help you help yourself, with minimal information.

1 Like

Not all distros do this - Debian does - the commented “headers” in a new crontab (probably built from a skeleton somewhere in /etc/default) explain the notation :

╭─x@beere253 ~  
╰─➤  crontab -l |tail -6 |head -3                                                                                                       1 ↵
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command

It’s all there for you -
m = minute
h = hour
dom = day of the month
mon = month
dow = day of the week

1 Like

Thanks @Akito and @daniel.m.tripp for chiming in on this thread.

Sorry, I wasn’t sure how detailed you wanted me to get as this is my 2nd or 3rd time posting to this community forum.

Here is more info to answer previous questions:

I am running Ubuntu 20.04 LTS.

The application I want to stop/start is called xmrig (which I run from the command line prefixed with sudo)

The way I start the process is with - sudo xmrig [blah… variables]
The way I kill the process is with - sudo killall xmrig

I do not run apps as root.
Question: Must I run crontab with the sudo prefix? E.g. sudo crontab -e

Because xmrig is a CPU intensive process. My intention is to stop this intensive process for a few hours when the electricity is at peak rate in order to reduce my electricity bill. But when the off-peak rate is back later in the day, I want the xmrig process is automatically start again.

I hope this makes more sense.

Another follow-up question…
Once I edit the crontab file and save, if my machine reboots (after an upgrade or power outage), will I need to manually start any crontab service, or will it just automatically run?

1 Like

harrumph

The recommended way of configuring a crontab entry for a specific user is through the -u option.

Example

crontab -u root -e

You could theoretically automate this, so you don’t have to do anything manually. However, that would require effort and it’s probably best to start the way you already do.

It’ll just run by itself, on its own.

All you would need to do is put the commands in scripts. One script for starting, the other one for stopping. Then, you, for example, let the app stop each Saturday at 3pm and start again at 9pm on the same day.
Creating the scripts is trivial, because you already have the commands ready and you only need to paste them into two files, each.
Then, you just create two crontab entries, one for running the stop script, the other one for running the start script, that’s it.

Hint

Make sure you use only absolute paths in your crontab and scripts. Do not rely on environment variables. For example, instead of writing ~/path/to/my/script.sh, you should write /home/mv02/path/to/my/script.sh.

2 Likes

Thanks for this tip @Akito , I would have totally missed this being a noob :slight_smile:

Another question spring to mind…

  • If I want my xmrig process to start automatically when my machine boots, can I use crontab to do this, or is there a better way?

@reboot (non-standard)

1 Like

Sincere thanks, I will give this a try.

More questions?

Have you got password prompt disabled for your account in /etc/sudoers, I know this is generally frowned upon (having said that, there’s a WHOLE school of thought who think sudo is overkill, and sysadmins should just be trusted to login as root! Not recommended for noobs).

e.g. my sudoers entry on MY machines (I wouldn’t normally do that on a customer site if they already have good automation, but ones that don’t have ansible or puppet, having “NOPASSWD” in sudoers is the ONLY way to automate repetitive tasks on literally HUNDREDS of headless servers) :

╭─x@titan ~/Documents/receipts  
╰─➤  sudo tail -1 /etc/sudoers                                                                                          1 ↵
x	ALL=NOPASSWD:	ALL

Note - ALWAYS use “visudo” (or sudo visudo) to edit /etc/sudoers - NEVER do it manually (i.e. DO NOT “sudo vi /etc/sudoers” or nano or whatever!).

If you’ve got sudo setup to NOT prompt for password - then I’d recommend you run your cron jobs in your OWN crontab. If not - then yeah - you have to use root’s crontab.

What @Akito is inferring / emphasising here, is that 'cause you prefix your command with “sudo” - you are in FACT running apps as root, it’s the SAME THING.

What @Akito suggest looks correct to me - I’ve never run crontab like that however, as for NEARLY everything else in GNU / Linux / UNIX - there’s a whole bunch of methods for skinning cats - me? I’d just “sudo -i”, then when I’m root, “crontab -e”

Here’s what your stop / start script might look like :

#!/usr/bin/bash
#
# $PROG is the name of this script ($0 is this script - WHATEVER the filename is): 
PROG=$(basename $0)
# EDIT line below with FULL path to "xmrig"
BINARY=PATH-to-xmrig # Where is the binary located?  /usr/local/bin ???

case "$1" in
  start|START|STA)
        echo "Starting XMRIG..."
        # Add start arguments : 
        sudo $BINARY # + args
        done
        ;;
  stop|STOP|STO)
        echo "Stopping XMRIG..."
        sudo killall $BINARY
        sleep 5
        # wait 5 seconds and do it again - just in case : 
        sudo killall $BINARY
        done
        ;;
*)
        echo "Usage: $PROG {start|stop}"
        exit 1
        ;;
esac
exit 0

Note - YMMV - I don’t use “killall” either… I mostly just use something like :

sudo kill -9 $(ps -ef |grep xmrig |grep -v grep| awk '{print $2}')
and quite possibly - have to run that twice (note above - that’s just legacy history and muscle memory from killing errant procs / PIDS on Solaris UNIX servers ~20-25 years ago).
there’s also something like
sudo kill -i $(pgrep xmrig)
or
sudo pkill xmrig

All might - or may - work - but YMMV and so many ways to skin a cat again… :smiley:

2 Likes

I do it like this since I read somewhere some time ago, that the only way to make absolutely sure you are accessing the correct crontab is by specifying the user explicitly. Maybe I misinterpreted it, because it seems like it should always run from the user that issued the crontab command to begin with…

It’s also useful, when behaving “administratively” by configuring crontab entries for several different users at once. You switch once to root, then go by each user, through explicit specification of the target user by using the corresponding CLI option.

Any of the kill commands are essentially the same, anyway. The interface just changes. One works like this, the other one works like that, being more convenient, where you don’t have to manually search for the PID, etc. It’s just a matter of how precise or convenient you want it to be. It’s similar to useradd vs adduser. It’s essentially the same, but adduser with its prompt is better fitted for human interaction, because it does not require to manually craft a useradd CLI array of options.
On the other hand, in a script, you would always use useradd, for obvious reasons.

1 Like

It’s often best to adhere to the Irish “to be sure, to be sure” :smiley: principle…

I sometimes still do something like :

passwd -r files root

So I know I’m changing root’s local password (“-r files”) - and not some other user from some other authentication system (e.g. NIS, or LDAP or whatever)…