Go tutorial in Dutch

During the last few weeks I’ve attempted to translate the Go tutorial to Dutch. This was a lot more work than anticipated and I’m still not finished, but I just wanted to share what I’ve got up to now.

You can get the text version here.

Things do

  • Finish translating the last few paragraphs;
  • Proof read;
  • Spell check;
  • Update it to the latest Go release;
  • Get this included in Go?
Read more →

upstart and booting with init=/bin/bash

One of the oldest tricks in the sys admin’s arsenal is booting with init=/bin/bash. You’ll need this when you want to reset the password for root for instance.

It used to go like this: Boot with init=/bin/bash and after some time you greeted with a prompt ala

root@(none):/# 

Most often I then took the following steps:

mount -o rw,remount /
/etc/init.d/networking start

Now you also have networking, so you may upgrade the system with apt-get or whatever… You are now a happy puppy.

Read more →

My f() function in Zsh (and maybe Bash)

Familiar with the following?

You are aware of (shell)file which contains a interesting line and you think: “I want to execute this line on the command prompt”. Most people will do the following:

% more <file>
[select interesting bit with your mouse]
[paste]<enter>

And the code gets executed.

I propose the following function: f(), which does the following:

  1. It opens the file in $EDITOR (:= vim of course);
  2. You delete everything you don’t want to execute;
  3. What’s left gets executed;
  4. And it is added to your shell’s history.

The code of the function looks like this:

Read more →

map function in Go

There is better stuff in the standard Go release but I wanted to try something for myself. In Go, this function is also called Map(), but is (of course) nicer. Anyhow, I’m liking this Go stuff more and more. Next I want to rewrite the DNS stuff in Go.

package main

import (
    "fmt"
)

type e interface{}

func mult2(f e) e { 
    switch f.(type) {
    case int:
	    return f.(int) * 2 
    case string:
	    return f.(string) + f.(string)
    }   
    return f
}

func Map(n []e, f func(e) e) {
    for k, v := range n { 
	    n[k] = f(v)
    }   
}

func main() {
    m := [...]e{1, 2, 3, 4}
    s := [...]e{"a", "b", "c", "d"}
    Map(&m, mult2)
    Map(&s, mult2)
    fmt.Printf("%v\n", m)
    fmt.Printf("%v\n", s)
}
Read more →

Inotify

This is a translation from this article which is published in Dutch

During our work at Octrooicentrum Nederland somebody came up with the following question. During the night a file was created in a directory and he wanted to know who (which process) was responsible for that. My first reaction was: “Can’t be done”.

However, that evening I thought of inotify which could be of help. With inotify you can watch your file system and get notified when “something” (read, write, create, etc.) happens. For (much) more detailed information look in inotify(7).

Read more →

Prime sieve (in Go ofcourse)

After reading up on the prime sieve, and playing with Go for the past week I thought needed to implement this algorithm in Go and make it parallel.

I want to create a set (n in 2..N) goroutines. Each of these routines will check if it can divide a number (i) by n (integer division). If so the number i is not prime, otherwise it is given to the next goroutine. Communication between the goroutines is done via channels as in this example.

Read more →

More Go

Still learning and playing with Go, I’ve rewritten my cat experiment, to use a *bufio.Reader, which is more correct I think. I’m also slowly wrapping my mind around the concept of Interfaces. As a non-OO programmer (C and non-OO Perl) is starting to see why this is useful.

So today’s exercises:

  1. Write a cat implementation in Go. See below.
  2. Write a grep implementation in Go. See below.

Cat in go

package main

// A implementation of cat in Go

import (
    "os";
    "fmt";
    "bufio";
    "flag";
)

var numberFlag = flag.Bool("n", false, "number each line")

func cat(r *bufio.Reader) bool {
    i := 1;
    for {
	    buf, e := r.ReadBytes('\n');
	    if e == os.EOF {
		    break
	    }
	    if *numberFlag {
		    fmt.Fprintf(os.Stdout, "%5d  %s", i, buf);
		    i++
	    } else {
		    fmt.Fprintf(os.Stdout, "%s", buf)
	    }
    }
    return true;
}

func main() {
    flag.Parse();
    if flag.NArg() == 0 {
	    cat(bufio.NewReader(os.Stdin))
    }
    for i := 0; i < flag.NArg(); i++ {
	    f, e := os.Open(flag.Arg(i), os.O_RDONLY, 0);
	    if e != nil {
		    fmt.Fprintf(os.Stderr, "%s: error reading from %s: %s\n",
			    os.Args[0], flag.Arg(i), e.String());
		    continue;
	    }
	    if !cat(bufio.NewReader(f)) {
		    os.Exit(1)
	    }
    }
}

Grep in go

package main

// A implementation of Unix grep in Go
// TODO(mg) better error handling

import (
    "os";
    "fmt";
    "bufio";
    "regexp";
    "flag";
)

var numberFlag = flag.Bool("n", false, "number each line")
var filenameFlag = flag.Bool("l", false, "print names of matching files")

func grep(r *bufio.Reader, reg string) (match bool) {
    i := 0;
    for {
	    buf, e := r.ReadBytes('\n');
	    i++;
	    if e == os.EOF {
		    break
	    }
	    if m, _ := regexp.Match(reg, buf); m == true {
		    match = true;
		    if *filenameFlag {
			    return match
		    }
		    if *numberFlag {
			    fmt.Fprintf(os.Stdout, "%5.d:  %s", i, buf)
		    } else {
			    fmt.Fprintf(os.Stdout, "%s", buf)
		    }
	    }
    }
    return match;
}

func main() {
    flag.Parse();
    if flag.NArg() < 1 {
	    fmt.Fprintf(os.Stderr, "%s: missing regexp\n", os.Args[0]);
	    os.Exit(1);
    }
    if flag.NArg() == 1 {
	    if grep(bufio.NewReader(os.Stdin), flag.Arg(0)) {
		    if *filenameFlag {
			    fmt.Fprintf(os.Stdout, "(standard input)\n");
		    }
	    }
    }
    for i := 1; i < flag.NArg(); i++ {
	    f, e := os.Open(flag.Arg(i), os.O_RDONLY, 0);
	    if e != nil {
		    fmt.Fprintf(os.Stderr, "%s: error reading from %s: %s\n",
			    os.Args[0], flag.Arg(i), e.String());
		    continue;
	    }
	    if grep(bufio.NewReader(f), flag.Arg(0)) {
		    if *filenameFlag {
			    fmt.Fprintf(os.Stdout, "%s\n", flag.Arg(i))
		    }
	    }
    }
}
Read more →

cat in Go

After spending every free minute to Go I’m starting to get a feel for the language. Every one has to start somewhere, so I decided to “port” Unix utils to Go. I’m starting with cat, and thanks to the Go tutorial this is the result.

package main

// An implementation of Unix cat in Go

import (
    "os";
    "fmt";
    "flag";
)

func cat(filename string) bool {
    const NBUF = 512;
    var buf [NBUF]byte;
    if f, e := os.Open(filename, os.O_RDONLY, 0); e != nil {
	    fmt.Fprintf(os.Stderr, "cat: error reading from %s: %s\n",
		    filename, e.String());
	    return true;
    } else {
	    for {
		    switch nr, _ := f.Read(&buf); true {
		    case nr < 0:
			    os.Exit(1)
		    case nr == 0:	// EOF
			    return true
		    case nr > 0:
			    if nw, ew := os.Stdout.Write(buf[0:nr]); nw != nr {
				    fmt.Fprintf(os.Stderr,
					    "cat: error writing from %s: %s\n",
					    filename, ew.String());
				    return false;
			    }
		    }
	    }
    }
    return true;
}

func main() {
    flag.Parse();	// implement -n TODO
    if flag.NArg() == 0 {
	    cat("/dev/stdin")
    }
    for i := 0; i < flag.NArg(); i++ {
	    if !cat(flag.Arg(i)) {
		    os.Exit(1)
	    }
    }
}

In something like 50 lines you have a cat program. I’m really starting to like Go. Next up: extra features and a grep command.

Read more →

First steps with Go

I joined the go-nuts mailing list a few days ago and it really feels good to receive 200+ emails per day again. Just like in the good old days before good spam filtering (and anti-spam laws).

I also re-watched the presentation Rob Pike gave for Google Tech Talks on youtube.com. In there he presented the following program chain.go: (Formatted with gofmt as it should)

package main

import (
    "flag";
    "fmt";
)

var ngoroutine = flag.Int("n", 100000, "how may")

func f(left, right chan int)    { left <- 1+<-right }

func main() {
    flag.Parse();
    leftmost := make(chan int);

    var left, right chan int = nil, leftmost;
    for i := 0; i < *ngoroutine; i++ {
	    left, right = right, make(chan int);
	    go f(left, right);
    }
    right <- 0;             // bang!
    x := <-leftmost;        // wait for completion
    fmt.Println(x);         // 100000
}

In this short program we make a chain of 100000 goroutines which are connected to each other. Each one adds 1 to the value it gets from its right neighbor. We start it of by giving the last one (right) a value of 0. Then we wait until they are finished and print it.

Read more →

Go language

I’ve been wanting to learn (and do something) with the language Erlang for over two years now. But every time I fire up vim and start typing a get a this-is-not-Unix feeling (aka Java-sickness). The syntax is just not right for me.

But now Google, by the creators of Unix and C, give us Go! Which promises to give us Erlang functionality in a C-like language. Just what I wanted!

Basically just follow the steps on golang.org. In short it boils down to:

Read more →

New layout

After running with the old style for a couple of years I wanted something new. And after a few days battling with Wordpress I decided to stay with nb, because it just rules.

The theme is loosly based on the design from Wordpress called SimplicitlyDark and the css from daring fireball.

But still a new (clean) style. During the restyling I also fixed the archives and found out that nb cannot handle articles with [[ in their name.

Read more →

Dymo 400 Label Writer in Ubuntu (Jaunty/Karmic)

Apparently the cups driver (ppd) for Ubuntu (in both Karmic and Jaunty) is not installed by default, see this and this for more information.

The strange thing is that if you look at openprinting.org, it says

Dymo LabelWriter 400

Supplied with CUPS Works perfectly.

Supplied with cups??? Works perfectly?? How, where, when??

Well:

% apt-get source cups
% ls -l cups-1.3.9/ppd/dymo.ppd
-rw-rw-r-- 1 miekg miekg 24K Nov 27  2007 cups-1.3.9/ppd/dymo.ppd

And that’s your ppd file. For good measure I’ve put this up for download here too.

Read more →

Fedora 11 vs Ubuntu 9.10

My small and very personal comparison between Fedora 11 (which I run on my laptop) and Ubuntu 9.10 which is my main Linux distribution.

  1. yum vs apt-get
  • yum is a lot slower than apt-get
  • why do I need connectivity when using yum search
  • Why does yum defaults to ‘N’ (no) when I ask it to install software?

All in all I like apt-get a lot better.

  1. Default resolution
  • Ubuntu 9.10 configured my EeeBox and monitor out of the box, Fedora 11 didn’t.
  1. Plymouth graphical boot

Very nice to see this in Fedora 11, I want this too for Ubuntu. Too bad Ubuntu does not use this in 9.10. It will happen in 10.04 (I heard).

Read more →

KPN redux

I installed my new laptop with Fedora 11, and I must say that it is a very nice distribution. I’m even contemplating leaving PulseAudio enabled, ‘cause it just works. Unlike ubuntu.

To update my story on the KPN dongle (dongel). I just used it on this laptop and it worked out of the box. The only thing you need to remember is that you need to insert the stick before booting you machine. It will not work if you insert it afterwards. If you observe this rule it will just pop up in NetworkManager.

Read more →

Use upstart to replace rc.local

On my new netbook I wanted to get rid of gdm and just start X right away. I use auto-login anyway so it is a bit stupid to first start gdm and then immediately start X.

So I removed gdm and edited /etc/rc.local to start X:

    su - miekg -c xinit xterm

But this sort of does not work anymore in Ubuntu Karmic. Karmic now uses upstart as an init replacement. So I figured why not write an upstart job that starts X?

Read more →

Goodbye charm, welcome up

I’ve bought a new 11.1" netbook from Asus, this is going to replace my aging 4G Surf (named charm). I’ve named the new one up, so I’m hoping the Large Hadron Collider is up and running soon and discovers a new flavor of quarks - ‘cause I’m running out of names. (strange is already allocated if I ever buy a Mac and run Linux on that, top and bottom just don’t sound right).

Read more →

Microsoft rules . ?

Okay, I could not find this in the specs, but I do find this fishy. When querying a Windows DNS server it will give out an authoritative answer (aa bit set), but without an AUTHORITY section.

dig +nocmd +noidentify +multiline @ns5.msft.net. soa hotmail.com

;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;hotmail.com.	IN SOA

;; ANSWER SECTION:
hotmail.com.	86400 IN SOA ns1.msft.net. msnhst.microsoft.com. (
		    2009100802 ; serial
		    1800       ; refresh (30 minutes)
		    900        ; retry (15 minutes)
		    2419200    ; expire (4 weeks)
		    3600       ; minimum (1 hour)
		    )

;; ADDITIONAL SECTION:
ns1.msft.net.	3600 IN	A 65.55.37.62

And it gets worse:

Read more →

iotop

iotop is a very neat tool showing the processes which do the most i/o in a top-like manner.

Again having fun with SLES:

SLES-10:

# rpm -i /tmp/iotop-0.3.2-1.1.x86_64.rpm 
warning: iotop-0.3.2-1.1.x86_64.rpm: Header V3 DSA signature: NOKEY, key ID ee454f98
error: Failed dependencies:
python >= 2.5 is needed by iotop-0.3.2-1.1.x86_64

Goes off and installs SLES-11

SLES-11:

# rpm -i
warning: /tmp/iotop-0.3.2-1.1.x86_64.rpm: Header V3 DSA signature: NOKEY, key ID ee454f98
error: Failed dependencies:
python < 2.6 is needed by iotop-0.3.2-1.1.x86_64

Nooooo!

Read more →

Spot the problem

An unofficial rpm of e2fsprogs installed on a SLES 10 system:

# ldd /sbin/e2fsck 
libdb-4.3.so => /usr/lib64/libdb-4.3.so (0x00002b5e004e2000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00002b5e006d6000)
libc.so.6 => /lib64/libc.so.6 (0x00002b5e007ef000)
/lib64/ld-linux-x86-64.so.2 (0x00002b5e003c6000)

Now guess what happens when you reboot?

Read more →

nss-ldap

The nss-ldap module allows you to have your user information in a LDAP server. Within the module you can select some options on how to connect to the LDAP server:

  • hard, use an exponential back-off when connection, waiting up to 64 seconds before trying a different server.
  • soft, when the server is not responding give up immediately.

The problem is, both are insufficient…

With soft you don’t have any benefits for your backup LDAP server. With the hard policy you can failover to the second (or third) server, but when you boot the machine (and it does not have networking) you are stuck with the exponential back-off. This can mean that booting a server can take a couple of hours: every uid lookup will take 64 seconds.

Read more →

KPN Dongle with Ubuntu

Well, as I’m off to The Hague for the rest of the year, I need some kind of Internet in the evening. So off to KPN to get a umts card (or dongel as they call it). For late night gaming I’ve also bought a PSP :-)

Well, to make a long story short: this stuff is hard to get working in Ubuntu. When you insert the dongle it is first seen as a cdrom…, only after you successfully install the Windows software it will become a modem. Who comes up with this kind of crap?

Read more →

Monit and Munin

After trying out Zabbix, I’m back to munin and monit for my (small) monitoring needs.

I think the beautiful rrd images of munin are just unbeatable and monit has never let me down; you can easily restart daemons - something I was still configuring in zabbix. And our Ubuntu Certified Professional Course also has a few slides on munin. This was the last push I needed.

I was still a bit rusty so I just followed a howto to do the initial configuration.

Read more →

Ubuntu Karmic

Well, a lets-install-kernel-2.6.31-on-Ubuntu-Jaunty turned out to be a bad idea. The kernel install went OK, but my X went poef. No more bitmap fonts. Looks like some bad interaction between the X Intel driver and the new kernel mode settings.

Anyhow, I figured why not upgrade to Karmic? 15 minutes later my desktop system was completely hosed and I was left staring at a GRUB 1.97 menu.

I never knew that the GRUB command line allows you to type

Read more →

Remote commands with Zabbix actions

With monit services are restarted, ever since I’ve installed zabbix I wanted the same functionallity. Turns out this is possible, but it takes some configuration.

Also see the zabbix manual, where it gets interesting from page 160 onwards.

In zabbix go to Configuration->Actions.

Add a new ‘Action Operation’ in which you want to run a remote command.

  1. Operation type: remote command
  2. Remote command: host:script in my (test) case elektron:/home/miekg/bin/zabbix_service {TRIGGER.NAME}: {STATUS}

And zabbix_service is now a shell script which will echo its arguments to a file in /tmp.

Read more →