<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Retina Technology Blog &#187; perl</title>
	<atom:link href="http://www.retina.net/tech/category/perl/feed" rel="self" type="application/rss+xml" />
	<link>http://www.retina.net/tech</link>
	<description>John Adams' views on emerging technologies, software engineering, and various hacks</description>
	<lastBuildDate>Fri, 16 Sep 2011 09:06:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2</generator>
	<!-- podcast_generator="podPress/8.8.10.2" -->
	<copyright>2006-2007 </copyright>
	<managingEditor>jna@retina.net (John Adams)</managingEditor>
	<webMaster>jna@retina.net (John Adams)</webMaster>
	<ttl>1440</ttl>
	<image>
		<url>http://www.retina.net/tech/wp-content/plugins/podpress/images/powered_by_podpress.jpg</url>
		<title>Retina Technology Blog &#187; perl</title>
		<link>http://www.retina.net/tech</link>
		<width>144</width>
		<height>144</height>
	</image>
	<itunes:subtitle></itunes:subtitle>
	<itunes:summary>John Adams' views on emerging technologies, software engineering, and various hacks</itunes:summary>
	<itunes:keywords></itunes:keywords>
	<itunes:category text="Technology" />
	<itunes:category text="Technology">
		<itunes:category text="Tech News" />
	</itunes:category>
	<itunes:author>John Adams</itunes:author>
	<itunes:owner>
		<itunes:name>John Adams</itunes:name>
		<itunes:email>jna@retina.net</itunes:email>
	</itunes:owner>
	<itunes:block>no</itunes:block>
	<itunes:explicit>no</itunes:explicit>
	<itunes:image href="http://www.retina.net/tech/wp-content/plugins/podpress/images/powered_by_podpress_large.jpg" />
		<item>
		<title>Traktor to Snarkatron!</title>
		<link>http://www.retina.net/tech/traktor-to-snarkatron.html</link>
		<comments>http://www.retina.net/tech/traktor-to-snarkatron.html#comments</comments>
		<pubDate>Mon, 28 Jul 2008 09:04:29 +0000</pubDate>
		<dc:creator>John Adams</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[digitaldj]]></category>
		<category><![CDATA[digitalsign]]></category>
		<category><![CDATA[hacks]]></category>
		<category><![CDATA[mp3]]></category>
		<category><![CDATA[sign]]></category>
		<category><![CDATA[snarkatron]]></category>
		<category><![CDATA[traktor]]></category>
		<category><![CDATA[translux]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.retina.net/tech/?p=86</guid>
		<description><![CDATA[Awhile back I gave a talk about The Snarkatron at Ignite SF. It&#8217;s a digital sign, installed facing the crowd at the DNA Lounge here in San Francisco. I DJ a number of nights there, and my recent transition from CD and Vinyl to Laptop/MP3 with M-Audio&#8217;s Xponent has given me many more chances to [...]]]></description>
			<content:encoded><![CDATA[<p>Awhile back I gave a talk about <a href="http://www.retina.net/tech/snarkatron-slides-up.html">The Snarkatron</a> at Ignite SF. It&#8217;s a digital sign, installed facing the crowd at the <a href="http://www.dnalounge.com">DNA Lounge</a> here in San Francisco. I DJ a number of nights there, and my recent transition from CD and Vinyl to Laptop/MP3 with M-Audio&#8217;s Xponent has given me many more chances to do things with the playlist that I create each night. The main reason why I bought the sign was to let the public know what songs we were playing, but we were never able to do this without typing in each song name. The holy grail of getting the song titles onto the Snarkatron, automaticaly, has never been fulfilled <strong>until now</strong>.</p>
<p>The trick here is that you connect Traktor to a local <a href="http://www.icecast.org">Icecast2</a> install, turn on audio broadcast (with no listeners) in Traktor, and then read XML off the Icecast2 install to extract which song is playing from Traktor. Traktor is very smart about the current song as well. It looks at the decks and crossfader to determine the current, live song, and forwards that to Icecast.</p>
<p>We can extract this and use it for our digital display!</p>
<p>The source for this dumb trick follows below&#8230;</p>
<p>(Sorry for the bad layout of this code; I have to fix our CSS file after the recent site upgrade)</p>
<p>#!/usr/bin/perl -w<br />
#<br />
#<br />
# Pull the current song from my local icecast server and forward the<br />
# song data to the snarkatron.<br />
#<br />
# Whatever you set the server name to in Traktor, it will be used as<br />
# the &#8216;dj subtitle&#8217; on the 2nd line of the display.<br />
#<br />
# J. Adams <jna@retina.net><br />
#<br />
#</p>
<p>use strict;<br />
use LWP;<br />
use XML::Simple;<br />
use HTTP::Request::Common;</p>
<p>my $lastartist = &#8220;&#8221;;<br />
my $lasttitle = &#8220;&#8221;;</p>
<p>while (1) {<br />
    # fetch icecast stats.<br />
    my $browser = LWP::UserAgent->new;</p>
<p>    $browser->credentials(<br />
	&#8216;localhost:8000&#8242;,<br />
	&#8216;Icecast2 Server&#8217;,<br />
	&#8216;admin&#8217; => &#8216;XXXXXXXXXXX&#8217;<br />
	);</p>
<p>    my $url = &#8220;http://XXXXXXXXXX:8000/admin/stats.xml&#8221;;</p>
<p>    my $response = $browser->get($url);</p>
<p>    die &#8220;Error: &#8220;, $response->header(&#8216;WWW-Authenticate&#8217;) ||<br />
	&#8216;Error accessing&#8217;,<br />
	&#8220;\n &#8220;, $response->status_line, &#8220;\n at $url\n Aborting&#8221;<br />
	unless $response->is_success;</p>
<p>    # parse it<br />
    my $xs = new XML::Simple;<br />
    my $data = $xs->XMLin( $response->content );</p>
<p>    # no source, means no connection to icecast!</p>
<p>    if (defined($data->{source})) { </p>
<p>	if (($lastartist ne $data->{source}->{artist}) &#038;&#038;<br />
	    ($lasttitle ne $data->{source}->{title}) ) {<br />
	    print &#8220;Update&#8230;\n&#8221;;<br />
	    print $data->{source}->{server_name} . &#8220;\n&#8221;;<br />
	    print $data->{source}->{artist} . &#8220;\n&#8221;;<br />
	    print $data->{source}->{title} . &#8220;\n&#8221;;</p>
<p>	    # update snarkatron<br />
	    my $ua = LWP::UserAgent->new;<br />
	    my $req = (POST &#8216;http://XXXXXXXXXXXX/addsong.cgi&#8217;,<br />
		       ["djname"   => $data->{source}->{server_name},<br />
			"band"     => $data->{source}->{artist},<br />
			"sngtitle" => $data->{source}->{title},<br />
			"Add" => "Add"<br />
		       ]); </p>
<p>	    my $postrequest = $ua->request($req);<br />
	    my $postcontent = $postrequest->content;<br />
	}</p>
<p>	$lastartist = $data->{source}->{artist};<br />
	$lasttitle = $data->{source}->{title};<br />
    } else {<br />
	print &#8220;WARNING: Traktor is not transmitting to Icecast! Enable the Broadcast! (sleeping for retry&#8230;)\n&#8221;;<br />
    }</p>
<p>    # increase for production<br />
    sleep(5);</p>
<p>}</p>
]]></content:encoded>
			<wfw:commentRss>http://www.retina.net/tech/traktor-to-snarkatron.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Stealing log files from other processes.</title>
		<link>http://www.retina.net/tech/stealing-log-files-from-other-processes.html</link>
		<comments>http://www.retina.net/tech/stealing-log-files-from-other-processes.html#comments</comments>
		<pubDate>Mon, 04 Feb 2008 23:59:30 +0000</pubDate>
		<dc:creator>John Adams</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[systems administration]]></category>

		<guid isPermaLink="false">http://www.retina.net/tech/stealing-log-files-from-other-processes.html</guid>
		<description><![CDATA[It occurs to me that there&#8217;s hundreds of scripts, programs, and code snippets that I use on a daily basis that have just never seen the light of day.Time to change that. I&#8217;m not going to provide you with a pretty library like jwz has, but I&#8217;ll do what I can.At my day job, we [...]]]></description>
			<content:encoded><![CDATA[<p>It occurs to me that there&#8217;s hundreds of scripts, programs, and code snippets that I use on a daily basis that have just never seen the light of day.Time to change that. I&#8217;m not going to provide you with a pretty library like <a href="http://www.jwz.org/hacks/">jwz has</a>, but I&#8217;ll do what I can.At my day job, we had a piece of proprietary software (ATG Dynamo) that would only issue a thread dump if we asked nicely, and even then, it would write that data out to it&#8217;s own file with no timestamps or indication of which process the dump was coming from. The trick here, was to steal the data while it was entering the log file so we could post process it and tag it with the appropriate server name and timestamp.</p>
<p>
Here&#8217;s my perl code that makes this work, which may be of interested to anyone using java application servers.
</p>
<p># Find all running DRPs and request a thread dump, pulling the<br />
# thread dump out of ATG&#8217;s log and making a private copy for ourselves.<br />
#</p>
<p>my $ATGLOGDIR=&#8221;/gl/atg/ATG7.1/home/logs&#8221;;<br />
my $ATGOUTDIR=&#8221;/gl/atg/threaddump_logs&#8221;;</p>
<p>open(P,&#8221;ps -auxwww &#8211;forest|&#8221;);</p>
<p># prep output<br />
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =<br />
    localtime(time);</p>
<p>my $tm = sprintf(&#8220;%d%02d%02d-%02d:%02d:%02d&#8221;,$year+1900,$mon,$mday,$hour,$min,$sec);</p>
<p>open (W,&#8221;>$ATGOUTDIR/$tm-threaddump.log&#8221;) || die &#8220;cannot open log output file&#8221;;</p>
<p>while(
<p>) {<br />
    if (/startDynamo/) {<br />
        # we know that next line will be java<br />
        $_ =
<p>;</p>
<p>        # ps regexp<br />
        if (/\w+[ ]+([0-9]+).* .*\/servers\/(.*)\/logs/) {<br />
            print W &#8220;Java PPID = $1 name = $2\n&#8221;;<br />
            $SVR{$1}->{pid} = $1;<br />
            $SVR{$1}->{name} = $2;</p>
<p>        }</p>
<p>    }<br />
}</p>
<p>close(P);</p>
<p>foreach $k (sort keys %SVR) {<br />
    # before we do this, we need to open the other file<br />
    my $CMD=&#8221;ls -lat /gl/atg/ATG7.1/home/logs/  | grep &#8221; . $SVR{$k}->{name} . &#8220;_threadDump | awk &#8216;{ print \$NF }&#8217;&#8221;;<br />
    my $LOGFILE=`$CMD`;</p>
<p>    open (R,&#8221;<$ATGLOGDIR/$LOGFILE");<br />
    seek(R,0,2); # seek EOF</p>
<p>    system("kill -3 $k");</p>
<p>    # wait for buffer to accumulate<br />
    sleep 1;</p>
<p>    while(<r>) {<br />
        print W localtime(time) . &#8221; [" . $SVR{$k}->{name} . "]:  &#8221; . $_;<br />
    }</p>
<p>    close(R);<br />
}<br />
close(W);</p>
]]></content:encoded>
			<wfw:commentRss>http://www.retina.net/tech/stealing-log-files-from-other-processes.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

