How to simulate the environment cron executes a script with?

Solution 1:

Add this to your crontab (temporarily):

* * * * * env > ~/cronenv

After it runs, do this:

env - `cat ~/cronenv` /bin/sh

This assumes that your cron runs /bin/sh, which is the default regardless of the user's default shell.

Footnote: if env contains more advanced config, eg PS1=$(__git_ps1 " (%s)")$, it will error cryptically env: ": No such file or directory.

Solution 2:

Cron provides only this environment by default :

  • HOME user's home directory
  • LOGNAME user's login
  • PATH=/usr/bin:/usr/sbin
  • SHELL=/usr/bin/sh

If you need more you can source a script where you define your environment before the scheduling table in the crontab.

Solution 3:

Couple of approaches:

  1. Export cron env and source it:

    Add

    * * * * * env > ~/cronenv
    

    to your crontab, let it run once, turn it back off, then run

    env - `cat ~/cronenv` /bin/sh
    

    And you are now inside a sh session which has cron's environment

  2. Bring your environment to cron

    You could skip above exercise and just do a . ~/.profile in front of your cron job, e.g.

    * * * * * . ~/.profile; your_command
    
  3. Use screen

    Above two solutions still fail in that they provide an environment connected to a running X session, with access to dbus etc. For example, on Ubuntu, nmcli (Network Manager) will work in above two approaches, but still fail in cron.

    * * * * * /usr/bin/screen -dm
    

    Add above line to cron, let it run once, turn it back off. Connect to your screen session (screen -r). If you are checking the screen session has been created (with ps) be aware that they are sometimes in capitals (e.g. ps | grep SCREEN)

    Now even nmcli and similar will fail.