Writing a Cron Job That Can Access User Data - bash

I'm trying to write a cron job that runs a report, and emails the result to an address defined in my user's ~/.bashrc file. I had this working perfectly on Fedora, but when I switched to Ubuntu, my solution no longer works. The command my cron job currently runs is:
. /home/myuser/.bashrc; /home/myuser/bin/runreport
If I run that command manually, or start it via Gnome-Schedule, it works perfectly, but it never seems to run. Is there something specific to Ubuntu that would be blocking this from running?
Output of crontab -l:
0 8 * * * . /home/myuser/.bashrc; /home/myuser/bin/runreport # JOB_ID_1
Output of grep -i cron /var/log/syslog:
Aug 4 08:00:00 localhost CRON[23234]: (myuser) CMD (. /home/myuser/.bashrc; /home/myuser/bin/runreport # JOB_ID_1)

If /home/myuser/bin/runreport is a script, add the following two lines to the top:
env
set -x
and change the crontab line to:
. /home/myuser/.bashrc ; /home/myuser/bin/runreport >/tmp/qq 2>&1
Then, when it runs, you should have all the environment variables, and the commands that were run, in the /tmp/qq file.
If it isn't a script, make a script that calls it and add the env line to it. That will at least give you the environment you're running in.

Related

Cron Job Running Shell Script to Run Python Not Working

As written in the title, I am having some problem with my cron job script not executing. I am using CentOS 7.
My crontab -e looks like this:
30 0 * * * /opt/abc/efg/cron_jobs.sh >> /opt/abc/logs/cron_jobs.log
My cron_jobs.sh looks like this:
#!/bin/bash
#keep this script in efg folder
#run this daily through crontab -e
#45 0 * * * /opt/abc/efg/cron_job.sh
cd "$(dirname "$0")"
export PYTHONPATH=$PYTHONPATH:`pwd`
#some daily jobs script for abc
date
#send email to users whose keys will expire 7 days later
/usr/local/bin/python2.7 scripts/send_expiration_reminder.py -d 7
#send email to key owners whos keys will expire
/usr/local/bin/python2.7 scripts/send_expiration_reminder.py -d -1
# review user follow status daily task
# Need to use venv due to some library dependencies
/opt/abc/virtualenv/bin/python2.7 scripts/review_user_status.py
So, what I've found is that the log for the cron jobs in /var/logs/cron states that the cron ran at 0:30 am accordingly.
Strangely, I find that /opt/abc/logs/cron_jobs.log empty, and the scripts does not seem to run at all. It used to output some log before I re-inputted the crontab (to re-install the cron jobs), and replaced cron_jobs.sh, so I think the problem might have arose from those actions.
And also, I would like to know if there are any ways to log the error from executing a python script. I have been trying to run /opt/abc/virtualenv/bin/python2.7 scripts/review_user_status.py but it never seem to work as intended (does not run the main function at all), and there is no log output whatsoever.
I tried to run this on a different machine and it works properly, so I am not sure what is wrong with the cron job.
Here is a snippet of the log I got from /var/log/cron to show that the cron called the job:
Mar 22 18:32:01 web41 CROND[20252]: (root) CMD (/opt/abc/efg/cron_jobs.sh >> /opt/abc/logs/cron_jobs.log)
There are a few areas to check if you haven't performed these already,
if your executable permissions set on the script,
chmod +x <python file>
in addition permissions for the user to access the directories.
Run the script manually to test the script works from beginning to end, as the user who will be running the script, will be more realistic.
You can test your crontab schedule by temporarily setting every minute for testing, unlike Windows where you can right, click and click Run.
First, thank you all for the suggestions and heads up. I found out that what was ruining my script is the existence of /r in the line break. Apparently, Linux in general does not accept /r and only accepts /n.
It is because I ftp my files to the machine where the script breaks. On the other hand, it works fine on another machine because I used git pull instead of ftp.
Hope that this info will also be a helpful to others!

Cron job does not run

Following is the entry in the crontab:
MAILTO=abc#gmail.com
45 14 * * * /home/user/simple.sh
I've also done chmod +x on the simple.sh But the crontab does not run, it doesn't even send an email.
pgrep cron shows an Id. I also tried bouncing crond. But no luck!
Could someone please point out the mistake here
The simple.sh script is:
#! /bin/bash
echo hello
Thanks
Since you are doing a echo within the cron job script, you need to capture its output somewhere.
Your shebang and file mode (using chmod +x) are all right, so those aren't the issue here and running without /bin/sh should work fine.
Try using the following to see the output in cron.log file (This runs every minute)
* * * * * /home/user/simple.sh >> /home/user/cron.log
Note that cron jobs run in separate subprocess shell, with reduced environment, so its output won't be visible on your terminal.
Regarding sending of email - you need to have some mail package (like postman, mutt etc) configured for the cron daemon to send out error mails.
Do not use relative paths, but absolute ones. Also, indicate the binary running the script, that is /bin/sh (or whatever coming from which sh):
45 14 * * * /bin/sh /path/to/script/simple.sh
Maybe there shouldn't be a space in line 1 of your .sh script:
#! /bin/bash
to
#!/bin/bash
Although I could see why it would still seem to work from when invoked in an interactive shell (# could merely comment out the rest of the line).
Still, I'd guess at worst it'd merely ignore that line and inherit cron's interpreter of /bin/sh

Crontab not executing bash script

I very very rarely use Linux and so don't have any experience with bash scripts and cron jobs.
This is in fact my first attempt. So it's probably something really simple to fix.
I have the following:
/etc/cron.d/clear-mixtape-dir.sh
permissions are: 644
#!/bin/bash
# Clears the /tmp/mixtape2 directory
rm -rf "/tmp/mixtape2/"*
My crontab file looks like so:
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/
*/15 * * * * /etc/cron.d/clear-mixtape-dir.sh >/dev/null 2>&1
I'm trying to execute the .sh script every 15 minutes.
Everything i've found says this should work, but it doesn't.
Does anything like file permissions (on files within /tmp/mixtape2/) matter in this case?
Or perhaps the permissions set on the actual .sh script - maybe they need setting to executable?
Any advice appreciated.
Remove the .sh extension from the script in /etc/cron.d and it will be called.
run-parts ignores files with a period in the name, so the .sh extension is preventing your script from running.
From man cron -
Files must conform to the same naming convention as used by run-parts(8): they must consist solely of upper- and lower-case letters, digits, underscores, and hyphens.
Note: These comments refer to /etc/crontab.
Before doing anything else, which cron are you accessing crontab -e or
su -vim
<your-favorite-editor> /etc/crontab
If you are using crontab -e, then no user field exists in that form of crontab. That might be why you're not running.
In your example, your user field is *. I would make it root or a user that has proper permissions.
Before running this program, I would make a dummy crontab entry that just does
echo "Hello" and runs every minute. Get that to work on which ever crontab you're editing (crontab -e or vim /etc/crontab). Then using that as a template, get your script to run.
Next, see if cron is running:
ps -ef | grep cron
If it is not running, become root and start it by enter
/etc/init.d/cron start (Ubuntu and Red Hat).
You already have a good answer suggesting you add root as the user because of a permissions problem. I'm going to suggest more things to help you debug. I have run into a lot of cron problems over the years.
1) Set the email to a known address, unless you will continually monitor root's email
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/local/bin:/usr/bin
MAILTO=fred#somewhere.com
HOME=/
2) Until everything runs properly, take out the >/dev/null 2>&1 out of your cron entry, so you see the outputs in your email generated after the script runs.
3) Bump */15 down to an interval greater than it takes your script to run -- likr */5, so the script runs more often.
4) I do not know the exact reason, but scripts I run out of cron have to set up their own environments despite being run as that user in cron. This may include steps like cd /home/script-owner and running source .bashrc and calling other script(s) that set environment variables.
*/15 * * * * root /etc/cron.d/clear-mixtape-dir.sh >/dev/null 2>&1
Add user root because your permission seems to be only for root.

Bash Script with Crontab

I'm trying to setup a crontab I have this in my current job in the current user I'm logged into
* * * * * /CS/day/get_info.sh
get_info.sh is supposed to output a text file every minute and I suspected that it would output a file in the same directory as the script is located but it doesn't.
I've also checked the syslogs to see if I could figure this out.
(user) CMD (/CS/day/get_info.sh)
(user) MAIL (mailed 46 bytes of output but got status 0x0001#012)
Can someone explain to me why this is happening?
Thanks
man cron tells you:
When executing commands, any output is mailed to the owner of the
crontab (or to the user named in the MAILTO environment variable in the
crontab, if such exists). The children copies of cron running these
processes have their name coerced to uppercase, as will be seen in the
syslog and ps output.
So you have to
cd into the appropriate directory yourself (cron will use $HOME)
redirect ANY output to a file of your choice
You can do both things in the crontab. But I recommend to do it in the first lines of the script itself:
#!/bin/bash
cd WHEREEVER_YOU_WANT
exec > YOUR_LOG_FILE 2&>1
The script is run in the home directory of the user and the file should be there as well. If you want it in the same directory as the script, either do a cd in your script or modify your crontab entry:
*/1 19-20 * * * cd /CS/day; /CS/day/get_info.sh
Another common problem with crontab entries is the environment. If the script works correctly in your terminal, try debugging it, when it is run from cron:
40 11 * * * bash -x /CS/day/get_info.sh >/tmp/get_info.sh.log 2>&1
Run it once only with current time, because otherwise you will overwrite your log file every minute.
On my case, I just had to install and configure an smtp client.

Cron job terminates early

In my crontab file I execute a script like so (I edit the crontab using sudo crontab -e):
01 * * * * bash /etc/m/start.sh
The script runs some other scripts like so:
sudo bash -c "/etc/m/abc.sh --option=1" &
sleep 2
sudo bash -c "/etc/m/abc.sh --option=2" &
When cron runs the script start.sh, I do ps aux | grep abc.sh and I see the abc.sh script running.
After a couple of seconds, the script is no longer running, even though abc.sh should take hours to finish.
If I do sudo bash /etc/m/start.sh & from the command line, everything works fine (the abc.sh scripts run for hours in the background until they complete).
How do I debug this?
Is there something I'm doing that is preventing these scripts from running in the background until they are done?
The program(s) you're starting might be expecting a terminal to send their output to, or receive input from.
If you set the MAILTO= variable, and you have a sendmail(-like) daemon installed, you will get an email with the error message(s) it prints, if there are any:
MAILTO=your#email.address.here.com
01 * * * * bash /path/to/something.sh
Another way to debug would be to run the script from the command line, while redirecting all inputs and outputs:
$ sudo bash -c "foo.sh" > output_file 2>&1 < /dev/null
Also, the system log files (usually found in /var/log) might contain useful hints.

Resources