Imagemagick / MagickWand under alpine linux / python-alpine

The python implemention of MagickWand, aptly named Wand, requires ImageMagick and MagickWand installed. While building docker images using the python:alpine base images, these dependencies can be installed through:

ENV MAGICK_HOME=/usr
RUN apk add --no-cache imagemagick && \
apk add --no-cache imagemagick-dev

The first one is required for Wand to find the installed MagickWand libraries, while the second installs the imagickmagick development dependencies (and thus, the magickwand shared library).

cmd.exe – program has stopped working – but it works in Windows Explorer?

After digging through this issue for _at least_ four hours today, I’ve revisited an issue that crept up 1,5 years ago. This time I found out that it actually happened to most 32-bit programs launched under cmd. Since the Android SDK’s utilities are compiled in 32-bit mode by default, this time I had to actually find out what was causing the issue.

Turns out it was ansicon.exe. After starting the 32-bit cmd.exe from windows\SysWOW64 and stuff worked – I discovered I got an error about ansicon.exe not being able to load. Removing ansicon.exe completely solved the problem. I’m .. stunned.

Google Doubleclick DFP – Getting the Debug Console When Running in Asynchronous Mode

When trying to find out why a particular ad campaign isn’t being delivered as you thought it should, the DFP documentation indicates that you should apply “google_debug” to the URL and a new window show pop up with the debug information. After digging through documentation and searching Google for a couple of hours without getting this to work, I finally found the relevant part of the DFP documentation.

Here’s the kicker: in the new, improved ad handler (gpt.js) you’ll have to append “google_console=1” in your URL, then press CTRL+F10 to launch the debug console. No google_debug, no google_pubconsole, just google_console and CTRL+F10.

Hopefully this will help someone trying to find out by searching for relevant terms.

Checking Status of a Background Task in python-gearman

After stumbling over a question on stackoverflow about how you’d use python-gearman for checking the current status of a running background task, I decided to dig a bit deeper into python-gearman and .. well, answer how you’d do just that.

It turns out it wasn’t as straight forward as it should have been, but at least I managed to solve it by using the current API. First of all you’ll have to keep track of which Gearman server gets your task, and what handle it has assigned to the task. These two values identify a current running task, and since the identifiers (handle) isn’t globally unique, you’ll also have to keep track of the current server (so you know where to ask).

To request the current status of a long running task you’ll have to create appropriate instances of the GearmanJob and GearmanJobRequest yourself.

Here’s a small example of how you can do this:

import gearman
    
client = gearman.GearmanClient(['localhost'])
result = client.submit_job('reverse', 'this is a string', background=True);

The connection information is available through result.job.connection (.gearman_host and .gearman_port), while the handle is available through result.job.handle.

To check the status of a currently running job you create a GearmanClient, but only supply the server you want to query for the current state:

client = gearman.GearmanClient(['localhost'])

# configure the job to request status for - the last four is not needed for Status requests.
j = gearman.job.GearmanJob(client.connection_list[0], result.job.handle, None, None, None, None)

# create a job request 
jr = gearman.job.GearmanJobRequest(j)
jr.state = 'CREATED'

# request the state from gearmand
res = client.get_job_status(jr)

# the res structure should now be filled with the status information about the task
print(str(res.status.numerator) + " / " + str(res.status.denominator))

That should at least solve the problem until python-gearman gets an easier API to do these kinds of requests.

Update: I’ve also added a convenience function to my python-gearman fork at github.

btinfohash – A Small Python Utility for Getting an info_hash

While attempting to add torrents to a closed tracker I needed the info_hash structure for a given torrent file, as this is what the tracker uses to identify a given torrent file. I tried searching the regular sources but came up empty (I later discovered that btshowmetainfo from the original python bittorrent client package also shows the calculated info_hash for a torrent file), so I wrote a simple python script for all your shell scripting or command line needs.

#!/usr/bin/python
import bencode, BTL, hashlib, sys

if (len(sys.argv) < 2):
    sys.stderr.write("Usage: " + sys.argv[0] + " \n")
    sys.exit()

try:
    with open(sys.argv[1], "rb") as torrent_file:
        try:
            bstruct = bencode.bdecode(torrent_file.read())

            if 'info' in bstruct:
                print(hashlib.sha1(bencode.bencode(bstruct['info'])).hexdigest())
            else:
                sys.stderr.write("Did not find an info element in the torrent file.\n")
                sys.exit()
        except BTL.BTFailure:
          sys.stderr.write("Torrent file did not contain a valid bencoded structure.\n")
          sys.exit()
except IOError as e:
    sys.stderr.write("Could not open file: " + str(e) + "\n")
    sys.exit()

This depends on the bencode.py and BTL.py from the bencode python package (their .eggs are borked, so you’ll have to copy the two .py files yourself after downloading the source file).

Replacing / Moving a Branch to Trunk in Subversion (SVN)

After developing a feature branch for Way Too Long, we finally reached our milestone a couple of weeks ago. In the meantime a few patches had been ported back to trunk, but most work had been done in the branch. The easiest way to handle this dependency in Subversion seemed to be to simply switch trunk with the current feature branch, and so we did. It works something along the lines of:

  • svn del trunk
  • svn commit
  • svn mv branches/Name trunk
  • svn commit

A handly little recipe can be found at BigSmoke: Replacing SVN trunk with branch. Enjoy!

Getting ÆØÅ to Work in mutt / putty

After reinstalling the server (see the previous post), mutt didn’t show the norwegian letters ÆØÅ properly any longer (.. and yes, I use mutt to read my E-mails. Nothing else comes close.) .. The issue was apparently related to the settings for the current locale, but a quick check showed things to be perfectly valid (.. although not UTF-8, but that’s another issue):

mats@computer:~$ locale
LANG=nb_NO.iso88591
LC_CTYPE="nb_NO.iso88591"
LC_NUMERIC="nb_NO.iso88591"
LC_TIME="nb_NO.iso88591"
LC_COLLATE="nb_NO.iso88591"
LC_MONETARY="nb_NO.iso88591"
LC_MESSAGES="nb_NO.iso88591"
LC_PAPER="nb_NO.iso88591"
LC_NAME="nb_NO.iso88591"
LC_ADDRESS="nb_NO.iso88591"
LC_TELEPHONE="nb_NO.iso88591"
LC_MEASUREMENT="nb_NO.iso88591"
LC_IDENTIFICATION="nb_NO.iso88591"

Why didn’t mutt show the proper letters then? Everything seems to be OK .. Instead, it just kept showing “?” where either of ÆØÅ should be.

Well, the settings are one thing, but if the locale itself isn’t available, things ain’t gonna be any better. So let’s fix that:

apt-get install locale-all

And .. well, at least we have the locale available now, but before we can use it, we need to generate the binary version. Find /etc/locale.gen and open the file in a suitable editor.

Find the line for the locale you’re using and uncomment it:

# nb_NO ISO-8859-1
# nb_NO.UTF-8 UTF-8

becomes:

nb_NO ISO-8859-1
nb_NO.UTF-8 UTF-8

Then run ‘locale-gen’ as root. Wait a few seconds and the locales will be generated. Run mutt. Be happy.

Back From Some Semi-Unscheduled Downtime

The blog (and everything else hosted on this server) was down for a total of 8 hours tonight. We started seeing disk read errors in the kernel log on friday, and spent the weekend backing up and saving configuration files that weren’t already in the off site backup. My host (NGZ) responded quickly and told me to just give them a hint when the server was ready for the disk change.

We decided to stop postfix from accepting email last sunday night, after which I ran a complete rsync and dumped the contents of MySQL and other services. We’ve just started up postfix again, and everything seems to be working as it should (.. after remembering to start spamd and install procmail again…).

Oh well. Back from the dead to haunt you yet again!

We’ll have a few minutes downtime in a couple of days when we remove the troubled disk again, but until then, stay happy!

Pinouts for the Guitar Hero World Tour Wireless Controller

If you’ve ever wondered exactly which buttons correspond to which pins on the internal layout of the Xbox 360 Guitar Hero World Tour Wireless Controller, look no further! If you ever see the insides of such a controller and are wondering exactly which buttons are designated to which pins or wires, this can save you the trouble of opening both the neck and the base:

Green (A): 1 + 8
Red (B): 2 + 7
Yellow (Y): 2 + 6
Blue (X): 2 + 3
Orange (LB): 4 + 5

Attach a multimeter to measure the resistance between the two pins for each button, and you’ll see the value drop towards zero each time you press the corresponding button. This is very useful for debugging an issue where one of the buttons seems broken.

Good luck!

jQuery – IE triggers several click events

Strange problem occurred today, one of the very rare occasions were the behaviour of jQuery differed between Internet Explorer and Firefox. I’ve been trying to create a minimal example that replicates the behaviour, but have failed so far.

The problem was that in IE a click event triggered several times, which led an element to be expanded and then contracted again. This did not happen in Firefox. I found out that the problem was that I had placed my jQuery segment further inside the loop than I meant to, leading to code being duplicated four or five times through the page. After removing the duplicated function names and binds to .click(), everything worked as it should.

If you get several events triggered in Internet Explorer, but not in Firefox, check that you’re not accidentally binding the same function several times (.. while creating a minimized example that does this, I got the expected behaviour in both browsers, so I’m not completely sure of the reason). It might be worth a try as a fix, tho.