A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Combine STDOUT and STDERR

It's supposed to be done by adding 2>&1 to the end of the command, but that doesn't work for certain commands like time.

Instead make a script combine.sh containing this:
$1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15} ${16} ${17} ${18} ${19} ${20} 2>&1

Call it like this:
./combine.sh command_to_capture with parameters 2>&1 > outputfile 
 

Mount a directory using Samba

mount -t smbfs //host/subdir hostname -o username=yourusername,fmask=555,dmask=555,ro 
 
Don't use Samba though, use SSHFS.

XSL array/hash/lookup table

The lookup file:

<?xml version="1.0"?>
<lookup>
<location id="1769" guide="TT00379a" average="TT123456"/>
<location id="1230" guide="TT003999" average="TT000001"/>
</lookup>

The code: NOTE: $id is a local variable:


<!-- look up the country guide ID -->
<xsl:variable name="guide">
<xsl:for-each select="document('lookup.xml')">
<xsl:value-of select="key('map',$id)/@guide"/>
</xsl:for-each>
</xsl:variable>

Using Apache::Registry

When a script uses a config file that is a perl package, and that package gets changed, it must be reloaded. This can happen either through Apache::StatINC, or Apache::Reload. With both methods you must wait for about a second for perl to 'let go' of the config packages before performing any actions on those files. Otherwise all sort of intermittent weirdness will occur, (e.g. when running the script multiple times in a test and changing the config files inbetween).

Using StatINC_UndefOnReload On can cause all manner of strange errors if you run a script/module, then do :w on the module in vim but don't change anything, then run the script/module again.

Using PerlFreshRestart On causes lots of "Attempt to free unreferenced scalar" errors

Also, when changing the contents of perl configuration 'packages', the modification date on the file must be changed for any Apache module to reload it. Remember that move doesn't change the modification date of files, but copy does. So copy and unlink files, don't move them.


Make vi recognise different filetypes

In ~/.vimrc:

" load custom filetypes
:filetype on
au BufNewFile,BufRead *.tt set filetype=html

Perl test coverage

Select files to cover and run the tests, capturing coverage data:
perl -MDevel::Cover=,+ignore,.*,-select,^lib t/path/to/test.t

Meaning:
  • ignore all paths...
  • except ones starting with "lib"

After it's run, at the command prompt, type this to generate the HTML report:
cover

And then open this file in your web browser:
cover_db/coverage.html

(docs)

Timing out a system call

as seen in perldoc perlipc
 
#!/usr/bin/perl

use warnings;

my @cmd = @ARGV;
my @ls = ();
my $t = 10;

    eval {
        local $SIG{ALRM} = sub { die "alarm went off" };
        alarm $t;
            @ls = `@cmd`;
        alarm 0;
    };

if (! @ls) {
        print "No response after $t seconds\n";
}
else {
        foreach (@ls) { print $_; }
}

# actually never gets to here
if ($@ and $@ !~ /alarm went off/) { die "Command timed out after $t seconds\n"; };

Perl: Tailing a file

seek() can remove the end-of-file marker:
 
while (1) {
    while () {
        # do something
    }
    sleep $for_a_while;
    seek( FILE, 0, 1 );
}

Perl: Simplest way to get a formatted date

use POSIX 'strftime';
my $now_string = strftime( "%Y%m%d", localtime );

Perl: convert a number of seconds into days, hours, mins, secs

printf("That took %d"."d %d"."h %d"."m %d"."s",(gmtime($seconds))[7,2,1,0])); 
 

URI encoding in Java

Deprecated Apache Commons HttpClient 3.x:
 
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.util.URIUtil;

String uriTest1(String uri) {
    String encodedUri = null;
    try {
        encodedUri = URIUtil.encodePath(uri,"UTF-8");
    } catch (URIException e) {
        System.err.println("Caught URI Exception");
        e.printStackTrace();
    }
    return encodedUri;
}

URIEncoder encodes to application/x-www-form-urlencoded (i.e. spaces turn to +)

import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLEncoder;

String uriTest2(String uri) {
    String encodedUri = null;
    String encoding = "UTF-8";
    try {
        encodedUri = URLEncoder.encode(uri, encoding);
    } catch (UnsupportedEncodingException e) {
        System.err.println("Unsuported encoding: "+encoding);
        e.printStackTrace();
    }
    return encodedUri;
}

java.net.URI requires the whole URI to be input, but you can extract just the URI encoded query part (turns spaces to %20)

import java.net.URI;

private static String uriTest3(String path) {
    String encodedUri = null;
    URI uri = null;
    try {
        uri = new URI("http","bbc.co.uk","/search/news/",path,null);
    } catch (URISyntaxException e) {
        System.err.println("Caught URI Syntax Exception");
        e.printStackTrace();
    }
    encodedUri = uri.getRawQuery();
    return encodedUri;
}
See also.

Have unattended scripts look after themselves

# Send all output to a logfile and supress input
typeset LOG="/tmp/${0##*/}.out"
mv $LOG ${LOG}.old >/dev/null 2>&1
[[ -t 1 ]] && echo "Writing to logfile '$LOG'."
exec > $LOG 2>&1
exec < /dev/null 2<&1

OpenZaurus documentation

  • Wiki: http://wiki.openzaurus.org/Main_Page (No longer accepting edits - I have a mediawiki backup)
  • Blog: http://www.openzaurus.org/wordpress/ (Last post: April 26th, 2007 -- post says OpenZaurus is dead and suggests that the future is Angstrom)
  • Sourceforge: http://sourceforge.net/projects/openzaurus/ (No downloads, no issue tracking, nothing is accessible)

Sending an email to yourself

You can't send an email from your blackberry phone, through a gmail account, and expect to see it arrive.
It just doesn't work. For reasons explained here:
http://www.blackberry.com/btsc/search.do?cmd=displayKC&docType=kc&externalId=KB18070
http://www.google.com/support/forum/p/Google+Mobile/thread?tid=196b521f8b4b7a76&hl=en

SSH on Blackberry

MidpSSH

I want to use SSH on my Blackberry, for example with the program MidpSSH.
I am using a Blackberry 8900 on the Orange UK network.

When I try to connect to a server using MidpSSH, I get the error: "Session error: Writer: Invalid parameter".
Apparently I need to set my APN to fix this. What is an APN? List of APNs

On my device in Options | Advanced Options | TCP/IP there's a tickbox for "APN Settings Enabled".
There I can set APN: orangeinternet But this doesn't help. Tried rebooting.

Perhaps it won't work because:
Orange would have had to setup the normal Orange GPRS APN on your account, ... which they don't do for blackberry users (understandably, we're all meant to use BIS).
(I can also see in Advanced Options | Host Routing Table, all the "Host Routing Information" entries have APN: blackberry.net)


Orange


UPDATE 10/09/10:
I called Orange and spoke to the "online services" team (439). A nice man called Ben (CMTS Darlington) found some instructions on their system for using SSH from a Blackberry. They recommended downloading the client from xk72.com. But then he spoke to the 2nd line support team for me and they said that SSH is "Not supported anymore".
Well, what does that mean? That I won't be able to get an SSH connection? Or that I will be able to get a connection, but they won't give me any help should a problem arise? How do I know if their system is working properly for me to try and make an SSH connection?

Here's an unrelated typical example of poor Orange customer service.

PaderSyncSSH

I tried connecting with PaderSyncSSH free trial from the Blackberry App Store.

When I set the Networking connection type in 'Misc. Settings' to "Direct TCP", and set my APN to orangeinternet, I get the error: Connect failed: Error opening socket. java.io.IOException: Peer refused the connection. (Note: This is the same message as I get when connecting to a server that does not offer SSH).
With Networking connection type 'BES/MD5' I got the error: Connect failed: Error opening socket. java.io.IOException: Invalid URL parameter (that's the same as MidpSSH!)
With Networking connection type 'BIS-B' I got the error: Connect failed: Connect failed. ab: Session.connect: java.io.IOException: BIS-B connection failed. (and a recommendation to try Direct-TCP, or have the server listen on a port above 1024 because some carriers block lower ports).

UPDATE 14/09/10:
After connecting once via wifi, I tried connecting to an SSH server via Orange's GRPS phone data network again, and it worked perfectly. Success! I discovered that sometimes I get the error "Connect failed: Error opening socket. java.io.IOException: Peer refused the connection", but other times it works just fine.




Telnet

I succeeded in making a telnet connection to bbc.co.uk:80 through GPRS and issuing a GET HTTP/1.1 command, which resulted in the HTML text of the BBC homepage.



Wifi

I succeeded in using PaderSyncSSH SSHing to shellmix.com:30 (newuser/newuser) when I connected my BlackBerry to a wifi network. It worked really well! MidpSSH gave the same error (but then it doesn't have a network type selection option like PaderSync does).