Executing Azure CLI from shell script as cron job - linux

Inside the shell script sing the full path to the Azure CLI & Node JS.
#!/bin/bash
/opt/nodejs/bin/node /opt/nodejs/bin/azure vm disk list > /tmp/tmpfile
/opt/nodejs/bin/node /opt/nodejs/bin/azure vm disk upload $SRCURL $DESURL <KEY>
When executed manually both the commands are getting executed successfully. But when executed using crontab vm disk list command is working but vm disk upload is not working.
Azure JS script requires another cli.js which is been referenced through relative path var AzureCli = require('../lib/cli'); and the cli.js script requires lots of other scripts which is been referenced through relative path.
Is there any way to provide the same environment profile as the user to cron hence it works or is there any best way to make this work without editing individual JS file and rename the relative path to absolute path?

The issue was because the HOME environment variable was not getting set when executed through cron and that was causing the Azure command to fail.
When the HOME variable is set to the specific user's home directory in the script, it works fine.

You can set your path of required file in PATH environment variable in /etc/profile file
export PATH=$PATH:/path to your files

just redeclare environment variable inside the cron.
example crontab:
NODE_ENV=production
* * * * * /bin/sh /path/to/your/shellscript/nodejs

Check for environment variable SHELL=/bin/sh.
Most times /bin/sh is a symbolic link to /bin/bash, but on Ubuntu /bin/sh is a symbolic link to /bin/dash:
$ ls -la /bin/sh
lrwxrwxrwx 1 root root 4 feb 19 2014 /bin/sh -> dash
So in this case you need to redeclare this environment variable:
export SHELL=/bin/bash
In my case, I export the environment variable in my script and have the following in crontab:
# run azure test every 5 minutes
*/5 * * * * /opt/bin/azure-test >/tmp/azure-test.out 2>&1

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

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.

Trouble with running a shell script via a Cronjob on an EC2 Instance

I am trying to to run a cronjob of a script on an EC2 Instance but it's simply not working
The way I am running it right now is
15 * * * * root /home/ec2-user s3_upload.sh TestBucket
I wrote this when I did crontab -e
Right now I am in this directory /home/ec2-user/ so I don't know if maybe that has something to do with why it's not running.
I just don't understand this whole cron thing and how permissions work.
Any help is greatly appreciated!
You can't specify a username in a user's crontab, only in /etc/crontab.
You can't specify a directory in any form of crontab. To change directory, use cd.
The environment is not the same. If you e.g. set PATH in .bashrc, these will not be automatically included, so it's safest to use full paths.
As root (assuming you want to run this as root and not ec2-user or something), run crontab -e and add
15 * * * * cd /home/ec2-user && /full/path/to/s3_upload.sh TestBucket
Make sure you can copy-paste the command in a root terminal and get it working, and read root's mail afterwards to see the command's output with possible error messages. If it still doesn't work, make sure you have these errors available.

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