Crontab Script File Syntax - shell

I am in a UNIX system administration course at school and have to generate a Cron job that does the following:
Queries the system each hour to find
out who is logged in.
Mails the result to my email account.
I know that the actual crontab will look like the following:
# Check to see who is logged in every hour.
MAILTO="me#email.com"
0 * * * * root /tmp/loggedin.sh
OR
# Check to see who is logged in every hour.
MAILTO="me#email.com"
#hourly /tmp/loggedin.sh
But I have been Googling for some time and have been unable to find any examples of what exactly the .sh file should look like. I know it starts with:
#!/bin/bash
# Shell script to see who is logged in, to be run every hour.
And I have no idea what else to put in there. Any help is greatly appreciated!

I think who should do the trick. It will show you a list of all the users that are logged in to the system at a time. You can write this to a file and then have it mailed to you.
w would get you what the people logged in are currently doing.
So, the script would look like:
#!/bin/sh
HOME=<your home directory>
who > ${HOME}/usersLoggedIn.txt
w > ${HOME}/whatLoggedInUsersAreDoing.txt
${HOME} refers to your home directory. On the command prompt, echo $HOME should give you your home directory. The output of the command who and w will get redirected to the files usersLoggedIn.txt and whattLoggedInUsersAreDoing.txt within your home directory. You can, of course, change the directory and file names to which you want this data to be written.
HTH,
Sriram

Any output from a cron job is mailed to the user. If you don't care about the subject line your cron entry is as simple as this:
#hourly w
If you do care about it,use mail(1):
#hourly w|mail -s'Users logged in' me#work.example.com

#!/bin/bash
# Shell script to see who is logged in, to be run every hour.
who | mail -s "Who is logged in `date`" "$MAILTO"

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!

Redirect crontab stdout to stdout instead of default email

By default crontab jobs stdout is sent to the email of the crontab user like the crontab file says in the description:
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
I want to use slacktee same as using (tee) to post a message to slack inside the script run by crontab.
In other scripts (daily scheduled by putting them in /etc/cron.daily/ directory) I do this:
echo "New message!" | slacktee -i "tada" -c "messages"
And when they run, there are no issues. But in my custom scheduled script I see no message on slack though they run correctly.
My job starts every four hours with this scheduling:
* */4 * * * /scripts/mysql_backup.sh
I've tried many redirecting (inside the script, inside the cron command) but anything seems working.
How can I use slacktee inside my custom sheduled script?
EDIT:
I'm a bit late sorry for that and thanks for all your time.
#PhilDenfer no, slacktee does not log anything on /tmp.
#Gedge i've tried sudo echo "test" | slacktee.sh and it works. Also using su and then doing echo "test" | slacktee.sh works.
#isp-zax cron jobs runs successfully because the script makes the backup of the database.
Redirecting the stderr I got slacktee.sh command not found. So using slacktee.hs as root works but not when root uses it in crontab scheduled job (in a daily scheduled script i use slacktee successfully). Why?
Redirecting the stderr I got slacktee.sh command not found. So using slacktee.hs as root works but not when root uses it in crontab scheduled job (in a daily scheduled script i use slacktee successfully). Why?
Because the PATH variable for user root and for user cron are different.
Instead of just 'slacktee' use a full path, i.e. /usr/local/bin/slacktee and it should work OK.

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.

Run a Bash Script automatically upon login

I wrote a script that sends the date and username of the person who logs in to a log file to keep a record of who has logged in. I am wondering how can you set this script to execute automatically when a user logs in rather than have to manually run it in the terminal. NOTE: the USERNAME is the current user that is logged in.
my code:
#!/bin/bash
printf "$(date) $HOSTNAME booted!\n" >> /home/USERNAME/boot.log
A more elegant way to solve this problem is to read from log files that are already being written and cannot be changed by the user. No one could say it better than Bjørne Malmanger's in his answer:
I wouldn't trust the user to GIVE you the information. As root you
TAKE it ;-)
A nice way to do this is the last command, which is great because it neatly displays all logins: Graphical, console and SSH.
last
A less elegant but still secure way is to do a grep on /var/log/auth.log. On my Gnome/Ubuntu system I can use this to track graphical logins:
grep "session opened for user USERNAME"
The right pattern for your machine needs to be found for each login type: graphical, console and SSH. This is cumbersome, but you might need to do it if you need information that goes further back than last reaches.
To directly answer your question:
You can modify the script like this to get the username
#!bin/bash
printf "$(date) $HOSTNAME booted!\n" >> /home/$(whoami)/boot.log
And add this line to /etc/profile
. /path/to/script.sh
This is not secure though because the user will be able to edit his own log
Why don't you use the last command?
I wouldn't trust the user to GIVE you the information. As root you TAKE it ;-)
Put it in ~/.bash_profile. It will be run each time they log in.
More information is available at the women's rights page (i.e. man bash).

Resources