$ grep -lr 'use autodie' lib/ checks/ collection/ frontend/lintian wc -l 75As a simple benchmark, lets consider the following Perl one-liner:
$ /usr/bin/time -f "%es %Us %Ss" perl -Mautodie \
-e 'print $autodie::VERSION, " => ";' \
-e 'eval join("\n", map "package X$_; use autodie;" (1..74));'
A quick-n-dirty comparison gives:
2.20 => 0.91s 0.90s 0.01s 2.21 => 0.15s 0.15s 0.00s # NB: the times are "wall, user and sys" in that order, in case you # are too lazy to read time(1).So, 2.21 is now closer to a factor 6 rather than the original factor 4. I have to admit that the timings seem to be very machine dependent as my laptop shows a factor 7 improvement (from ~1.39 to ~0.22s). With at least 370 tests cases running in the Lintian testsuite, I can look forward to a reduction in user time on about 4 minutes.![]()
Yesterday, I pushed my first sizable contribution to GHC, the Haskell compiler. The feature solves the problem that newtypes are not always free: If we have newtype Age = MkAge Int, then we have all learned that the Age function has zero run-time cost. But if the Int that we want to convert is inside another type, the conversion is no longer free: Converting a Maybe Int to a Maybe Age using, for example, fmap Age, will cause time and space overhead at runtime, and there was no way around it. Well, there is unsafeCoerce, but really, that ought to be avoided.
So after some discussion with and encouragement of Simon Peyton Jones at RDP in Eindhoven this year I worked on a design (which was developed, as far as I know, by Simon, Roman Cheplyaka, Stephanie Weirich, Richard Eisenberg and me). In GHC 7.8, there will be a function coerce :: Coercible a b => a -> b that works, from the user point of view, like unsafeCoerce (i.e. no run-time cost), but with the big difference that it will only typecheck if the compiler can infer that it indeed is safe to coerce between a and b. So it will derive Coercible Age Int, and Coercible Int Age, and Coercible (Maybe Age) (Maybe Int) and even stuff like Coercible (Int -> Age) (Age -> Int), but not Coercible Int Bool. It will also not coerce between Age and Int if the constructor MkAge is not exported, to respect module boundaries.
Under the hood this relies on the also new feature of roles, which were solved to make the previously unsafe GeneralizedNewtypeDeriving feature safe again, and which also guarantee that coerce is indeed as safe as the name suggests.
The feature will come with 7.8, but not fully advertised , so things might change again for 7.10, and bugs with the feature may not necessarily qualify to be fixed in further 7.8.x releases, so beware. It also does not automatically convert fmap Age into coerce, but it is a step in that direction.




I signed up to take part of an online, massive course Arte y cultura en circulaci n: crear y compartir en tiempos digitales (The circulation of arts and culture: Creating and sharing in digital times). As the activities of us the attendees are to be published by each on their personal blog/space, I will be publishing them here. I hope they are interesting to some of my other regular readers.
I am late in joining, and I should already be posting the second activity. Anyway, this text goes towards the first week's lesson: Qu es un autor: la (de)construcci n hist rica del concepto de autor a (What is an author? Historic (de)construction of the concept of authorship). Our homework is to find an example of a current discussion where the notion of authorship is discussed, and share it this way.
And I'm somewhat in a hurry right now, so this will be hasty. But I didn't want to delay my (late) submission anymore!
In the Debian Ruby mailing list, Hleb Valoshka asks basically how deep should copyright recognition be. Because, yes, while copyright attribution is simple (simpler, at least) in literary / artistic works, computer programs (and even more those developed following the Free Software distributed fashion) are harder to properly attribute.
Is a two-line patch to a tens-of-thousands-of-lines project enough to warrant mention in the copyright file? Most of us would agree it is not. Few would contend this were the amount of changes to make up, say, even 1% of that scale of project.
In the coding projects where I am the main author (which, yes, are usually very small I cannot recognize myself as a good programmer, and the size of my successful works proves me), I try to take care to mention explicitly each of the contributors, even if their contribution is quite small. But were I to lead a larger development work, with enough following to generate on the order of one submitted patch a day, would it make sense for me to follow up with such detail the authorship information?
And as a minor side note: How much does the law require me? A very small patch can fix important functionality issues (think security or performance). If somebody sends a very small patch fixing an intellectually hard to grasp problem... I am sure it should be properly acknowledged!
Anyway, I have to flee now. I am just dropping some ideas on the table. Of course, if anybody is willing to discuss them further, I'm interested in any debate that springs off it!
(Meanwhile... I expect to spam you with this topic a couple of times. But it should not bug you much, as it's one of my usual blog topics!)
Many thanks to Vincent Meurisse who solved my node.js callback woe.
Some history of the blogspam service:
Back in 2008 I was annoyed by the many spam-comments that were being submitted to my Debian Administration website. I added some simple anti-spam measures, which reduced the flow, but it was a losing battle. In the end I decided I should test comments, as the users submitted them, via some kind of external service. The intention being that any improvements to that central service would benefit all users. (So I could move to testing comments on my personal blog too, for example). Ultimately I registered the domain-name "blogspam.net", and set up a simple service on it which would test comments and judge them to be "SPAM" or "OK". The current statistics show that this service has stopped 20 million spam comments, since then. (We have to pretend I didn't wipe the counters once or twice.)I've spent a while now re-implementing most of the old plugins in node.js, and I think I'll be ready to deploy the new service over the weekend. The new service will have to handle two different kinds of requests:
Here s some documentation about a hack I ve been working on to allow publication of RDF views for Tastypie resources (in Django applications).
While working on implementing support for RDF meta-data for descriptions of Debian packages for the Debian Package Tracking System rewrite, I ve tried and idetify which libraries/frameworks would allow to create some RDF views for Django model objects with a minimal effort.
Ideally, this would save the hassle of writing code, and could just be a matter of mapping some Django model fields to proper ontology attributes.
I haven t found an existing tool to do so, but it seemed to me that Tastypie could offer a nice starting point. Tastypie (I focused on v. 0.9.15 which is currently in Debian testing) offers some REST content-negociation support, and other niceties.
This post is an attempt at documenting an initial implementation for my problem. I ve implemented it as some code in the example blog application described in the Tastypie documentation. Unfortunately, it s not yet a patch that could be applied to Tastypie, to add this as a standard feature.
The code is available in my git clone of Tastypie, based on 0.9.15, and lies in the commit(s) between the example_myapp and rdfviews branches. It needs an up to date RDFLib to work (Debian s is too old, btw).
It basically relies on the addition of a _rdf_mapping dict in the Django model objects, and an RdfModelResource as a base class for Tastypie ModelResources.
To provide an RDF view for a ModelResource, it also requires to declare a particular MetaClass, and adding a few bits to its Meta subclass.
The principle is that the dehydratation steps of the Tastypie system will replace fields values by their RDF objects counterparts, as either RDFLib Literals or URIRefs. Then the resuting Bundle will be converted to some RDFLib Graph. It is then just a matter of serialization of that Graph to turtle (I ve not added another format, but it should be pretty straightforward).
There s a bit of hackish drak magic in the code, in particular when introspecting the Tastypie / Django resource / model objects to be able to dynamically add some dehydrate_FOO methods to perform the conversion to Literals or URIRefs.
Custom dehydrateFoo methods can still be written to process the fields in particular ways.
I ve added some LDP style paging along the way, so I hope it will be quite usable by LDP compatible tools.
Here s the result :
First, listing all resources :
$ curl -H 'Accept: text/turtle' "http://localhost:8000/api/v1/entry/"
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix ldp: <http://www.w3.org/ns/ldp#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sioc: <http://rdfs.org/sioc/ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
</api/v1/entry/#list> dcterms:hasPart </api/v1/entry/1/#post>,
</api/v1/entry/2/#post>,
</api/v1/entry/3/#post> .
Then, details of one particular post :
$ curl -L -H 'Accept: text/turtle' "http://localhost:8000/api/v1/entry/1"
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sioc: <http://rdfs.org/sioc/ns#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
</api/v1/entry/1/#post> a sioc:Post ;
dcterms:created "2011-05-21T22:46:38+00:00"^^xsd:dateTime ;
dcterms:title "Another Post" ;
sioc:content "MESSAGE: This will prbbly be my lst post. /MESSAGE" ;
sioc:has_creator </api/v1/user/1/> ;
owl:sameAs </posts/another-post#post> .
Today I started hacking on a re-implementation of my BlogSpam service - which tests that incoming comments are SPAM/HAM - in node.js (blogspam.js)
The current API uses XML::RPC and a perl server, along with a list of plugins, to do the work.
Having had some fun and success with the HTTP+JSON mstore toy I figured I'd have a stab at making BlogSpam more modern:
shelob ~/git/blogspam.js $ node blogspam.js Loaded plugin: ./plugins/10-example.js Loaded plugin: ./plugins/20-ip.js Loaded plugin: ./plugins/80-sfs.js Loaded plugin: ./plugins/99-last.js Received submission: "body":"This is my body ..","ip":"109.194.111.184","name":"Steve Kemp" plugin 10-example.js said next :next plugin 20-ip.js said next :next plugin 99-last.js said spam SPAM: Listed in StopForumSpam.comSo we've loaded plugins, and each has been called. But the end result was "SPAM: Listed .." and yet the caller didn't get that result. Instead the caller go this:
shelob ~/git/blogspam.js $ ./client.pl 200 OK 99-last.jsThe specific issue is that I iterate over every loaded-plugin, and wait for them to complete. Because they complete asynchronously the plugin which should be last, and just return "OK" , has executed befure the 80-sfs.js plugin. (Which makes an outgoing HTTP request). I've looked at async, I've looked at promises, but right now I can't get anything working. Meh. Surprise me with a pull request ;)
It has been nearly six years with a netbook and five since I last wrote about wifi roaming from the bus to stay on irc without a costly celluar link during the daily commute. Since then, some readers have asked me to share my refinements to the method in a followup post. So here it is.
The software
On the server:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
network=
key_mgmt=NONE
network=
ssid="default"
key_mgmt=NONE
network=
ssid="linksys"
key_mgmt=NONE
...
Since you ll be using ssh repeatedly to connect and it has to be fast, make sure your server is set up to accept your key and use ssh-add so that you only have to enter your ssh key password once.
You can tweak isc-dhcp-client to make connections faster. In /etc/dhcp/dhclient.conf, use:
backoff-cutoff 1; initial-interval 1;Here are a few scripts I wrote to facilitate quick roaming from one open AP to another and reconnect to irssi running in screen, to break a connection and try the next one, and to recover from occasional lockups (more about that later). ~/bin/screen_reconnect This is a script to reconnect continuously via ssh to a screen session:
#!/bin/sh reset while ! ssh -t 10.9.8.7 'screen -UDr' 2>/dev/null ; do echo -n "." ; sleep .1 ; doneJust substitute the IP of your own server here. Using an IP instead of domain name makes the connection faster because a DNS lookup is not required. ~/bin/wifi_reassociate This script closes any open ssh sessions and informs wpa_supplicant to attempt to connect again.
#/bin/sh /sbin/wpa_cli rea killall ssh >/dev/null 2>&1~/bin/wifi_killall This optional, somewhat ugly script addresses an issue I hope you never have. On my ASUS Eee PC 1001PX, occasionally scanning stops. When this happens, and I have never figured out why, apparently ACPI events are blocked. At this point wifi becomes unusable and ACPI sleep is inhibited. By trial and error I found that if you bring down the interface, kill all network-related processes, and bring it up again, ACPI events are unblocked and wifi is usable once more (and any pending request to sleep will finally happen). The script requires sudo, and to use the openbox key binding, gksudo.
#/bin/sh sudo ifdown wlan0 # in case any of these are hung sudo killall dhclient3 sudo killall wpa_cli sudo killall wpa_action sudo killall wpa_supplicant # in case any of these are *really* hung sleep 1 sudo killall -9 dhclient3 sudo killall -9 wpa_cli sudo killall -9 wpa_action sudo killall -9 wpa_supplicant sudo dhclient -r sudo ifup wlan0Openbox Since certain actions need to be performed repeatedly and quickly, it is useful to have hotkeys bound in your window manager to the scripts. In ~/.config/openbox/rc.xml, key bindings for <alt>-r to reassociate and <alt>-d to disconnect a hung connection would look like:
<keyboard>
<!-- My keybindings -->
<keybind key="A-R">
<action name="Execute">
<execute>/home/synrg/bin/wifi_reassociate</execute>
</action>
</keybind>
<keybind key="A-D">
<action name="Execute">
<execute>gksudo /home/synrg/bin/wifi_killall</execute>
</action>
</keybind>
</keyboard>
Putting it together: on the server
There is very little to do here. Just start screen, and start irssi in screen. Running screen on the client as well as the server means you should either bind the screen meta keys to a different key sequence on each system, or else learn to press meta twice to pass through meta to the server screen as needed. I use the latter approach. Alternatively, you could use a tabbed terminal on the client, or separate terminals per client process instead of screen. This is a matter of personal taste.
Ready to roam
Here is a typical setup for roaming on the bus:
In a terminal (I use urxvt), first ssh-add, then start screen with these three processes running in separate virtual terminals:
> select_network 5 ... > reconfigureYou can use tab-completion in wpa_cli to type these commands quickly or else just abbreviate the commands. Another common scenario is when you pass through a business area with many captive portal hotspots. These rarely make good choices because they either require a password not known to you or else you can t click through I agree in time before the bus moves on. In this case, you might just disable the catch-all stanza and let the common open network stanzas you listed ( default , linksys , etc.) do the work:
> disable_network 1Become a type ahead wizard While running, a continuous stream of periods fills the screen, which provides you with a highly visible cue that no available APs are in range. When the movement stops, you know a connection is being attempted. While waiting to connect, you can type ahead any comments you want to make in the current irssi window (taking care to remember which one you are in!) While having periods interspersed in what you type may be disorienting at first, you get used to it. There is a point when a connection is first established and ssh is accepting input, but anything you type can no longer be seen while you re typing. Depending on whether the connection was completely successful or not, what you type now may or may not finally be sent. For best results, only type ahead before the dots stop moving. Eventually you can become skilled enough at this to type ahead a comment in one channel, switch channels with /win # and continue typing ahead in the new channel, all buffered until the next few seconds (or even fraction of a second) of connection time. Fine-tune antenna direction with wavemon When the bus has come to a standstill, you may find wavemon useful to pull in a weak signal. Because wavemon has continuously updated signal level and link quality bars, you can use it to fine-tune the antenna position. Just turn your laptop until the bars are at their maximum. Captive portals I have not figured out how to do any automation for this, so it really is a crapshoot, as it is likely the bus has moved on by the time you ve managed to manually navigate the login through a captive portal. But in rush hour, you may have the luxury of time to connect to these as you pass them. I have recently learned about the CoovaFX Firefox plugin which automates logins to captive portals. I m going to give it a try to see if it helps. Update: I can t recommend this plugin, as it is not compatible with Iceweasel >= 23.0. Also, the standard it is based on, WISPr, appears to have an uncertain future. That, coupled with the fact that the plugin appears to not be open source means I m still looking for alternatives. Summary If all of this sounds a bit nuts to you, well, it probably is. But after half a decade enjoying free access to irc from the bus, it all seems perfectly natural to me! If you try this method and like it, please let me know in the comments. Likewise, if you have any improvements to the process or scripts, please share them!
When it comes to provide redundant services, several options are available:
router id 1.1.1.2; protocol static NETS # import all; export none; route 2001:db8::/40 reject; protocol bgp R1 # import all; export where proto = "NETS"; local as 64496; neighbor 2001:db8:1000::1 as 64511; protocol bgp ER3 # import all; export all; next hop self; local as 64496; neighbor 2001:db8:1::3 as 64496;
router id 1.1.1.6; protocol kernel persist; import none; export all; protocol ospf INTERNAL import all; export none; area 0.0.0.0 networks 2001:db8:1::/64; 2001:db8:6::/64; ; interface "eth0"; interface "eth1" stub yes; ; ;
protocol static DEFAULT import all; export none; route ::/0 via 2001:db8:1000::1; filter default_route if proto = "DEFAULT" then accept; reject; protocol ospf INTERNAL import all; export filter default_route; area 0.0.0.0 networks 2001:db8:1::/64; ; interface "eth1"; ;
Let s explain it step by step:
2001:db8:30::1, 2001:db8:30::2 and 2001:db8:30::3. Those are
distinct from the real IP addresses of W1, W2 and W3.
| Route | W1 | W2 | W3 | Best | Backup |
|---|---|---|---|---|---|
| 2001:db8:30::1 | 102 | 101 | 100 | W3 | W2 |
| 2001:db8:30::2 | 101 | 100 | 102 | W2 | W1 |
| 2001:db8:30::3 | 100 | 102 | 101 | W1 | W3 |
group rs neighbor 2001:db8:1::4 router-id 1.1.1.11; local-address 2001:db8:6::11; local-as 65001; peer-as 65002; neighbor 2001:db8:8::5 router-id 1.1.1.11; local-address 2001:db8:6::11; local-as 65001; peer-as 65002; process watch-nginx run /usr/bin/python /lab/healthcheck.py -s --config /lab/healthcheck-nginx.conf --start-ip 0;
$ python /lab/healthcheck.py --config /lab/healthcheck-nginx.conf --start-ip 0 INFO[healthcheck] send announces for UP state to ExaBGP announce route 2001:db8:30::3/128 next-hop self med 100 announce route 2001:db8:30::2/128 next-hop self med 101 announce route 2001:db8:30::1/128 next-hop self med 102 [...] WARNING[healthcheck] Check command was unsuccessful: 7 INFO[healthcheck] Output of check command: curl: (7) Failed connect to ip6-localhost:80; Connection refused WARNING[healthcheck] Check command was unsuccessful: 7 INFO[healthcheck] Output of check command: curl: (7) Failed connect to ip6-localhost:80; Connection refused WARNING[healthcheck] Check command was unsuccessful: 7 INFO[healthcheck] Output of check command: curl: (7) Failed connect to ip6-localhost:80; Connection refused INFO[healthcheck] send announces for DOWN state to ExaBGP announce route 2001:db8:30::3/128 next-hop self med 1000 announce route 2001:db8:30::2/128 next-hop self med 1001 announce route 2001:db8:30::1/128 next-hop self med 1002
2001:db8:30::3/128 with metric 101).
This healthcheck script is now part of ExaBGP.
template bgp INFRABGP export all; import none; local as 65002; rs client; protocol bgp ER2 from INFRABGP neighbor 2001:db8:1::2 as 65003; protocol bgp ER3 from INFRABGP neighbor 2001:db8:1::3 as 65003; protocol bgp DR6 from INFRABGP neighbor 2001:db8:1::6 as 65003; protocol bgp DR7 from INFRABGP neighbor 2001:db8:1::7 as 65003; protocol bgp DR8 from INFRABGP neighbor 2001:db8:1::8 as 65003;
# Only import loopback IPs filter only_loopbacks # if net ~ [ 2001:db8:30::/64 128,128 ] then accept; reject; # General template for an EXABGP node template bgp EXABGP local as 65002; import filter only_loopbacks; # export none; route limit 10; # rs client; hold time 6; # multihop 10; igp table internal; protocol bgp W1 from EXABGP neighbor 2001:db8:6::11 as 65001; protocol bgp W2 from EXABGP neighbor 2001:db8:7::12 as 65001; protocol bgp W3 from EXABGP neighbor 2001:db8:8::13 as 65001;
router bgp 65002 view EXABGP bgp router-id 1.1.1.5 bgp log-neighbor-changes no bgp default ipv4-unicast neighbor R peer-group neighbor R remote-as 65003 neighbor R ebgp-multihop 10 neighbor EXABGP peer-group neighbor EXABGP remote-as 65001 neighbor EXABGP ebgp-multihop 10 neighbor EXABGP timers 2 6 ! address-family ipv6 neighbor R activate neighbor R soft-reconfiguration inbound neighbor R route-server-client neighbor R route-map R-IMPORT import neighbor R route-map R-EXPORT export neighbor 2001:db8:1::2 peer-group R neighbor 2001:db8:1::3 peer-group R neighbor 2001:db8:1::6 peer-group R neighbor 2001:db8:1::7 peer-group R neighbor 2001:db8:1::8 peer-group R neighbor EXABGP activate neighbor EXABGP soft-reconfiguration inbound neighbor EXABGP maximum-prefix 10 neighbor EXABGP route-server-client neighbor EXABGP route-map RSCLIENT-IMPORT import neighbor EXABGP route-map RSCLIENT-EXPORT export neighbor 2001:db8:6::11 peer-group EXABGP neighbor 2001:db8:7::12 peer-group EXABGP neighbor 2001:db8:8::13 peer-group EXABGP exit-address-family ! ipv6 prefix-list LOOPBACKS seq 5 permit 2001:db8:30::/64 ge 128 le 128 ipv6 prefix-list LOOPBACKS seq 10 deny any ! route-map RSCLIENT-IMPORT deny 10 ! route-map RSCLIENT-EXPORT permit 10 match ipv6 address prefix-list LOOPBACKS ! route-map R-IMPORT permit 10 ! route-map R-EXPORT deny 10 !
# BGP with route servers protocol bgp RS4 import all; export none; local as 65003; neighbor 2001:db8:1::4 as 65002; gateway recursive; protocol bgp RS5 import all; export none; local as 65003; neighbor 2001:db8:8::5 as 65002; multihop 4; gateway recursive;
gateway recursive because most of the time,
the next-hop is not reachable directly. In this case, by default,
BIRD will use the IP address of the advertising router (the route servers).
# show ipv6 bgp BGP table version is 0, local router ID is 1.1.1.5 Status codes: s suppressed, d damped, h history, * valid, > best, i - internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path * 2001:db8:30::1/128 2001:db8:6::11 102 0 65001 i *> 2001:db8:8::13 100 0 65001 i * 2001:db8:7::12 101 0 65001 i * 2001:db8:30::2/128 2001:db8:6::11 101 0 65001 i * 2001:db8:8::13 102 0 65001 i *> 2001:db8:7::12 100 0 65001 i *> 2001:db8:30::3/128 2001:db8:6::11 100 0 65001 i * 2001:db8:8::13 101 0 65001 i * 2001:db8:7::12 102 0 65001 i Total number of prefixes 3
2001:db8:30::2 should be routed through
2001:db8:7::12 (which is W2). Other IP are affected to W1 and
W3.
RS4 should see the same thing4:
$ birdc6 show route BIRD 1.3.11 ready. 2001:db8:30::1/128 [W3 22:07 from 2001:db8:8::13] * (100/20) [AS65001i] [W1 23:34 from 2001:db8:6::11] (100/20) [AS65001i] [W2 22:07 from 2001:db8:7::12] (100/20) [AS65001i] 2001:db8:30::2/128 [W2 22:07 from 2001:db8:7::12] * (100/20) [AS65001i] [W1 23:34 from 2001:db8:6::11] (100/20) [AS65001i] [W3 22:07 from 2001:db8:8::13] (100/20) [AS65001i] 2001:db8:30::3/128 [W1 23:34 from 2001:db8:6::11] * (100/20) [AS65001i] [W3 22:07 from 2001:db8:8::13] (100/20) [AS65001i] [W2 22:07 from 2001:db8:7::12] (100/20) [AS65001i]
$ birdc6 show route 2001:db8:30::1/128 via fe80::5054:56ff:fe6e:98a6 on eth0 * (100/20) [AS65001i] via fe80::5054:56ff:fe6e:98a6 on eth0 (100/20) [AS65001i] 2001:db8:30::2/128 via fe80::5054:60ff:fe02:3681 on eth0 * (100/20) [AS65001i] via fe80::5054:60ff:fe02:3681 on eth0 (100/20) [AS65001i] 2001:db8:30::3/128 via 2001:db8:6::11 on eth1 * (100/10) [AS65001i] via 2001:db8:6::11 on eth1 (100/10) [AS65001i]
2001:db8:30::3 is owned by W1 which is behind DR6 while the
two others are in another part of the network and will be reached
through the appropriate link-local addresses learned by OSPF.
Let s kill W1 by stopping nginx. A few seconds later, DR6 learns
the new routes:
$ birdc6 show route 2001:db8:30::1/128 via fe80::5054:56ff:fe6e:98a6 on eth0 * (100/20) [AS65001i] via fe80::5054:56ff:fe6e:98a6 on eth0 (100/20) [AS65001i] 2001:db8:30::2/128 via fe80::5054:60ff:fe02:3681 on eth0 * (100/20) [AS65001i] via fe80::5054:60ff:fe02:3681 on eth0 (100/20) [AS65001i] 2001:db8:30::3/128 via fe80::5054:56ff:fe6e:98a6 on eth0 * (100/20) [AS65001i] via fe80::5054:56ff:fe6e:98a6 on eth0 (100/20) [AS65001i]
--no_kernel flag for bgpd instead. You
may want to look at the whole thread for more details.
birdc6 shows both the next-hop as
advertised in BGP and the resolved next-hop if the route
have to be exported into another protocol. I have
simplified the output to avoid confusion.
Pretend I run a cluster, for hosting a site. Pretend that I have three-six web-nodes, and each one needs to know which database host to contact.
How do I control that?
Right now I have a /etc/settings.conf file, more or less, deployed by Slaughter. That works. Another common pattern is to use a hostname - for example pmaster.example.org.
However failover isn't considered here. If I wanted to update to point to a secondary database I'd need to either:
The first alpha of syslog-ng 3.4 was released more than a year ago, and the first stable release earlier this year, development on syslog-ng 3.5 has been going on steadlily since then, with a lot of interesting features and changes pouring in. While the 3.5 release will not bring as many overwhelming changes as the previous two releases did, the sheer number of improvements is still substantial. Our focus was on smaller developments all over the place this time, instead of big sweeping changes. In this post, we will go over most of these features, with use-cases, examples and a few words about why they are so useful and awesome.Multi-line support, new destinations, new template functions, type hinting, unit suffixes, and other things. Read on, and be amazed!These are only bigger features, there has been a lot of small tweaking going on, and of course, all of the fixes that went into prior versions will also be in 3.5 too, and there's still a chance that something else may find its way in before the feature freeze.Multi-line supportOne of the major new features in the 3.5 release will be support for multi-line messages, a feature that has been available in syslog-ng PE for a good while, and which has been ported to and improved upon to the open source edition. Two variants of multi-line are supported, which will be detailed below. Both of them are available for the file() and pipe() sources only.Indented multi-lineThe easiest variant is indented multi-line, where each line can be followed by others, indented by whitespace, and the message continues until the first non-indented line. This is the format used by the Linux kernel too, from version 3.5, for /dev/log. This type of multi-line can be used as follows:
source s_multiline file("/path/to/file" multi-line-mode(indented)); ;Consider that /path/to/file has the following content:
First line Continuation 1; Continuation 2; Second lineWith the indented
multi-line-mode() setting, this would turn into two log messages:
First line\n Continuation 1;\n Continuation 2; Second lineRegexp-based multilineIf multi-line input is not based on indentation, one can use the regexp
multi-line-mode() instead, which makes two new settings available: multi-line-prefix() and multi-line-garbage(). These can be used to define the start and the end of a log message: any string between a the beginning matching prefix and a matching garbage will be considered a single message. That is, the prefix will be included, the garbage will not be: it will be discarded.To illustrate:
source s_multiline
file("/path/to/file" multi-line-mode(regexp)
multi-line-prefix("^prefix")
multi-line-garbage(" garbage$"));
;If the source contains these lines:
prefix message continuing garbageThis will turn into the following log message:
prefix message\ncontinuingNew destinationsIt would be pretty hard to do a syslog-ng release without new destinations, and with 3.5, we will have three of them!STOMPWhile we had AMQP before, we now have a STOMP destination too, so we can stream logs to any STOMP server, with a few simple lines:
stomp(
host("localhost")
port(61613)
destination("/topic/syslog")
routing_key("")
persistent(yes)
ack(no)
username("someone")
password("something")
body("This is the body! YAY! Here's a message: $MESSAGE!\n")
value-pairs(scope(nv-pairs, syslog-proto, selected-macros))
)Of course, none of these settings need to be set, you can just use the defaults, and it will just work!RiemannDid you know that syslog-ng is far more than a log collector and processor? No? You do now. When you have access to a lot of logs, and a tremendous amount of power in parsing them, you can use these tools for monitoring easily! And when we're talking monitoring, riemann is a great asset in our toolbox, and with the new destination, we can easily forward metrics to it:
riemann(
server("localhost")
port(5555)
host("$HOST")
service("$PROGRAM")
description("$PROGRAM pids")
metric(int("$PID"))
ttl(300)
);Of course, the above is a very silly example, it would make much more sense to extract data from a log message instead, but this will serve as an example.New template functions
$(upper-case TEXT...), $(lower-case TEXT...)$(delimit DELIMITERS NEW-DELIMITER TEXT)template("$(delimit \"\t \" \" \" $MESSAGE)\n")
$(env VARIABLE...)mongodb() destination and the $(format-json) template function for now. When no type hint is specified, syslog-ng defaults to string.To add type hints, simply wrap the respective template with the hinted type, like this:
mongodb(
value-pairs(pair("date", datetime("$UNIXDATE"))
pair("pid", int64("$PID")))
);Currently the following type hints exist: boolean (anything that begins with a t or 1 is true, anything that begins with f or 0 is false, everything else is an error), string, literal (same as string, but not quoted if it would be quoted otherwise), int32 (int is an alias for this), int64, and datetime. Only UNIX timestamps can be type-hinted to datetime, anything else will likely result in a casting error.It is also possible to control what happens when type casting fails: syslog-ng can drop the whole message, drop the property, or fall back to string. It can also do all of these silently:
options typecast(on-error(silently-drop-property)); ;Using this feature with
$(format-json) is very similary too:
$(format-json date=datetime("$UNIXDATE") pid=int64("$PID"))With this feature in place, you can now store your non-string values with their proper types!Unit suffixesUnit suffixes make it considerably easier to set limits and describe numbers within the syslog-ng configuration. We no longer need to spell out sizes to the byte precious, it is now enough to write: log-fifo-size(200MiB). Now, syslog-ng will understand suffixes for kilo-, mega-, and giga-bytes, (K, M, G, respectively) either in base-10 or base-2 (with an extra i after the suffix). One can also omit the trailing b from the end.So, to set the log-fifo-size() to 2097152 bytes, one can simply use 2MiB. Or, to set it to 2000000, 2Mb. That's a whole lot easier, isn't it? No more counting zeros, no more silly typos in a ten-digit number, no more pain, but easily readable units!Miscellaneous featuresApart from the features above, there have been a lot of other changes and improvements in the code base:
username() and password() settings of the
mongodb() driver), some were renamed and deprecated:
the replace() key transformation function of
value-pairs() was renamed to
replace-prefix(), as that makes the intent clearer. In
this latter case, the old name is still valid, but obsoleted.
in-list, with which one
can implement efficient white- or blacklists.
To use it, you will need a file with one value a line, and do
something along these lines:
filter f_whitelist
in-list("/path/to/file.list", value("PROGRAM"));
;
To do a blacklist, just negate the filter:
filter f_blacklist
not in-list("/path/to/file.list", value("HOST"));
;
/dev/kmsg, and
will use that instead of /proc/kmsg when a sufficiently
recent kernel is detected (assuming one is using the
system() source).
The new kernel log format supports structured messages, and
syslog-ng is smart enough to parse them, and make them accessible
like all other message properties (with a .linux. prefix).
The Garmin 910XT is the premier GPS watch for triathlon training and racing.
You'll probably need a newer version of pyusb:
$ git clone git://github.com/walac/pyusbThere is no need to install it systemwide - you can simply leave it checked out somewhere.
Get the Garmin-Forerunner-610-Extractor project from GitHub:
$ git clone git://github.com/Tigge/Garmin-Forerunner-610-Extractor.git
Turn your watch on and plug in the USB adaptor.
You can now sync your activities:
$ sudo env PYTHONPATH=/path/to/pyusb ./garmin.py
Request basic information...
ANT version: AJK1.04RAF
Capabilities: array('B', [8, 3, 0, 186, 54, 0])
Serial number: 3480039
Starting system...
Searching...
Authenticating with Forerunner 910XT (3863343203)
- Passkey: OK
Downloading 1 file(s)
Downloading 2013-09-03_21-09-32-80-19364.fit [..........]
The first time you sync, you will have to authenticate on the watch itself. Downloading the activities will be much slower than you expect.
After the syncing has finished, don't forget to turn the watch off. If you are used to the Garmin Edge 800 (which turns itself off when you insert the USB cable) you will probably not have the habit of turning off the unit.
Rather confusingly, your .FIT files are available in the Xdg configuration folder. For example:
ls -l ~/.config/garmin-extractor/3863343203/activities/ -rw-r--r-- 1 root root 2688 Jun 9 15:23 2013-06-08_12-33-24-80-2688.fit -rw-r--r-- 1 root root 1171 Jun 9 15:23 2013-06-08_12-37-14-80-1171.fit -rw-r--r-- 1 root root 6111 Jun 9 15:23 2013-06-08_22-19-28-80-6111.fit -rw-r--r-- 1 root root 170327 Jun 9 15:26 2013-06-09_11-09-44-80-170327.fit
Strava supports these .fit files through the From File upload option.
The Garmin 910XT is the premier GPS watch for triathlon training and racing.
You'll probably need a newer version of pyusb:
$ git clone git://github.com/walac/pyusbThere is no need to install it systemwide - you can simply leave it checked out somewhere.
Get the Garmin-Forerunner-610-Extractor project from GitHub:
$ git clone git://github.com/Tigge/Garmin-Forerunner-610-Extractor.git
Turn your watch on and plug in the USB adaptor.
You can now sync your activities:
$ sudo env PYTHONPATH=/path/to/pyusb ./garmin.py
Request basic information...
ANT version: AJK1.04RAF
Capabilities: array('B', [8, 3, 0, 186, 54, 0])
Serial number: 3480039
Starting system...
Searching...
Authenticating with Forerunner 910XT (3863343203)
- Passkey: OK
Downloading 1 file(s)
Downloading 2013-09-03_21-09-32-80-19364.fit [..........]
The first time you sync, you will have to authenticate on the watch itself. Downloading the activities will be much slower than you expect.
After the syncing has finished, don't forget to turn the watch off. If you are used to the Garmin Edge 800 (which turns itself off when you insert the USB cable) you will probably not have the habit of turning off the unit.
Rather confusingly, your .FIT files are available in the Xdg configuration folder. For example:
ls -l ~/.config/garmin-extractor/3863343203/activities/ -rw-r--r-- 1 root root 2688 Jun 9 15:23 2013-06-08_12-33-24-80-2688.fit -rw-r--r-- 1 root root 1171 Jun 9 15:23 2013-06-08_12-37-14-80-1171.fit -rw-r--r-- 1 root root 6111 Jun 9 15:23 2013-06-08_22-19-28-80-6111.fit -rw-r--r-- 1 root root 170327 Jun 9 15:26 2013-06-09_11-09-44-80-170327.fit
Strava supports these .fit files through the From File upload option.
Some of you might have noticed there is a new nagios-plugins version in the row. To support upstream in evaluating bugs and bringing the code to a wider audience, I uploaded the latest development version into Debian unstable.
Since this package version contrib/ is dropped by upstream. But we stopped shipping the latest plugins of contrib/ with Debian wheezy. We also removed perlmods/ from the upstream tarball, as this was never used by our package.
The packaging changes are:
* New upstream git snapshot (b15adb7762)
- Adjust debian/copyright
* Droped the following upstream integrated patches
- 05_fix_gets_undefined_in_iso_c11.dpatch
- 10_check_apt_perfdata.dpatch
- 11_check_nt_npe.dpatch
- 12_check_smtp_double_threshold.dpatch
* Fix removing empty /usr/include
* Add new check_dbi into nagios-plugins-standard
* Remove whois from Recommands, as check_bgpstate is removed
* Cleanup debian/rules from unused stuff
* Provide information about repackaging
- Extend debian/README.source
- Add debian/bin/repack.sh
* Updating standards version to 3.9.4 (no changes needed)
* Add libfreeradius-client-dev to build-deps and remove libradiusclient-ng-dev
(Closes: #721621)
* Remove traces of contrib/ from debian/copyright
* Remove command.cfg from examples in nagios-plugins-common, it was removed
upstream
The Debian Nagios Maintainer and Upstream Developer are asking you to try out this new package on non production systems. Not that we think there might be a high risk for damage, but you know .. :) The latest version of the plugins are running on several systems already, but it is nearly impossible to test all scenarios even automated.
If you find bugs, please report all packaging bugs into the BTS. Upstream bugs you might consider to report in the upstream bugtracker.
If you want to give it a try on Debian wheezy, you could install the packages from our wheezy-backports repository:
For adding our archive key, you can just install the package "debian-cyconet-archive-keyring"# wget "http://ftp.cyconet.org/debian/sources.list.d/wheezy-backports-cyconet.list" \ -O /etc/apt/sources.list.d/wheezy-backports-cyconet.list # aptitude update # aptitude -t wheezy-backports install nagios-plugins
http://gallery.mailchimp.com/3021e68df9a7200135725c633/images/Email_Header_ThisisLabor.jpgThere it is, that big long code 3021e68df9a7200135725c633. On it's own, you may think this number can't do much harm. Think again. After all, as the filename says, "ThisisLabor". Reaching the grass roots by long distance email When a party member sees any of the images in the email or clicks any of the links, their email software or web browser sends a HTTP request to the ALP's outsourced tracking server in the United States. Here is an example of what that request may contain:
TCP Headers: SOURCE IP ADDRESS: 198.51.100.56 HTTP headers: GET /3021e68df9a7200135725c633/images/Email_Header_ThisisLabor.jpg HTTP/1.1 Host: gallery.mailchimp.com User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130515 Firefox/17.0 Iceweasel/17.0.6 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate X-Forwarded-For: 192.168.1.54 Connection: keep-aliveThese codes are all transmitted from the recipient of the email back to the ALP. Notice the tracking number is in the very first line of the HTTP request? These codes send many details to the tracking server. Just what is revealed?
"Dig even deeper with Subscriber Activity Reports, which give you a real time report for every subscriber s email activities: when they opened, what they clicked, and when they came back for more. You can even generate a list of people who didn t open, and send them a modified campaign."That's right: if ALP members don't read their emails fast enough, they will send even more of them. Just who has access to this data? Well, the scope is quite broad. According to these rules, it is not only the dubious officials in the party's state office, but Labor Party regulations also list a whole lot of other officials who have access to some subset of the data: branch and FEA district committees, policy committees and maybe some trade union officials too. Once you start to contemplate this, it becomes apparent that the probability of somebody profiling members at an individual level is very real. On the other hand, those rules clearly do not permit the state branch to process the member's data offshore. Double whammy In fact, even MailChimp is further outsourcing the data. When receiving an image from the booby-trapped link in the email, we receive a response like this:
HTTP/1.1 200 OK Content-Type: image/jpeg Content-Length: 407474 Connection: keep-alive Date: Wed, 10 Jul 2013 06:25:55 GMT Last-Modified: Tue, 03 Sep 2013 04:05:37 GMT ETag: "df9a7200135725c6331369a22" Accept-Ranges: bytes Server: AmazonS3 Age: 62097 Via: 1.0 e71fe855f29513f54a41e213fe653fb1.cloudfront.net (CloudFront) X-Cache: Hit from cloudfront X-Amz-Cf-Id: S2V2aW4gUnVkZCBpcyBhIGJhZCBib3kuCg==which contains more tracking numbers and clearly indicates that the data is being processed in the massive AmazonS3 (a.k.a Amazon online bookstore) cloud platform. Thanks to cloud computing, there is considerable scope for cross-referencing records across other web sites. The IP address becomes a magic key, allowing a range of sinister forces to join the dots at the click of a button and profile the whole private and professional identity of any individual ALP member. Googling ALP members It doesn't stop there however, after following these links a victim will eventually end up on one of the ALP's own web pages. Looking through the HTML code underneath http://www.viclabor.com.au is very easy, in most web browsers, you can just press Control-U to see what is hidden away in the shadows. Buried in the code, I found this little gem:
var _gaq = _gaq [];
_gaq.push(['_setAccount', 'UA-35325645-1']);
_gaq.push(['_trackPageview']);
(function()
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
)();
This may be even scarier: it's a JavaScript code that channels all access to the ALP web site into an outsourced tracking system provided by Google. Google can now cross-reference ALP members against their Gmail accounts, their friends and the topics they search for to further profile the type of advertising they should be exposed to. Google, like any private company, has a loyalty to its shareholders and the laws of the country where it is domiciled. Will that coincide with the best interests of ALP members in Victoria?
Australia's other parties: samples needed
Do you have similar communications from Australia's other political parties? Please send them to me and I'll be happy to examine them for similar shortcomings.
So that forum I mentioned? I've setup a test-installation at:
What does this forum offer? A cross between hacker news and reddit. If the admin of the forums enables it you can create arbitrary tags, and then view them. For example:
Next.