Learning cron

So I am starting to learn some linux basics and i have reached cron.

I am attempting to get some commands to run at system start.

Can anyone tell if my formatting is wrong from this:
image

(Attempting to connect to proton VPN UK and launch bridge but not show the window)

Both these commands work when i type them in in the terminal but not here…

(Learning cron… IMO, don’t, unless you really need to. systemd timers are more functional, and without systemd, anacron is better.)

When I last messed with cron, at least a decade ago, the main trap was that jobs don’t run login scripts and get a very limited environment. Running in a terminal but not as a cron job is a classic consequence.

I prefer cron to systemd because of their simplicity. I do not need complex environments, all my scripts can work in dash and oksh, because I keep them as close to posix-compatible as possible (also trying to avoid bashism and gnuism).

Put those 2 proton-cli and bridge into a script and make it executable by using chmod u+x on it. Also use the full paths to them, not just the environment variables. Keep in mind that if you use 2 cron entries for commands that should be ran sequentially, you may run into a race problem. So better off to just make them into scripts. See if that works.

1 Like

crond has a different, stripped-down PATH compared to your shell (put a PATH line above or specify full paths to everything), doesn’t necessarily run commands in the order you want (put them in a shell script) doesn’t deal well with programs that look for input (Put </dev/null after the command), spew output (Put &>/dev/null after the command), or run continuously (Put & after the command).

Additionally, crond has no network dependency so it may run your commands before your system enables the network card.

And probably multitude other considerations that don’t come to mind.

well its good that you’re learning cron, but just be aware those those macros you’re using in your crontab for @reboot are non-standard and are not used everywhere.

I find this website very helpful

2 Likes

Respectfully disagree, I find systemd much easier and more versatile to the archaic nature of cron while being only 2-3% more complex.

While systemd requires you to keep track of two files (service + timer) + your script, instead of just crontab, the advantage of a uniform way to manage the system is mind boggling.

While I am not completely sold on the Linux systemd implementation I am completely sold on systemd as a standard.

Now I just wish FreeBSD and OpenBSD would make a systemd compatible system daemon that kicks arse instead of going “Systemd must DIE UUURGH” whenever someone mentions it’s name…

Anyway, back to the topic, make sure that the cron user has the right permissions. That is probably your #1 concern here.

To run a command as the cron user you could use

su - cron -c 'echo $(whoami)'
1 Like

Youre probably better off writing a systemd unit file for these. A oneshot for the config and a unit file for the bridge.

Script 1:

*#!/bin/bash*

*sleep 5 && protonvpn-cli c --cc UK >/dev/null 2>&1*

Script 2:

*#!/bin/bash*

*sleep 7 && ch.protonmail.protonmail-bridge --no-window >/dev/null 2>&1*

Crontab:

@reboot ./script1.sh
@reboot ./script2.sh

Adapt to your environment…

2 Likes

Just a quick systemd counter in case you want to learn a more modern workflow, now that I have access to a real workstation. The process is slightly more verbose, but also more human-readable. FIrst you want to create two systemd services (plain text files):

# File: /etc/systemd/system/protonvpn.service

[Unit]
Description=Timed service that keeps calling protonvpn
Wants=protonvpn.timer

[Service]
Type=oneshot
User=protonvpn
ExecStart=sh -c 'protonvpn-cli c --cc UK'

[Install]
WantedBy=multi-user.target
# File: /etc/systemd/system/protonmail.service

[Unit]
Description=Timed service that keeps calling protonvpn
Wants=protonmail.timer

[Service]
Type=oneshot
User=protonvpn
ExecStart=sh -c 'ch.protonmail.protonmail-bridge --no-window'

[Install]
WantedBy=multi-user.target

Next, set up the timers, coincidentally also text files:

# File: /etc/systemd/system/protonvpn.timer

[Unit]
Description=Keeps protonvpn service running
Requires=protonvpn.service

[Timer]
Unit=protonvpn.service
AccuracySec=1s
OnUnitActiveSec=5s

[Install]
WantedBy=timers.target
# File: /etc/systemd/system/protonmail.timer

[Unit]
Description=Keeps protonmail service running
Requires=protonmail.service

[Timer]
Unit=protonmail.service
AccuracySec=1s
OnUnitActiveSec=7s

[Install]
WantedBy=timers.target

Finally, to enable them, simply type systemd enable protonvpn and systemd enable protonmail. Then it should start automatically at next boot.

Systemd timers are a bit more runway than Cron but once up in the air, soooo much nicer and way more reliable. Systemd also allows you to wait for one thing to finish - what if, for instance, you had a particularly slow boot and network did not come up on time?

In your case, maybe what you want to do is not timers at all, but first run the VPN command and then the mail command, in which case a systemd chain is the much better, simpler, and more logical alternative to do. Just skip the timers and for protonvpn service, change wantedBy to wantedBy=protonmail.service.

And that does not even begin to cover things like logging being handled automagically by journald for instance.

2 Likes

Politely disagree. I don’t mind systemd being used in most major distros, but it shouldn’t be a standard in general and it shouldn’t merge with the kernel more than it already did (from what I know systemd requested only a kernel patch to fix a problem with systemd, instead of fixing systemd itself, adding more than this makes it a risk to break compatibility with other software that could replace it).

I also abhor the dependency on systemd specific tools in general, like GNOME Shell using systemd utilities for login instead of doing it in an agnostic way, however, I don’t hold it against GNOME developers. I understand it doesn’t make a ton of sense to support everything that’s out there, or even to keep 2 authentication methods. Thus, I don’t use GNOME Shell on my system. I don’t boycott GS, just that I stay away from it. And only from the shell, GNOME software like Nautilus doesn’t have the same dependency, so no point in not using things like that (although I avoid GNOME stuff because they are heavy on resources). That doesn’t stop people from patching GS, or adding compatibility layers like elogind or seatd.

Systemd compatible systems would probably be a nightmare to implement and I highly doubt the OpenBSD folks would do that. FreeBSD, maybe.

I don’t think systemd should die, its complexity probably makes sense on a lot of complex systems. But it is definitely not my first choice. I am completely sold on s6, even though I don’t use it (yet), I probably will. Thus far, I just made some very simple dependency checks on runit for some services, like ntp checking that I have an IP address allocated. It’s not hard to do basic checks.

@TimHolus
Crontab doesn’t keep track of the order of scripts, you always run a risk of a race condition. What if proton-cli takes 10 seconds to execute after it sleeps those 5, while the bridge executes instantly? The bridge will fail using that logic if you run them in parallel. They must be sequentially ran.

crontab -l should look like this:

@reboot /home/user/path/to/script/script.sh > /dev/null 2>&1

script should be executable by running chmod +x script.sh

The script.sh should look like this:

#!/bin/sh
while ( [ $(/bin/ip a | /bin/grep '192.168.' -c) -lt 1 ] ); do /bin/sleep 2 ; done
/path/to/installdir/proton-cli c --cc UK
/path/to/installdir/ch.protonmail.protonmail-bridge --no-window
1 Like

Note: my script assumes that proton-cli runs in the background and doesn’t keep running forever. Otherwise, the output needs to be escaped, to something like this:

#!/bin/sh
while ( [ $(/bin/ip a | /bin/grep '192.168.' -c) -lt 1 ] ); do /bin/sleep 2 ; done
/path/to/installdir/proton-cli c --cc UK &

while [ $(/bin/ps -ef | grep proton-cli -c) -lt 1 ]); do /bin/sleep 3 ; done
/path/to/installdir/ch.protonmail.protonmail-bridge --no-window

You probably want to add a systemd requires and after networking for the protonvpn service. You don’t want protonvpn to be started before the networking service, especially because it is a oneshot and not a daemon or simulated daemon.

2 Likes

I am familiar with what the crontab does. I gave an absurdly simple solution and clearly said to adopt it to your environment. Which means adjusting the delay times as well or not using them at all.
The OP asks a simple question, I give a simple answer, 5, 7 seconds is just an example, not a recommendation!

The crontab calls script1 which waits 5 seconds to execute, while script2 waits 7 seconds to execute, ie 2s after “protonvpn-cli c --cc UK”. Rather obvious that these are times just for example and not so tight on purpose.

Change 5s to 5 minutes to let the system boot up slowly. You can then add 7 minutes to script2 which will give you a two minute break to freely execute “protonvpn-cli c --cc UK” before doing “ch.protonmail.protonmail-bridge --no-window”…

Archaic? Yes, but simple…

OP can’t cope with crontabs and simple commands yet, and you want him to be a swimmer right away when he’s just starting to learn to swim.
Your approach is to throw the OP deep into the water in a situation where the OP cannot swim yet.

charlie-day

2 Likes

Why not? While you may not like systemd, it does have a few good points and is at this point, objectively speaking, the absolutely best system management system. There is no shame in admitting a thing you dislike does something good.

Now, I’m not saying the standard must be necessarily systemd unit files, perhaps it would be better to have JSON unit files and a more simplified file tree - I do not know what a systemd alternative could be, just that FreeBSD needs a working counterpart and the two should be easy to move between. I am expecting the FreeBSD version to be much more interesting btw.

systemd in and of itself has a few problems, like moving away from a dirt-simple PID1 and the whole insistence on binary logs, which means a potentially more unstable system.

I agree. I think faulty behavior should be reported to the kernel for sure but systemd should be separate from the kernel, definitely. A lot of what systemd does could be platform agnostic though, even though the Linux CGroup dependency is hard to do much about.

In the end, I see no point in five different ways to do the same thing for something this central. It only hurts rather than help if you need to keep a different config for Ubuntu vs FreeBSD vs Redhat vs OpenBSD vs Arch. Therefore I think a system manager standard should emerge and then different implementations should be free to tie into that.

systemd was the first system manager on Linux; so rather than clinging to old and outdated concepts like cron, maybe we should start having a discussion about how to implement a better system manager standard that all can follow? I also do not want systemd to take over everything, but this is where the current path is heading.

Anyway, this is moving way off topic, and probably the wrong place to discuss this in, so we might want to take the discussion elsewhere. Just wanted to say I’m not against other system manager suites, just that they should be configured in a similar way and systemd is already the de-facto standard out there.

To save responding to everyone :smiley:

Thank you all for your responses and I will be trialing a lot of what I have seen here.

As I said, and a lot of you have mentioned I am just dipping my toes in for the first time and (Supposedly) simple things like this are where I have chosen to start.

For those of you who have mentioned solutions other than cron such as systemd, thanks for your recommendation. I will look into this too and decide what works for me (At least what works for me while I am still learning).

This is going to be a long project to learn everything from scratch but I think it will be worthwhile.

2 Likes

Crontab was fine for ~4 decades before systemD and will do the job fine. It’s portable to any unix workalike.

open 2 terminal windows
in one type

  • man crontab
    in the other type
  • sudo crontab -e

have at it.

3 Likes

Ah, that youth. they always want to reinvent the wheel at every opportunity. :slight_smile:

2 Likes

Yeah I get that systemD is the new shiny etc.

But learning the Unix way will serve you well if you ever need to work with literally anything else. And it still works with Linux.

Relatively speaking every man and his dog is learning Linux. But there are plenty of high end mission critical systems still running stuff like AIX, Solaris, etc.

1 Like

Yes and it’s horrible. But I found that some high end mission critical systems can also run FreeBSD.

(sorry, I have PTSD from dealing with AIX, Solaris and HP-UX, they have such weird behavior that it’s not even funny, like kill -9 not working on Solaris and programs refusing to die, or multi-threaded programs using certain libraries crashing on AIX without the OS having certain patches applied to it, or weird behavior of programs on HP-UX - and I have seen my fair share of software screwups on Linux too, but all of these were easily identifiable and made sense).

1 Like

They also had things going for them, like we joked about Solaris on SPARC in the day: these systems are turned on and off once in their lifetime, on when put in service, and off when taken out of service.

Not sure what Solaris on x86 has going for it, but AIX still has POWER going for it, I suppose.

2 Likes