Ubuntu cron shebang not working - linux

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.

Related

Linux Cronjob not running powershell script, but the script is able to run in terminal

I have a PowerShell Script that updates a database table. I would like to set this up in the Cronjob to run daily. However it doesnt seem to work in the cronjob. At the moment I have setting it forward a couple minutes so that I dont have to wait.
CronTab:
* * * * * pswh -File "/home/administrator/PowerShellScripts/Update-Set-Table.ps1"
Terminal:
pswh -File "/home/administrator/PowerShellScripts/Update-Set-Table.ps1"
Working perfectly when I run that command in the terminal but it doesnt seem to be running from the cronjob.
you need to specify the full path to the executable pwsh. you can do so by using which APPNAME in a terminal.
which pwsh
then change the line in your crontab accordingly. for me the working result looks like this:
* * * * * /snap/bin/pswh -File "/home/administrator/PowerShellScripts/Update-Set-Table.ps1"
Cron's lack of environment has this side effect: the working directory changes. In my case I was writing to a file I expected to be in the script's directory which was being created & written to nicely in $HOME.
The script's directory is held in the PoSh variable $PSScriptRoot
PoSh has a symlink at /usr/bin/pwsh so the full path is not necessary (for me anyway)
The current (Vixie) cron allows standard variables which can be used for paths. Check the author in man crontab
If you're script has a #!/usr/bin/pwsh shebang & is executable it executes like any script without specifying 'pwsh'
BTW if you're displaying to screen, say a dialog, the cron job must be prefaced with env DISPLAY=:0(or some other number) in order to display. eg env DISPLAY=:0 pwsh $ScriptHome/DiskFull-WereGoingToCrash.ps1 -display

crontab is returning error

I'm trying to run some crawler with Linux crontab.
This should go to the Python environment with
pyenv shell jake-crawler
Here is my crontab -e
*/10 * * * * /home/ammt/apps/crawler/scripts/bat_start.sh
This will run every 10 minutes. This command line works fine when I type
(jake-crawler) [jake#KIBA_OM crawler]$ /home/jake/apps/crawler/scripts/bat_start.sh
[DEBUG|run.py:30] 2017-09-24 19:55:49,980 > BATCH_SN:1, COLL_SN:1, 1955 equal 0908 = False
Inside of bat_start.sh I have init.sh which changes the environment to Python.
Here is my init.sh
#!/usr/bin/env bash
export PATH="${HOME}/.pyenv/scripts:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
pyenv shell jake-crawler
This has no problem when I personally run it from command line. But when cron run it by itself, it cannot find the pyenv command.
I think that you can specify which user should run that script in cron configuration file.
So, if that script is working with your user, then define it in your cron configuration filr.
See this answer for example... https://stackoverflow.com/a/8475757/3827004.
There are two things that diferentiate when you launch an application from the terminal, and when you do from a crontab file:
the environment is not the same, at least if you don't execute your .profile script from your cron job.
You don't have access to a terminal. Cron jobs don't use a terminal, so you will not be able, for example to open /dev/tty. You will have to be very careful on how redirections are handled, as you have them all directed to your tty when running on an interactive session, but all of them will be redirected possibly to a pipe, when run from cron(8).
This makes your environment quite different and is normally a source of errors. Read crontab(1) man page for details.

Start bash script from bash script as cronjob

I'm trying to start a bash script(test.sh) from a second bash script that runs as a cronjob(startTest.sh) on Ubuntu 14.04.
Cron is running and both scripts work perfectly if called from command line.
startTest.sh looks like this:
#!bin/bash
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/local/sbin:/sbin:/usr/sbin:/bin:/usr/bin:/home/username/path/to/script
bash /home/username/path/to/script/test.sh
test.sh looks like this:
#!/bin/bash
touch it_works.txt
My crontab entry looks like this
* * * * * /usr/local/bin/startTest.sh
Best practice is generally not to use relative paths (unless you do an explicit cd) in scripts run as cron jobs.
crond is probably not running from whatever directory you expect it to. Depending on what user this cron job runs as, the script either does not have permission to create it_works.txt in crond's current working directory, or it is creating the file and you're looking in the wrong place.

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

crontab issue while scheduling

I have a perl script and I scheduled it to run daily through crontab. The script is working fine if executed. But while executing through crontab, it's posting error mail to my mailbox.
Is there any thing that I should modify to successfully execute the script through crontab?
It could be a $PATH problem. Ensure that your Perl script either is on a place mentioned by $PATH, or has an absolute path in the crontab. This is also valid for any script or program that you run in the Perl script. The $PATH variable usually has to be set inside the crontab file.
It could be a file used in the Perl script having relative path, which could work when executed manually, but fail when run by cron (different working directories).
Does the Perl script have execute permissions (the x mode bit set)? This is not necessary when it's run with perl /path/to/script.pl, but would fail when it's run with /path/to/script.pl.
EDITED:
Suggestions for how to fix:
Add to $PATH in the crontab (for the sample script /path/to/script.pl):
PATH=/bin:/usr/bin:/path/to
Remember to include other needed paths as well (e.g. /bin and /usr/ucb).
Chances are there already is a PATH definition in the file. In that case, just append your path to it.
Alternatively, you can specify full path in the cron job line, e.g.:
17 * * * * root /path/to/script.pl
To fix permissions:
chmod a+r+x /path/to/script.pl

Resources