building tmux 1.9a statically

At work, I use tmux on daily basis. Unfortunately, the version shipped in epel (extra packages for enterprise linux) is slightly dated, v1.6. I didn’t want to update tmux system wide as this would impact other users. A single statically linked library that I could store in my home area would be perfect.

I discovered the build process was bit of a challenge. Although I found answers to my problems, they were not in a centrally located. Therefore, I am documenting my steps below.

These steps allowed me to build tmux 1.9a. These same steps should work for newer versions, however at some point, these steps may break. Additionally, these steps were performed on RHEL6 – they should apply to nearly any distro.

  1. Install glibc-static:
    $ yum install glibc-static
  2. Download libevent-2.0.21-stable
    $ ./configure --prefix=/tmp/local --disable-shared
    $ make
    $ make install
  3. Download ncurse 5.9
    $ ./configure --prefix=/tmp/local --with-default-terminfo-dir=/usr/share/terminfo  --with-terminfo-dirs="/etc/terminfo:/lib/terminfo:/usr/share/terminfo"
    $ make
    $ make install
  4. Download Tmux Source
    $ ./configure --enable-static CFLAGS="-I/tmp/local/include -I/tmp/local/include/ncurses" LDFLAGS="-L/tmp/local/lib -L/tmp/local/include -L/tmp/local/include/ncurses" LIBEVENT_CFLAGS="-I/tmp/local/include" LIBEVENT_LIBS="-L/tmp/local/lib -levent"
    $ make -j5
    $ cp tmux /home/$USER/bin

 

Troubleshooting / Build Issues:
(more…)



Android: Email deletion does not propagate to IMAP server

Problem: When deleting a message in the Email client, the deletion does not propagate to the IMAP server.

Device: Motorola Moto X
OS: Android 4.4
App: Email 4.4-51
Server: CentOS 6.5 – dovecot 2.0.9 (version that ships with centos)

Solution: Upgrade dovecot from 2.0.9 to 2.2.10

There has been an open android bug (1029) regarding this issue since 2008.

Comment 86 on Android bug 1029 provides a possible explanation for what is happening:

“I believe the root cause is that the route Google and others have gone with IMAP is to try and make it perform like Exchange, where it stays connected and “pushes” emails immediately when they arrive. The big problem with this is that while IMAP was designed to work this way, it assumed
1. that there would be only one client connected to an account at a time, and
2. the internet connection and IP address of connected clients would be constant, not changing as you move between wifi hotspots and cell towers.
So, most mail servers queue up the “delete” commands until the user has disconnected. If we disable the ill-conceived “PUSH” crap, the mail program SHOULD operate like POP – connect, sync, disconnect. But either it is failing to disconnect, or a second connection (such as a home desktop you left logged in) is keeping your account open. K-9 seems to deal with this better by “remembering” what messages have been deleted and not restore them when it sees that they are still on the server.

GOOGLE, PLEASE FIX!

Meanwhile, you can make the problem *somewhat* better if you set your IMAP mail to check less often than the timeout on the server (usually 30 minutes). That way, the hanging connection times out between mail checks, and the server will perform the deletions you’ve asked for.”

When reviewing the dovecot changelog, I did not see any changes that seemed related to this problem. I suspect (I have no real knowledge of IMAP and/or dovecot) that dovecot has changed the way it handles delete commands and thus the problem has been worked around. If anyone has information about what changed in dovecot please share!

Sadly, my solution only works if you can update or switch your mail server software.

ATrpms provides dovecot-2.2.10 for Centos6: http://packages.atrpms.net/dist/el6/dovecot/



Configuring a Router with Comcast Business Class

For the last two months, I used NAT to make use of my 5 static ips. I wanted to do away with NAT and create another network for public ip space. My goal was simple; a router that was attached to two networks: a RFC1918 LAN and a LAN for my public ip block; however this would not be an easy task.

Desired Network Topology:

                       /-------------------\          ____Host A_____
                       +        LAN1       + ------> | 23.31.174.84 |
                       +  23.31.174.80/29  +         ----------------
                       \-------------------/
                                 ^
                                 |
                                eth1
+-----------------+          +--------+          /--------------------\
|      modem      | --> eth0 | router | eth2 --> + LAN2 (192.168.1.1) +
| 10.1.10.1/24    |          +--------+          \--------------------/
| 23.31.174.86/29 |
+-----------------+ 

router:
eth0: 10.1.10.2
eth1: 23.31.174.81
eth2: 192.168.1.1

Ideally, the modem would be configured as bridge, with a default route via eth0 to comcast’s gateway. The routing should be simple. Sadly, comcast made this way more difficult.

The modem, a SMCD3G (cable gateway), is a switch and router with modem functionality. In theory, it should be possible to disable the router/switch functionality and turn it into a bridge, however comcast refuses to provision the modems in this manner.

The modem has two interfaces, a coax interface and switched virtual interface (svi). The coax interface is provisioned automatically and is used to communicate with comcast’s gateway. The svi is configured with two network blocks: 10.1.10.1/24 (RFC1918) and 23.31.174.86/29 (static ip block). Unfortunately, it is not possible to see how the modem is configured, therefore the above is an educated guess, based on the network traffic I saw from the modem.

The modem’s configuration posed, a slight problem. The modem was configured with 23.31.174.86/29, but I wanted to assign 23.31.174.81/29 to the router. After some trial and error, I figured out how to make this configuration work. The secret: proxy arp.

General Configuration / Theory

Disable the firewall/router functionality on the modem. The modem configuration can be accessed via 10.1.10.1; the username is ‘cusadmin’ and the password is ‘highspeed’. Comcast follows similar steps when you request them to bridge your modem.
Note, this configuration will not disable the routing and switching functionality of the modem.

Under …

Firewall -> Firewall Options
  * [checked] Disable Firewall for True Static IP Subnet Only
  * [checked] Disable Gateway Smart Packet Detection
  * [unchecked] Disable Ping on WAN Interface

Firewall -> Port Configuration
  * [checked]  Disable all Port Forwarding rules

Firewall -> 1-to-1 Network Address Translation
  * [checked] Disable all

LAN -> IP Setup
  * [unchecked] Enable LAN DHCP

Insure there are no static routes configured on the modem; filtering is disabled; a dmz has not been configured; and website blocking is disabled.

Assign 23.31.174.81/29 to router:eth1 (lan1) and assign 192.168.1.1/24 (lan2) to router:eth2

To get traffic between the modem and router, router:eth0 needs to be configured. Assign 10.1.10.2/24 to router:eth0 and set the default gateway to 10.1.10.1 (the modem’s lan ip).

At this point, it should be possible to access the internet from the router. The src ip of packets going out eth0, will be 10.1.10.2. Since 10.1.10.1/24 is not routeable on the internet, the modem will SNAT 10.1.10.2 to 23.31.174.86. To fix this we need set the src ip of the default route, to match the ip that is configured on router:eth1 (23.31.174.81).

Example: ip route add default via 10.1.10.1 src 23.31.174.81

A tool such as ifconfig.me will show the external src ip of the host.
From your host run: curl http://ifconfig.me

23.31.174.86/29 lives on the modem, outside of LAN1, therefore a static route to 23.31.174.86 via 10.1.10.1 (modem) should be configured.
ip route add 23.31.174.86/32 via 10.1.10.1.
Note: overlapping network space is a poor configuration practice and should be avoided. In this case, it is the only way to configure the network.

The problem

Host A (23.31.174.84) tries to ping 8.8.8.8. Echo requests go out, but Host A never receives echo replies. A tcpdump of router:eth0, verifies the icmp traffic is leaving the router with the correct src/dst ips, but does not show any return/inbound traffic, except for the modem. From the tcpdump, one will see the modem is sending the following arp requests:

ARP, Request who-has 10.1.10.2 tell 10.1.10.1, length 28
ARP, Reply 10.1.10.1 is-at c4:39:3a:02:02:02 (oui Unknown), length 46
ARP, Request who-has 23.31.174.81 (Broadcast) tell 23.31.174.86, length 46
ARP, Request who-has 23.31.174.83 (Broadcast) tell 23.31.174.86, length 46
ARP, Request who-has 23.31.174.82 (Broadcast) tell 23.31.174.86, length 46
ARP, Request who-has 23.31.174.85 (Broadcast) tell 23.31.174.86, length 46
ARP, Request who-has 23.31.174.84 (Broadcast) tell 23.31.174.86, length 46

The router can reply to the request for 23.31.174.81 and 10.1.10.2. The router can not reply for addresses not configured. No other devices will respond to these arp requests, because the router and modem are the only devices on the layer 2 segment. Why does this happen? The modem’s svi has an ip address of 23.31.174.86/29. The 23.31.174.80/29 network is directly attached and is the final destination. Luckily, we can make use of proxy arp. Proxy arp will make the router respond to all arp requests.

Enable proxy arp on router:eth0.

Now, when HOST A (23.31.174.84) pings 8.8.8.8 icmp echo requests are sent and echo replies are received.

SNAT needs to be configured so hosts in LAN2 (192.168.1.1/24) can communicate on the internet. Keep in mind, the address used for SNAT can’t be the router gateway (23.31.174.81), modem gateway (23.31.174.86), or any host addresses in LAN1.

Applying the above configuration to a Linux router

Make sure the modem has been configured appropriately (see above).

Router Configuration

# set ip addresses
router$ ip addr add 10.1.10.2/24 dev eth0
router$ ip addr add 23.32.174.81/86 dev eth1
router$ ip addr add 192.168.1.1/24 dev eth2

# bring up interfaces
router$ ip link set eth0 up
router$ ip link set eth1 up
router$ ip link set eth2 up

# add routes
ip route add default via 10.1.10.1 src 23.31.174.81 # change src to the ip on eth1
ip route add 23.31.174.86/32 via 10.1.10.1 # route to the modem's IP

# enable proxy arp on eth0
sysctl net.ipv4.conf.eth0.proxy_arp=1

# NAT
iptables -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 23.31.174.85


pidgin: disconnect specific accounts from cron

At the end of the day, I needed a way to automatically disconnect from my personal instant messaging accounts (jabber, aim), while staying connected to my work jabber server. This could be done manually ( Accounts -> Manage Accounts -> Uncheck $AccountName), however I tend to be extremely forgetful and often stay logged in.

With the aid of python, I wrote a script that will disconnect specific libpurple/pidgin accounts. Modify the accounts list in the script to reflect that accounts you want to disconnect.

This script was a bit tricky, because purple-remote uses dbus to communicate with pidgin/libpurple. Since cron sets up a bare minimum environment, we need to detect the active dbus session and set the following dbus environmental variables: DBUS_SESSION_BUS_ADDRESS, DBUS_SESSION_BUS_PID, DBUS_SESSION_BUS_WINDOWID. With these environment variable set, we identify the account id for each account you specified, and then tell libpurple to disable that account.

#!/usr/bin/python

import subprocess
import sys
import os
import re

accounts=[{'name':'pyther24', 'protocol':'prpl-aim' },
          {'name':'matthew@pyther.net/Work', 'protocol':'prpl-jabber'},
          {'name':'pyther24@gmail.com/Work', 'protocol':'prpl-jabber'}]

def check_pid(pid):
    """ Check For the existence of a unix pid. """
    try:
        os.kill(pid, 0)
    except OSError:
        return False
    else:
        return True

def main():
    if len(sys.argv) > 1 and sys.argv[1] == "login":
        ACCOUNT_ENABLE=1
    else:
        ACCOUNT_ENABLE=0

    # We need to get the dbus environment variable for purple-remote to work
    # These environment variables are stored in $HOME/.dbus/session-bus
    # there may be old sessions stored in .dbus/session-bus, we need to determine
    # which session to use

    env = os.environ.copy()
    # Fetch all sessions in $HOME/.dbus/session-bus
    dbus_dir=os.path.join(env['HOME'],'.dbus/session-bus')
    dbus_sessions=[]
    for filename in os.listdir(dbus_dir):
        filepath = os.path.join(dbus_dir,filename)
        session=dict()
        with open(filepath, 'r') as f:
            for line in f.readlines():
                if re.match('^#',line):
                    continue
                var,value=line.strip().split('=',1)
                session[var]=value
        dbus_sessions.append(session)

    # Determine which dbus session to use
    # Check pid to see if it is alive
    # If pid is alive see if the name contains dbus-daemon
    for s in dbus_sessions:
        pid=s['DBUS_SESSION_BUS_PID']

        if os.path.exists('/proc/{0}'.format(pid)):
            with open('/proc/{0}/cmdline'.format(pid)) as f:
                cmdline = f.readline().strip()
        else:
            # DBUS process must be dead
            continue

        if re.search('dbus-daemon',cmdline):
            env['DBUS_SESSION_BUS_ADDRESS'] = s['DBUS_SESSION_BUS_ADDRESS']
            env['DBUS_SESSION_BUS_PID'] = s['DBUS_SESSION_BUS_PID']
            env['DBUS_SESSION_BUS_WINDOWID'] = s['DBUS_SESSION_BUS_WINDOWID']
            break

    # Get account ids for each account define above
    # Disable / Enable each account

    for a in accounts:
        p = subprocess.Popen(['purple-remote',
          'PurpleAccountsFind({0},{1})'.format(a['name'],a['protocol'])],
          stdout=subprocess.PIPE,stderr=subprocess.PIPE,env=env)

        p.wait()

        # Store ID
        try:
            id = int(p.communicate()[0].strip())
        except ValueError:
            print('Could fetch id for account {0}'.format(a['name']))
            continue

        # Disable Account
        p = subprocess.call(['purple-remote',
          'PurpleAccountSetEnabled({0},{1},{2})'.format(int(id),'gtk-gaim',ACCOUNT_ENABLE)],env=env)
    return

if __name__ == '__main__':
    main()


nxt2004 firmware

I needed to obtain the firmware for my KWorld ATSC 115 which uses the nxt2004 demodulator. The kernel module saa7134 requires the nxt2004 firmware to operate correctly. In the past the process to obtain the firmware was easy, but now that avermedia-usa now longer makes available the driver, it was much harder to track down the need firmware file.

The problem:

m2n:~ $ /tmp/get_dvb_firmware nxt2004
--2012-07-06 22:51:22--  http://www.avermedia-usa.com/support/Drivers/AVerTVHD_MCE_A180_Drv_v1.2.2.16.zip
Resolving www.avermedia-usa.com... 66.85.153.58
Connecting to www.avermedia-usa.com|66.85.153.58|:80... connected.
HTTP request sent, awaiting response... 404 Not Found
2012-07-06 22:51:22 ERROR 404: Not Found.

wget failed - unable to download firmware at /tmp/get_dvb_firmware line 662.

I figured I could just search for AVerTVHD_MCE_A180_Drv_v1.2.2.16.zip or dvb-fe-nxt2004.fw and be in business. Unfortunately, it was not that easy as it took me over an hour to find the file.

I came across linux-firmware-nonfree_1.11_all.deb which contained nxt2004.fw

Since it was so hard to find the firmware file I decided to mirror it along with the original deb package that I got it from.

Files:

To Install:

  1. wget http://pyther.net/files/firmware/nxt2004/dvb-fe-nxt2004.fw
  2. cp dvb-fe-nxt2004.fw /lib/firmware
  3. reload appropriate module or reboot
  4. check out dmesg to confirm firmware was loaded

Hope this has helped someone…



Password Manager

Best practice states that passwords should contain letters (mixed case), numbers, and symbols, should be at least 8 characters in length, and should never be used twice. However, this isn’t very practical! How are you suppose to remember a different password for each site you have an account for?

I have been using 4 different password for my various accounts. This method has been working moderately well, but from a security standpoint, it’s suicide. I wanted to use a random password for each of my accounts. But, how would I ever remember all my passwords? A password manager, of course!

What I needed:

  • Passwords stored in an encrypted file
  • Master password to unlock the encrypted file
  • View passwords from the cli/ssh
  • Include additional information such as Security Questions and Answers
  • Integrated support for Firefox

What I used…

Vim Outliner

Vim Outliner is an outline processor. A screenshot is worth a thousand words.

Encryption

By default when you save the file it will be a simple tab delimited text file. Vim, however, supports encryption. First, you need to set the encryption method by typing :setlocal cm=blowfish. If you want Blowfish to be the default encryption method for vim add the setlocal command to ~/.vimrc. Next, to encrypt the file, type :X. You will be prompted to set a password. Finally, save the file. When you open the file, you will be prompted for the password. If you fail to enter the right password you will see garbage characters.

Firefox Integration  (Mozilla-gnome-keyring)

Mozilla-gnome-keyring allows Firefox to store passwords and form logins in gnome-keyring. Gnome-keyring is much more secure than the default password manager in Firefox. The mozilla keyring must be unlocked to add / retrieve passwords. You can define how long the keyring should remain unlocked for (never, 15 minutes, 60 minutes, etc…). On my desktop I unlock the keyring for 60 minutes, but on my laptop I only unlock it for 10. When logging into a site, Firefox still prompts to  “Remember the Password”.  If you let Firefox remember the password, the password automatically gets recorded in the keyring.

Conclusion

I have been using this solution for about a month and it has fit my needs perfectly. I updated most of my accounts so they each have an unique password such as Dmqngi8ZoPyO or XGVoBOmd7Gar. Passwords are being stored twice: in the password file and in gnome-keyring. Since mozilla-gnome-keyring takes care of adding the passwords into gnome-keyring when I login to a site, I only have to record/update my passwords in the encrypted text file. In the rare case that I’m not at my computer, and I need a password, I simply ssh into my server and open the password file in vim.

Although the password file and keyring is encrypted it is still subject to a brute force attack. Make sure to use a strong master password, the longer the better. I would suggest at least 20 characters. In 2009, it would take a super computer 1.5hrs to crack an 8 character (alpha only; lower-case) password, but it would take 631 Billion years to crack a 20 character (alpha only; lower-case) password. Remember, as computers advance these times will decrease. And of course, a key logger could compromise the master password nearly instantly.

http://www.lockdown.co.uk/?pg=combi&s=articles



Modem Power Level Graphing

I wanted to monitor the downstream and upstream power levels on my Scientific-Atlantic modem (provided by my ISP). My intended goal was to keep logs of the power levels and if my modem “froze” then I could go back to the logs and look for any abnormal power levels.

At first, I just logged the power levels to a simple text file. This worked, but the aggressive logging I was doing generated a lot of data. I thought it’d be nice to see how the power levels changed throughout the day.

The following emerged:

Logging Script (python)

#!/usr/bin/env python2

import urllib2
from BeautifulSoup import BeautifulSoup
from lxml import etree
from StringIO import StringIO
import sys
import datetime

URL = 'http://192.168.100.1/system.asp'

def timestamp():
    now=datetime.datetime.now()
    return now.strftime("%b %d %H:%M:%S")

def error():
    print "Error"
    return

try:
    page = urllib2.urlopen(URL, timeout=10)
except:
    print timestamp() + ": # dBmV (rx), # dBmV (tx)"
    sys.exit()

soup = BeautifulSoup(page)

# Remove   markups, because they break the XML parser.
f = StringIO(str(soup.findAll('tbody')[0]).replace(' ', ''))

dom = etree.parse(f)
nodes = dom.xpath('//font')
# We take every value we can get, but do not use them, yet
modemvalues = []
for i in xrange(0, len(nodes), 2):
    modemvalues.append((nodes[i].text, nodes[i+1].text.strip()))

rpl = float(modemvalues[5][1].split(' ')[0]) # dBmV
tpl = float(modemvalues[6][1].split(' ')[0]) # dBmV

print timestamp() + ": " + str(rpl) + " dBmV (rx), " + str(tpl) +" dBmV (tx)"

Usage: ./getModemPl.py >> logFile (cron job)

Output:

Nov 06 22:30:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:31:41: 0.8 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:32:41: 0.9 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:33:41: 0.5 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:34:41: 0.5 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:35:41: 0.5 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:36:41: 0.6 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:37:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:38:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:39:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:40:41: 0.7 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:41:41: 0.6 dBmV (rx), 35.4 dBmV (tx)
Nov 06 22:42:41: 0.7 dBmV (rx), 35.4 dBmV (tx)

Graph Generator (takes every 5th log entry)

#!/bin/bash

if [[ ! $1 ]]; then
    echo "No File to Parse"
    exit
fi

startRange=$2
endRange=$3

tmpDir="/tmp"
currentDir="$PWD"
logFile="$1"
data="/tmp/modempowerdata"

# Takes every sample from log File
#cat $logFile | sed 's/.dBmV.(rx),//' | sed 's/.dBmV.(tx)//' | sed 's/: / /'  | perl -pe 's/(.*?)\s(.*?)\s(.*)/$1-$2-$3/;' > $data

# Takes every 5th sample (we log every minute)
cat $logFile | sed 's/.dBmV.(rx),//' | sed 's/.dBmV.(tx)//' | sed 's/: / /'  | sed -n 'p;n;n;n;n;' | perl -pe 's/(.*?)\s(.*?)\s(.*)/$1-$2-$3/;' > $data

date=$(head -1 $logFile | cut -d' ' -f1,2)
date2=$(echo $date | sed 's/ /-/')

png="$currentDir/$date2.png"
svg="$currentDir/$date2.svg"

#rm "$data"

plot=""

cat << EOF | gnuplot
#
# --- gnuplot ---
#
# PNG output
#set terminal png enhanced size 1400,900
set terminal pngcairo size 1200,600 enhanced font 'Verdana,10'
set output "$png"

# SVG Output
#set terminal svg enhanced size 1440,900

# Adds White Background to SVG
set object 1 rect from screen 0, 0, 0 to screen 1, 1, 0 behind
set object 1 rect fc  rgb "white"  fillstyle solid 1.0
#set output "$svg"

# Line Sytes
set style line 1 lc rgb "#8b1a0e" pt 1 ps 1 lt 1 lw 2
set style line 2 lc rgb "#5e9c36" pt 6 ps 1 lt 1 lw 2
set style line 12 lc rgb '#808080' lt 0 lw 1

set timefmt "%b-%d-%H:%M:%S"
set grid
#set grid back ls 12
set key left box
set title "$date - Power Levels"

# X Label
set xdata time
set format x "%H:%M"
#set xlabel "Time"

# Y Data
set ylabel "dBmV (rx)"
#set yrange [-2:2]
#set ytics 0.2
set yrange [-1.6:4.4]
set ytics 0.2

# Y2 Data
set y2range [31:37]
set y2label "dBmV (tx)"
set y2tics 0.2

plot "$data" u 1:2 ls 1 axis x1y1 ti "rx" with lines, "$data" u 1:3 ls 2 axis x1y2 t "tx" with lines

EOF

Notes:

  • Usage: ./graphModemPower.bash /path/to/logfile
  • Modify yrange and y2range to scale to appropriate power levels for you

Graph:

 

Feel free to use the scripts,  they work for me, and hopefully they work for you. As always, use at your own risk.



Weather Underground Script

Since weather.com is ending their free XOAP service conkyForecast will no longer work at the end of this month.

Therefore I wrote a small script to get the temperature and condition from Weather Underground

#!/usr/bin/python
#
# Fetches Weather info from Weather Underground
#
# Usage: ./wundergound.py zipcode
#
# International:
#  * Go to http://www.wunderground.com/
#  * Find your city
#  * Click the RSS icon
#  * Station ID is the number that follows /stations/ in the url
#
#

# Values are either True or False
metric=False
international=False

import sys
import feedparser

def usage():
    print("Usage:")
    if international:
        print("  ./wunderground.py StationID")
    else:
        print("  ./weunderground.py zipcode")
    sys.exit(1)

if not len(sys.argv) == 2:
    usage()

location=sys.argv[1]

if international:
    url="http://rss.wunderground.com/auto/rss_full/global/stations/"
else:
    url="http://rss.wunderground.com/auto/rss_full/"

feed=feedparser.parse(url+location)

if not feed.feed:
    # Assume Error
    print("Error")
    sys.exit(1)

current=feed['items'][0].title

if metric:
    temp=current.split(",")[0].split(":")[1].split("/")[1].strip()
else:
    temp=current.split(",")[0].split(":")[1].split("/")[0].strip()

condition=current.split(",")[1].split("-")[0].strip()

print('%s - %s' % (temp, condition))

 

Example:


$ ./wunderground 11201
69.6F - Clear

I’m using this script for my conky config:

${execi 600 /home/pyther/scripts/wunderground 11201}


Make Windows 7 USB installer in Linux

So for whatever reason you need to install Windows 7 from a flash drive that’s not a problem!

In Linux:

  1. Format flash drive: mkfs.vfat -F 32 /dev/sdx
  2. Set Label: mlabel -i /dev/sdd1 ::WIN7x64 (optional)
  3. Download Grub4Dos – http://download.gna.org/grub4dos/
  4. unzip grub4dos-0.4.4.zip
  5. Run ./bootlace.com /dev/sdx
  6. Copy grldr and menu.lst to the root of the flash drive
  7. Add to menu.lst
    title Install Windows 7
    root (hd0,0)
    chainloader (hd0,0)/bootmgr
  8. Copy Win 7 Install files to root of USB flash drive.
  9. Boot Flash Drive – Select Install Windows 7

TIP: To install any version of Windows 7 (Home Premium, Professional, Ultimate) remove ei.cfg from the sources directory. However, you still need a product key for the appropriate version.

In Windows:

  1. Format Drive as Fat32
  2. Copy Files from Install DVD to Flash drive

That’s it, boot from the flash drive you are all good.

Note: The windows disk formater writes code to the MBR and VBR. This obvisouly doesn’t happen in Linux therefore we need to use grub4dos as our bootloader.



Remote Assistance – Win XP/Vista/7

I was looking for a solution that would allow me to remotely connect to machines on the local network. We often get phone calls form users asking for help. It is way easier to provide help if we can see their screens and we usually end up having to visit their workstation. This can be time consuming, especially when we are in the middle of a project.

In my search, I came across a wonderful gem called Microsoft Remote Assistance which happens to be included in Windows XP/Vista/7.

How does it Work?

  1. Tech enters the Machine name of the client that he/she wants to provide Remote Assistance to.
  2. User is prompted to allow Tech to view their computer (Yes/No)
  3. Tech then can request to take control
  4. Again, the user is prompted to allow the tech to take control

Enabling Remote Assistance on the Domain (via Group Policy)

Computer Configuration -> Policies -> Admin Templates -> System -> Remote Assistance

  • Offer Remote Assistance -> Enable
  • Solicited Remote Assistance -> Disable (If you don’t want your users requesting others for Remote Assistance)

You then have two choices “Allow helpers to control the computer” or “Allow helpers to only view the computer”. In addition to selecting one of these choices, you have to add the users and groups that should be able to provide remote assistance.

Offering Remote Assistance

  • Start -> All Programs -> Maintenance -> Windows Remote Assistance or type in msra.exe
  • Click “Help Someone who has invited you”
  • Click “Advance connection option for the help desk”
  • Lastly, enter the machine name or ip address of the machine you want to provide Remote Assistance to

 

How can I possibly remember all the host names?

I’ve created a small C# application that you can have your users run. I would put it on a shared drive and push out a shortcut via group policy.

WhoAmI

Source: WhoAmI.zip
Bin: Included in source ./WhoAmI/bin/Release/WhoAmI.exe

Offering Remote Assistance – A nice GUI app

Although the method mentioned above works it is long and convoluted. I put together a small  C# app to easily offer Remote Assistance to a user.

The app simply calls msra.exe /offerra <hostname>

Source: RemoteAssistance.zip
Bin: Included in souce ./RemoteAssistance/bin/Release/RemoteAssitance.exe

Ideas for the two Easy GUI apps came from SYNACK over at edugeek. http://www.edugeek.net/forums/coding/49448-easy-gui-remote-assistance-support.html

More Information: