array declaration of shellscript doesnot work in scheduled cron job? - linux

I have created a shell script named "script.sh" which reads an arrays elements and prints it on terminal. The script is as follows:
arr=("hello" "world")
for i in ${arr[#]}
do
echo $i;
done
It gives expected output i.e 'Hello World' on executing it in terminal, but if I schedule the same script in crontab jobs to get executed automatically every minute and store the output in another file,the job fails and gives
/home/vikash/script.sh: 1: Syntax error: "(" unexpected error.
The crontab job to execute the script every minute and store the output in another file is as follows:
* * * * * $HOME/script.sh >> $HOME/output.log 2>&1
How to use array in this scenario?? please help.

Add this before the first line of your script:
#!/bin/bash

if this question is still valid, just run your script with
bash script.sh
I also tried it with sh somehow it is not working with sh but with bash it suns smooth.

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.

storing the variable value while run from cron

sh
!/bin/sh
export count=$(sqlplus -s 'username/passwd#xyz'<
When I run this script manual , script runs fine.
When I keep it in crontab entry as follows
27 16 * * * /www/abc/a4.sh >a4.log
The a4.log doesnot have any data echoed.
Please let us know how to hold the value returned to a variable via sql query
Instead of putting
&>> your_file.log
behind a line in
crontab -e
Try using
#!/bin/bash
exec &>> your_file.log
…
at the beginning of a BASH script.
Also use >> which appends to the file rather than overwriting to it.

crontab failing to run a shell script that wgets a url at a specified interval

I have the following command inside a shell script at /home/ubuntu/wget_my_url.sh
the conent of ping_my_url are as follows -
wget -O - -q -t 1 http://www.someurl.com/baseurl/
There is no line break in the above file.
I did chmod +x wget_my_url.sh
Inside my /etc/crontab I have the following - */1 * * * * /home/ubuntu/wget_my_url.sh
There is a line break after the above line inside the crontab file.
When I run manually wget_my_url.sh, I get the desired result, but inside a cron tab, it does not run.
Please let me know, whats wrong with it.
Thanks.
What do you mean with the "desired result" ?
Your script just print choses on the screen (the standard out), but, the scripts on the crontab doesn't have a screen to print.
So, I think that it's running normally but you can't realize cause you don't see the script's output.
Instead of just print, why don't you print on a file making something like
wget -O - -q -t 1 http://www.someurl.com/baseurl/ > /home/ubuntu/OUT_FILE
?
Like that you'll be able to check if it works just checking if the file /home/ubuntu/OUT_FILE exists and you'll be able to use the script's output too.

How to test the script deployed with crontab

I have a script which I need to run daily at 01.00 am of every month. This is what I did with cron tab to make it happen
#housekeeping
0 1 1 * * sh /product/abc/tools/housekeeper.sh -t ABC
How can I check whether this script is running? Do I have to wait till it runs or is there a process running for this script so that I can confirm it is running?
The usual approach to test crontab scripts follows these guidelines:
Set the time pattern to "ten minutes from now". Wait ten minutes. Check cron's logfile and the log files of your script/app for errors.
Set the desired time pattern
This way, you can make sure that the script works. If something breaks, it must be because of the time pattern.
You should also redirect all output of the script to a log file. cron will send a mail with any output that the script produces but that's rarely desired.
If you always add an entry like "${timestamp} Started" to the log, you can check at your leisure that the script worked as expected.
If you want both, then you must make your script/app write the log file itself (i.e. without output redirection in the crontab) and print any errors to stdout; this will then make cron send an email.
Simple thing I use is to append something to a particular file before and after the desired command, like
*/2 * * * * (echo "Starting" >> ~/monitorCron.log; <Actual operation>; echo "End" >> ~/monitorCron.log;) > ~/cron.log 2>&1
This runs every 2 minutes, and appends the strings to ~/monitorCron.log.
This is the same thing I do in programming, writing a print statement where-ever and when-ever I get a doubt.

Test run cron entry

I added a cron job recently, but made a mistake in the path while giving the command and hence, the job never succeeded. Is there some way to test the cron changes we have done?
Please note that I had indeed copied and pasted the command from my command line and it was just an stray keypress that caused this.
When I want to test my cron jobs I usually set the interval very low and monitor the logs closely. When I am convinced the entry is correct, I set the interval back to a sane value.
For example, run job every two minutes:
*/2 * * * * echo "Hello World"
And the I run tail -f on my log file (/var/log/syslogon debian).
This question has also been asked on serverfault and has garnered a couple additional answers
The following is a paraphrased version of Marco's solution:
(Not sure if best etiquette is not providing a link only answer or not copying someone else's solution)
Create a environment file with a temporary cron entry
* * * * * /usr/bin/env > /home/username/cron-env
Then create a shell script called run-as-cron which executes the command using that environment.
#!/bin/sh
. "$1"
exec /usr/bin/env -i "$SHELL" -c ". $1; $2"
Give it execute permission
chmod +x run-as-cron
and then it is then used like this:
./run-as-cron <cron-environment> <command>
e.g.
./run-as-cron /home/username/cron-env 'echo $PATH'
Joshua's answer does not work for me. Two problems:
Variables in cron-env file are not exported (set -a needed).
Script is still tied to current tty (setsid needed).
The script run-as-cron should be
#!/bin/sh
. "$1"
exec setsid /usr/bin/env -i "$SHELL" -c "set -a; . $1; $2" </dev/null
Not enough rep' to fix his answer or add a comment...
use command crontab -e
This will open a vim editor and all you got to do here is
* * * * * /somepath/urscript.sh , make sure you have the appropriate spaces between dates and the path of the script
After the execution , you can check in the /var/spool/mail there will a complete trail of the script execution or errors.
For testing there is no way .. but in case ur sh urscript.sh works then cron tab will have no problem as it is exactly same thing what u do manually.

Resources