wiki:OpenOsTricks

OS Tricks

This page details some Linux / Windows / MacOS tricks we find very useful.

retrieve your OpenLBR's dynamic IP address

You may have configured your OpenLBR to acquire it's IPv4 address through DHCP. If that is the case, chances are that the DHCP server gives it a different IPv4 address everytime the OpenLBR reboots. Since the OpenLBR does not have a screen, you don't know what IPv4 address to point your PuTTY to configure it.

One solution is to have the OpenLBR load a PHP script on a remote server. That server can store the IPv4 address of the OpenLBR which contacted it, and display it on some webpage for your to see.

On the remote server (in our case  http://wsn.eecs.berkeley.edu/), create a folder openserver/ under your server's DocumentRoot and create the file record_openlbr_address.php:

<?php
$file_name = "ipv4_".$_GET["hostname"].".txt";
$file_handler = fopen($file_name, "w");
$logdetails = $_SERVER['REMOTE_ADDR'];
fwrite($file_handler, $logdetails);
fclose($file_handler);
?>

<html><body>This should be accessed only by an LBR.</body></html>

Make sure you can see that page, in our case  http://wsn.eecs.berkeley.edu/openserver/record_openlbr_ipv4.php. Once you have visited that page once, a file ipv4_<hostname>.txt should have been created, with hostname the value of the GET parameters passed when opening that page.

On the OpenLBR, create the file /etc/network/if-up.d/openlbr/reportaddress.sh with the following content:

#!/bin/bash
wget -O - http://wsn.eecs.berkeley.edu/openserver/record_openlbr_ipv4.php?hostname=`cat /etc/hostname`
exit 0

We use the -O flag of wget so that it does not store any file when loading the PHP script. Don't forget to give the script execution privileges used chmod.

Now, add the following line at the end of /etc/network/interfaces on your OpenLBR:

post-up /etc/network/if-up.d/openlbr/reportaddress.sh

This instructs Debian to execute that script right after the OpenLBR's Ethernet interface is up. So now, each time your OpenLBR boots, read it's current IPv4 address at  http://wsn.eecs.berkeley.edu/openserver/.

open up a serial port in Python, without knowing its number

When you plug a mote in your Linux-based OpenLBR, it will appear as /dev/ttyUSBx, where x is a number. Similarly, when plugged into Windows, it appears as COMx in your device manager. It is frustrating, each time you plug in a mote, to look for that number and change a global variable in your Python script.

Instead, the following script scans for the connected motes and returns a list containing the list of the serial ports a mote is connected to.

import os

serialport_names = []

def findSerialPortsNames():
   global serialport_names
   if os.name=='nt':
      path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
      key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
      for i in range(winreg.QueryInfoKey(key)[1]):
         try:
            val = winreg.EnumValue(key,i)
         except:
            pass
         else:
            if val[0].find('VCP') > -1:
               serialport_names.append(str(val[1]))
      serialport_names.sort()
   elif os.name=='posix':
      serialport_names = glob.glob('/dev/ttyUSB*')
      serialport_names.sort()

After running the findSerialPortsNames() function, you script can open the first serial port using:

serialHandler = serial.Serial(serialport_names[0],baudrate=115200)

plugging/unplugging a mote without crashing your Python script

When you start a script which attaches to the serial port your mote is attached to, chances are it will crash if you unplug your mote while the script is running. Similarly, if you start your script while the mote is not connected, chances are your script will crash and exit.

The following script is a way around. The function scan() looks for connected motes. If no mote is connected, the script will run scan() every second, until a mote is connected. When a mote connects, it constantly reads characters the mote sends and prints those. If the mote gets disconnected, it goes back to running scan() every second.

#!/usr/bin/python
import serial, signal, sys, time, glob

serialHandler = ''

def scan():
   return glob.glob('/dev/ttyUSB*')

def serialRx():
   while True:
      availableports = scan()
      if (len(availableports)>0):
         try:
            serialHandler = serial.Serial(availableports[0],baudrate=115200,timeout=5)
         except:
            err = sys.exc_info()
            sys.stderr.write( "Error serialRx 1: %s (%s) \n" % (str(err[0]), str(err[1])))
         else:
            print "connected to "+serialHandler.portstr
            while True:
               try:
                  char = serialHandler.read(1)
               except SystemExit:
                  return
               except:
                  err = sys.exc_info()
                  sys.stderr.write( "Error serialRx 2: %s (%s) \n" % (str(err[0]), str(err[1])))
                  break
               else:
                  print char
      else :
         print "no mote connected"
         time.sleep(1)

def signal_handler(signal, frame):
   sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)
serialRx()

This means that you can start running your script regardless of whether the mote is connected to the OpenLBR or not. Similarly, you can unplug your mote and replug it later on without having to deal with restarting the script.

startup a script at boot time, using screen

screen is a Linux command which allows you to leave a script running even though you log out of the computer, and to go back interacting with it when you log back in, as if you had never logged of. On the OpenLBR, we use the script openlbr.py to interact with the attached mote. We start that script as soon as the Ethernet connection is up, by adding the following line to /etc/network/interfaces:

post-up screen -d -m /etc/network/if-up.d/openlbr/openlbr.py

The double flag -d -m of screen start in "detached" mode. This creates a new session but doesn't attach to it.

Whenever the interface is up, the script is running. When logging on to the OpenLBR, use the flag -list to see the identifier of the screen session running:

openlbr:~# screen -list
There is a screen on:
        1290..openlbr         (06/03/10 19:40:56)     (Detached)
1 Socket in /var/run/screen/S-root.

Then reconnect to that session using the -r flag:

openlbr:~# screen -r 1290

To "detach" from a screen session (i.e. leave without terminating it), type Ctrl-A d. If you type exit, you will terminate it.

reconnect to a "lost" screen session

For some reason, it happens sometimes that the screen -list command tells you there is no session running, although a ps -aux tells you there is. You can force a screen session to recreate the sessions number (in fact a file in /var/run/screen/S-root/) by sending it a CHLD signal. The following shows you a typical sequence of commands:

openlbr:~# screen -list
No Sockets found in /var/run/screen/S-root.

openlbr:~# ps -aux
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
[...]
root      1290  0.0  3.2   3000   948 ?        S<s  19:40   0:00 SCREEN -d -m /etc/network/if-up.d/wsnlbr/wsnlbr_reportdata.py
[...]
openlbr:~# kill -CHLD 1290
openlbr:~# screen -list
There is a screen on:
        1290..openlbr         (06/03/10 19:40:56)     (Detached)
1 Socket in /var/run/screen/S-root.

openlbr:~# screen -r 1290

kill a process without knowing its PID

kill -9 `ps -aef | grep 'python' | grep -v grep | awk '{print $2}'`

ping an IPv6 address from outside of the IPv6 cloud

If you happen to be outside of the IPv6 cloud, and you still want to check whether a node is alive, you can ask  http://lg.he.net/, which sits on the IPv6 cloud, to ping it for you.

have your OpenLBR reprogram itself at boot-time, using the OpenLBR bootstrap loader

The OpenLBR is meant to be "forgetted" once installed. Yet, the firmware which needs to run on it may need to be updated. One elegant solution is to enable a minimal script which runs as soon as the Ethernet interface of the OpenLBR comes up, and which downloads a script from a remote server. This technique can function in a cascading effect, i.e. the downloaded script can download another script, and so on. This is the technique we choose to use in the OpenWSN project. It is described in detail in OpenLbrRunIt.

replace all occurrences of a string in multiple files by another string

Credit goes to Ankur. From a terminal cd to the desired directory then do the following:

mkdir ../theNewDirectory
for i in `find . -type d`; do mkdir -p ../theNewDirectory/"$i"; done
for i in `find . -type d`; do sed 's/oldString/newString/ig' "$i"; done 

Note: use only /g for the command not to ignore case.

in Vista, increase the MTU of an interface

An an Administrator command window:

C:\Windows\system32>netsh interface ipv4 show interface

Idx  Met   MTU   State        Name
---  ---  -----  -----------  -------------------
  1   50 4294967295  connected    Loopback Pseudo-Interface 1
 11    5   1300  disconnected  Wireless Network Connection
 10   20   1300  connected    Local Area Connection


C:\Windows\system32>netsh interface ipv4 set interface "10" MTU=1375
Ok.


C:\Windows\system32>netsh interface ipv4 show interface

Idx  Met   MTU   State        Name
---  ---  -----  -----------  -------------------
  1   50 4294967295  connected    Loopback Pseudo-Interface 1
 11    5   1300  disconnected  Wireless Network Connection
 10   20   1375  connected    Local Area Connection

If everything works, go on to OpenLbrRunIt.

connect an TelosB to a MAC OSX computer

Install Xcode from Mac OS X install DVD. This adds developer support applications. You must check Unix development tools or something like that during the install to get unix support for the typical gcc, perl, etc. Python 2.5.4 is run by typing python2.5 at the terminal. NOTE: this may change with future releases of Apple xcode.

Install pyserial from  http://pyserial.sourceforge.net/

Install virtual com port driver from  http://www.ftdichip.com/Drivers/VCP.htm for MAC OSX.

A Crossbow TelosB mote shows up as something like /dev/tty.usbserial-XBRAHH4P.

use the auto-indent feature in vi

We recommend vi as a code editor. You can install it:

  • in Linux by typing apt-get install vim;
  • in Windows by install  gVim.

It comes with an auto-indent feature. To configure that, edit the configuration file:

  • C:\Program Files\Vim\_vimrc in Windows;
  • ~/.vimrc in Linux

Add the following lines at the beginning to instruct the auto-indent engine to use soft tabulations of 3 spaces

set sw=3

When you edit some code, hit Esc and type gg=G to edit the whole file. Other vi tips at  http://www.vim.org/tips/.

public-key authentication in OpenSSH

You can connect remotely to an OpenLBR or your OpenServer using  PuTTY in Windows. Normally, you would specify a username in Connection > Data > Auto-login username and enter the password when prompted. The problems are:

  • you don't want to enter the password every time;
  • a brute force attack will break you password and you'll end up reinstalling the server.

Instead, you should use public key authentication:

  • download  puttygen.exe
  • double-click on it and choose Generate. Follow the instructions so you end up with two files public_key.pub and private_key.ppk on your hard drive.
  • on your Linux server:
    • create a file called ~/.ssh/authorized_keys2 (Ubuntu) or ~/.ssh/authorized_keys (all other Linux flavors) which contains your public key.
    If your public_key.pub contains:
    ---- BEGIN SSH2 PUBLIC KEY ----
    Comment: "rsa-key-thomas"
    AAAAB3NzaC1yc2EAAAABJQAAAIBx8jcskAQwgmw2ZR18K1cyW4NyQDFhLYiva4WL
    DHyVgxBuo95ndyeYHoc1lk6FpRpV9jdvTCD4rGx8OT28dFyVFvDSiNxbwm/qMHhv
    Y9Vtu7842h0Hkelb5w2DU8Qvp33OQ67frQNKcvnYOP2MQxkfKVRInP/pfzuux0Ni
    ErcFxQ==
    ---- END SSH2 PUBLIC KEY ----
    
    Your ~/.ssh/authorized_keys should contain:
    ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIBx8jcskAQwgmw2ZR18K1cyW4NyQDFhLYiva4WLDHyVgxBuo95ndyeYHoc1lk6FpRpV9jdvTCD4rGx8OT28dFyVFvDSiNxbwm/qMHhvY9Vtu7842h0Hkelb5w2DU8Qvp33OQ67frQNKcvnYOP2MQxkfKVRInP/pfzuux0NiErcFxQ==
    
    • If you want only public authentication, and never a password (recommended), add the following line to /etc/ssh/sshd_config:
      PasswordAuthentication no
      
    • restart your OpenSSH server:
      sudo /etc/init.d/ssh restart
      
  • on your Windows computer
    • Load the session to your server
    • In Connection > SSH > Auth, put the path to your private key in tehe Private key file for authentication field

retrieve the IP address of an interface

ifconfig eth0 | sed -n '/inet addr:/s/.*addr:\([^ ]*\) .*/\1/p'

change the name of your Linux machine

echo 'openlbr5' > /etc/hostname

then reboot.

have you Linux machine set its time from the Internet

# apt-get install ntp