I am trying to run this comamand from bash script through crontab, it just gets SystemOut.log, though I expect to get SystemOut_* as well.
/app/hdup/get_logs SystemOut*
But when i tried to run this above command from terminal, it worked properly and got both SystemOut.log and SystemOut_*
Any idea what could have gone wrong?
As pointed out in the comments already: The cron is using a different shell than you do. You can set the shell to be used by cron via a variable at the top of your crontab to have the same result as in your terminal:
SHELL=/bin/bash
Details can be found at https://serverfault.com/a/678414
cron is executed by /bin/sh which is the key point why many special string like * , {},etc not work.
put SHELL=/bin/bash on the first line of you cron file after "crontab -e"
Related
The following script is running git pull and then write the status to file.
#!/bin/bash
git pull
git log -7 > /var/www/domain.com/v.txt
When I run the file manually, the file v.txt is created and the content inside as expected.
bash /var/www/domain.io/update.sh
When I run it via cron the file is created but the content is empty
* * * * * bash /var/www/domain.io/update.sh
Whats wrong?
If I remember correctly the runtime environment of the interactive shell vs cron are different. Specifically the setting of environment variables like PATH can be different. This can effect how scripts run via cron.
As a test you could try the following. Create a small bash shell script that dumps your environment to a file and run this script from both the command line and cron and look for differences.
Eg. file named: r1.sh
#! /bin/bash
env
From the command line:
$ r1.sh > cmd-line.out
From cron
* * * * * /home/your-user-name/r1.sh > /home/your-user-name/cron.out
NOTE: use full path names for shell script and the output file.
When I did this test on my system, there where a number of difference between the two, for example the PATH variable was much shorter.
If this is the case on your system maybe "git" is not available in the cron env.
Anyway, just an idea to try.
I hope this helps.
I have a script to invalidate Amazon CloudFront in a .sh file and it works fine when I run it with bash (bash /../filename.sh). I need to invalidate my distribution every thursday, so I wrote a cron job, but it is giving the error "aws: command not found".
This is my cron job
45 10 * * 2 /usr/bin/bash /var/www/cms/file.sh
What I am missing? Why the cron job is failing when bash could run the script?
This is because your system depends on an environment variable for places where to search for executable files and that variable is not set in the cron sessions. This variable is named $PATH. You can see it's contents in your current session by just typing echo $PATH in your terminal.
When a cron session is started for a job to be executed, this variable is not set.
To solve this issue, there are a few ways:
Method 1:
Use full path names in your shell script and do not depend on the PATH variable for finding executables.
Method 2:
Add the following at the beginning in your script (adjust if needed):
PATH=/sbin:/bin:/usr/sbin:/usr/bin
Method 3:
(This method is generally discouraged)
Add the following line in your crontab (adjust if needed):
PATH=/sbin:/bin:/usr/sbin:/usr/bin
You can do echo $PATH in your terminal and copy the output in the above variable in the crontab.
Thank you Sakis your answer worked perfectly for me.
I was baffled why my scripts would run just fine from the command line but error out when run from cron. The reason was i was trying to use an executable from within bash that was not a recognized command due to lack of reference to a path. Now it's clear.
Did exactly this - no root or other sudo required.
From your own shell, echo $PATH. Copy this line and enter in your own cron (affects all jobs in that cron) or at the top of your script.
PATH=/home/myuser/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
And voila !
I have the following script that runs perfectly when I execute it:
#!/bin/bash
zip logs.zip -r *
However when I run it from crontab, i get
/home/ubuntu/script.sh: line 2: zip: command not found
Why is that? Do I need to set up some sort of path? I have no luck searching for it.
Thanks!
Your login shell will have zip in the PATH, however cron will not run commands in a login shell. You can specify environment variables in your crontab file, you should probably set the PATH to the same as your login shell and possibly add some more variables too. I have:
SHELL=/usr/local/bin/bash
MAILTO="my#email.address"
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
So that cron runs bash, sends emails to a working address and uses a decent PATH
Use the following command to find full path of zip
which zip
then use full path is your script... ie:
/usr/bin/zip logs.zip -r *
I am curious about the following:
I have a bash script, which is executed once in a month through a cronjob. The following line is giving an error "unknown command" when ran through the cronjob:
echo $P | chpasswd
When I execute the bash script directly, it is working properly.
Anyone with an idea?
Converting commentary into an answer.
What is the PATH supplied to your cron job? Where is chpasswd stored? Since the directory where chpasswd is stored is not listed in the path provided by cron, it fails to find it. You get a very limited environment with cron; running anything the least out of the ordinary means great care is required.
Either set PATH more fully in the script run by the cron job, or specify the absolute pathname of the commands that are not in /bin or /usr/bin.
Incidentally, how do you set P for echo to echo it? Doesn't it set the same value each month? Is that wise?
There are numerous other questions on Stack Overflow about difficulties running commands from cron jobs. Amongst others, see Bash script not running in cron correctly and Perl script works but not via cron and Is there a special restriction on commands executed by cron?, to name but three.
I pass the file path, containing variables to be sourced, as an argument to my Bash script.
The file is created on Windows, in case that makes any difference.
The following check is performed:
CONFIG_FILE=$1
if [[ -f ${CONFIG_FILE} ]]; then
echo "Is a file"
. ${CONFIG_FILE}
else
echo "Not a file"
fi
When I run the script manually, from the command line, the check is fine and the variables get sourced.
However, when I set up a Cron job using
*/1 * * * * /full/path/to/script.sh /full/path/to/configfile
I get "Not a file" printed out.
I attempted every single setup I found online to solve this:
setting up environment variables both in crontab and script itself (PATH & SHELL)
sourcing the profile (both . /etc/profile and . /home/user/.bash_profile) both in crontab (before executing the script) and in the script itself.
trying to run crontab with the -u user parameter, but don't have permissions for this (and it doesn't make sense, as I am already logged in as the user who should setup the crontab)
I am setting up the crontab with the proper user under whom the script should be run. The user has access rights to the location of the files (as can be observed through running the script from the command line).
Looking for further advice on what can be attempted next.
What you're doing here is (I think) making sure that there is a separate argument behind your /path/config-file. Your original problem seems to be that on Unix your config file was stated as /path/config-file\r (note the trailing \r). You are doing it by adding an argument -q\r so that the config file itself is "clean" of the carriage return. You could add blabla\r for that matter instead of -q\r. Your script never interprets that extra argument; but if you put it on the cron line then your config file argument is "protected", because there's stuff following it, that's all.
What you also could do, is make sure that your cron defintion is Unix-styled (\n terminted lines) instead of DOS styled (\r\n terminated lines). There's probably a utility dos2unix on your Unix box to accomplish that.
Or you could remove the crontab on Unix using crontab -r and then re-create the crontab using crontab -e. Just don't upload files that were created on MS-DOS (or derived).
Found another attempt and it worked.
I added the -q flag in the cronjob line.
*/1 * * * * /path/script.sh /path/config-file -q
Source: Cron Job error "Could not open input file"
Can someone please explain to me what does it do?
I am not so literate in bash.