Running bash script from crontab - bash

I am having difficulty running the below simple script from crontab:
#!/bin/bash
notify-send "battery.sh working"
The permissions of the file are rwxr-xr-x and its running fine with either of the commands bash battery.sh and sh battery.sh.
In my crontab, I have tried running it with both bash and sh, with absolute as well as local path. My current crontab looks as follows:
* * * * * /home/marpangal/battery.sh
* * * * * sh battery.sh
* * * * * bash battery.sh
* * * * * sh /home/marpangal/battery.sh
* * * * * bash /home/marpangal/battery.sh
However the cron does not execute the script and I get no message from notify-send.

notify-send needs the DBUS_SESSION_BUS_ADDRESS environment variable in order to communicate with the current desktop session. Since cron runs with an almost empty environment, this variable is not available.
But you can set it directly in your battery.sh script:
export $(egrep -z DBUS_SESSION_BUS_ADDRESS /proc/$(pgrep -u $LOGNAME gnome-session)/environ)
notify-send "Message from cron"
This looks up the process id of your gnome-session and extracts the DBUS_SESSION_BUS_ADDRESS (along with its value) from then gnome-sessions' environment.
Now notify-send is able to display notifications in your desktop session.

Flopps’s answer gives me a -bash: warning: command substitution: ignored null byte in input – so i tried something different:
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus
notify-send "Message from cron"
i assume this is not as flexible as the original export but it works for me in my user crontab.

Related

Read Env Variable in Crontab

I want to read a env variable in crontab.
I tried with run printenv from crontab and it runs fine:
* * * * * BASH_ENV=/etc/profile bash -c "printenv CNE_CLUSTER_NAME >> output.txt"
I need to run a job with some operation performed by python's script. I sheduled it in crontab like this:
* * * * * BASH_ENV=/etc/profile bash -c "/usr/bin/python3 /var/cne/cluster/$(echo $(printenv CNE_CLUSTER_NAME))/scripts/setup/job.py"
But when running from crontab is var CNE_CLUSTER_NAME is empty
python3: can't open file '/var/cne/cluster//scripts/setup/job.py': [Errno 2] No such file or directory)
So, how can i do to read variable or replaced the values's variable in the string ? Please.
You don't need printenv to acces the value of CNE_CLUSTER_NAME.
* * * * * BASH_ENV=/etc/profile bash -c '/usr/bin/python3 /var/cne/cluster/$CNE_CLUSTER_NAME/scripts/setup/job.py'
$CNE_CLUSTER_NAME is passed literally, and the shell that executes the command will expand the parameter to the value found in its environment.

How to set environment variable inside cron tab and get those value inside shell script [duplicate]

I have a crontab running every hour. The user running it has environment variabless in the .bash_profile that work when the user runs the job from the terminal, however, obviously these don't get picked up by crontab when it runs.
I've tried setting them in .profile and .bashrc but they still don't seem to get picked up. Does anyone know where I can put environment vars that crontab can pick up?
You can define environment variables in the crontab itself when running crontab -e from the command line.
LANG=nb_NO.UTF-8
LC_ALL=nb_NO.UTF-8
# m h dom mon dow command
* * * * * sleep 5s && echo "yo"
This feature is only available to certain implementations of cron. Ubuntu and Debian currently use vixie-cron which allows these to be declared in the crontab file (also GNU mcron).
Archlinux and RedHat use cronie which does not allow environment variables to be declared and will throw syntax errors in the cron.log. Workaround can be done per-entry:
# m h dom mon dow command
* * * * * export LC_ALL=nb_NO.UTF-8; sleep 5s && echo "yo"
I got one more solution for this problem:
0 5 * * * . $HOME/.profile; /path/to/command/to/run
In this case it will pick all the environment variable defined in your $HOME/.profile file.
Of course $HOME is also not set, you have to replace it with the full path of your $HOME.
Setting vars in /etc/environment also worked for me in Ubuntu. As of 12.04, variables in /etc/environment are loaded for cron.
Have 'cron' run a shell script that sets the environment before running the command.
Always.
# #(#)$Id: crontab,v 4.2 2007/09/17 02:41:00 jleffler Exp $
# Crontab file for Home Directory for Jonathan Leffler (JL)
#-----------------------------------------------------------------------------
#Min Hour Day Month Weekday Command
#-----------------------------------------------------------------------------
0 * * * * /usr/bin/ksh /work1/jleffler/bin/Cron/hourly
1 1 * * * /usr/bin/ksh /work1/jleffler/bin/Cron/daily
23 1 * * 1-5 /usr/bin/ksh /work1/jleffler/bin/Cron/weekday
2 3 * * 0 /usr/bin/ksh /work1/jleffler/bin/Cron/weekly
21 3 1 * * /usr/bin/ksh /work1/jleffler/bin/Cron/monthly
The scripts in ~/bin/Cron are all links to a single script, 'runcron', which looks like:
: "$Id: runcron.sh,v 2.1 2001/02/27 00:53:22 jleffler Exp $"
#
# Commands to be performed by Cron (no debugging options)
# Set environment -- not done by cron (usually switches HOME)
. $HOME/.cronfile
base=`basename $0`
cmd=${REAL_HOME:-/real/home}/bin/$base
if [ ! -x $cmd ]
then cmd=${HOME}/bin/$base
fi
exec $cmd ${#:+"$#"}
(Written using an older coding standard - nowadays, I'd use a shebang '#!' at the start.)
The '~/.cronfile' is a variation on my profile for use by cron - rigorously non-interactive and no echoing for the sake of being noisy. You could arrange to execute the .profile and so on instead. (The REAL_HOME stuff is an artefact of my environment - you can pretend it is the same as $HOME.)
So, this code reads the appropriate environment and then executes the non-Cron version of the command from my home directory. So, for example, my 'weekday' command looks like:
: "#(#)$Id: weekday.sh,v 1.10 2007/09/17 02:42:03 jleffler Exp $"
#
# Commands to be done each weekday
# Update ICSCOPE
n.updics
The 'daily' command is simpler:
: "#(#)$Id: daily.sh,v 1.5 1997/06/02 22:04:21 johnl Exp $"
#
# Commands to be done daily
# Nothing -- most things are done on weekdays only
exit 0
If you start the scripts you are executing through cron with:
#!/bin/bash -l
They should pick up your ~/.bash_profile environment variables
Expanding on #carestad example, which I find easier, is to run the script with cron and have the environment in the script.
In crontab -e file:
SHELL=/bin/bash
*/1 * * * * $HOME/cron_job.sh
In cron_job.sh file:
#!/bin/bash
source $HOME/.bash_profile
some_other_cmd
Any command after the source of .bash_profile will have your environment as if you logged in.
Whatever you set in crontab will be available in the cronjobs, both directly and using the variables in the scripts.
Use them in the definition of the cronjob
You can configure crontab so that it sets variables that then the can cronjob use:
$ crontab -l
myvar="hi man"
* * * * * echo "$myvar. date is $(date)" >> /tmp/hello
Now the file /tmp/hello shows things like:
$ cat /tmp/hello
hi man. date is Thu May 12 12:10:01 CEST 2016
hi man. date is Thu May 12 12:11:01 CEST 2016
Use them in the script run by cronjob
You can configure crontab so that it sets variables that then the scripts can use:
$ crontab -l
myvar="hi man"
* * * * * /bin/bash /tmp/myscript.sh
And say script /tmp/myscript.sh is like this:
echo "Now is $(date). myvar=$myvar" >> /tmp/myoutput.res
It generates a file /tmp/myoutput.res showing:
$ cat /tmp/myoutput.res
Now is Thu May 12 12:07:01 CEST 2016. myvar=hi man
Now is Thu May 12 12:08:01 CEST 2016. myvar=hi man
...
For me I had to set the environment variable for a php application. I resolved it by adding the following code to my crontab.
$ sudo crontab -e
crontab:
ENVIRONMENT_VAR=production
* * * * * /home/deploy/my_app/cron/cron.doSomethingWonderful.php
and inside doSomethingWonderful.php I could get the environment value with:
<?php
echo $_SERVER['ENVIRONMENT_VAR']; # => "production"
I hope this helps!
Instead of
0 * * * * sh /my/script.sh
Use bash -l -c
0 * * * * bash -l -c 'sh /my/script.sh'
You can also prepend your command with env to inject Environment variables like so:
0 * * * * env VARIABLE=VALUE /usr/bin/mycommand
Expanding on #Robert Brisita has just expand , also if you don't want to set up all the variables of the profile in the script, you can select the variables to export on the top of the script
In crontab -e file:
SHELL=/bin/bash
*/1 * * * * /Path/to/script/script.sh
In script.sh
#!/bin/bash
export JAVA_HOME=/path/to/jdk
some-other-command
I'm using Oh-my-zsh in my macbook so I've tried many things to get the crontab task runs but finally, my solution was prepending the .zshrc before the command to run.
*/30 * * * * . $HOME/.zshrc; node /path/for/my_script.js
This task runs every 30 minutes and uses .zshrc profile to execute my node command.
Don't forget to use the dot before the $HOME var.
I tried most of the provided solutions, but nothing worked at first. It turns out, though, that it wasn't the solutions that failed to work. Apparently, my ~/.bashrc file starts with the following block of code:
case $- in
*i*) ;;
*) return;;
esac
This basically is a case statement that checks the current set of options in the current shell to determine that the shell is running interactively.
If the shell happens to be running interactively, then it moves on to sourcing the ~/.bashrc file.
However, in a shell invoked by cron, the $- variable doesn't contain the i value which indicates interactivity.
Therefore, the ~/.bashrc file never gets sourced fully. As a result, the environment variables never got set.
If this happens to be your issue, feel free to comment out the block of code as follows and try again:
# case $- in
# *i*) ;;
# *) return;;
# esac
I hope this turns out useful
Unfortunately, crontabs have a very limited environment variables scope, thus you need to export them every time the corntab runs.
An easy approach would be the following example, suppose you've your env vars in a file called env, then:
* * * * * . ./env && /path/to_your/command
this part . ./env will export them and then they're used within the same scope of your command
Another way - inspired by this this answer - to "inject" variables is the following (fcron example):
%daily 00 12 \
set -a; \
. /path/to/file/containing/vars; \
set +a; \
/path/to/script/using/vars
From help set:
-a Mark variables which are modified or created for export.
Using + rather than - causes these flags to be turned off.
So everything in between set - and set + gets exported to env and is then available for other scripts, etc. Without using set the variables get sourced but live in set only.
Aside from that it's also useful to pass variables when a program requires a non-root account to run but you'd need some variables inside that other user's environment. Below is an example passing in nullmailer vars to format the e-mail header:
su -s /bin/bash -c "set -a; \
. /path/to/nullmailer-vars; \
set +a; \
/usr/sbin/logcheck" logcheck
All the above solutions work fine.
It will create issues when there are any special characters in your environment variable.
I have found the solution:
eval $(printenv | awk -F= '{print "export " "\""$1"\"""=""\""$2"\"" }' >> /etc/profile)
For me I had to specify path in my NodeJS file.
// did not work!!!!!
require('dotenv').config()
instead
// DID WORK!!
require('dotenv').config({ path: '/full/custom/path/to/your/.env' })
I found this issue while looking at a similar problem that matched the title, but I am stuck with the environment file syntax that systemd or docker use:
FOO=bar
BAZ=qux
This won't work for Vishal's excellent answer because they aren't bash scripts (note the lack of export).
The solution I've used is to read each line into xargs and export them before running the command:
0 5 * * * export $(xargs < $HOME/.env); /path/to/command/to/run
Set Globally env
sudo sh -c "echo MY_GLOBAL_ENV_TO_MY_CURRENT_DIR=$(pwd)" >> /etc/environment"
Add scheduled job to start a script
crontab -e
*/5 * * * * sh -c "$MY_GLOBAL_ENV_TO_MY_CURRENT_DIR/start.sh"
=)
what worked for me (debian based):
create a file with all the needed env var :
#!/bin/bash
env | grep VAR1= > /etc/environment
env | grep VAR2= >> /etc/environment
env | grep VAR3= >> /etc/environment
then build the crontab content, by calling the env file before calling the script that needs it, therefore start the cron service
(crontab -l ; echo '* * * * * . /etc/environment; /usr/local/bin/python /mycode.py >> /var/log/cron-1.log 2>&1') | crontab
service cron start
nb : for python use case, be sure to call the whole python path, else wrong python could be invocated, generating non-sense syntax error

How to execute a script using crontab

I'm trying to execute a particular script located in /logann/myFile through crontab file.
I've already tried a lot of ways but no one makes any results.
I add in crontab file this line to call my script
26 10 * * * root cd /logann && ./apagar_temp_tomcat
(The time I change to test)
And my script is
#!/bin/sh
rm /tmp/tomcat7-tomcat7-tmp/*.tmp
rm /tmp/tomcat7-tomcat7-tmp/*.xml
I just want to execute this script. This script will delete every .tmp/.xml files in the folder tomcat7-tomcat7-tmp.
Any ideas?
Thank you guys!
cron jobs will run in their own shell. So you can't expect to see tedvs on your console.
Try to write something in file, for example
* * * * * echo tedvs > file_in_your_directory.txt
Just make one function in file and call that file or function in cron as per your time interval.
I did this in PHP
shell_exec(\'(crontab -l ; echo "* * * * * curl www-data http://localhost/sp/delete.php") | crontab -\');

Cannot run tumblr-rb ruby script in bash script from crontab

I wrote the following bash script named /home/pi/test.sh (that uses the ruby gem "tumblr-rb"):
#!/bin/bash
echo "starting script"
/usr/local/bin/tumblr post /home/pi/test.jpg --host=myhost.tumblr.com --credentials=/home/pi/.tumblr
echo "end of script"
If I run it from the command line, I get:
starting script
Post was successfully created! Post ID: 82238814640
end of script
And my picture gets posted to Tumblr. Then if I put the bash script in my pi user's crontab with * * * * * /home/pi/test.sh, I get the following cron output e-mailed to me:
starting script
end of script
And nothing gets posted to Tumblr. Why does nothing happen?
Cron passes a minimal set of environment variables to your jobs.
You can use a simple shell to check the environment crontab provided:
* * * * * env > /home/pi/cron_env.dat
Try to add the full path of your ruby binary to execute the ruby script.
You can also set the PATH variable in the crontab file, which will apply to all cron jobs. e.g.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
* * * * * bash -c /home/pi/test.sh

cron job not working for xwindow

I have following line in crontab
*/1 * * * * xeyes
it does not show any xwindow but on the contrary
*/1 * * * * touch somefile.txt works fine
Tried to search on google but didnt get any specific answers!!
You have to tell cron where to find the X server if the command you run uses it.
So use: env DISPLAY=:0.0 xeyes or export DISPLAY=:0.0; xeyes.
Some cron implementations (Debian, Ubuntu, ...) allows to set enviroment simply in cron file.
DISPLAY=:0.0
# m h dom mon dow command
*/1 * * * * xeyes

Resources