script behaves differently via cron - bash

Edit: Updated to reflect some answers
I have this script, test.sh on my home computer:
Note: $USER = john
#!/bin/bash
/usr/bin/scp -q john#mysite.com:/home/$USER/tmp/$USER /home/$USER/tmp/ > /dev/null 2>&1
error_code="$?"
if [ "$error_code" != "0" ]; then #if file NOT present on mysite then:
echo "File does not exist."
exit
fi
echo "File exists."
Now, lets say I create the file on the server mysite.com like so:
echo > tmp/$USER
Now, when I run the above script on my desktop manually, like so:
./test.sh
I get the result "File exists."
But if I run it via crontab, I get the result "File does not exist"
My crontab looks like this:
* * * * * /home/user/test.sh >> /home/user/test.log 2>&1
I've spent all day trying to check the logic and everything... I can't seem to figure out why this is so. Thanks for all your help in advance :)
Edit: scp looks in mysite.com:/home/$USER/tmp/ dir
The $USER on my desktop and the server are same. So I don't think it's an issue of relativeness.
If I were to
ssh $USER#mysite.com
and then do
ls tmp/
I'll see the file there.
Also, the crontab entry is in my crontab, not another users' or root's crontab.
#Jonathan: I've set up key based authentication. No password required!
#netcoder: In my log file, I see repeated lines of "File does not exist."
#sarnold: in my scp line, I've put john#mysite.com, just to make sure that cron uses john's account on mysite.com when crond runs the script. Still, same result.

I expect the problem is right here: mysite.com:tmp/$USER -- tmp/ is a relative path, relative to the current working directory. When your code is executed via crond(8), your cwd might be different than when you execute it by hand.
As #netcoder points out in his comment, absolute paths are the best way to work with scripts / programs executed out of crontab(5) files.

It may be a problem with your $USER environment variable not being set when run under cron.
You could try adding something like this to your script:
echo "User: $USER" > /tmp/crontest.log
After getting cron to run the script have a look at what is in /tmp/crontest.log
If nothing is being set you might want to try something like this: Where can I set environment variables that crontab will use?

Related

run.sh contains activating conda environment - Calling it from bash works but crontab does not [duplicate]

I'm trying to get cron to call in the correct PATHs. When I run a Python script from shell the script runs fine as it uses the PATHs set in bashrc but when I use cron all the PATHs are not used from bashrc. Is there a file I can enter the PATHs into for cron like bashrc or a way to call the PATHs from bashrc?
Sorry I don't think I worded this correctly, I can get the correct script to run (meaning the PATH to the script in crontab is not the problem here), it's just when that script is running I run a build and this uses the PATHs set in .bashrc. When I run the script when I'm logged in, the .bashrc PATHs are pulled in. Since cron doesn't run in a shell per say it does not pull in .bashrc. Is there a way of pulling this in without having to write a bash script wrapper?
I used /etc/crontab. I used vi and entered in the PATHs I needed into this file and ran it as root. The normal crontab overwrites PATHs that you have set up. A good tutorial on how to do this.
The systemwide cron file looks like this:
This has the username field, as used by /etc/crontab.
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file.
# This file also has a username field, that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
42 6 * * * root run-parts --report /etc/cron.daily
47 6 * * 7 root run-parts --report /etc/cron.weekly
52 6 1 * * root run-parts --report /etc/cron.monthly
01 01 * * 1-5 root python /path/to/file.py
Most likely, cron is running in a very sparse environment. Check the environment variables cron is using by appending a dummy job which dumps env to a file like this:
* * * * * env > env_dump.txt
Compare that with the output of env in a normal shell session.
You can prepend your own environment variables to the local crontab by defining them at the top of your crontab.
Here's a quick fix to prepend $PATH to the current crontab:
# echo PATH=$PATH > tmp.cron
# echo >> tmp.cron
# crontab -l >> tmp.cron
# crontab tmp.cron
The resulting crontab will look similar to chrissygormley's answer, with PATH defined before the crontab rules.
You should put full paths in your crontab. That's the safest option.
If you don't want to do that you can put a wrapper script around your programs, and set the PATH in there.
e.g.
01 01 * * * command
becomes:
01 01 * * * /full/path/to/command
Also anything called from cron should be be very careful about the programs it runs, and probably set its own choice for the PATH variable.
EDIT:
If you don't know where the command is that you want execute which <command> from your shell and it'll tell you the path.
EDIT2:
So once your program is running, the first thing it should do is set PATH and any other required variable (e.g. LD_LIBRARY_PATH) to the values that are required for the script to run.
Basically instead of thinking how to modify the cron environment to make it more suitable for your program/script - make your script handle the environment it's given, by setting an appropriate one when it starts.
Adding a PATH definition into the user crontab with correct values will help...
I've filled mine with this line on top (after comments, and before cron jobs):
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
And it's enough to get all my scripts working... Include any custom path there if you need to.
Setting PATH right before the command line in my crontab worked for me:
* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing
Make your variables work for you, this will allow access t
Define your PATH in /etc/profile.d/*.sh
System-wide environment variables
Files with the .sh extension in the /etc/profile.d directory get executed whenever a bash login shell is entered (e.g. when logging in from the console or over ssh), as well as by the DisplayManager when the desktop session loads.
You can for instance create the file /etc/profile.d/myenvvars.sh and set variables like this:
export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin
Execute crontab with login option!
CRONTAB run script or command with Environment Variables
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c 'php -f ./download.php'
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c download.sh
Problem
Your script works when you run it from the console but fails in cron.
Cause
Your crontab doesn't have the right path variables (and possibly shell)
Solution
Add your current shell and path the crontab
Script to do it for you
#!/bin/bash
#
# Date: August 22, 2013
# Author: Steve Stonebraker
# File: add_current_shell_and_path_to_crontab.sh
# Description: Add current user's shell and path to crontab
# Source: http://brakertech.com/add-current-path-to-crontab
# Github: hhttps://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh
# function that is called when the script exits (cleans up our tmp.cron file)
function finish { [ -e "tmp.cron" ] && rm tmp.cron; }
#whenver the script exits call the function "finish"
trap finish EXIT
########################################
# pretty printing functions
function print_status { echo -e "\x1B[01;34m[*]\x1B[0m $1"; }
function print_good { echo -e "\x1B[01;32m[*]\x1B[0m $1"; }
function print_error { echo -e "\x1B[01;31m[*]\x1B[0m $1"; }
function print_notification { echo -e "\x1B[01;33m[*]\x1B[0m $1"; }
function printline {
hr=-------------------------------------------------------------------------------------------------------------------------------
printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}"
}
####################################
# print message and exit program
function die { print_error "$1"; exit 1; }
####################################
# user must have at least one job in their crontab
function require_gt1_user_crontab_job {
crontab -l &> /dev/null
[ $? -ne 0 ] && die "Script requires you have at least one user crontab job!"
}
####################################
# Add current shell and path to user's crontab
function add_shell_path_to_crontab {
#print info about what's being added
print_notification "Current SHELL: ${SHELL}"
print_notification "Current PATH: ${PATH}"
#Add current shell and path to crontab
print_status "Adding current SHELL and PATH to crontab \nold crontab:"
printline; crontab -l; printline
#keep old comments but start new crontab file
crontab -l | grep "^#" > tmp.cron
#Add our current shell and path to the new crontab file
echo -e "SHELL=${SHELL}\nPATH=${PATH}\n" >> tmp.cron
#Add old crontab entries but ignore comments or any shell or path statements
crontab -l | grep -v "^#" | grep -v "SHELL" | grep -v "PATH" >> tmp.cron
#load up the new crontab we just created
crontab tmp.cron
#Display new crontab
print_good "New crontab:"
printline; crontab -l; printline
}
require_gt1_user_crontab_job
add_shell_path_to_crontab
Source
https://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh
Sample Output
The simplest workaround I've found looks like this:
* * * * * root su -l -c command
This example invokes su as root user and starts the shell with the user's full environment, including $PATH, set as if they were logged in. It works the same on different distros, is more reliable than sourcing .bashrc (which hasn't worked for me) and avoids hardcoding specific paths which can be a problem if you're providing an example or setup tool and don't know what distro or file layout on the user's system.
You can also specify the username after su if you want a different user than root, but you should probably leave the root parameter before su command since this ensures su has sufficient privileges to switch to any user you specify.
The default environment for cron jobs is very sparse and may be very different from the environment you develop your python scripts in. For a script that might be run in cron, any environment that you depend on should be set explicitly. In the cron file itself, include full paths to python executables and to your python scripts.
On my AIX cron picks up it's environmental variables from /etc/environment ignoring what is set in the .profile.
Edit: I also checked out a couple of Linux boxes of various ages and these appear to have this file as well, so this is likely not AIX specific.
I checked this using joemaller's cron suggestion and checking the output before and after editing the PATH variable in /etc/environment.
If you don't want to have to make the same edits in various places, then roughly do this:
* * * * * . /home/username/.bashrc && yourcommand all of your args
The . space and then the path to .bashrc and the && command are the magic there to get your environment changes into the running bash shell. Too, if you really want the shell to be bash, it is a good idea to have a line in your crontab:
SHELL=/bin/bash
Hope it helps someone!
#Trevino: your answer helped me solve my problem. However, for a beginner, trying to give a step by step approach.
Get your current installation of java via $ echo $JAVA_HOME
$ crontab -e
* * * * * echo $PATH - this lets you understand whats the PATH value being used by crontab at present. Run crontab and grab $PATH value used by crontab.
Now edit crontab again to set your desired java bin path: a) crontab -e; b) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin (its a sample path); c) now your scheduled job/script like */10 * * * * sh runMyJob.sh &; d) remove echo $PATH from crontab as its not needed now.
Set the required PATH in your cron
crontab -e
Edit: Press i
PATH=/usr/local/bin:/usr/local/:or_whatever
10 * * * * your_command
Save and exit :wq
I know this has been answered already, but I thought that his would be useful to some. I had a similar issue that I recently solved (found here) and here are the highlights of the steps I took to answer this question:
make sure that you have the variables you need in PYTHONPATH (found here and here and for more info here) inside the .profile or .bash_profile for any shell you want to test your script in to make sure it works.
edit your crontab to include the directories needed to run your script in a cron job (found here and here)
a) be sure to include the root directory in the PATH variable (.) as explained here (basically if you are running an executable with your command it needs to be able to find root or the directory where the executable is stored) and probably these (/sbin:/bin:/usr/sbin:/usr/bin)
in your crontab file, create a cronjob that will change directory to the directory where you have successfully ran the script before (i.e. Users/user/Documents/foo)
a) This will look like the following:
* * * * cd /Users/user/Documents/foo; bar -l doSomething -v
Should you use webmin then these are the steps how to set the PATH value:
System
-> Scheduled Cron Jobs
-> Create a new environment variable
-> For user: <Select the user name>
-> Variable name: PATH
-> Value: /usr/bin:/bin:<your personal path>
-> Add environment variable: Before all Cron jobs for user

Bash script runs fine when called directly, but cron seemingly refuses to run it at all?

I'm at my wits end with this. I have the following script:
#!/usr/bin/env bash
declare -a nriArray=(newrelic-cli node-newrelic nri-flex helm-charts infrastructure-agent opentelemetry-exporter-java opentelemetry-exporter-go newrelic-lambda-cli newrelic-node-apollo-server-plugin nri-kubernetes nri-prometheus nri-redis infrastructure-bundle newrelic-lambda-layers nri-jmx newrelic-winston-logenricher-node nri-cassandra micrometer-registry-newrelic newrelic-fluent-bit-output nri-kafka node-newrelic-aws-sdk nri-elasticsearch nri-mysql nri-nagios nri-snmp node-newrelic-superagent nri-kube-events nri-mssql newrelic-module-util-java newrelic-logenricher-dotnet aws-log-ingestion newrelic-lambda-tracer-java nri-docker nri-oracledb k8s-metadata-injection nri-discovery-kubernetes nri-haproxy nri-postgresql node-native-metrics nri-consul nri-rabbitmq nri-vsphere nri-winservices nri-ecs newrelic-airflow-plugin newrelic-monolog-logenricher-php node-newrelic-koa nri-f5 aws_s3_log_ingestion_lambda dropwizard-metrics-newrelic k8s-webhook-cert-manager newrelic-fluentd-output nri-couchbase nri-memcached nri-mongodb java-aws-lambda logstash-output-plugin nri-apache nri-varnish java-log-extensions nri-nginx nri-statsd newrelic-opencensus-exporter-go newrelic-opencensus-exporter-python python-agent-extension)
cd /Users/aschneider/NewRelic-OpenSource/
counter=0
while [[ "$counter" -lt "${#nriArray[#]}" ]]; do
cd "${nriArray[$counter]}"
git pull &>> /Users/aschneider/NewRelic-OpenSource/cronLog.log
gsed -i '/Already up to date./d' /Users/aschneider/NewRelic-OpenSource/cronLog.log
git clean -q -d -f
cd ..
((counter=counter+1))
done
printf "\n\n" >> /Users/aschneider/NewRelic-OpenSource/cronLog.log
holdingVar=$(cat -s /Users/aschneider/NewRelic-OpenSource/cronLog.log) && echo "$holdingVar" > /Users/aschneider/NewRelic-OpenSource/cronLog.log
/Applications/Utilities/terminal-notifier.app/Contents/MacOS/terminal-notifier -message "~/NewRelic-OpenSource/ repositories were updated."
The script recursively goes through an array of GitHub repos, pulls in any updates to them, and then moves onto the next folder. It removes any lines stating that the folder is up to date in order to only keep changes in the log file, and then it uses Terminal Notifier to alert me after each update. It works perfectly when I run it with bash ~/NewRelic-OpenSource/updateOpenSource.sh, but it doesn't even seem to execute when I put the script in crontab. My crontab -l output is below:
SHELL=/usr/local/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
*/30 8-17 * * 1-5 /usr/local/bin/bash /Users/aschneider/NewRelic-OpenSource/updateOpenSources.sh
I have it running every 30 minutes, from 8am to 5pm, on weekdays. Even if I switch to * * * * * [command], it doesn't do anything, so I don't think it's a scheduling syntax issue. I'm currently running it all on my MacBook, which uses GNU bash, version 5.1.4(1)-release (x86_64-apple-darwin20.2.0). I've tried adding the PATH definition to the crontab, as well as to the script itself. I've also verified the script is executable with chmod +x {script}. Any ideas on what I'm doing wrong here?
Cronjobs run as root by default. You may want to run as the user you would normally run the script as, if you were running the script manually. For example,
*/5 * * * * (add the username here) sample_executable
I have also read, but I may be wrong they do not use your PATH variables. So all executables should be fully refrenced before running the script.
Also check the permissions to run the script in crontab.

Debian bash script, checking gateway by ping script as cron job [duplicate]

I'm trying to get cron to call in the correct PATHs. When I run a Python script from shell the script runs fine as it uses the PATHs set in bashrc but when I use cron all the PATHs are not used from bashrc. Is there a file I can enter the PATHs into for cron like bashrc or a way to call the PATHs from bashrc?
Sorry I don't think I worded this correctly, I can get the correct script to run (meaning the PATH to the script in crontab is not the problem here), it's just when that script is running I run a build and this uses the PATHs set in .bashrc. When I run the script when I'm logged in, the .bashrc PATHs are pulled in. Since cron doesn't run in a shell per say it does not pull in .bashrc. Is there a way of pulling this in without having to write a bash script wrapper?
I used /etc/crontab. I used vi and entered in the PATHs I needed into this file and ran it as root. The normal crontab overwrites PATHs that you have set up. A good tutorial on how to do this.
The systemwide cron file looks like this:
This has the username field, as used by /etc/crontab.
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file.
# This file also has a username field, that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
42 6 * * * root run-parts --report /etc/cron.daily
47 6 * * 7 root run-parts --report /etc/cron.weekly
52 6 1 * * root run-parts --report /etc/cron.monthly
01 01 * * 1-5 root python /path/to/file.py
Most likely, cron is running in a very sparse environment. Check the environment variables cron is using by appending a dummy job which dumps env to a file like this:
* * * * * env > env_dump.txt
Compare that with the output of env in a normal shell session.
You can prepend your own environment variables to the local crontab by defining them at the top of your crontab.
Here's a quick fix to prepend $PATH to the current crontab:
# echo PATH=$PATH > tmp.cron
# echo >> tmp.cron
# crontab -l >> tmp.cron
# crontab tmp.cron
The resulting crontab will look similar to chrissygormley's answer, with PATH defined before the crontab rules.
You should put full paths in your crontab. That's the safest option.
If you don't want to do that you can put a wrapper script around your programs, and set the PATH in there.
e.g.
01 01 * * * command
becomes:
01 01 * * * /full/path/to/command
Also anything called from cron should be be very careful about the programs it runs, and probably set its own choice for the PATH variable.
EDIT:
If you don't know where the command is that you want execute which <command> from your shell and it'll tell you the path.
EDIT2:
So once your program is running, the first thing it should do is set PATH and any other required variable (e.g. LD_LIBRARY_PATH) to the values that are required for the script to run.
Basically instead of thinking how to modify the cron environment to make it more suitable for your program/script - make your script handle the environment it's given, by setting an appropriate one when it starts.
Adding a PATH definition into the user crontab with correct values will help...
I've filled mine with this line on top (after comments, and before cron jobs):
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
And it's enough to get all my scripts working... Include any custom path there if you need to.
Setting PATH right before the command line in my crontab worked for me:
* * * * * PATH=$PATH:/usr/local/bin:/path/to/some/thing
Make your variables work for you, this will allow access t
Define your PATH in /etc/profile.d/*.sh
System-wide environment variables
Files with the .sh extension in the /etc/profile.d directory get executed whenever a bash login shell is entered (e.g. when logging in from the console or over ssh), as well as by the DisplayManager when the desktop session loads.
You can for instance create the file /etc/profile.d/myenvvars.sh and set variables like this:
export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin
Execute crontab with login option!
CRONTAB run script or command with Environment Variables
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c 'php -f ./download.php'
0 9 * * * cd /var/www/vhosts/foo/crons/; bash -l -c download.sh
Problem
Your script works when you run it from the console but fails in cron.
Cause
Your crontab doesn't have the right path variables (and possibly shell)
Solution
Add your current shell and path the crontab
Script to do it for you
#!/bin/bash
#
# Date: August 22, 2013
# Author: Steve Stonebraker
# File: add_current_shell_and_path_to_crontab.sh
# Description: Add current user's shell and path to crontab
# Source: http://brakertech.com/add-current-path-to-crontab
# Github: hhttps://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh
# function that is called when the script exits (cleans up our tmp.cron file)
function finish { [ -e "tmp.cron" ] && rm tmp.cron; }
#whenver the script exits call the function "finish"
trap finish EXIT
########################################
# pretty printing functions
function print_status { echo -e "\x1B[01;34m[*]\x1B[0m $1"; }
function print_good { echo -e "\x1B[01;32m[*]\x1B[0m $1"; }
function print_error { echo -e "\x1B[01;31m[*]\x1B[0m $1"; }
function print_notification { echo -e "\x1B[01;33m[*]\x1B[0m $1"; }
function printline {
hr=-------------------------------------------------------------------------------------------------------------------------------
printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}"
}
####################################
# print message and exit program
function die { print_error "$1"; exit 1; }
####################################
# user must have at least one job in their crontab
function require_gt1_user_crontab_job {
crontab -l &> /dev/null
[ $? -ne 0 ] && die "Script requires you have at least one user crontab job!"
}
####################################
# Add current shell and path to user's crontab
function add_shell_path_to_crontab {
#print info about what's being added
print_notification "Current SHELL: ${SHELL}"
print_notification "Current PATH: ${PATH}"
#Add current shell and path to crontab
print_status "Adding current SHELL and PATH to crontab \nold crontab:"
printline; crontab -l; printline
#keep old comments but start new crontab file
crontab -l | grep "^#" > tmp.cron
#Add our current shell and path to the new crontab file
echo -e "SHELL=${SHELL}\nPATH=${PATH}\n" >> tmp.cron
#Add old crontab entries but ignore comments or any shell or path statements
crontab -l | grep -v "^#" | grep -v "SHELL" | grep -v "PATH" >> tmp.cron
#load up the new crontab we just created
crontab tmp.cron
#Display new crontab
print_good "New crontab:"
printline; crontab -l; printline
}
require_gt1_user_crontab_job
add_shell_path_to_crontab
Source
https://github.com/ssstonebraker/braker-scripts/blob/master/working-scripts/add_current_shell_and_path_to_crontab.sh
Sample Output
The simplest workaround I've found looks like this:
* * * * * root su -l -c command
This example invokes su as root user and starts the shell with the user's full environment, including $PATH, set as if they were logged in. It works the same on different distros, is more reliable than sourcing .bashrc (which hasn't worked for me) and avoids hardcoding specific paths which can be a problem if you're providing an example or setup tool and don't know what distro or file layout on the user's system.
You can also specify the username after su if you want a different user than root, but you should probably leave the root parameter before su command since this ensures su has sufficient privileges to switch to any user you specify.
The default environment for cron jobs is very sparse and may be very different from the environment you develop your python scripts in. For a script that might be run in cron, any environment that you depend on should be set explicitly. In the cron file itself, include full paths to python executables and to your python scripts.
On my AIX cron picks up it's environmental variables from /etc/environment ignoring what is set in the .profile.
Edit: I also checked out a couple of Linux boxes of various ages and these appear to have this file as well, so this is likely not AIX specific.
I checked this using joemaller's cron suggestion and checking the output before and after editing the PATH variable in /etc/environment.
If you don't want to have to make the same edits in various places, then roughly do this:
* * * * * . /home/username/.bashrc && yourcommand all of your args
The . space and then the path to .bashrc and the && command are the magic there to get your environment changes into the running bash shell. Too, if you really want the shell to be bash, it is a good idea to have a line in your crontab:
SHELL=/bin/bash
Hope it helps someone!
#Trevino: your answer helped me solve my problem. However, for a beginner, trying to give a step by step approach.
Get your current installation of java via $ echo $JAVA_HOME
$ crontab -e
* * * * * echo $PATH - this lets you understand whats the PATH value being used by crontab at present. Run crontab and grab $PATH value used by crontab.
Now edit crontab again to set your desired java bin path: a) crontab -e; b) PATH=<value of $JAVA_HOME>/bin:/usr/bin:/bin (its a sample path); c) now your scheduled job/script like */10 * * * * sh runMyJob.sh &; d) remove echo $PATH from crontab as its not needed now.
Set the required PATH in your cron
crontab -e
Edit: Press i
PATH=/usr/local/bin:/usr/local/:or_whatever
10 * * * * your_command
Save and exit :wq
I know this has been answered already, but I thought that his would be useful to some. I had a similar issue that I recently solved (found here) and here are the highlights of the steps I took to answer this question:
make sure that you have the variables you need in PYTHONPATH (found here and here and for more info here) inside the .profile or .bash_profile for any shell you want to test your script in to make sure it works.
edit your crontab to include the directories needed to run your script in a cron job (found here and here)
a) be sure to include the root directory in the PATH variable (.) as explained here (basically if you are running an executable with your command it needs to be able to find root or the directory where the executable is stored) and probably these (/sbin:/bin:/usr/sbin:/usr/bin)
in your crontab file, create a cronjob that will change directory to the directory where you have successfully ran the script before (i.e. Users/user/Documents/foo)
a) This will look like the following:
* * * * cd /Users/user/Documents/foo; bar -l doSomething -v
Should you use webmin then these are the steps how to set the PATH value:
System
-> Scheduled Cron Jobs
-> Create a new environment variable
-> For user: <Select the user name>
-> Variable name: PATH
-> Value: /usr/bin:/bin:<your personal path>
-> Add environment variable: Before all Cron jobs for user

Run Script on AWS #reboot?

I'm currently trying to run script that will run in the background when my AWS instance boots for the duration of the instance life. I'm testing it with a simple script to see if it works, before I test with my more complicated one:
#!/bin/bash
while [true]; do
sleep 1
echo "Hello World" >> "tempStorage.json"
done
And my sudo crontab -l returns:
# All the comment stuff
#reboot sh /home/ubuntu/test/testScript/test.sh
Which is the path to the script. I've also obviously run chmod +x test.sh to make sure its an executable.
The problem is when I stop and then start the AWS instance there's nothing in the tempStorage.json file. I've checked other threads and they all suggest this is what I should be doing, so I'm very confused and advice would be appreciated. Thanks.
As Mark B mentioned, the issue is the execution directory of the cron script. There are two solutions then.
A) Change the path to file as Mark B recommended so the script would look something like:
#!/bin/bash
while [true]; do
sleep 1
echo "Hello World" >> "/home/ubuntu/test/testScript/tempStorage.json"
done
B) Change the directory of the cron execution and keep the script as it was. This works better if you need to put the script in any directory. It would look like this for the crontab:
# All the comment stuff
#reboot cd /home/ubuntu/test/testScript && sh test.sh
That should work fine. I think the issue is that you aren't giving the full path to the tempSTorage.json file within your script. So it is being written to in a different folder than the one you are looking in, specifically whatever folder cron starts processes in by default. Try changing it to something like /tmp/tempSTorage.json and then rebooting the server again.
Note that if you are wanting something that starts on boot and runs forever, this probably isn't the best method. In that case I would look into running your process as a service.

Run cron from specific directory and log time in log file

I have this script that parses images from an external address.
I need to make sure that the script is running in a specific directory. I also want to log the time.
This is what I have done for the cronjob:
*/2 * * * * cd /path/to/script; (time /path/to/script/code.sh arg) &>> /path/to/log/time.log)
And my shell script is pretty simple:
#!/bin/sh
timestamp()
{
date +"%Y-%m-%d %T"
}
echo "###########################"
echo $(timestamp)
python /path/to/script/parser1.py "-s$1"
python /path/to/script/parser2.py "-s$1"
I get mail to my user, but it is just of the $(timestamp) echo. I should have the timestamp and also have output from both parser1 and parser2 updating in my time.log file. I don't know why this isn't working! I can run the cronjob command from the command line and it works.
So, I think the problem is that cron is running your script, but not from the directory you want to run it FROM. I am not sure, but I believe cron executes scripts from either the /root or / directories.
Try this - Add this right below your timestamp function - modified with the proper path, of course.
DIRNAME=/path/to/directory
LOGFILE=logfile.log
cd ${DIRNAME}
echo $(timestamp) >> ${LOGFILE}
And then remove the current echo $(timestamp) line.
Also, make sure the log file exists, and you have write access to the file.

Resources