# Best way to schedule one-time-only tasks



## shuxuef (Jan 6, 2017)

I have been wondering what the best way is, on FreeBSD (in the base system), to schedule a task that will be executed one time only at a particular time in the future, for a regular user. I have been using a regular-user crontab to periodically check email, running an alarm clock, etc. By default, FreeBSD doesn't allow a normal user to run at(1); even if at(1) was enabled, by default it would only be executed every 5 minutes, by cron(8). So it seems that FreeBSD really wants to discourage the use of at(1). Without at(1), it seems that one's best bet, as a regular user, would be to use crontab(1). However, it one wishes to schedule a periodic task, then it is reasonable to use `crontab -e` every time to interactively edit the crontab file. If one wishes only to schedule a one-time-only task,  then `crontab -e` suddenly seems very excessive, not to mention, for the sake of cleanness, one needs to remove the crontab item for that particular task afterwards. My impression is that by default, FreeBSD doesn't provide an easy way to schedule one-time-only tasks for a regular user, other than the 'not-recommended' at(1). I know that tcsh provides a built-in sched(1), but it seems to need the parent shell present all the time, which is not very convenient. I could of course write a wrapping script to implement such a scheduler using crontab(1) itself, but I can't help but wondering whether I am missing something obvious. What do you think is the best way to schedule one-time-only tasks for regular users in the base system (taking system security into consideration of course)?


----------



## ondra_knezour (Jan 6, 2017)

See at(1)


----------



## aragats (Jan 6, 2017)

ondra_knezour said:


> See at(1)


ondra_knezour , have you actually read the original post?..


----------



## ASX (Jan 6, 2017)

ondra_knezour is right:



> The superuser may use these commands in any case.  For other users, per‐
> mission to use at is determined by the files /var/at/at.allow and
> /var/at/at.deny.


----------



## aragats (Jan 6, 2017)

I've never said ondra_knezour is not right 
Sometimes people miss obvious things, so a three-line quote is at the order of magnitude is better than _rtfm_.


----------



## ondra_knezour (Jan 6, 2017)

To be honest, I was in hurry but still wanted to help, so I only quickly scanned OP and didn't see at at all


----------



## shuxuef (Jan 7, 2017)

I was very much aware of how to enable at(1). I also know that if you want at(1) to be more precise at the time of execution, you need to change the atrun(8) entry in /etc/crontab,  otherwise it'll only be run every 5 minutes. Even after doing that, you can't make at(1) to be precise to the second (one can combine at(1) and sleep(1) to achieve that though). But like I said, by default, FreeBSD seems to be deliberately discouraging the use of at(1)

Perhaps I should have been more clear about this in my original post, but let's assume that I don't want to change the system's default, or that at(1) is not available to the regular user in question. But if you insist that at(1) is the best, would you be so kind as to explain why there is not a better way and why it is not enabled by default on FreeBSD? Thanks!


----------



## shuxuef (Jan 10, 2017)

To hopefully induce more conversation about this topic, here is a quick-and-dirty script to automatically add items to and removing them from a regular user's crontab file, which could be use as a reduced at(1). Support for scheduling tasks to be executed more than 1 year after the current time has not been implemented yet.

I named the following script khrontab, and put it in a regular user's bin directory, /home/someone/bin.


```
#!/bin/sh
if [  $# -gt 2 -o $# = 0  -o  $# -gt 1 -a "$1" != "remove"  ]
then
    echo "khrontab usage: "
    echo -e "\tTo remove an item in your crontab: khrontab remove [TIMESTAMP]"
    echo -e "\tTo add an item in your crontab: khrontab [crontab item]"
    exit 1
fi
TIMESTAMP=${2:-$(date -j -f "%a %b %d %T %Z %Y" "`date`" "+%s")}
BEGIN_STR="#One-time-only job begin ${TIMESTAMP}"
END_STR="#One-time-only job end ${TIMESTAMP}"
if [ -n "$2" ]
then
    CURRENT_CRONTAB="$(crontab -l | grep \. |\
               sed "/${BEGIN_STR}/,/${END_STR}/s/.*//g" | grep \.)"
    echo "${CURRENT_CRONTAB}" | crontab -
else
    CURRENT_CRONTAB="$(crontab -l | grep \. )"
    { if [ -n "$CURRENT_CRONTAB" ]; then echo "${CURRENT_CRONTAB}"; fi ;\
               echo ${BEGIN_STR};\
               echo "$@" " ;\
               `which khrontab` remove ${TIMESTAMP} ";\
               echo ${END_STR} ; } | crontab -
fi
```

For example, command `khrontab '15 21 * * * /usr/local/bin/mplayer /home/someone/*.mp3'` will schedule a task to use mplayer to play all the mp3 files inside the directory /home/someone at the next 21:15 (either today, if the current time is before 21:15, or tomorrow if the current time is already after 21:15). You can check the crontab, `crontab -l`, to see that three lines have been added:

```
#One-time-only job begin 1484054097
15 21 * * * /usr/local/bin/mplayer /home/someone/*.mp3  ;          /home/someone/bin/khrontab remove 1484054097
#One-time-only job end 1484054097
```
After the execution, the above item will be automatically removed from the crontab.


----------



## ANOKNUSA (Jan 10, 2017)

aragats said:


> Sometimes people miss obvious things...



The OP didn't bother explaining what this one-time event actually is, why it only needs to happen one time, or why something that's so utterly important that it must happen at a specific time on one specific day of a person's life should be entrusted to a personal computer. So ondra_knezour can hardly be blamed for suggesting the most obvious "solution."

If this one-time event is so important that the very second at which it happens really matters, do it yourself. Your machine will fail you, and if someone gets hurt as a result the machine can't be held responsible. You certainly will, though. However, this does seem like it might be yet another X-Y Problem, and it's possible the OP is overthinking it.


----------



## aragats (Jan 10, 2017)

I don't think it's an X-Y problem, shuxuef just wanted to understand the most appropriate way of scheduling such tasks in FreeBSD.
Nobody needs one-second accuracy in real life, but it's good to know all possibilities available.


----------

