Running NPM script as a crontab (Ubuntu) is not working [duplicate] - node.js

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.

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.

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>

You could try running the bash file directly from the cron?
i.e.
0 4 * * * source ~/.bashrc && cd /projects/my-project && node index.js

Related

Can't get Crontab jobs to work at all [duplicate]

This question already has answers here:
CronJob not running
(19 answers)
Closed 4 years ago.
New to Crontab use, I am trying to get a simple bash script to run.
add_temp:
#!/bin/bash
rnd1=$RANDOM
range1=20
let "rnd1 %= $range1"
rnd2=$RANDOM
range2=50
let "rnd2 %= $range2"
echo $rnd1
echo $rnd2
cd /var/www/html
sqlite3 test.db <<EOF
INSERT INTO temps (date, temp) VALUES ($rnd1, $rnd2 );
EOF
crontab -e:
SHELL:/bin/bash
* * * * * /var/www/html/add_temp
This doesn't seem to run at all. Works fine if run manually with /var/www/html/add_temp.
My guess is that the sqlite3 is not found when the cron daemon run the script.
You could modify the script and provide the full pathname of this command. Use a terminal to display the full pathname of the command:
type sqlite3
The cron daemon which will run the script does not have the exact same environment than the bash login shell used to run manually the script.
The variable that is usually differently set is PATH.
The first step to troubleshoot this situation is to compare the environments and debug the script.
I suggest to insert these lines below, after the very first line of the script
env
set -x
Run the script manually and redirect output, from a terminal:
/var/www/html/add_temp >/var/tmp/output_m.txt 2>&1
Change the crontab line for:
* * * * * /var/www/html/add_temp >/var/tmp/output_c.txt 2>&1
Wait that the cron daemon executes the script and compare the /var/tmp/output_m.txt and /var/tmp/output_c.txt files.
When the script will be fixed, remove the 2 debug lines from the script and restore the crontab original content.

Trying to run script through crontab which won't work

I'm having issues getting my crontab to run I have the following line added to my crontab -e but it won't start. The command runs fine if I run it manually.
0 */3 * * * cd /home/sam/p/ && /usr/bin/python3.5 start.py
Not getting any error messages and can't see the process when I run top or grep for it.
Usually this happens because the cron environment is different from your own. Make sure your start.py script uses full paths to any referenced files or external scripts. Make sure that your start.py script does not rely on environment variables that you have in your shell but it may not. Try piping the cron output to a mail command so you can see what it is doing, like so:
0 */3 * * * cd /home/sam/p/ && /usr/bin/python3.5 start.py | mail -s "cron output" myself#example.com
An easier way to troubleshoot this is to write a wrapper shell script and send the output to a log file.
Create file python_start_cron.sh with contents
#!/bin/bash
cd /home/sam/p/ && /usr/bin/python3.5 start.py
Set the execute bit on this script script and make sure the script works manually
Modify the cronjob as shown below
0 */3 * * * python_start_cron.sh >/tmp/python_start_cron.log 2>&1
After cron executes, check the contents of the log file to ascertain the cause of the problem.

cronjob does not execute a script that works fine standalone

I have my php script file in /var/www/html/dbsync/index.php. When cd /var/www/html/dbsync/ and run php index.php it works perfectly.
I want to call PHP file through sh file, the location of SH file is as below
/var/www/html/dbsync/dbsync.sh
This is the content of the dbsync.sh file is:
/usr/bin/php /var/www/html/dbsync/index.php >> /var/www/html/dbsync/myscript.log 2>&1 -q -f
When I cd /var/www/html/dbsync/ and run ./dbsync.sh it works perfectly as well.
Now if I set up crontab as below:
1 * * * * /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync
However, this crontab is not working as expected.
What can be wrong?
As seen in comments, the problem is that you are not defining what program should be used to execute the script. Take into account that a cronjob is executed in a tiny environment; there, not much can be assumed. This is why we define full paths, etc.
So you need to say something like:
1 * * * * /bin/sh /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync
# ^^^^^^^
/bin/sh being the binary you want to use to execute the script.
Otherwise, you can set execution permissions to the script and add a shell-script header telling it what interpreter to use:
#!/bin/sh
If you do this, adding the path of the binary is not necessary.
From Troubleshooting common issues with cron jobs:
Using relative paths. If your cron job is executing a script of some
kind, you must be sure to use only absolute paths inside that script.
For example, if your script is located at /path/to/script.phpand
you're trying to open a file called file.php in the same directory,
you cannot use a relative path such as fopen(file.php). The file must
be called from its absolute path, like this: fopen(/path/to/file.php).
This is because cron jobs do not necessarily run from the directory in
which the script is located, so all paths must be called specifically.
Also, I understand you want to run this every minute. If so, 1 * * * * won't do. Intead, it will run at every 1st minute past every hour. So if you want to run it every minute, say * * * * *.
It is important to understand "login shell" and "interactive shell" what they means.
login shell: is briefly when you sign in with ssh session and get a terminal window where you can enter shell commands. After login the system executes some files(.bashrc) and sets some environment variables such as the PATH variable for you.
interactive shell :After login on a system, you can startup manually shell terminal(s). The system executes some profile file assigned to your account (.bash_profile, .bash_login,.profile). This files also sets some environment variables and initialize PATH variable for your manually opened shell session.
By OS started shell scripts and cron jobs does not fit in above mentioned way for starting a shell. Therefore no any system scripts(.bashrc) or user profiles are executed. This means our PATH variable is not initialized. Shell commands could not found because PATH variable does not point to right places.
This explains why your script runs successfully if you start it manually but fails when you start it via crontab.
Solution-1:
Use absolute path of every shell command instead of only the command name used in your script file(s).
instead of "awk" use "/usr/bin/awk"
instead of "sed" use "/bin/sed"
Solution-2: Initialize environment variables and especially the PATH variable before executing shell scripts!
method 1, add this header in your dbsync.sh:
#!/bin/bash -l
method 2, add bash -l in your cron file:
1 * * * * bash -l /var/www/html/dbsync/dbsync.sh /var/www/html/dbsync

Ubuntu cron shebang not working

I have a script with this as the shebang #!/usr/bin/env node.
When cron runs my script, I get this error /usr/bin/env: node: No such file or directory.
When i run the script as my user the script runs fine, just not as cron. I'm guessing it's because node is not on the PATH of the user that runs cron?
How can I get this shebang to work with cron?
$ which node gives me
/home/myuser/.nvm/v0.11.14/bin/node
Cron jobs run in a restricted environment. In an interactive shell, your $PATH is probably set in your $HOME/.bash_profile or $HOME/.bashrc. Cron jobs are executed in an environment that hasn't sourced those files, so your user-specific $PATH settings will not be available.
You can see what that environment looks like by temporarily creating a crontab entry like:
* * * * * printenv > crontab-environment
You can explicitly set $PATH in your crontab, either in the command itself:
* * * * * PATH=$PATH:/home/myuser/.nvm/v0.11.14/bin some_command
or in a separate line in your crontab:
PATH = /usr/bin:/bin:/home/myuser/.nvm/v0.11.14/bin
You can't (directly) use the usual PATH=$PATH:/new/dir syntax to append a directory to your $PATH in an environment setting line, because variable references are not replaced in such a line. They are processed in crontab command lines.
man 5 crontab for details.
Another option is to use an explicit full path in the script itself, changing
#!/usr/bin/env node
to
#!/home/myuser/.nvm/v0.11.14/bin/node
You'll need to customize this for each system where node is installed in a different place. Or you can arrange for node (or nodejs?) to be installed in a consistent place.

Why won't cron execute my node.js script?

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.
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.
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>
You could try running the bash file directly from the cron?
i.e.
0 4 * * * source ~/.bashrc && cd /projects/my-project && node index.js

Resources