Inspired by the C-Reduce project, which reduces C programs that cause compiler crashes to a minimal program that still causes the crash, I have started perl-reduce, which does the same for perl programs which segfault, cause valgrind issues, etc. The first draft is at:
and I'm hoping to collect some user experiences for a bit more tweaking before widely advertising it in the perl community. If you have a crasher that you've never narrowed down because it looked too tedious, please give perl-reduce a try.
Twitter recently got rid of the ability to get search results as an RSS as part of their API update of 11 June 2013.
I found those feeds rather useful, so I made a little screen scraper that reimplements the functionality without needing to auth against their API (it just pulls the results out of the web search page). I guess this will be good for a while longer, like enough time to switch to statusnet, identica, or whatever.
It might be of use to some others in the monastry and illustrates the power of HTML::TreeBuilder::XPath.
I run ffmpeg from a windows console. It colors its messages, eg. warnings are (red) yellow and errors are bright red. That's all good, but when I interrupt ffmpeg, it sometimes leaves the console color changed and then all further text in the same console will be written in that color.
The cls command does not restore the color like it used to in some windows versions. Rerunning ffmpeg doesn't help because it checks the console color when it starts and restores that when it exits. I don't wish to close the console and start a new one because that would lose the command history. Thus, I need a separate command to reset the console colors. Here's a simple command to do that (put it into a batch file). Works with ActiveState perl 5.16.1.
I read a lot on this topic. There are solutions for this mater. The most promising involves a module named Number::Format. I found also regexp based solutions, which gave me a headache and which I could not get to work properly. Finally there are millions of fancy code bits around for this purpose. There is also one solution to forget definitively: sprintf!
The solution I am posting here is thought for web-application. Web-application written in PERL have performance issues and unfortunately performance, meaning user perceived response times, are THE acceptance factor for your application. To solve this issue we fortunately have a wonderful Apache module named mod_perl.
Mod_perl can be tuned by loading modules into memory with the PerlModule directive. However you can not load infinitely modules in memory, since it is a scarce resource (more information on http://perl.apache.org/docs/1.0/guide/performance.html). Therefore I discarded the Number::Format module solution, which holds much more functions than what I need.
A web-application can have two layers of validation and formating. The first layer being the browser, the second being the PERL code on the server. The best is of course to validate and format your data at both layer. Therefor I was looking for a solution in JavaScript and one in PERL, which would be similar. So I realized them...
Here the JavaScript function:
<script type='text/javascript'>
function formatNumber(myElement) { // JavaScript function to inser
+t thousand separators
var myVal = ""; // The number part
var myDec = ""; // The digits pars
// Splitting the value in parts using a dot as decimal separat
+or
var parts = myElement.value.toString().split(".");
// Filtering out the trash!
parts[0] = parts[0].replace(/[^0-9]/g,"");
// Setting up the decimal part
if ( ! parts[1] && myElement.value.indexOf(".") > 1 ) { myDec
+= ".00" }
if ( parts[1] ) { myDec = "."+parts[1] }
// Adding the thousand separator
while ( parts[0].length > 3 ) {
myVal = "'"+parts[0].substr(parts[0].length-3, parts[0].le
+ngth )+myVal;
parts[0] = parts[0].substr(0, parts[0].length-3)
}
myElement.value = parts[0]+myVal+myDec;
}
</script>
<!-- in the html page -->
<input name="amount" id="amount" type="text" onkeyup="formatNumber(thi
+s);">
I've put together a new perl module on CPAN called Yote. It directly and automatically binds javascript client objects to perl server objects. The objects are container objects that live in an object database. The objects are lazily loaded as needed and are automatically stored with their contents automatically. The following example works out of the box as long as the Hello package is in the Yote server's perl classpath. The hello count will be preserved in Yote's data store.
Server Side Perl
package Hello;
use base 'Yote::AppRoot';
sub hello {
my( $self, $input ) = @_;
$self->set_hello_count( $self->get_hello_count( 0 ) + 1 );
return "Hello $input, I have said hello ".
$self->get_hello_count() . " times";
}
1;
I recently ran into a bunch of problems where our MPLS provider inadvertently modified the MTU sizes of several of our locations. Unfortunately at about the same time we had swapped out our firewall, so after spending significant time thinking we had weird issues with the new firewall, we finally discovered the actual problem was an incorrect MTU size for those sites.
This wasn't the first time the MTU sizes had been monkeyed with, so I decided to throw something together that might help us identify MTU problems more quickly.
I'd found Network Duplex speed test so, I used much of that for the actual ping packet creation, which referenced Net::Ping code, so I also compared the current version
of that against what was given in the duplex test node. Then I had to figure out how to turn on the don't fragment flags of the packet. Anyway, the results are below.
I had a bunch of music lyrics that I wanted to print and I didn't want to manually drive gedit. I did, however, want to retain the document formatting. I found a hint in Re^2: using Brother QL-570 printer with Perl and also found sample commands in an Ubuntu Community Documentation post for using the Open Office command line interface for batch printing or viewing. The are also posts out there for doing a similar thing with MS-Word.
The following is what I threw together. It does the job for me, YMMV. I needed to print UTF-8 text files, but Open Office will try to print whatever file you give it using the file extension as a guide to the file format. I have also printed .odt files.
I'm currently using the following to run commands on remote systems through ssh. I'd appreciate any comments or improvements.
One specific question is how to capture STDERR and assign it to the remote host it came from. (I haven't spent much time investigating this issue, so there's probably some easy fix I've overlooked.)
The current library supports basic commands, such as takeoff, pitch, roll, yaw, vert speed, and land. All the preprogrammed flight animations are also in place. Navigation data and video are not yet supportedsee the ROADMAP file for future plans.
I spend today reading about how to pipe a mail received by postfix into a perl script.
I read a lot but could hardly find a solution for my setup. So I give one here.
The case
An application must be able to process email coming in from the net and it must be also able
to respond to these emails.
The setup:
The machine is configured to send all emails over an MTA somewhere in the network
The MTA hosts a virtual mail domain for which it forwards all its email to the machine
The machine holds an application written in PERL
A PERL script īs used as delivery agent to process some mails
The tested platform: Linux Ubuntu 12.04 LTS, postfix 2.9.6
The postfix main.cf configuration created by dpkg-reconfigure postfix
myhostname = [host name]
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = [list for local delivery]
relayhost = [the MTA name for sending emails]
mynetworks = [see posfix documentation]
mailbox_size_limit = [you would rather set it!]
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
mail_spool_directory = /var/mail
Notice: If you intent to open(OUT ">", $filename); in your PERL script it will fail with a missing privilege error. To avoid this you have to set default_privs = to an other user than nobody in the postfix main.cf. This has impact on the whole postfix setting. I did not analyse it until now. So if you do this, you do it at your own risk.
Enjoy!
K
The best medicine against depression is a cold beer!
Despite an incredible amount of literature on this topic, I could not find a proper solution for this issue. Accordingly I post my one here.
I had to realize a relatively complex web application. This application bases on CGI.pm and mod_perl for performance reasons and supports several languages. I wanted to have one single code for the logic of the application. An additional requirement was be to be able to add languages easily. After reading a lot about solutions involving templates or dictionaries (typically gettext), I figured out using PERL language packages would fulfill most of my requirements. The problem was to load the appropriate language module at application start up time and to allow the user to change the language for example for print outs. Here is the solution I worked out.
First make a set of simple language packages with names like EN.pm, FR.pm, DE.pm. Each of these modules holds hashes with the texts for the application's forms. For this solution to work properly, the hash names must be in lower case. Example for a log in form:
- French in FR.pm: $login{msg1} = "Identifiant";
- German in DE.pm: $login{msg1} = "Benutzername";
- English in EN.pm: $login{msg1} = "User name";
Next use the following at the beginning of each language package to export the content. Example for EN.pm:
This will export all hashes in lower case and avoid for example the EXPORT array. Next you will have to import the correct languages package in your cgi script with a statement like use [Modulename];.
Unfortunaltely you can hardly load modules dynamically and can hardly reference a variable in a module dynamically. Constructs like use $language; or ${language}::login{msg1}; will not work.
Despite lot of posts on this topic, I haven't found a solution to solve this issue. This means so or so I will not be able to load the languages dynamically but will have to manage the supported languages in the code of the application's logic.
My solution bases on a language variable I called syslang. This variable is either set by the calling cgi script or defined by the selected language of the client's browser. I begin my cgi scripts the following way and include a global language variable:
# ----------------------------------------------------------------
+----------------
# Script header
# ----------------------------------------------------------------
+----------------
# Loading perl modules
my $start = time();
use FindBin qw($Bin);
use File::Basename;
use Cwd;
use CGI qw/:standard *table tr td select/;
use CGI::Carp;
use CGI::Session;
use Data::Dumper;
use strict;
# Our global language variable
our $syslang = undef;
Next I add the path to my application or packages to @INC array. My application packages are always in a lib directory. This is also the location of the language packages. For the solution to work the @INC array must be enhanced with a begin block or the script will not compile:
# Notice: this will work with Apache, cheap web-server might be a
+serious issue!
# a) Detect if we are called by the web-server or not
# b) Set the path accordingty
BEGIN {
# Adding application lib path
my $libdir = undef;
if ( not defined($ENV{SERVER_NAME}) ) { $libdir = getcwd; }
else { $libdir = File::Basename::dirname($ENV{SCRIPT_FILENAME}
+); }
# I know.... but sometimes I am lazy!
chdir "$libdir/../lib";
$libdir = getcwd;
if ( not grep(/$libdir/, @INC) ) { push (@INC, $libdir); }
undef $libdir;
}
Now we need to manage the languages. We need to load the package with the correct texts, knowing the user can change the language of the application. Because of mod_perl we need to unload the language modules first and the reload the correct module to force Apache to recompile the script. Here my solution for this:
# Setting the language
# This one is to fool the compiler! Don't ask!
use EN;
# Testing if the language has allready be set or using the one def
+ines by the browser
# frdlang is my cgi language parameter
my $q = new CGI;
if ( $q->param("frdlang") ) { $syslang = uc($q->param("frdlang"));
+ }
elsif ( not $syslang ) { $syslang = uc(substr($ENV{HTTP_ACCEPT_LAN
+GUAGE}, 0, 2)); }
# Unloading language modules to force recompiling under mod_perl
foreach my $lang ( grep(/DE.pm$|FR.pm$|EN.pm$/, keys(%INC)) ) { de
+lete $INC {$lang}; }
# Loading apropriate language module
if ( uc($syslang) =~ /^DE/ ) { require DE; DE->import(); }
elsif ( uc($syslang) =~ /^FR/ ) { require FR; FR->import(); }
elsif ( uc($syslang) =~ /^EN/ ) { require EN; EN->import(); }
Now we might have the issue that some packages return some part of the HTML form, tipically the menus. The language of these parts musst also be changed each time the user switches the language. So we need to reload all the modules impacted. Here my solution for this:
# Unloading the application language related module to force recom
+pile under mod perl
foreach my $module ( grep(/utils.pm$|install.pm$|login.pm$/, keys(
+%INC)) ) { delete $INC{$module}; }
# setting languages for each modules to load
$utils::syslang = $syslang;
$install::syslang = $syslang;
$login::syslang = $syslang;
# Loading language dependent modules
require utils; utils->import();
require install; install->import();
require login; login->import();
# ... your cgi code.
Not sure if this counts as "cool use" but this little thing has become one of my favorite tools over the past few years. Pass any plaintext data through it and emphasize any text you want using regular expressions. Useful for tcpdump, server logs...anything really.
Update: After posting version 1 the problem of overlapping matches has been bugging me so much I've actually found a solution. Instead of using straight regex substitution I now do all the matching first, then apply the colors afterwards. I've tested it quite a bit but it's still experimental.
#!/usr/bin/perl
use strict;
use warnings;
use Term::ANSIColor;
my @rules = @ARGV;
while (my $line = <STDIN>) {
print rewrite($line, @rules);
}
exit;
# Process a single line
sub rewrite {
my $line = shift;
my @rules = @_;
my @marks = ();
# Process each rule and find areas to mark
while (@rules) {
my $regex = shift @rules;
my $color = shift @rules || 'bold yellow';
$color = color('reset').color($color);
while ($line =~ /$regex/ig) {
my $reset = undef;
# Scan match area to find last color
foreach my $i (reverse $-[0] .. $+[0]) {
if (defined $marks[$i]) {
$reset = $marks[$i] unless defined $reset;
$marks[$i] = undef; # Cancel previous color
}
}
# If necessary, keep scanning to beginning of line
unless (defined $reset) {
foreach my $i (reverse 0 .. $-[0]) {
if (defined $marks[$i]) {
$reset = $marks[$i];
last;
}
}
}
# Mark area
$marks[$-[0]] = $color;
$marks[$+[0]] = $reset || color('reset');
}
}
# Apply color codes to the string
foreach my $i (reverse 0 .. $#marks) {
substr($line, $i, 0, $marks[$i]) if defined $marks[$i];
}
return $line;
}
=pod
=head1 NAME
em - console emphasis tool version 2
=head1 DESCRIPTION
em is a command line tool for visually emphasizing text in log files e
+tc. by
colorizing the output matching regular expressions.
=head1 SYNOPSIS
em REGEX1 [COLOR1] [REGEX2 [COLOR2]] ... [REGEXn [COLORn]]
=head1 USAGE
REGEX is any regular expression recognized by Perl. For some shells
this must be enclosed in double quotes ("") to prevent the shell from
interpolating special characters like * or ?.
COLOR is any ANSI color string accepted by Term::ANSIColor, such as
'green' or 'bold red'.
Any number of REGEX-COLOR pairs may be specified. If the number of arg
+uments
is odd (i.e. no COLOR is specified for the last REGEX) em will use 'bo
+ld yellow'.
Overlapping rules are supported. For characters that match multiple ru
+les,
only the last rule will be applied.
=head1 EXAMPLES
In a system log, emphasize the words "error" and "ok":
=over
tail -f /var/log/messages | em error red ok green
=back
In a mail server log, show all email addresses between <> in white, su
+ccesses in green:
=over
tail -f /var/log/maillog | em "(?<=\<)[\w\-\.]+?\@[\w\-\.]+?(?=\>)" "b
+old white" "stored message|delivered ok" "bold green"
=back
In a web server log, show all URIs in yellow:
=over
tail -f /var/log/httpd/access_log | em "(?<=\"get).+?\s"
=back
=head1 BUGS AND LIMITATIONS
Multi-line matching is not implemented.
All regular expressions are matched without case sensitivity.
=head1 AUTHOR
Andreas Lund <floyd@atc.no>
=head1 COPYRIGHT AND LICENSE
Copyright 2009-2013 Andreas Lund <floyd@atc.no>. This program is free
+software;
you may redistribute it and/or modify it under the same terms as Perl
+itself.
=cut
1. I would love for someone to adopt this and put it on CPAN so myself and others can get easy access to it 2. There's one annoying limitation; overlapping matches don't behave the way they should, and I can't find a way to fix it.
Update: There is one other cool way to use this tool, and that's regex testing. Simply type "em" and the regex you want to test. Example: em "0x[0-9a-f]+"
Now input your test strings one by one, and "em" will show you exactly what matches and what doesn't. Hit Ctrl+D (EOF) to exit.
--
Time flies when you don't know what you're doing