My blog has moved!

You should be automatically redirected. If not, visit
http://benohead.com
and update your bookmarks.

Friday, April 27, 2012

Debian: Configure a static IP address

In order to configure a network device statically, you have to edit /etc/network/interfaces:

# vi /etc/network/interfaces

There you can configure a static IP address and the subnet mask:

auto eth0
iface eth0 inet static
address 192.168.128.128
netmask 255.255.255.0

In order to have the changes enabled, you need to restart the network interface either with:

# /etc/init.d/networking restart
or
# /etc/init.d/networking stop
# /etc/init.d/networking start
or
# ifdown eth0
# ifup eth0

You can then check the new eth0 settings with:

# ifconfig -a

Debian: change the keyboard layout from the console

I've installed a new test system to play around a little bit (a Debian Squeeze install). Since I was too lazy to install it from scratch and I'm using VMWare anyway, I thought I'd just download a pre-installed virtual machine.

Now this virtual machine had a US keyboard configured and I'm using a German keyboard. After googling for how to change the keyboard layout from the console, I found a few hints:

dpkg-reconfigure console-data

Unfortunately the package console-data is not installed on my system.

Then I found the following:

dpkg-reconfigure keyboard-configuration

This package is installed and you can choose a keyboard layout. Great !

After saving, I pressed "Z" and got a "Y" on the console. So still having a US keyboard configured.

Since keyboard-configuration modifies the file /etc/default/keyboard, I checked this file:

# cat /etc/default/keyboard
# Check /usr/share/doc/keyboard-configuration/README.Debian for
# documentation on what to do after having modified this file.
 
# The following variables describe your keyboard and can have the same
# values as the XkbModel, XkbLayout, XkbVariant and XkbOptions options
# in /etc/X11/xorg.conf.

XKBMODEL="pc105"
XKBLAYOUT="de"
XKBVARIANT="nodeadkeys"
XKBOPTIONS=""

# If you don't want to use the XKB layout on the console, you can
# specify an alternative keymap. Make sure it will be accessible
# before /usr is mounted.
# KMAP=/etc/console-setup/defkeymap.kmap.gz

Everything looks fine... But the hint in the beginning of the file might be pointing to the solution. So let's check this README.Debian file:

# cat /usr/share/doc/keyboard-configuration/README.Debian
After modifying /etc/default/keyboard, you can apply the changes to the linux console by running setupcon. If X is configured to use that file too, then the changes will become visible to X only if

udevadm trigger --subsystem-match=input --action=change

There is the solution:

#setupcon

And the keyboard layout is German !!

Linux: get info regarding a process ID

With the following, you can get some information regarding a given process ID. It displays the following:
  • working directory
  • environment variables
  • cpu usage
  • memory usage
  • TCP connections
  • UDP connections
  • List of open file handles

Here an example of the ouput for the rpcbin process:

# processinfo.sh 3822
Information about process 3822

----- Working Directory -----

/

----- Command line -----

/sbin/rpcbind CONSOLE=/dev/console SELINUX_INIT=YES ROOTFS_FSTYPE=ext3 SHELL=/bin/sh TERM=linux ROOTFS_FSCK=0 crashkernel=128M-:64M LC_ALL=POSIX instmode=cd INIT_VERSION=sysvinit-2.86 REDIRECT=/dev/tty1 COLU

----- Environment -----

CONSOLE=/dev/console
SELINUX_INIT=YES
ROOTFS_FSTYPE=ext3
SHELL=/bin/sh
TERM=linux
ROOTFS_FSCK=0
crashkernel=128M-:64M
LC_ALL=POSIX
instmode=cd
INIT_VERSION=sysvinit-2.86
REDIRECT=/dev/tty1
COLUMNS=96
PATH=/bin:/sbin:/usr/bin:/usr/sbin
vga=0x314
DO_CONFIRM=
RUNLEVEL=3
PWD=/
SPLASHCFG=/etc/bootsplash/themes/SLES/config/bootsplash-800x600.cfg
PREVLEVEL=N
LINES=33
HOME=/
SHLVL=2
splash=silent
SPLASH=yes
ROOTFS_BLKDEV=/dev/sda2
_=/sbin/startproc
DAEMON=/sbin/rpcbind

----- Resource usage -----

CPU : 0.0%
MEMORY: 0.0%

----- TCP connections -----

Status: LISTEN local: 0.0.0.0:111 remote: 0.0.0.0:*
Status: LISTEN local: :::111 remote: :::*

----- UDP connections -----

Local: 0.0.0.0:605 remote: 0.0.0.0:*
Local: 0.0.0.0:111 remote: 0.0.0.0:*
Local: :::605 remote: :::*
Local: :::111 remote: :::*

----- Open files -----

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rpcbind 3822 root cwd DIR 8,2 4096 2 /
rpcbind 3822 root rtd DIR 8,2 4096 2 /
rpcbind 3822 root txt REG 8,2 56536 123002 /sbin/rpcbind
rpcbind 3822 root mem REG 8,2 61467 466970 /lib64/libnss_files-2.11.1.so
rpcbind 3822 root mem REG 8,2 19114 466959 /lib64/libdl-2.11.1.so
rpcbind 3822 root mem REG 8,2 39712 466992 /lib64/libgssglue.so.1.0.0
rpcbind 3822 root mem REG 8,2 108213 466964 /lib64/libnsl-2.11.1.so
rpcbind 3822 root mem REG 8,2 1661454 466953 /lib64/libc-2.11.1.so
rpcbind 3822 root mem REG 8,2 135646 466979 /lib64/libpthread-2.11.1.so
rpcbind 3822 root mem REG 8,2 160248 467049 /lib64/libtirpc.so.1.0.10
rpcbind 3822 root mem REG 8,2 42016 467021 /lib64/libwrap.so.0.7.6
rpcbind 3822 root mem REG 8,2 149797 466946 /lib64/ld-2.11.1.so
rpcbind 3822 root 0u CHR 1,3 0t0 2372 /dev/null
rpcbind 3822 root 1u CHR 1,3 0t0 2372 /dev/null
rpcbind 3822 root 2u CHR 1,3 0t0 2372 /dev/null
rpcbind 3822 root 3r REG 8,2 0 361286 /var/run/rpcbind.lock
rpcbind 3822 root 4u sock 0,6 0t0 8357 can't identify protocol
rpcbind 3822 root 5u unix 0xffff880233c4a3c0 0t0 8319 /var/run/rpcbind.sock
rpcbind 3822 root 6u IPv4 8321 0t0 UDP *:sunrpc
rpcbind 3822 root 7u IPv4 8325 0t0 UDP *:soap-beep
rpcbind 3822 root 8u IPv4 8326 0t0 TCP *:sunrpc (LISTEN)
rpcbind 3822 root 9u IPv6 8328 0t0 UDP *:sunrpc
rpcbind 3822 root 10u IPv6 8330 0t0 UDP *:soap-beep
rpcbind 3822 root 11u IPv6 8331 0t0 TCP *:sunrpc (LISTEN)

And here's the script. It's not too spectacular, just gathering data from /proc/xxx, ps, netstat and lsof:
 
#!/bin/sh

if [ $# -ne 1 ]; then
echo Usage: $0 PID
exit 1
fi

PID=$1

if kill -0 $PID; then
echo Information about process $PID
echo
echo ----- Working Directory -----
echo
readlink /proc/$PID/cwd
echo
echo ----- Command line -----
echo
ps eho command -p $PID
echo
echo ----- Environment -----
echo
strings -f /proc/$PID/environ | cut -f2 -d ' '
echo
echo ----- Resource usage -----
echo
echo CPU : `ps eho %cpu -p $PID`%
echo MEMORY: `ps eho %mem -p $PID`%
echo
echo ----- TCP connections -----
echo
netstat -pan | grep " $PID/" | grep tcp | awk ' { print "Status: "$6" local: "$4" remote: "$5; }'
echo
echo ----- UDP connections -----
echo
netstat -pan | grep " $PID/" | grep udp | awk ' { print "Local: "$4" remote: "$5; }'
echo
echo ----- Open files -----
echo
lsof -p $PID
else
echo Process $PID does not exist
exit 2
fi

Thursday, April 26, 2012

Sybase: Find all tables in a database with a unique index

The following statement will return a list of all user tables in the current database which have a unique index:

SELECT o.name FROM sysobjects o, sysindexes i WHERE o.id = i.id AND o.type='U' AND i.status & 2 = 2 GROUP BY o.name ORDER BY o.name
 
If you're also interested in the index name, use the following:
 
SELECT o.name, i.name FROM sysobjects o, sysindexes i WHERE o.id = i.id AND o.type='U' AND i.status & 2 = 2 ORDER BY o.name

Sybase: create a proxy for a remote database

Note that all strings in bold+italic should be changed to something which is relevant for your setup.

First you have to make the remote server known locally:

sp_addserver "logical_name" , ASEnterprise, "xxx.xxx.xxx.xxx:2055"
 
You can choose anything as a logical name. This is how the remote server will be called in master..sysservers and the name used by the other commands we'll use.
If you use another port than 2055, you of course have to change it in the statement above.
"ASEntreprise" is the remote server type and means it is also an ASE server.

You can check whether the remote server has been added properly:

SELECT * FROM master.dbo.sysservers WHERE srvname = "logical_name"

Now you need to create an entry in the sysremotelogins table for the remote server. This is done with the stored procedure sp_addremotelogin.

If you have the same users on both server, you can just execute the following to map remote names to local names:

sp_addremotelogin logical_name

If you want to map all logins from the remote server to a local user name:

sp_addremotelogin logical_name, local_user_name

If you only want to map a single remote login from a remote user on the remote server to a local use:

sp_addremotelogin logical_name, local_user_name, remote_user_name

Now we can create the proxy database:

create database proxy_db_name on default = 200M with default_location = 'logical_name.remote_db_name..' for proxy_update
 
If you do not want to create it on default but on a new device, you'll need to first create the device.

disk init name="proxy_dev", physname="/var/sybase/ASE/proxy_dev.dat", size="200M"

Of course the parent directory of the file which path is set in physname should exist and the appropriate rights should be set.
(you can also added the parameter directio=true to this command if required)

And then create the database:

create database proxy_db_name on proxy_dev = 200M with default_location = 'logical_name.remote_db_name..' for proxy_update

Now you can use the proxy database to access data of all tables in the remote database:

select name from proxy_db_name..sysobjects

The data are still residing on the remote server so you do not need to do anything when data change. But if the structure changes (i.e. if you add or remove tables or update the structure of a table), you need to update the proxy:

alter database proxy_db_name for proxy_update

Tuesday, April 24, 2012

Abstract classes in python

Abstract classes (or abstract types) are a common concept in object-oriented programming. They cannot be instantiated and may contain methods without implementation (called abstract methods). In order to be used, they need to be derived to concrete classes (which fully implement all methods defined in the parent abstract class). Interfaces are also very similar to abstract classes without any implementation (although they are different from a sementical point of view).

Python has neither abstract classes nor interfaces. But there is a couple of ways to replicate this behavior:

A class can define "placeholder" methods which do nothing (pass):

class AbstractClass(object):
    def abstractMethod(self):
        pass


The issue with this way of defining an abstract class is that this class can be instantiated and the method can be called (but will have no effect).

In order to make sure that this class cannot be instantiated, you can implement some login in __init__:

def __init__(self):
    if type(self) == AbstractClass:
        raise Exception("AbstractClass is an abstract class and cannot be instantiated.")


And in order to make sure that the empty methods cannot be called, you can raise an exception instead of passing:

def abstractMethod(self):
        raise NotImplementedError


These two checks are of course not providing the same as abstract classes in other languages since the check will only be performed at runtime and not at compile time.

Monday, April 23, 2012

Debian: Remove packages in status rc

The status rc says that the package was removed but the configuration files are still on disk. This happens either when the packages are deleted with apt-get remove or they are automatically removed due to a dependency. In this second case, it also happens if the main package was purged and not only removed.

You can determine which package are in this status with:

# dpkg -l | grep ^rc

So executing this will return only the names of all these packages:

# dpkg -l | grep ^rc | awk '{print $2}'

And to purge all these packages:

# dpkg -l | grep ^rc | awk '{print $2}' | xargs dpkg -P

If you want to first see what dpkg would do, use:

# dpkg -l | grep ^rc | awk '{print $2}' | xargs dpkg --no-act -P