10

I want my server to execute a node script every minute. The program executes perfectly if I execute the file manually (./main.js), so I'm pretty sure it's not the problem. But when I hand it over to cron to execute, nothing happens.

Here's the line from the cron file.

*/1 * * * * /home/bryce/scripts/wudu/main.js

And here's a sample log:

Oct 11 15:21:01 server CROND[2564]: (root) CMD (/home/bryce/scripts/wudu/main.js)

The executable: home/bryce/scripts/wudu/main.js

#!/usr/bin/env node

var program = require('commander');
var v = require('./cli/validation');
var a = require('./cli/actions');

program
  .version('0.0.1')
  .option('-u, --url', 'Register url')
  .option('-s, --selector', 'Register selector')
  .option('-p, --pagination', 'Register pagination')
  .option('-i, --index', 'Pass an index, to destroy')
  .parse(process.argv);

var args = process.argv.slice(2),
        mode = v.mode(args[0]),
        options = v.hasArgs(mode, program);

a.init(mode, options);

Any idea why I'm getting radio silence? Somewhere else I should be looking to debug?

UPDATE:

I believe the problem has to do with my relative filepaths, and main.js being executed from outside its own directory.

So now, I've placed exe.sh in the wudu directory. It looks like this:

#!/bin/bash

cd ${0%/*}
./main.js mail

exit

Now, I've set cron to execute this file every minute. I tried executing this file from other folders, and it works as expected. But again, cron isn't picking it up.

Bryce Johnson
  • 6,689
  • 6
  • 40
  • 51
  • Might check the execution privileges on the file. – Brendan Oct 11 '14 at 15:31
  • That messed me up earlier on, but I fixed that already. Thanks though. – Bryce Johnson Oct 11 '14 at 15:32
  • relative pathname : `var v = require('./cli/validation');` Your cron job is not started in the `/home/bryce/scripts/wudu/` directory, but pwd is most probably `/home/bryce/` when called from cron. – wildplasser Oct 11 '14 at 15:35
  • @wildplasser Yes, I just thought of that. I decided to try using the crontab to execute a shell script (located in `wudu`) that would then execute the ./main.js file. But that wouldn't work either. I also tried installing the module globally (npm install -g) and execute the global module from a shell script as well, but I'm running into the same problem. How do I make sure the relative paths target the right files? – Bryce Johnson Oct 11 '14 at 15:55
  • Normally, you'd wrap it into a shellscript. The shellscript sets some environment ( PATH ...) variables and changes working directory before calling the actual payload. Put a `set >>/tmp/mylog.log` into the shellscript to verify. – wildplasser Oct 11 '14 at 15:58
  • @wildplasser okay, let me try that. – Bryce Johnson Oct 11 '14 at 16:02
  • @wildplasser I just updated the question, with my progress. Still not working. – Bryce Johnson Oct 11 '14 at 16:18
  • Why `./main.js` instead of `node main.js`? – jfriend00 Oct 11 '14 at 16:22
  • @jfriend00 -- I guess, since I'm using it as a command line tool, I figured it wouldn't make a difference if I declared Node in the executable. I can try it with node. What would be the difference? – Bryce Johnson Oct 11 '14 at 16:25
  • @BryceJohnson the difference is that you need to tell your shellscript to use node to execute the script, a bit like you say `#!/bin/bash` to tell your system to use bash – xShirase Oct 11 '14 at 18:13

3 Answers3

17

Wrapping the execution in a shell script, it's likely the execution of the script in cron doesn't have the same environment set as when you run from the command line.

Try prefacing the execution of the shell script in cron with setting NODE_PATH & PATH
(if you need these values, on a command line type: echo $NODE_PATH and echo $PATH)

So, your cron entry would look like:

*/1 * * * * NODE_PATH=/usr/local/lib/node_modules PATH=/opt/local/bin:ABC:XYZ /home/bryce/scripts/wudu/exe.sh

Just make sure to substitute the actual values for NODE_PATH & PATH with what you get from the echo commands that you first did.

Marc Smith
  • 1,111
  • 10
  • 18
  • 1
    small comment: if you have many scripts like that you shouldn't add the env variables for each, just add it once at the beginning of the crontab file and it'll work for all. – Shlomi Jun 12 '20 at 06:50
3

I had the exact same problem, so I ended creating a passthrough script that would load my environment variables, then execute node like so:

##!/bin/bash

# Source bash profile to load env variables
# or any other that you want to set explicitly
. ~/.bash_profile

# tunnel that allows us to execute cron jobs
node $1 $2

To use just add it to your crontab

* * * * * <user> <passthrough_script> <arg1> <arg2>
Tigertron
  • 628
  • 6
  • 6
0

You could try running the bash file directly from the cron?

i.e.

0 4 * * * source ~/.bashrc && cd /projects/my-project && node index.js