Jeff Bailey: Language lessons
So which other language should I learn? For fun, I did the first lesson of Latin (got 81%) and Japanese (83%).
And now I'll have dreams of this voice going "Hoooah toe teh mah jusa".
Mmmm. and now I want juice.
Zzzzz...
Reading Kyle's view on Konqueror and KHTML's current status: I couldn't agree more. I use konqueror instead of Firefox because I quite like its GUI, and its integration into KDE is obviously better than Firefox'. Issues with various websites prompt me to have an Iceweasel window open as well quite a large part of the time. Let's just switch to WebKit, so the market only has to care about Gecko and WebKit and can ignore one more marginal rendering engine.
I see libqt-webkit 4.5 is in experimental and a Google query on debian konqueror webkit at least shows an Ubuntu packaging effort of the Konqueror WebKit KPart, so the days of khtml on my Desktop are certainly nearing its end.
At this point: Kudos to the KDE folks (Debian and upstream). KDE4.2 is really, really usable, the remaining issues are really small. And, if I don't try to manually interfer like I did in my first attempt, migrating the KDE settings from ~/.kde4 to ~/.kde actually did work just fine on my netbook.
Dear Friends,
While I'm not a fan of cut-n-paste coding, on the odd occasion it's handy
to grab a snippet of code out of someone else's blog and plop it in.
Jeff Atwood of Coding Horror
has a solution to some of the downsides of ripping a bit of code from
somewhere on the Internet: publishers of code snippets generate a new GUID, tag each code
snippet with a GUID, and you paste that comment in with the rest of
the code when you take it. Then, if you (or someone else) needs to look
at the context of the chunk of code, find it's author, look for
improvements or commentary, or see who else has used that snippet in their
own projects, you can search for that GUID and you should come up with
only that GUID as a result.
What I propose is this:How very, very cunning. He also proposes that if you modify a snippet and republish it, you should keep the old GUID and also add one of your own, so you can track the origin and help other people find your alternate version. Attaching unique identifiers to chunks of code and sending them all around the Internet. Does this sound like distributed revision control to anyone else? A lot easier to master than Git's UI, too...// codesnippet:1c125546-b87c-49ff-8130-a24a3deda659 - (void)fadeOutWindow:(NSWindow*)window // codeAttach a one line comment convention with a new GUID to any code snippet you publish on the web. This ties the snippet of code to its author and any subsequent clones. A trivial search for the code snippet GUID would identify every other copy of the snippet on the web:http://www.google.com/search?q=1c125546-b87c-49ff-8130-a24a3deda659
So. On Sunday, we worked through some of the bugs filed against KDE in Debian. Mostly, we cleaned up in old cruft, and a few bugs got forwarded.
A bunch of the Debian KDE people participated, and some KDE Bugsquad people also dropped by. And a special thanks goes to the apparant newcomer, Karl Ferdinand Ebert, for doing a fantastic work, and I also succeeded in getting Anne-Marie Mahfouf to take a look at the kdeedu reports.
We cleaned up in kdegraphics, kdeedu, kdeadmin and akregator reports, and did quite some work on the bug magnets of konqueror, kmail and kopete.
Total result was around 100 bugs down, and we discovered a few bugs that had hidden in between the others, that is actually packaging issues.
Today was the season opener for Tripoli Colorado
at their launch site on the buffalo ranch near Hartsel, Colorado. After huge
snowfalls along the front range of the mountains in the last few days, we were
a little tentative about going, but it turned out to be nearly perfect flying
conditions! There was apparently much less snow this week on the high plains
west of the front range, and by this morning the snow had almost entirely
disappeared, the skies were clear and blue, and the winds were calm except
for a few gusty bursts in the afternoon. This launch site is really something
special, at 8800 feet above mean sea level, in the middle of a huge area of
wide-open short grass prairie. We love flying there, and today the drive to
and from the launch site through the snow-covered Colorado Rockies was just
beautiful!
Son Robert and I flew three rockets today, including his
LOC/Precision
Lil Nuke with added
payload section on an Aerotech G54W-M reload,
and our
Polecat Aerospace 5.5 inch Goblin kit on one
of the relatively new Aerotech I245G-M "Mojave Green" green-flame reloads. But by far the highlight of the day was
flying my Giant Leap Vertical Assault on
a Cesaroni J335 red-flame reload... with
serial number 1 of TeleMetrum on
board collecting our first-ever flight data!
From the ground, it looked like a textbook perfect dual-deploy flight, with a
small drogue chute out at apogee around 4000 feet above ground, and the main
chute deploying at 700 feet above ground for a beautiful, soft landing only
a couple minutes walk from the launch rail.
The ejection events were controlled by a PerfectFlite
MiniAlt/WD. The data recovered from it shows a big
negative spike in the altitude right at apogee, coincident with firing of the
apogee deployment charge. I have to assume this means the aft bulkhead on the
avionics bay in the reconstructed coupler section isn't sealing well, and some
pressure from the apogee deployment charge leaked in to the avionics bay
"fooling" the altimeter into thinking the altitude was lower for a sample or
two. Clearly, that needs to get fixed before that airframe flies again.
Further evidence that we had a mighty kick from the apogee ejection charge
was discovered when we went to clean the motor casing. The Cesaroni reloads
are packaged in a plastic liner tube that slides into the reusable aluminum
case. When we pulled the spent reload out of the case, it was significantly
shorter than when it was loaded, suggesting that the ejection charge forced
the forward closure on the reload backwards compressing the heat-softened
plastic. This could be evidence that the reconstructed coupler was slow to
separate from the booster airframe due to excessive friction?
The flight data recovered from the
TeleMetrum board looks great until
apogee, when the data collection stopped. Since I flew firmware that was
compiled and flashed on the flight line from Keith's latest git commit as
of this morning, it's entirely possible that there was a software bug that
caused data collection to terminate at apogee. We'll investigate that. But
I personally think what actually happened is that we experienced a temporary
short in the power supply at the time the apogee ejection charge fired. On
extraction of the electronics sled from the avionics bay this evening, I
noticed that one of the mounting screws has gone missing. If it wasn't snug
enough, and vibrated loose during flight, it could have been torn loose at
the time of the ejection event and shorted something as it rattled around in
the avionics bay. The screw is now just missing, but may have fallen out
when we were extracting data on the flight line just after the flight without
being noticed at the time. So I'm not inclined to worry much about this, at
least until we can get some more flight data!
Keith post-processed the raw flight data and presented me with a
plot
showing two traces, acceleration and barometric altitude. The data from the
accelerometer closely matches the published data for the motor we flew, which
is a really cool result, and my 10-year-old son enjoyed figuring out why the
rocket showed negative acceleration after the motor burn out but was still
climbing. (See, there really is some science education hidden in the fun!)
All in all, we had a great time, and it's totally cool to have data from a
first flight of TeleMetrum! Can't wait
to fly it again!
xmodmap has long
been the only way to modify the keyboard map of the X server, short
of the complex configuration daemon approaches used by the large
desktop managers, like KDE and GNOME. But it has always been a
hack: it modifies the X keyboard map and thus requires a baseline
to work from, kind of like a patch needs the correct context to be
applicable.
Worse yet, xmodmap weirdness required me to
invoke it twice to get the effect I wanted.
When the recent upgrade to X.org 7.4 broke larger
parts of
my elaborate xmodmap configuration, I took the time to finally
ditch xmodmap and implement my modifications as proper
xkb configuration.
#xorg/irc.freenode.org IRC channel to get
me started.
The other resource worth mentioning is Ivan Pascal s collection of XKB
documents, which were instrumental in my gaining an
understanding of xkb.
And just as I am writing this document, Debian s X Strike Force
have published their Input
Hotplug Guide, which is a nice complement to this very document
you are reading right now, since it focuses on auto-configuration
of xkb with HAL. The default
xkb configuration comes with a lot of flexibility, and
often you don t need anything else.
But when you do, then this is how to do it:
xkbcomp, which can also be used to dump the currently
installed map into a file. So, to get a bit of an idea of what
we ll be dealing with, please run the following commands:
xkbcomp $DISPLAY xkb.dump
editor xkb.dump
xkbcomp xkb.dump $DISPLAY
The file is complex and large, and it completely went against my
aesthetics to simply edit it to have xkb work
according to my needs. I sought a way in which I could use as much
as possible of the default configuration, and only place
self-contained additional snippets in place to do the things I
wanted done differently.
setxkbmap and rule files
Thus began my voyage into the domain of rule files. But before
we dive into those, let s take a look at setxkbmap.
Despite the trivial invocation of e.g. setxkbmap us to
install a standard US-American keyboard map, the command also takes
arguments. More specifically, it allows you to specify the
following high-level parameters, which determine the sequence of
events between key press and an application receiving a KeyPress
event:
setxkbmap -model thinkpad -layout us -variant intl -option grp:win_switch
In many cases, between all combinations of the aforementioned
parameters, this is all you ever need.
But I wanted more.
If you append -print to the above command, it will
print the keymap it would install, rather than installing it:
% setxkbmap -model thinkpad -layout us -variant intl -option grp:win_switch -print
xkb_keymap
xkb_keycodes include "evdev+aliases(qwerty)" ;
xkb_types include "complete" ;
xkb_compat include "complete" ;
xkb_symbols include "pc+us(intl)+inet(evdev)+group(win_switch)" ;
xkb_geometry include "thinkpad(us)" ;
;
There are two things to note:
-option grp:win_switch argument has been turned
into an additional include group(win_switch) on the
xkb_symbols line, just like the model, layout, and
variant are responsible for other aspects in the output.
xkbcomp dumped
into the xkb.dump file we created earlier. Upon closer
inspection, it turns out that the dump file is simply a
pre-processed version of the keyboard map, with
include instructions exploded.
xkb_keymap
stanza by setxkbmap is actually governed by a rule
file. A rule is nothing more than a set of criteria, and what
setxkbmap should do in case they all match. On a
Debian system, you can find this file in
/usr/share/X11/xkb/rules/evdev, and
/usr/share/X11/xkb/rules/evdev.lst is a listing of all
available parameter values.
The xkb_symbols include line in the above
xkb_keymap output is the result of the following rules
in the first file, which setxkbmap had matched (from
top to bottom) and processed:
! model layout = symbols
[...]
* * = pc+%l(%v)
! model = symbols
* = +inet(evdev)
! option = symbols
[...]
grp:win_switch = +group(win_switch)
It should now not be hard to deduce the xkb_symbols
include line quoted above, starting from the setxkbmap
command line. I ll reproduce both for you for convenience:
setxkbmap -model thinkpad -layout us -variant intl -option grp:win_switch
xkb_symbols include "pc+us(intl)+inet(evdev)+group(win_switch)" ;
A short note about the syntax here:
group(win_switch) in the symbols column simply
references the xkb_symbols stanza named
win_switch in the symbols file group
(/usr/share/X11/xkb/symbols/group).
Thus, the rules file maps parameters to sets of snippets to
include, and the output of setxkbmap applies those
rules to create the xkb_keymap output, to be processed
by xkbcomp (which setxkbmap invokes
implicitly, unless the -print argument was given on
invocation).
It seems that for a criteria (option, model, layout, ) to be
honoured, it has to appear in the corresponding listing file,
evdev.lst in this case. There is also
evdev.xml, but I couldn t figure out its role.
Mod4, which can be
used e.g. to control the window manager.
~/.xkb/symbols/xkbtest and add two stanzas to it:
partial alphanumeric_keys
xkb_symbols "dashes"
key <AE11>
symbols[Group2] = [ endash, emdash ]
;
;
partial modifier_keys
xkb_symbols "caps_mod4"
replace key <CAPS>
[ VoidSymbol, VoidSymbol ]
;
modifier_map Mod4 <CAPS> ;
;
Now let me explain these in turn:
grp:win_switch earlier, which
told xkb that we would like to use the windows keys to
switch to group 2. In the custom symbols file, we now simply define
the symbols to be generated for each key, when the second group has
been selected.
Key <AE11> is the hyphen key. To find out the
names of all the other keys on your keyboard, you can use the
following command:
xkbprint -label name $DISPLAY - gv -orientation=seascape -
I had to declare the stanza partial because it is
not a complete keyboard map, but can only be used to augment/modify
other maps. I also declared it alphanumeric_keys to
tell xkb that I would be modifying alphanumeric keys
inside it. If I also wanted to change modifier keys, I would
also specify modifier_keys.
The rest should be straight-forward. You can get the names of
available symbols from keysymdef.h
(/usr/include/X11/keysymdef.h on a Debian system,
package x11proto-core-dev),
stripping the XK_ prefix.
VoidSymbol).
The important aspect of the second stanza is the
modifier_map instruction, which causes the key to
generate the Mod4 modifier event, which I can later
use to bind key combinations for my window manager (awesome).
setxkbmap -print output of the keyboard map you would
like to use as a baseline into ~/.xkb/keymap/xkbtest,
and append snippets to be included to the xkb_symbols
line, e.g.:
"pc+us(intl)+inet(evdev)+group(win_switch)+xkbtest(dashes)+xkbtest(caps_mod4)"
When you try to load this keyboard map with
xkbcomp, it will fail because it cannot find the
xkbtest symbol definition file. You have to let the
tool know where to look, by appending a path to its search list
(note the use of $HOME instead of ~,
which the shell would not
expand):
xkbcomp -I$HOME/.xkb ~/.xkb/keymap/xkbtest $DISPLAY
You can use xev to verify the results, or just type
Win-Hyphen into a terminal; does it produce ?
By the way, I found xev much more useful for such
purposes when invoked as follows (thanks to Penny for the idea):
xev sed -ne '/^KeyPress/,/^$/p'
Unfortunately, xev does not give any indication of
which modifier symbols are generated. I have found no other way to
verify the outcome, other than to tell my window manager to do
something in response to e.g. Mod4-Enter, reloaded it, and then
tried it out.
setxkbmap spit out the
right xkb_keymap and could install the new keyboard
map with xkbcomp, like so:
setxkbmap -I$HOME/.xkb [...] -print xkbcomp -I$HOME/xkb - :0
I wrote
a small script to automatically do that at the start of the X
session and could have gone to play outside, if it hadn t been
for the itch I felt due to the entire rule file stored in my
configuration. I certainly did not like that, but I could also not
find a way to extend a rule file with additional rules.
When I looked at the aforementioned script again, it suddenly
became obvious that I was going a far longer path than I had to.
Even though the rule system is powerful and allows me to e.g.
automatically include symbol maps to remap keys on my Thinkpad,
based on the keyboard model I configured, the benefit (if any) did
not justify the additional complexity.
In the end, I simplified
the script that loads the keyboard map, and defined
a default xkb_keymap, as well as
one for the Thinkpad, wich I identify by its fully-qualified
hostname. If a specific file is available for a given host, it is
used. Otherwise, the script uses the default.
LVM can be a virtue. However, it can also be a pain at times; for
instance, there's loss of diskspace due to LVM's metadata that needs to
be stored as well. This amounts to approximately 5% of the diskspace (if
I'm not mistaken), which can be quite a bit. Also, this is an extra
abstraction layer, which requires memory and CPU time to be processed.
This will be negligable on most modern computers, but sometimes it
isn't.
I had a system that had quite a few things on LVM, and wanted to get
rid of them. Unfortunately, to remove the LVM physical volumes would
mean that I'd have to get rid of the data, which would mean storing it
somewhere else, which in turn would probably mean that I wouldn't be
able to use the system for quite a long time. That wasn't
acceptable.
So, instead, what I did was to export a whole hard disk (one with
enough space to hold the logical volumes on that machine) using NBD, and
migrate stuff that way:
[generic] user = nbd group = disk [export] exportname = /dev/hde port = 1234This will export all of /dev/hde on port 1234. Obviously you wouldn't want to do this on an untrusted network, but that's always true with NBD (in my case, the link was a 1M crossed cable -- quite safe).
nbd-client <server> 1234 /dev/nbd0... assuming /dev/nbd0 is not in use yet. Provided the client machine is running kernel 2.6.26 or newer and nbd-client 2.9.10 or later (e.g., Debian Lenny or later), and you're running udev, this will create a number of /dev/nbd0pX device nodes, with X starting at 1, one for each partition on the disk. Of course, one can also export a specific partition rather than the whole disk, or just one file on a filesystem, or create a physical volume of the entire disk rather than just a partition -- your choice.
pvcreate /dev/nbd0p2 vgextend /dev/<vg> /dev/nbd0p2If you now run 'vgdisplay', you'll see that the size of the LVM volume has increased considerably.
pvmove -v /dev/sda7This will show progress information every 15 seconds while the data is being moved from the local hard disk to the NBD device. You'll be able to continue using the system as usual--although of course the system will gradually get slower and slower as more and more data is only available through a comparatively slow network connection.
vgreduce -a /dev/<vg> cfdisk /dev/sda ...
Do you listen to the radio?
I don t, and there are multiple reasons for that:
First and foremost, I don t like the music they play these days.
Even though there are stations which will occasionally play a more
eclectic tune, the Swiss government does not, to my knowledge,
dictate any quota, like New Zealand actually requires stations to
broadcast New Zealand music at least 20% of the time.
The result is music made by producers, who stand pop icons with
little clothing in front of microphones, instruct them to move
their bodies in obscene ways, and coach them to croak songs someone
else wrote en masse in some basement somewhere. All those
songs sound alike.
To ensure a constant supply of pop dolls, they hype television
shows with titles such as Germany s seeks the next superstar ,
when most of Germany actually couldn t care less, and only those
with vacuous brain capacity follow with excitement, because they
wouldn t know what else to do.
Second, I don t have the time or energy to listen to discussion
rounds on the radio, especially not when topic are about
society , which noone can define in the first place. Wittgenstein always
had it right.
The same goes for most commentaries. If I don t have anything to
do, I prefer to listen to birds in the trees, rather than someone s
polished opinion. The scariest aspect is that those people actually
believe that they have something worthwhile to say, and so
do their producers and the other staff, when in most cases, they
don t. At least not worthwhile to people who have other things
occupying their minds.
I also don t like someone to make a pre-selection of news and
squash that into 5-15 minute time slots, to be read out by
dull-sounding speakers. I d rather skim over articles, and the Web
ensures that I get the information I want much quicker than the
radio stations can transmit them.
And sports over the radio waves makes me come close to aural
epileptic seizures.
I am painting the sky black a bit. I am fully aware that there
exist people with thought-provoking arguments, that some stations
play interesting music I would otherwise never discover, and that
the radio is a source of entertainment in the lives of thousands of
other people who are less privileged than me.
But when the Billag rang my
doorbell today and wanted CHF 14,10 per month for posession of any
device capable of turning radio waves into sound, including those
radio waves broadcast over the Internet these days, I got a bit
furious.
In the past, they concentrated only on actual radio and TV
receivers. When I moved into my previous flat in Zurich in 2002,
they wanted money because my stereo had a tuner button. I refused
to pay, opened the device, unsoldered the radio coil, and sent it
to them with an angry letter of refusal; they let me off the
hook.
Since then, they changed the law in 2007 (but haven t actually
updated the forms they force you to sign) to include audio players,
cellular phones, and computers, which are all radio-capable. I d
really prefer if they used their funds to revert that trend, or at
least remove
the loudspeakers from all mobile phones.
But instead, this morning, I skid right into their claws.
As I said before, the radio is also a social support system, and
as such I have less of a problem to subsidise it. However, given
that I strongly disagree with the quality level broadcast, I would
prefer to direct my money towards causes I consider more useful,
and with which I could better identify. Unfortunately, the whole
system is governmentalised to the point where this choice is
taken away from me.
The Billag website helpfully offers answers to the common
questions, including one along the lines of quality. They suggest
that you get in touch directly with the programme directors to
complain about their content, and offer suggestions. Shortly after
I moved to Zurich, Radio Lora offered
me a radio show. Radio Lora is a private station, but they also
receive subsidies from the monies exacted by the government, so I
am using them as an example here.
I suggested that I concentrated only on progressive and
psychedelic rock from the sixties and the seventies. They refused
the show in the end, claiming that this would not be what their
listeners want.
So instead I now get to pay for content that is deemed more
appropriate.
I can only imagine the pains I d have to go through to be able
to host a radio show concentrating on eclectic tunes on one of the
public radio stations. And even if I succeeded (without becoming a
full-time public radio broadcaster), then I could only contribute a
few hours a week to that content.
If you ask me, the Swiss government is overstepping its
competencies a bit.
NP: Mono:
Hymn to the Immortal Wind
There are a lot of little git scripts and tools being written by
a lot of people. Including a lot of tools written by people I have
a lot of respect for. And yet, they are mostly useless for me. Take
git-pkg. Can t use it. Does not work with git submodules. Then
there is our nice, new, shiny, incredibly bodacious 3.0 (git)
source format. Again, useless: does not cater to submodules.
I like submodules. They are nice. They allow for projects to
take upstream sources, add Debian packaging instructions, and put
them into git. They allow you to stitch together disparate
projects, with different authors, and different release schedules
and goals, into a coherent, integrated, software project.
Yes, I use git submodules for my Debian packaging. I think it is
conceptually and practically the correct solution. Why submodules?
Well, one of the first things I discovered was that most of the
packaging for my packages was very similar but not identical.
Unfortunately, the previous incarnation of my packages with a
monolithic rules file in each ./debian/ directory, it
was easy for the rules files in packages to get out of sync and
there was no easy way to merge changes in the common portions an
any sane automated fashion. The ./debian/ directories
for all my packages package that they are instrumental in
packaging. So, since I make the ./debian/ directories
branches of the same project, it is far easier to package a new
package, or to roll out a new feature when policy changes the
same commit can be applied across all the branches, and thus all my
source packages, easily. With a separate debian-dir
project, I can separate the management of the packaging rules from
the package code itself.
Also, I have abstracted out the really common bits across all my
packages into a ./debian.common directory, which is
yet another project, and included in as a submodule in all the
packages so there is a central place to change the common bits,
without having to duplicate my efforts 30-odd times.
Now people are complaining since they have no idea how to clone
my package repositories, since apparently no one actually pays
attention to a file called .gitmodules, and even when
they do, they, and the tools they use, have no clue what to do with
it. I am tired of sending emails with one off-cluebats, and I am
building my own porcelain around something I hope to present as a
generic vcs-pkg implementation soon. The firs step is
a wrapper around git-clone, that understands git
submodules.
So, here is the
browsable code (there is a link in there to the downloadable
sources too). Complete with a built in man page. Takes the same
arguments as git-clone, but with fewer options. Have
fun.
Last night, I stayed up late reworking the avionics bay in my
Giant Leap
Vertical Assault
kit. This is the rocket I set my personal best altitude to date of 14,141 feet
above ground level with. The Missile Works
RRC2 mini will move to a lesser airframe to keep it below 10k feet AGL
since it's an early unit with the supposedly-buggy early firmware. In its
place, I've mounted a PerfectFlite
MiniAlt/WD to handle primary deployment duties... and
serial number 1 of TeleMetrum!
Meanwhile, Keith has completely rewritten the guts
of the firmware in the last few days to eliminate
FreeRTOS since it turns out to just be too heavy
for our needs on this project. My board is now running a snapshot of his
latest work, and in bench testing I've confirmed that it can do launch detect,
log sensor data until the non-volatile memory chip is full, and dump the raw
data over USB for analysis after a flight.
Weather has been an issue in Colorado recently, but as soon as we get a decent
launch day (maybe as early as this weekend?), I'm looking forward to flying
this rocket on one or all of the
Cesaroni I205, I540, and J285 currently in my box to get
some initial flight data recorded. Keep your fingers crossed for me that
the storm front headed towards us clears out by the weekend!
RewriteCond % REQUEST_URI !^/FR/fr
RewriteCond % REQUEST_URI !^/common/
RewriteCond % REQUEST_URI !^/favicon.ico$
RewriteRule ^(.*)$ /FR/fr$1 [PT,L]
The need here, is to get anything that wouldn t begin with /FR/fr from $DOCROOT/FR/fr (through, possibly, any other module rules, which was important in the setup where these rules were), except if they begin with /common/ or is /favicon.ico.
Depending on the requests pattern, reordering the RewriteConds can be better. Anyways, the case at hand was to massively duplicate this setup over different countries and languages.
Basically, domain.fr/foo/bar would need to come from $DOCROOT/FR/fr/foo/bar, domain.co.uk/foo/bar from $DOCROOT/GB/en/foo/bar, while anydomain/common/foo/bar would come from $DOCROOT/common/foo/bar.
In such a case, you have a lot of possible solutions, each of which has its pros and cons.
Pros: quite efficient for execution time. Cons: Doesn t scale very well for humans : a lot of virtual hosts and rewrite rules to maintain ; if the list of urls that don t need rewrite increases, all set of rules need to be updated.<VirtualHost *:80>
ServerName domain.fr
RewriteCond % REQUEST_URI !^/FR/fr
RewriteCond % REQUEST_URI !^/common/
RewriteCond % REQUEST_URI !^/favicon.ico$
RewriteRule ^(.*)$ /FR/fr$1 [PT,L]
</VirtualHost><VirtualHost *:80>
ServerName domain.co.uk
RewriteCond % REQUEST_URI !^/GB/en
RewriteCond % REQUEST_URI !^/common/
RewriteCond % REQUEST_URI !^/favicon.ico$
RewriteRule ^(.*)$ /GB/en$1 [PT,L]
</VirtualHost>
( )
SERVER_NAME:Pros: are there ?. Cons: Doesn t scale very well : a lot of rewrite rules to maintain ; rewrite rules being executed sequencially, the more domains there are, the more checks are done for the last domains ; if the list of urls that don t need rewrite increases, all set of rules need to be updated.<VirtualHost *:80>
ServerName domain.fr
ServerAlias domain.co.ukRewriteCond % SERVER_NAME =domain.fr
RewriteCond % REQUEST_URI !^/FR/fr
RewriteCond % REQUEST_URI !^/common/
RewriteCond % REQUEST_URI !^/favicon.ico$
RewriteRule ^(.*)$ /FR/fr$1 [PT,L]RewriteCond % SERVER_NAME =domain.co.uk
RewriteCond % REQUEST_URI !^/GB/en
RewriteCond % REQUEST_URI !^/common/
RewriteCond % REQUEST_URI !^/favicon.ico$
RewriteRule ^(.*)$ /GB/en$1 [PT,L](...)
</VirtualHost>
Pros: gives a canonical place for urls that don t need rewrite. Cons: Doesn t scale very well : a lot of rewrite rules to maintain ; rewrite rules being executed sequencially, the more domains there are, the more checks are done for the last domains.<VirtualHost *:80>
ServerName domain.fr
ServerAlias domain.co.ukRewriteCond % REQUEST_URI ^/common/ [OR]
RewriteCond % REQUEST_URI ^/favicon.ico$
RewriteRule .* - [L]RewriteCond % SERVER_NAME =domain.fr
RewriteCond % REQUEST_URI !^/FR/fr
RewriteRule ^(.*)$ /FR/fr$1 [PT,L]RewriteCond % SERVER_NAME =domain.co.uk
RewriteCond % REQUEST_URI !^/GB/en
RewriteRule ^(.*)$ /GB/en$1 [PT,L](...)
</VirtualHost>
RewriteMap.RewriteMap l10n txt:l10n.map # switch to dbm when necessary
RewriteCond % REQUEST_URI !^$ l10n:% SERVER_NAME
RewriteCond % REQUEST_URI !^/common/
RewriteCond % REQUEST_URI !^/favicon.ico$
RewriteRule ^(.*)$ $ l10n:% SERVER_NAME $1 [PT,L]
Or
RewriteMap l10n txt:l10n.map # switch to dbm when necessary
RewriteCond $ l10n:% SERVER_NAME ^(.+)$
RewriteCond % REQUEST_URI !^%1
RewriteCond % REQUEST_URI !^/common/
RewriteCond % REQUEST_URI !^/favicon.ico$
RewriteRule ^(.*)$ %1$1 [PT,L]
The map file would have on each line a domain name followed by the corresponding url start (/FR/fr for domain.fr, etc.).
Unfortunately, the above setup is not possible. A way around this lack of functionnality is to use some nice perl regexp trick.
RewriteMap l10n txt:l10n.map # switch to dbm when necessary
RewriteCond $ l10n:% SERVER_NAME ^(.+)$
RewriteCond %1% REQUEST_URI !^(.+)\1
RewriteCond % REQUEST_URI !^/common/
RewriteCond % REQUEST_URI !^/favicon.ico$
RewriteRule ^(.*)$ %1$1 [PT,L]
As you can see, only the second RewriteCond differs. What we really want to test is whether the % REQUEST_URI begins with the proper url start or not. Let s say we re considering domain.fr and the map gave us /FR/fr. Following the first RewriteCond, %1 contains /FR/fr.
At the second RewriteCond, if % REQUEST_URI begins with /FR/fr then %1% REQUEST_URI begins with /FR/fr/FR/fr. Otherwise, it will only begin with /FR/fr.
What we can test, then, is whether this %1% REQUEST_URI aggregate contains a repeating pattern at its beginning. This is exactly what the perl regexp does: it captures at least one character at the beginning of the tested string (^(.+)), and wants to find this captured string again (\1).
It is worth mentioning that this obviously falls flat when the url start itself contains a repeating pattern (e.g. /fr/fr instead of /FR/fr).
As we want the RewriteRule to work only when our % REQUEST_URI does not begin with /FR/fr, we negate the regexp, which means nothing will actually be captured, such that %1 in the RewriteRule will still be the last captured text, from the very first RewriteCond.
Note that if all the tested url starts are the same length and/or pattern, it may be worth changing the regexp to be more precise (and faster to match or not). Such as ^(/../..)\1 in our present case.
kbd today. I basically took an old Debian patch,
the only significant divergence from the original tarball, and altered
it in a way that I can read and understand it more easily (so I can send
it upstream in good conscience). This process naturally involved a lot
of errors. As I m talking about loadkeys here, they became
unpleasantly obvious whenever I tested my code: First I messed up
everything but plain printable ASCII characters (so the return key was
mapped to Unicode U+0201 instead of the correct K(0x02, 0x01)), then I
managed to completely freeze everything. In both cases, Alt+F7 was
affected by the damage. Just like Ctrl+Alt+Del. Time for the good old
boring
elephants.
I learn from mistakes when I make them twice, so a while sleep 60; do
chvt 7; done loop saved me from further reboots. I nuked /dev/tty1
once more (in the really cool, irreversible way that disables all
keypresses), but I could move on to the next VT. After a final
adjustment, my modified patch finally worked. I sent it upstream,
forgot about the troublesome debugging and went on to something else.
Later in the evening, I decided to end the last school holidays in my
life with a bit of instant messaging. BitlBee, a
Jabber IRC gateway, is running on my virtual private server for this
purpose. Being the occasional chatter that I am, I haven t touched it
since the recent upgrade to Lenny. The format of its account
configuration files has apparently changed, so I started to set up
BitlBee anew. It kept telling me that there is an Authentication
failure ; given the peculiar setup of the XMPP server I use, this didn t
really surprise me. But still, this thing had worked before. Perhaps I
really got my password wrong? I haven t typed it for ages, BitlBee
stored it for me. As the administrator of my Jabber server, I could
easily reset my password to what I thought it was. BitlBee still
refused to get past the identification stage.
I decided to install Gajim, entered my account
information and told it to connect. Gnah. One or the other Python
exception caused an eternal stream of error dialogue boxes to appear
simultaneously and steal my focus. I don t have a keyboard shortcut for
xkill and I couldn t type anything in a Urxvt (error message #54321
would receive the keystrokes). Ctrl+Alt+F1, get me out of here! Oh,
right, I broke that one! At that point, I burst into a laugh.
Somewhere in this post, there are a few bugs to report.
... turns out to be slightly over 31 and a half years.
According to the text
of my birth certificate, I was born at 13:20. So, with that, we can
make the following calculation:
wouter@celtic:~$ date -d '1978-05-06 + 13 hours + 20 minutes + 1000000000 seconds' Tue Jan 12 15:06:40 CET 2010Since I missed my 10000 days, and I was sortof unhappy about that, I guess this one is a good substitute. Unfortunately the 12th of January is a tuesday, but I guess I can throw a party during the weekend...
I bought a new machine recently; for the flat at present with the aim of it becoming an upgrade for the media box once my lease is up. Nothing spectacular; E5200 Dual Core Pentium at 2.5Ghz, MSI G41M-FIDP mobo and 4G of OCZ DDR2 800. I don't need that much, but for 30 how could I resist? Total price, including the extra postage tax to NI and a small case, 200 from eBuyer. I had an existing HD I could use and also managed to find a spare DVD writer too.
sed and regular expressions:
Host *+*
ProxyCommand ssh $(echo %h sed 's/+[^+]*$//;/+/! s/%%/@/;s/:/ -p / ;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/ ) PATH=.:\$PATH nc -w1 $(echo %h sed s/^.*+//;/:/!s/$/ %p/;s/:/ / )
The syntax you can use to connect through jump hosts is the following:
ssh login1%host1:port1+login2%host2:port2+host3:port3 -l login3
We ll see further down why we can t put a login for the final destination host. Or if you want to skip the boring implementation details, you can also skip to the end, where a slightly more compact version lies: while writing this post, I got some optimization ideas.
Let me try to split the sed syntax to make it a little more understandable:
The seconds/+[^+]*$//;# Remove all characters starting from the last + in the string (i.e. keep the n - 1 first hops)
/+/!# If the string doesn t contain a + after the previous command (i.e. there is only one hop remaining), do the following, otherwise, skip until the closing curly brace
s/%%/@/;# Replace % with @ (% is doubled because of theProxyCommand)
s/:/ -p /# Replace : with -p . Combined with the previous command, we rewrite login%host:port as login@host -p port
;
s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/# Rewrite hop1+hop2+login%lasthop as hop1+hop2+lasthop -l login
sed goes like this:
Let s see what thes/^.*+//;# Remove everything up to the last occurrence of + in the string (i.e. only keep the last hop)
/:/!# If there is no : in the string, do the following, otherwise, skip the next statement
s/$/ %p/;# Add %p at the end of the line
s/:/ /# Replace : with . These last three instructions prepare a host port combination for use withnc.
ProxyCommand looks like for some examples, skipping PATH setting and nc option for better readability:
host1+host2ssh host1 nc host2 %plogin1%host1+host2:port2ssh login1@host1 nc host2 port2login1%host1:port1+host2:port2ssh login1@host1 -p port1 nc host2 port2ssh process that runs the ProxyCommand and will actually talk to the remote host won t have any knowledge of it.
From the above examples, it also appears obvious why we replace login%host:port with login@host -p port : so that the ssh command in the ProxyCommand gets the proper arguments for login and port. Note we could also replace with host -p port -l login for the same effect.
With even more hops, this is what happens:
host1+host2+host3ssh host1+host2 nc host3 %plogin1%host1:port1+host2:port2+host3ssh login1%host1:port1+host2:port2 nc host3 %pProxyCommands will trigger another ProxyCommand quite looking like our first few examples.
In the first hops, if we d just replace all % with @ , in cases where logins are given everywhere, we d end up with a ProxyCommand like the following:
ssh login%host1+login%host2 nc host3 %p
As we saw above, we can t use a login on the last hop, which means this ProxyCommand wouldn t work as expected and is why we have to rewrite login1%host1+login2%hop2 as login%host1+host2 -l login2 with the last instruction in the first sed.
In the end, this is what happens:
ProxyCommand ssh login1%host1:port1+host2 -p port2 -l login2 would itself have ssh login1@host1 -p port1 nc host2 %p as ProxyCommand, in which %p would be replaced by port2, given as argument to -p.
Based on this and with further small optimizations, we can slightly shorten our ProxyCommand to the following :
Host *+*
ProxyCommand ssh $(echo %h sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p / ) PATH=.:\$PATH nc -w1 $(echo %h sed s/^.*+//;/:/!s/$/ %p/;s/:/ / )
sed instructions decryption is left as an exercise to the reader ;).
Update : modified the shortened version to fix the issue spotted in the comments.
Yeah, proprietary software is bad, but let's at least install it the Debian way. The following walkthrough assumes Debian lenny.
Install some prerequisites:
$ sudo apt-get install mysql-server-5.0 apache2-mpm-prefork libapache2-mod-php5 php5-mysql php5-curl php-pear mono-gmcs php5-imap curl dh-make-php dpkg-dev fakeroot build-essential cdbs php-http-request php-mail php-net-smtp php-db php-auth
Download and extract FogBugz:
$ cp ~/Downloads/fogbugz-setup-php-6.1.44.tar.gz . $ tar xvfz fogbugz-setup-php-6.1.44.tar.gz $ cd fogbugz
If you do not wish to install FogBugz to /opt/fogbugz, modify INSTALL_DIR at the top of install.sh to point to your intended target (e.g. /srv/bugs.example.com).
Create Debian packages of the missing PEAR libraries. For some reason, the php-mail-mime package in lenny is not recognised by FogBugz's install.sh, so we create a replacement.
#!/bin/sh set -e for PEAR_PKG in Auth_SASL HTTP_Client Mail_Mime XML_Tree do PKG_TEMP=$(mktemp -d) cd $ PKG_TEMP pear download $ PEAR_PKG dh-make-pear $ PEAR_PKG *.tgz cd $(find -mindepth 1 -type d head -n1) dpkg-buildpackage -uc -us -rfakeroot sudo dpkg -i ../*.deb rm -rf $ PKG_TEMP done
$ sudo ./install.sh /***************************************\ * FogBugz 6 Setup \***************************************/ -- Checking for required tools + found mono 1.9.1 [..]
FogBugz will offer to mangle your Apache configuration. Choose no and run the following, replacing /srv/bugs.example.com where appropriate:
$ sudo ln -s /srv/bugs.example.com/Accessories/fogbugz.conf /etc/apache2/sites-available/fogbugz $ sudo a2ensite fogbugz
FogBugz will then offer to mangle your PHP configuration. Choose yes; but move the last handful of lines from (e.g. /etc/php5/apache2) into /etc/conf.d/fogbugz.ini.
After restarting Apache, you should be able to visit http://bugs.example.com/fogbugz/install1.php to continue installation.
On first run, FogBugz will "warn" about the lack of missing eAccelerator, a PHP JIT. Unfortunately, whilst eAccelerator is "open-source", useful distribution of it is illegal. Alternatives available in lenny would include php-apc and php-xcache.
Next.