LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 09-01-2015, 02:10 PM   #1
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 870

Rep: Reputation: 43
script paths for cron job


Ladies & Gents

I am developing a script to periodically check the external ip of a server, dhcp from my isp, and email it to me if it has changed. I want this to run as a cron job. My question is if the paths I have set as variables should be changed to something else.

Code:
#/bin/bash
#set -x

# email address which is receiving the email
receiver="yourEmail@what-ever.com"

# email subject
subject="$RANDOM"

# random bs for payload
payload="$HOME/payload"

# file to save previous ip address
oldip="$HOME/.ip.address"

# temp file for email
tmpemail="$HOME/tmp/ip.mail"
tmpemail2="$HOME/tmp/ip.mail.gpg"

touch $oldip
rm -f $tmpemail
rm -f $tmpemail2
ipaddress=$(curl -s http://checkip.dyndns.org | sed 's/[a-zA-Z/<> :]//g')
ipaddress2=$(cat $oldip)
echo "Is: $ipaddress" >> $tmpemail
echo "Was: $ipaddress2" >> $tmpemail
if [ "$ipaddress" != "$ipaddress2" ]
	then echo "There different!"
	gpg --yes --batch --passphrase=[SomeRandomPassword] -c $tmpemail
	mutt -s "$RANDOM`date`" -a "$tmpemail2" -- $receiver < $payload
	rm -f $oldip
	echo $ipaddress >> $oldip
fi
I am not sure that I like the paths myself because I am not sure the temp files are being stored in a secure place. I don't know where $HOME will point from the cron job. And even though the script does not really need root permissions I think it will run as root and I want to keep the info secure.
 
Old 09-01-2015, 02:20 PM   #2
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,258

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
$HOME will point to the user's home directory.

Quote:
Originally Posted by rbees
And even though the script does not really need root permissions I think it will run as root and I want to keep the info secure.
Then why run it as root? Each user has its own crontab, put it in one of those.

You should also check the paths to your executables - curl, gpg, mutt, etc. Make sure they're in the PATH you get from cron. If not, then either add their location to the PATH at the top of your script or use the absolute path to them.
 
Old 09-01-2015, 02:31 PM   #3
michaelk
Moderator
 
Registered: Aug 2002
Posts: 14,930

Rep: Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520
A user cronjob does not run as root. To see the difference between the cron and the regular environment create a cronjob like:

* * * * * env > /home/username/env_output.txt

Just because the standard environment is limited does not mean it can not be changed in the script. You want to keep your public IP address secure from whom?
 
Old 09-01-2015, 02:36 PM   #4
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 870

Original Poster
Rep: Reputation: 43
Thanks suicidaleggroll

There are only two users on the machine, the non root account is more likely to be access by someone that is not me. If i use root then the script and data files are less likely to be seen by someone that shouldn't see them.

So I gather that if I scp the script to the machine and into /root, provided that the commands work correctly from cron, have seen some posts that indicate that it may not, I should be as secure as I can get with it.
 
Old 09-01-2015, 02:45 PM   #5
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 870

Original Poster
Rep: Reputation: 43
Thanks michaelk

Quote:
You want to keep your public IP address secure from whom?
I am actually more concerned about the actual email than the server. I this case the email has to go through my isp, who can read it, then gmail ,who can read it, then verison, who can read it. And who knows how many other hops to get from my server to my phone. Not than "security through obscurity" is good security but why make it any easier for someone to get my external ip than necessary. That is why the script encrypts the email payload.

But should someone happen to actually get in the machine via the normal user account I would rather they just not be able to get the email address the ip is sent to or the passcode to unlock the encrypted file.
 
Old 09-01-2015, 02:58 PM   #6
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,258

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
Your public IP is going to be in the email header anyway...in fact you don't even need to send the IP in the email, encrypted or not, just send a blank email and parse the header and you'll get the hostname and public IP from where it was sent.

Last edited by suicidaleggroll; 09-01-2015 at 03:02 PM.
 
Old 09-01-2015, 04:32 PM   #7
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 870

Original Poster
Rep: Reputation: 43
Quote:
just send a blank email and parse the header and you'll get the hostname and public IP from where it was sent.
Guess I knew that, just never made the connection before. Still I think I will stay with the script because I want to add some other info that is not publicly available to the email. Besides there is the "look what I setup" to impress the wife with. Not that it will get me any bonus points, but ya gota try something.

Aside from all that, does the script look good? Or could it be more efficient?

Thanks
 
Old 09-01-2015, 04:39 PM   #8
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,258

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
Seems straight forward enough. A couple of things I would change:

1) Change tmpemail2 from "$HOME/tmp/ip.mail.gpg" to "${tmpemail}.gpg". That way you only have to change the name once in the future, instead of having to change two variables to the same thing plus the extension that gpg will add. Or just remove tmpemail2 and have mutt attach ${tmpemail}.gpg directly.

2) Change "rm -f $oldip; echo $ipaddress >> $oldip" to "echo $ipaddress > $oldip". The single arrow will overwrite the contents. You can do the same with "echo Is: $ipaddress > $tmpemail" as well.

You should also add a catch for curl and/or mutt failing (internet down or similar). If curl can't go through you don't want the new IP to be set to an empty string which gets propagated through the rest of the program. If mutt can't go through, then leave the old IP in place so the next time it runs it will send the email again, otherwise the email with the update will be lost forever.

Last edited by suicidaleggroll; 09-01-2015 at 04:43 PM.
 
Old 09-01-2015, 05:19 PM   #9
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 870

Original Poster
Rep: Reputation: 43
Thanks

My grade school scripting experience has never required me to add a "catch for fail" before. But a little googling brought me to http://superuser.com/questions/74240...if-curl-failed

So I added "set -e" which if I understand correctly will just cause the script to exit if either curl or mutt fail, there by leaving the data intact.

I had thought to cron the script hourly even though the ip seldom changes as I am on a cable modem. I would think that if I went looking historically my ip would be mostly the same over the last several years as it changes so seldom. So I though hourly would be often enough to catch the change in a reasonable amount of time should I need access with out have to wait to long.

I have never set up a cron from the command line before, and only once from webmin. Do you know of a good how-to for debian testing?

Last edited by rbees; 09-01-2015 at 05:21 PM.
 
Old 09-01-2015, 05:54 PM   #10
michaelk
Moderator
 
Registered: Aug 2002
Posts: 14,930

Rep: Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520Reputation: 1520
To add/edit a cronjob the command is crontab -e

Lots of help can be found on the web for adding a cronjob. Most distributions use vixiecron so the syntax is the same but the only difference could be the default text editor.
 
Old 09-01-2015, 06:00 PM   #11
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,258

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
Pick an editor, set the environment variable EDITOR for it:
Code:
export EDITOR=vi
or similar, then run "crontab -e" as the user you want to run the script.

First 5 columns are the schedule, use "0 * * * *" to run it every hour on the hour. The 6th column is the command to run, and you should probably redirect the output to a log file, at least until you know it's working and can then move the redirect to /dev/null.

Code:
0 * * * * /home/user/ip_check.sh &> /home/user/ip_check.out &
I have run into a cron bug in the past where the last entry wouldn't be executed if there wasn't a blank line after it, so as a matter of habit I always put a blank line after the last entry.
 
Old 09-01-2015, 06:04 PM   #12
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,258

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
Quote:
Originally Posted by rbees View Post
Thanks

My grade school scripting experience has never required me to add a "catch for fail" before. But a little googling brought me to http://superuser.com/questions/74240...if-curl-failed

So I added "set -e" which if I understand correctly will just cause the script to exit if either curl or mutt fail, there by leaving the data intact.
Never used "set -e", I usually just watch for exit codes, eg:
Code:
var=$(curl -s http://checkip.dyndns.org)
errstat=$?
if [[ $errstat -ne 0 ]]; then
   echo "curl exited with error code $errstat"
   exit 1
fi
ipaddress=$(echo $var | sed 's/[a-zA-Z/<> :]//g')
and so on.

"set -e" could be promising, but a lot of commands can throw a non-zero exit status without there actually being anything wrong (at least not wrong enough to warrant killing the script), so it might be more headache than it's worth.
 
Old 09-01-2015, 08:20 PM   #13
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 870

Original Poster
Rep: Reputation: 43
Thanks michaelk && suicidaleggroll

I have reworked the script following your advice. I am not sure about the fail/exit lines for gpg and mutt, I made my best guess following your example. I am hoping the "set -e" will work correctly as I think it will be slightly more efficient.

Code:
#/bin/bash

# Script to get the users external ip, encrypt it and email it as an 
# attachment to someone. Would be a simple matter to add other data 
# to the email attachment before it is encrypted. Making it possible
# to send senitive data via this script.

# make script exit on error to preserve data
set -e

# for cron do "crontab -e" as user and add
#  0 * * * * /path/to/script &> /home/user/ip_check.out &
# don't for get to keep a new-line at the end!

# email address which is receiving the email
receiver="yourEmail@what-ever.com"

# email subject
subject="$RANDOM"

# random bs for the payload
payload="$HOME/payload"

# file to save previous ip address
oldip="$HOME/.ip.address"

# temp file for email
tmpemail="$HOME/tmp/ip.mail"

touch $oldip
rm -f $tmpemail
rm -f $tmpemail2

##########################################333
# # enable this section if "set -e" above does not work as expected
# var=$(curl -s http://checkip.dyndns.org)
# errstat=$?
# if [[ $errstat -ne 0 ]]; then
#    echo "curl exited with error code $errstat"
#    exit 1
# fi
# ipaddress=$(echo $var | sed 's/[a-zA-Z/<> :]//g')

# disable this section if "set -e" above does not wark as expected
ipaddress=$(curl -s http://checkip.dyndns.org | sed 's/[a-zA-Z/<> :]//g')
########################################

ipaddress2=$(cat $oldip)
echo "Is: $ipaddress" > $tmpemail
echo "Was: $ipaddress2" >> $tmpemail
if [ "$ipaddress" != "$ipaddress2" ];then
	sed -i 1i There different $tmpemail
	echo "There different!"

	#############################################################
	# # enable this section if "set -e" above does not work as expected
	# var2=$(gpg --yes --batch --passphrase=[SomeRandomPassword] -c $tmpemail)
	# errstat2=$?
	# if [[ $errstat2 -ne 0 ]]; then
	#    echo "gpg exited with error code $errstat2"
	#    exit 1
	# fi

	# disable this section if "set -e" above does not wark as expected
	gpg --yes --batch --passphrase=[SomeRandomPassword] -c $tmpemail

	# # enable this section if "set -e" above does not work as expected
	# var3=$(mutt -s "$RANDOM`date`" -a "${tmpemail}.gpg" -- $receiver < $payload)
	# errstat3=$?
	# if [[ $errstat3 -ne 0 ]]; then
	#    echo "mutt exited with error code $errstat3"
	#    exit 1
	# fi

	# disable this section if "set -e" above does not wark as expected
	mutt -s "$RANDOM`date`" -a "${tmpemail}.gpg" -- $receiver < $payload
	#########################################################
	
	echo $ipaddress > $oldip
fi
 
Old 09-01-2015, 08:33 PM   #14
suicidaleggroll
LQ Guru
 
Registered: Nov 2010
Location: Colorado
Distribution: OpenSUSE, CentOS
Posts: 5,258

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
The var=$(command) business was just for the curl, since $? only grabs the exit code from the most recent command, which in the case of the curl line is your sed parsing. In order to get the exit code of curl you have to remove the pipe and split it up, otherwise you'd just get the exit code from sed.

Your gpg and mutt commands are stand-alone, so you don't need it. $? will happily grab their exit codes without having to redirect their output to a temporary variable. And if you don't want to print the exit code like I have in those if blocks, you can skip the "errstat=$?" line and just directly check $?:
Code:
command
if [[ $? -ne 0 ]]; then
   echo "command exited with a non-zero status"
   exit 1
fi
The advantage of using this over "set -e" is you may find one or more commands will give a non-zero exit status without there actually being a critical failure. For example rsync will throw out a non-zero status for all sorts of things, including not being able to set ACL permissions or timestamp a file properly, but most of them aren't that critical. With "set -e" you're kind of stuck, but by checking the status by hand you can do something like:
Code:
rsync -av source dest
errstat=$?
if [[ $errstat -ne 0 && $errstat -ne 12 && $errstat -ne 23 ]]; then
   echo "rsync exited with status: $errstat"
   exit 1
fi
Either way, if you want to test your error handling, just unplug your ethernet cable and run your script, see what happens at the curl. Then plug the cable back in, stick a big sleep in between the curl and the mutt, run it again, and during the sleep unplug your ethernet cable, see what happens at the mutt.

Last edited by suicidaleggroll; 09-01-2015 at 08:39 PM.
 
Old 09-01-2015, 09:20 PM   #15
rbees
Member
 
Registered: Mar 2004
Location: northern michigan usa
Distribution: Debian Squeeze, Whezzy, Jessie
Posts: 870

Original Poster
Rep: Reputation: 43
Thanks sucidaleggroll

Quote:
The var=$(command) business was just for the curl
I figured as much, that is why I did it the way I had it, just was no sure the variable was needed or that a further command was needed. Thanks for the clarification.

If there are no other issues that I should address I will make these changes and push the files to the server and start the debugging process. If I was good at following your teachings then I won't be bugging you any more about this script.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Help with Script and Cron Job to e-mail df - h knewtolinux Linux - Newbie 9 02-14-2008 07:48 PM
adding a perl script to cron.daily / cron.d to setup a cron job CrontabNewBIE Linux - Software 6 01-14-2008 09:16 AM
Bash script and cron job rust8y Linux - General 2 07-08-2006 08:45 AM
Cron Job with a Script bravored Linux - General 4 08-05-2005 11:27 AM
cron job for expect script ruchitadesai Programming 9 05-27-2005 05:34 AM


All times are GMT -5. The time now is 12:14 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration