More from: script

Conky Weather


Changes in weather.gov formats for available weather information recently required me to revise my conky script. Conky can be installed from the Ubuntu / MINT repos or downloaded from github and documentation is on sourceforge or by the man page. This information is furnished AS IS – use it at your own risk. Most recent version of the GPL applies.

The following code is how I get my weather information directly from weather.gov and display up to date weather information for my area. The code for surface weather observations is found on the Weather.Gov web page for your zip code and the state / county codes for weather alerts is at the bottom of the page here.  My code is KFWA and my county is INC003. Replace these with the ones appropriate for your area.

The recommended pull time for your area is in the xml file that you get from weather.gov. Here is a sample of part of the lines in that file showing the suggested pick time and frequency:


<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="latest_ob.xsl" type="text/xsl"?>
<current_observation version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.weather.gov/view/current_observatio.xsd">
<credit>NOAA's National Weather Service</credit>
<credit_URL>http://weather.gov/</credit_URL>
<image>
<url>http://weather.gov/images/xml_logo.gif</url>
<title>NOAA's National Weather Service</title>
<link>http://weather.gov</link>
</image>
<suggested_pickup>15 minutes after the hour</suggested_pickup>
<suggested_pickup_period>60</suggested_pickup_period>
<location>Fort Wayne International Airport, IN</location>
<station_id>KFWA</station_id>
<latitude>40.97251</latitude>
<longitude>-85.20637</longitude>
...

The part of my .conkyrc script dealing with weather is as follows:

${color FFAA00}WEATHER ${hr 2}$color${font Verdana:size=9}
#${execi 3600 curl -s w1.weather.gov/xml/current_obs/KFWA.xml > wwraw.txt}
#${execi 3600 wget -q --output-document="walerts.xml" http://alerts.weather.gov/cap/wwaatmget.php?x=INC003&y=0}
${color 00FF00}${exec cat wwraw.xml | sed -n '//p' | cut -d'>' -f2 | cut -d'<' -f1}${color}
${color 00FF00}${exec cat wwraw.xml | sed -n '//p' | cut -d'>' -f2 | cut -d'<' -f1}${color}
${color 888888}Wind: ${exec cat wwraw.xml | sed -n '//p' | cut -d'>' -f2 | cut -d'<' -f1}${color}
${color FFFF00}Humidity: ${exec cat wwraw.xml | sed -n '//p' | cut -d'>' -f2 | cut -d'<' -f1}% ${color}
${color 00FF00}Temperature: ${exec cat wwraw.xml | sed -n '//p' | cut -d'>' -f2 | cut -d'<' -f1}${color}
${color 888888}Dew Point: ${exec cat wwraw.xml | sed -n '//p' | cut -d'>' -f2 | cut -d'<' -f1}${color}
${color 888888}Pressure: ${exec cat wwraw.xml | sed -n '//p' | cut -d'>' -f2 | cut -d'<' -f1} in Hg${color}${font}
${font Verdana:style=bold:size=10}Warnings:${font}${color}
${exec cat walerts.xml | sed -n '/\/p' | cut -d'>' -f2 | cut -d'<' -f1}

Notice the two lines which I have commented out with the pound # sign. These fetch the surface weather observations and weather alerts from weather.gov. They are commented out in my conky script because I fetch them instead using cron, 15 minutes after each hour,  the time recommended by weather.gov. They don’t HAVE to be in the script but I leave them there in case I need to refer back to them at some future date, such as if I accidently delete my weather fetching bash script. Edit your crontab in terminal by typing “crontab -e”.

# m h dom mon dow command
15 * * * * ./weather-fetch.sh

The .xml file provided by weather.gov says what time is recommended to pull. I try to avoid pinging weather.gov more frequently than needed as a matter of respect: the weather is updated once per hour so more frequent pulls achieve nothing useful and cost weather.gov in bandwidth.

To pull the weather information I use a bash script as follows. Remember a bash script must be “executable” for your login. Search on linux permits if you need more information. I can let cron call this once per hour, and it is also called through my .bash_profile when I log in.

#!/bin/bash
#pull weather from weather.gov

wget -q --output-document="wwraw.xml" http://w1.weather.gov/xml/current_obs/KFWA.xml
wget -q --output-document="walerts.xml" http://alerts.weather.gov/cap/wwaatmget.php?x=INC003&y=0

To have the script prevent excessive downloads, I use this complete bash script:

#!/bin/bash
#pull weather from weather.gov
#ONLY IF it has not been pulled recently
#weather is updated once per hour
# recommended time to pull is hour+15
# manually noted weather is updates about
# 54 minutes after the hour
#last_update: 20170826 JDN
#
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# define minimum time lapse before new pull is permitted
declare -i MINAGE=22
echo 'Min age' $MINAGE

# calculate time lapsed since last pull
if [ -f wwraw.xml ];
then
declare -i LAPSE=$(( ( $(date +%s) - $(stat wwraw.xml -c %Y)) / 60 ))
echo 'Lapse' $LAPSE
else
declare -i LAPSE=999
fi

# allow override of command line parameter #1 is --force
if [ -n "$1" ]; then declare -i FORCE=1; else declare -i FORCE=0; fi
echo force is $FORCE

# calculate if pull is permitted (boolean)
DOPULL=$(( $LAPSE >= $MINAGE ))
echo dopull is $DOPULL

# test time lapse vs. minimum time lapse to allow pull or override
# Check if file older
if [[ $(($DOPULL + $FORCE)) -gt 0 ]]; then
# debugging message output if pull was performed
echo "File was pulled $LAPSE minutes ago. Pulling new weather data"
# get surface observations
# file will have date / time from weather.gov
wget -q --output-document="wwraw.xml" http://w1.weather.gov/xml/current_obs/KFWA.xml
# mark file with current time to prevent hammering weather.gov
touch wwraw.xml
# get weather alerts
wget -q --output-document="walerts.xml" http://alerts.weather.gov/cap/wwaatmget.php?x=INC003&y=0
else
# debugging message output if pull was not performed
echo "File was pulled $LAPSE minutes ago. Ignoring request to pull again."
fi

#cleanup
unset FORCE
unset DOPULL
unset MINAGE
unset LAPSE
exit 0

Backup using rsync with non-standard ssh port

locked-computer-cartoon*nix systems have rsync to back up or synchronize (mirror) their files to a backup computer. For example I can back up the files on my home computer to my office computer. rsync does not copy files that have not changed. The syntax is something like

rsync -avzhe ssh /home/mydir/ mylogin@myserver.org:/home/mydir/ 

The -a is archive, same as for cp. -v is verbose so you can see each file in process and how long until it is finished. the -e lets you specify an alternate communications protocol, in my case ssh.

Note: SSH must be working on both systems for rsync to work using SSH. Also note OpenSSH can be unreasonable and inobvious about permits — the target login directory (example: /home/mylogin) must NOT be writable by group or other. Mostly this will not be a problem — chmod 06755 /home/mylogin will work. BUT also note the /home/mylogin/.ssh folder MUST be 0700 (or possibly 0744) and the /home/mylogin/.ssh/authorized_keys file must be 0700. Otherwise SSH simply returns “Permission denied (publickey).” and refuses to connect. Yeah, someone didn’t think that one through all the way.
Note: you can pull / push files around a few at a time without checking dates and such by using scp. It is like the copy command, cp, but works through ssh. Format example:

scp mylogin@mycomain:/myfilename .

I had a couple problems when I tried rsync initially:

  1. It wiped out my ssh credentials (2048 bit key in /home/mydir/.ssh/authorized_keys) on the remote system by copying the .ssh/authorized_keys in my local system right over the top of it — probably not a good idea to copy your hidden folders up to the remote system.
  2. I use non-standard port numbers for ssh to make hacking me a little more interesting and I found nothing obvious in the docs about how to do it.

I solved these problems in the little script below and also email myself a report when it is done. Note the app I used to send the email is “sendemail” with an “e” in the middle, not “sendmail”: I removed mailutils because I do not run mail servers at this time and that makes it a bit more interesting to hijack my systems for spamming since there is no app to send the spam — remove all programs you don’t need to reduce vulnerabilities. The sendemail program can be installed from the repositories.

#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DEBIAN_FRONTEND=noninteractive
#
NOW=$(date +"%Y%m%d-%H%M%S")
LOGME="/home/mydir/log/rsync-$NOW.log"
LOGDIR="/home/mydir/log"

if [ -d "$LOGDIR" ]
then
echo "Log folder located at $LOGDIR"
else
echo "Creating log folder at $LOGDIR"
mkdir $LOGDIR
fi

echo ===
echo $HOSTNAME batch job nightly mirror to my backup server $NOW
echo ===

rsync -avzhe 'ssh -p2222' --progress --exclude='\.*' /home/mydir/ mylogin@myserver.org:/home/mydir/ >$LOGME

sendemail \
-f $HOSTNAME@myserver.org \
-t receiver@mydomain.com \
-u "$HOSTNAME Nightly Mirroring Report" \
-s my-mail-server.net:port# \
-xu "sender@mydomain.com" \
-xp "my-password" \
-o message-file=$LOGME

GoDaddy, MySQL, and the Time Zone Problem

My public charity helps senior generational social dependents (hereditary poor due to a number of factors) learn middle class work ethics and job skills through a Federal program know as the “Senior Aides” or SCSEP program. This program pays seniors minimum wage to learn job skills in a working context. We must sign off on their time sheet every other week to attest that they really, truly, did actually work the hours shown on the time sheet, however these seniors sometimes forget days that they called in sick or left early, so I wrote a simple script as part of our web site that provides a time clock. One button for IN and one button for OUT and the MySQL database records the timestamp perfectly.

The problem I ran into is that we buy hosting on GoDaddy.com which is on the Pacific coast on Pacific time, my agency is located in Fort Wayne, Indiana in the midwest on EDT, and the normal MySQL commands to set the time zone do not work.

mysql_query("SET time_zone = 'America/Fort_Wayne';"); // Does Not Work
mysql_query("SET time_zone = 'America/Indianapolis';"); // Does Not Work

Apparently GoDaddy has not loaded the standard TZ file and they refuse to disclose what I should tell the MySQL server my timezone is. Several of their customer service people told me that if I knew how to tell MySQL which time zone I am in it would leave them open to cyber attack. I have no idea how knowing your timezone string would leave GoDaddy.com open to attack. Moving right along…

This left me changing the timezone manually every spring and fall, which is tedious and occasionally results in very confused Seniors telling me that the time clock is broken because it shows they clocked out an hour early (they never complain that it shows they clocked in an hour early).

// mysql_query("SET time_zone = '-5:00';"); // Uncomment in Fall
mysql_query("SET time_zone = '-4:00';"); // Uncomment in Spring

I found a way around this today in the comments on a post at http://www.electrictoolbox.com/mysql-set-timezone-per-connection/

date_default_timezone_set('America/Fort_Wayne'); // set timezone in php
mysql_query("SET `time_zone` = '".date('P')."'"); // set timezone in MySQL

Some of the comments say this does not work on BlueHost, but it does work for me on GoDaddy.com.

Hope this helps!

–Kubulai