Se assim como eu, você precisa invariavelmente entregar programas binários e sem o código fonte, então também está sentindo falta do perlcc, que compilava o programa em perl em um belo binário.
Devido à vários bugs, incompatibilidades e falta de manutenção, o perlcc foi removido já no perl 5.8.
Eu testei várias outras soluções, mas ultimamente estava entregando binário utilizando o freeze do python, que eu achava mais simples.
Hoje, buscando uma outra coisa perl, topei com um PAR packer. Tanto a sintaxe quanto a funcionalidade é idêntica ao perlcc.
Eu testei aqui, e funcionou muito bem.
helio@shibboleet:tmp$ pp -B -o accumulatorEventSender accumulatorEventSender.pl helio@shibboleet:tmp$ ls accumulatorEventSender accumulatorEventSender.pl helio@shibboleet:tmp$ file accumulatorEventSender accumulatorEventSender: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.15,
BuildID[sha1]=0x75828a5e4b38f0a935c9461e07d6ac23d3282d73, stripped
O aplicativo se encontra no pacote libpar-packer-perl no Ubuntu (e possivelmente no Debian).
No sistema de agendamento de tarefas, o cron, existe a possibilidade de controle de acesso pelos arquivos /etc/cron.allow e /etc/cron.deny. Existindo somente o /etc/cron.allow no sistema, o usuário deverá ter seu login incluso nesse arquivo para fazer uso do cron. Do contrário será brindando com uma mensagem semelhante a essa:
You (helio) are not allowed to use this program (crontab)
See crontab(1) for more information
Nos ambientes de telecomunicações, onde muitos dos sistemas operacionais em uso são Solaris, ex-Sun e agora da Oracle, esses vêm com essa forma de controle do cron habilitada por padrão.
Isso aumenta a segurança do sistema, mas também torna alguns trabalhos simples mais difíceis, principalmente quando é necessário ter agendamento de trabalho. Claro que isso poderia ser resolvido com ajuda de um bom administrador de sistemas, o sysadmin, e conhecimento em Unix, mas isso parece estar se tornando cada vez mais raro nesses dias.
Então criei o mycrond, um daemon escrito em perl, para rodar periodicamente como o crond do sistema. A sintaxe não é perfeita e tem alguns furos, como não aceitar "*/5" para tarefas a cada 5 intervalos, mas utiliza uma sintaxe que somente Solaris aceita como, por exemplo para tarefas agendadas para cada 5 minutos, utilizar "0,5,10,15,20,25,30,35,40,45,50,55". O restante é parecido com o uso normal da crontab.
Não é 100% perfeito, pois acabei deixando a análise de sintaxe incompleta para todos os valores de data, mas funciona perfeitamente como daemon, não morrendo ao sair do sistema, e é capaz de analisar e rodar formas mais simples da crontab.
O conteúdo do programa é o seguinte:
#! /usr/bin/perl
# $Id: mycrond 29 2011-06-22 20:42:35Z helio $
# Date: Wed Jun 22 12:37:00 BRT 2011
# Author: Helio Loureiro
# Description: an user level alternative to system crond.
#
my $ROOTDIR = "/home/helio/AUDIT";
exit(0); # Edit $ROOTDIR settings and comment this exit.
my $CRONFILE = $ROOTDIR."/etc/crontab";
my $PIDFILE = $ROOTDIR."/var/run/mycrond.pid";
$SIG{CHLD} = 'IGNORE'; #avoid zombies, or they can eat your brain
### Starting in daemon mode
&Daemonize();
sub CheckDir() {
my $dir = $_[0];
if ( ! -d "$dir" ) {
system("mkdir -p $dir");
}
}
sub ParseCronLine() {
my $cron = $_[0];
chomp($cron);
my @params = split(/ /, $cron);
my $r_minute = $params[0];
my $r_hour = $params[1];
my $r_day = $params[2];
my $r_month = $params[3];
my $r_dow = $params[4];
my $command = $params[5];
for (my $x = 6; $x < @params; $x++) {
$command .= " ".$params[$x];
}
my ($second, $minute, $hour, $dayOfMonth, $month, $year, $dayOfWeek,
$dayOfYear, $daylightSavings) = localtime();
$year += 1900;
$month++;
### Day of week requires some more work
if ($r_dow != '*') {
if ($r_dow != $dayOfWeek) {
return 0;
}
}
if ($r_month != '*') {
$run_status = 0;
@months = split(/,/, $r_month);
foreach $m (@months) {
if ($m == $month) {
$run_status++ ;
}
}
return if (! $run_status);
}
if ($r_day != '*') {
$run_status = 0;
@days = split(/,/, $r_day);
foreach $d (@days) {
if ($d == $dayOfMonth) {
$run_status++ ;
}
}
return if (! $run_status);
}
if ($r_minute != '*') {
$run_status = 0;
@minutes = split(/,/, $r_minute);
foreach $m (@minutes) {
if ($m == $minute) {
$run_status++ ;
}
}
return if (! $run_status);
}
if ($r_hour != '*') {
$run_status = 0;
@hours = split(/,/, $r_hour);
foreach $h (@hours) {
if ($h == $hour) {
$run_status++ ;
}
}
return if (! $run_status);
}
# If it is ok, then run your command
if (defined($DEBUG)){
print "Running: $command\n";
}
exec "$command" or exit(1);
exit(0);
}
sub Run() {
### Saving process PID
my $pid = getppid();
$pid++;
&CheckDir($ROOTDIR."/var/run");
open(PID, ">$PIDFILE") or die "Impossible to create $PIDFILE: $!\n";
print PID $pid."\n";
close(PID);
open(FD, $CRONFILE) or die "Impossible to read crontab: $!\n";
my @cronlines = ;
close(FD);
my @PIDS;
while (1) {
foreach my $line (@cronlines) {
next if ($line =~ m/^#/);
my $runpid = fork();
if ($runpid == 0) {
&ParseCronLine($line);
exit(0);
}
if ($runpid > 0) {
push(@PIDS, $runpid);
}
}
sleep(60);
}
}
sub Daemonize() {
# Change to /
chdir("/");
my $pid = fork(); #first fork
if ($pid > 0) { #Parent exists
exit(0);
}
if ($pid == 0) { # Son forks again
my $pid2 = fork();
if ($pid2 > 0) {
exit(0);
}
if ($pid2 == 0) {
&Run();
}
}
}
Faz tempo que não me deparo com esse tipo de problema, mas acabei vendo novamente depois que um colega de trabalho pediu ajuda nisso.
A primeira vez que trabalhei com conversão de caracteres foi em português mesmo, de ISO-8859-1 para UTF-8. Não guardei lembranças boas. Dessa vez o desafio era para converter supostos caracteres no mesmo formato para UTF-8, mas não da nossa língua pátria.
Para quem nunca viu isso, o código em Perl que faz a conversão está no pacote Encode , disponível no CPAN, da seguinte forma:
use Encode;
...
...
foreach $line () {
next if ($line =~ m/^$/);
chomp($line);
$i = Encode::decode("iso-8859-1", $line);
$line = Encode::encode("utf8", $i);
print $line."\n";
}
...
Dessa vez tive um problema com a palavra "ΑστέριαΑστέρια". Juro que não sei o que significa, mas a droga da palavra, escrita em grego (CP1253) estava junto ao restante do texto codificado em ISO-8859-1.
Apanhei pra achar o formato certo... ainda falta fazer um conversor inteligente o suficiente para usar o formato certo antes de processar, mas já é alguma coisa...