Showing posts with label shell script. Show all posts
Showing posts with label shell script. Show all posts

Thursday, February 28, 2008

command line email in Cygwin

As mailx is not part of the Cygwin distribution, you don't have that many choices if you want to send an email from a shell script. In this regard, Jeremy Reed has kindly provided a nice substitute script that can help us out:
http://cygwin.com/ml/cygwin/2005-02/msg00635.html

If you have Cygwin installed, you'll need to do the following things:
1) install ssmtp
2) configure ssmtp with ssmtp-config
3) install Jeremy's mailx shell programs

There are a couple of gotchas with step 2 above.
1) make sure you have the directory /etc/ssmtp created
- for some reason, the ssmtp-config program doesn't create it
2) make sure you define a fully qualified hostname
- if not, you'll get the following error
$ /usr/bin/mailx -s "test" cacasododom@gmail.com < test.txt
3) make sure that you have a symbolic link created for /usr/sbin/sendmail that links to /usr/sbin/ssmtp and that /usr/sbin is in your PATH. Otherwise, you'll get this error:
$ mailx.sh -s "test" joe.user@yahoo.com < test.txt

That's it.

I preferred to use Jeremy's program over nail, because it gives me the same arguments as mailx did.

Thanks Jeremy!
TAG

Wednesday, February 06, 2008

upgrading Cygwin: dos2unix

I recently converted from a very old version of Cygwin Beta 20 (circa 1999) to the latest 1.5.25-7 version of the Cygwin DLL. I noticed when I tried to execute some of my existing scripts that had executed under the old beta version, I now would receive a lot of these errors:
./script.sh: line 40: $'\r': command not found
or
./script.sh: line 5: syntax error near unexpected token `$'do\r''

Looks to me like the command interpreter on the new version of Cygwin is a lot more picky than the old one. Specifically, Cygwin is choking on the carriage returns that Windows XP Notepad inserts at the end of each line of the file. Yuk.

I wondered if this was something configurable with an environment variable (http://www.cygwin.com/cygwin-ug-net/setup-env.html), so I first tried setting the CYGWIN environment variable to nobinmode (http://www.cygwin.com/cygwin-ug-net/using-cygwinenv.html). Unfortunately, this change had no effect. I did find a bit of background here:
http://cygwin.com/faq/faq-nochunks.html#faq.api.cr-lf

I had a bit more success using one of the nice little utilities Cygwin has called "dos2unix". Dos2Unix strips out any carriage return or line feed characters in text files and automatically saves the file. The command is simple:
dos2unix [filename]

where [filename] is the name of the file you wish to convert. Dos2Unix has no man page, so don't bother looking for it.

Unfortunately, I had quite a few scripts in various directories, so I just went through each directory and typed:
dos2unix *.sh

I could have written a script to interate through the directories, but there were only about fifteen, so I got lazy and just ran the command manually. After running the command, I was able to execute the scripts without error.

Nice!
Cacasodo

Monday, August 13, 2007

scripted gnuplot graphs

One of my many tasks as a webmaster is to monitor the traffic to and from our web servers. As a follow up to my quick start guide to gnuplot: /2007/07/quick-start-guide-to-gnuplot-plotting.html
I will expand upon that posts' themes and give you a simple script that will output a nice PNG graphic of a data set without having to use gnuplot interactively.

As in the previous post, my goal is to plot HTTP connections. I want the script to generate the graph for the previous days' activity. Should be simple enough!

As review, my data file looks like this:
20070727151200 215 210 5
20070727151259 191 186 5
20070727151401 207 201 6
20070727151500 186 180 6
20070727151600 165 156 9
20070727151700 167 161 6
20070727151801 182 174 8
20070727151900 197 190 7
20070727152001 197 191 6
20070727152100 187 181 6

* The first column is date/time stamp.
* The second column is total HTTP connections.
* The third column is HTTP connections from the client browser to the cache.
* The last column is HTTP connections back to the origin server.

Here is the script:
!#/bin/bash
TITLE="Caching server HTTP connections"
TODAY="`date +%Y%m%d`000000"
YESTERDAY="`date +%Y%m%d --date="-1 day"`000000"
YMAX=350

gnuplot -noraise <<-finis


set xdata time
set timefmt "%Y%m%d%H%M%S"
set yrange [0:$YMAX]
set ytics 50
set bmargin 3
set grid xtics mxtics ytics
set title "$TITLE"
set xrange ["$YESTERDAY":"$TODAY"]
set term png medium
set output "webconn.png"
plot 'webconn.txt' using 1:3
title "HTTP_WEB" with lines,\
'webconn.txt' using 1:4 title "HTTP_OWS" with lines
finis

You can see I have a few constants up top that set a title and the date range. Note the neat little "date -1" trick in the date command for the YESTERDAY constant. That has come in handy more than once!

I then set a maximum value for the Y axis.

Using the -noraise switch tells gnuplot to not raise the graph window. Next, I use the input redirector (<<) to feed in parameters to gnuplot. The "-finis" is simply a label to the input that I call at the beginning and the end of my input. I then feed in as many parameters as I need. When I am done, I just call "finis" without the hyphen and this turns off the input.

You can see I feed in a lot of the parameters that I had to manually enter during the last post regarding interactive gnuplot. I've thrown a few more in with this example:

set yrange sets the maximum range of the y axis
set ytics sets the spacing of the bars in the y axis
set bmargin sets the spacing of the bottom margin in pixels
set grid xtics mxtics ytics sets your grid preferences
set term sets the output type; in this case, a medium sized png graphic
set output specifies the name of the file

The rest of the commands you already know from my first post on the subject. At the end of all the parameters I set, I make sure to close the input by entering the keyword "finis" that I defined at the beginning of the input redirection. You can use any non-shell script word for the keyword. I just chose "finis" because it means "The End" and has no other special meaning to the Unix shell.

Finally, here is the lovely output:


Hope you liked it!
'sodo

Thursday, July 19, 2007

why doesn't my shell script run under cron?

OK! Today's lesson is that using absolute paths to point to executables and the PATH statement in bash shell scripts are VERY important in allowing your shell script to run properly in cron!

Absolute Paths
For example, here is the start of a typical script that shuts down a service:
#!/bin/bash
echo "Stopping web server.."

service httpd stop

Well, the bad part of this script is that is does not reference the full, absolute path to the service command. To fix this, make sure the full path is identified as in the sample code below:
#!/bin/bash
echo "Stopping web server.."

/sbin/service httpd stop

PATH Statement
If you start a Cygwin bash script using an NT command script like so:
PATH=c:\winnt\system32;c:\cygwin\bin;
SET CYGWIN=ntsec
cd \scheduledTasks\500errors
bash -v "500errors.sh" 2>&1 log.txt


Your PATH statement may interfere with the running of your bash script. In my case, you can see I list c:\winnt\system32 first in my PATH. When the above script encountered a "sort" statement, the "sort" command that was used was the Windows sort command and NOT the Cygwin "sort". So, I got strange errors when I ran the script.

To reiterate, depending on the order of the directories in your PATH, sometimes a Windows executable will be chosen before the Cygwin executable. The "sort" and "head" commands are famous for doing this. So make sure the Cygwin bin directory is the first one listed in your PATH, like in the corrected version listed below:
PATH=c:\cygwin\bin;c:\winnt\system32;
SET CYGWIN=ntsec
cd \scheduledTasks\500errors
bash -v "500errors.sh" 2>&1 log.txt

Troubleshooting
When in doubt, do the following:
1) first, execute the bash script as your local user
2) if this works and you are starting the bash script from an NT script, execute the NT command or bat script to see if the script completes successfully
3) use Cygwin's own cron to kickoff the script. But that has issues of its own:
/2008/01/setting-up-cron-in-cygwin-on-xp.html

In cases where the Cygwin bash script is not working:
1) turn up debugging by using the -v switch to bash:
bash -v "script.sh"
2) write standard error and standard output to a file:
bash -v "script.sh" 2>&1 log.txt
3) compare environments
- run the command "env > myenv.log" from the shell where the program works and then execute "env > scriptenv.log" from the script. Then compare the two output files using diff:
diff myenv.log scriptenv.log

Other Good Troubleshooting Ideas
Here is some excellent advice from the Spike Source bloggers:
http://blog.spikesource.com/crontab.htm

Hopefully, some of these suggestions may answer the exasperated cry, "Why doesn't my shell script run?!"

'sodo
Feel free to drop me a line or ask me a question.