Bash Script with Crontab - bash

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.

Related

Shell script doesn't run properly while running from crontab

I read the other related topics but they didn't help me.
I have a shell script which checks if my python script is not running,it will run it. Otherwise it will just skip and do nothing.
It totally works when I use:
bash myshellscrip.sh
And I get the result that I want which is doing some tasks and sending emails to some correspondents. However, when I try to run this particular shell script on crontab, it doesn't send out the emails and doesn't do the other tasks.
I tried the following on crontab and none of them worked.
* * * * * /bin/bash /path/to/my/script/myshellscrip.sh
* * * * * /bin/bash /path/to/my/script/myshellscrip.sh >> /some/other/path/output.txt
When I save the changes into 'output.txt' file, it creates the file but it doesn't send the emails or doing other tasks.
I also tried the option of reboot because I need this program to run at start up too, and this didn't work:
#reboot /bin/bash /path/to/my/script/myshellscrip.sh
Does anyone know how to fix it?
EDIT:
As I was checking with the simplest shell scrip like:
#!/bin/sh
/usr/bin/python /home/pi/DCA/code.py
My crontab wouldn't have any output in my output.txt file although my code.py have something printing out, too.
However, when I use a very simple python code for example only a 'print' statement it will run and save the output into output.txt.
Seems like your shell script crashes / stops before it can do something (possibly due to the environment being different or permission issues). You can check /var/log/syslog to find out.
You could try removing /bin/bash, I don't think that's necessary?
Run the cron job in debug mode. for that, Add -x to the bash command on the cronjob and save their output in the file.
bash -x /path/to/script.sh >> /path/to/the/output.txt
You can find the problem.
Apparently crontab was running my script several times. So I tried to use different locking mechanisms to put a lock around my scrip but only using flock worked for me. In my crontab I added this line:
* * * * * /usr/bin/flock -n /tmp/ms.lockfile /bin/bash /path/to/my/script/myShellScript.sh

"getpwnam() failed" in /bin/sh only when called from cron

Here's the content of my crontab file:
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO="example#example.com"
*/5 * * * * sh /robot/1/master.sh >/dev/null 2>&1
*/5 * * * * sh /robot/2/master.sh >/dev/null 2>&1
*/5 * * * * sh /robot/3/master.sh
*/5 * * * * sh /robot/4/master.sh >/dev/null 2>&1
*/5 * * * * sh /robot/5/master.sh >/dev/null 2>&1
This is the error that keeps showing in /var/log/cron when it tries to run:
crond[669]: (sh) ERROR (getpwnam() failed)
If I run any of these files manually, they work without any issues.
What's wrong with the crontab file?
It surprises me that nobody has the correct answer to this. Today i faced exactly the same problem and google didn't help.
After 2 hours i found that when placing a file in /etc/cron.d the schedule line has to contain an extra option.....
I allways use this for my crontab -e
# Minute Hour Day of Month Month Day of Week Command
# (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat) /my/fancy/script.sh
So it contains 6 items.
When placing this in a file inside /etc/cron.d the cron needs an extra option, being the user to run your fancy/script.
# Minute Hour Day of Month Month Day of Week Who Command
# (0-59) (0-23) (1-31) (1-12 or Jan-Dec) (0-6 or Sun-Sat) root /my/fancy/script.sh
This is documented in man crontab(5). For example https://linux.die.net/man/5/crontab . It says:
Jobs in /etc/cron.d/
The jobs in cron.d are system jobs, which are used usually for more than one user. That's the reason why is name of the user needed. MAILTO on the first line is optional.
The sixth position is reserved for username running the job. You specified a user called sh which is most probably not present on the machine.
simple answer
on your crontab you need to specify the USER to run the command
example to run as ROOT is:-
0,10,20,30,40,50 * * * * root /path_to_script/script_name
or to run as user FRED
0,10,20,30,40,50 * * * * fred /path_to_script/script_name
default with no USER specified is to run as user CRON and that user would not have permissions to execute the script
We can create cron jobs for system as well for individuals. The crontab in /etc/crontab specifically used for system cronjobs. So you need to specify the cronjob command executed by whom. In the question the username not specified. Hence the ERROR (getpwnam() failed) occurs. You can create user specific cronjobs in /var/spool/cron/username
NOTE:: Cron jobs are very useful but disastrous on failures!
Nothing is wrong with the crontab file (so long as by "my" crontab, you mean that it's a user crontab rather than a system crontab; otherwise, see other answer).
On the other hand, something is wrong with your system's directory service -- as configured, in Linux, with nsswitch.conf. Perhaps you're using a Kerberos-authenticated LDAP store, and your cron daemon doesn't have a Kerberos token to connect to it (or is sandboxed, as with SELinux, not to have network access); perhaps it's a file store that isn't readable by the user whose crontab is being run; perhaps some other odd and interesting thing is going on.
getpwnam() is a C library call that performs a lookup for the name of the currently-logged-in user. If your shell were bash, it would fall back to a name of I have no name! -- so this error means your sh implementation is something different. (If you want to run your scripts with bash, use bash, not sh).

cron job not running with adding "2>&1"

I am setting up a cron job using crontab -e on a machine where I do not have a root privilege.
The initial command in crontab is like this:
0 10 * * * /bin/bash /path/myscript.sh >/path/log
I found the script did not run, since the system created an empty log file. Then I add 2>&1 at the end of the above command:
0 10 * * * /bin/bash /path/myscript.sh >/path/log 2>&1
And try to find errors of whatsoever. Strangely, with adding the 2>&1, cron did not even create an empty log file. Nothing.
Any idea on what's going on here when adding the 2>&1?
The default behaviour of cron is to send stderr via email to the user running the cronjob.
From man cron:
When executing commands, any output is mailed to the owner of the
crontab (or to the user specified in the MAILTO environment
variable in the crontab, if such exists).
To circunvent this behaviour, you can indeed redirect the stderr like you are trying. However, it needs some extra tuning.
As seen in Redirect stderr with date to log file from Cron, you can use a subshell to redirect stderr to stdin and then redirect everything normally: (cron expression 2>&1) > /your/log/file. In your case:
0 10 * * * (/bin/bash /path/myscript.sh 2>&1) >/path/log

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.

Resources