Num desses dias que começaram o ano, precisei fazer o monitoramente de uma mensagem em SOAP (padrão de comunicação dos sistema de pré-pago com que trabalho). Estava acostumado ao uso do wireshark pra fazer isso, mas descobri que não tinha o mesmo instalado.
Instalar um wireshark não é nada demais pra quem tem apt-get, mas como eu estava dentro do ambiente da empresa e não queria problemas com a área de segurança da informação, que monitora o download de aplicativos como o wireshark, resolvi fazer direto com tcpdump.
Para isso basta usar os parâmetros "-s 0", para definir tamanho máximo de pacote (não pegar somente alguns bytes), "-l" pra fazer a saída sem bufferização e, finalmente, "-A" para ter uma saída em modo texto dos caractéres ASCII dos pacotes capturados.
Com isso, utilizei o comando "tcpdump -n -s 0 -l -A -i lo port 10066" e pude verificar se meu protocolo SOAP estava enviando os cabeçalhos corretamente.
root@shibboleet:~# tcpdump -n -s 0 -l -A -i eth0 port 10066
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes
17:04:12.661207 IP 10.1.2.5.43789 > 10.1.2.5.10066: Flags [S], seq 2942898742, win 32792, options [mss 16396,sackOK,TS val 284979440 ecr 0,nop,wscale 7], length 0
E..<b.@.@...
{..
'R.i.6........KB....@....
..p.........
17:04:12.661232 IP 10.1.2.5.10066 > 10.1.2.5.43789: Flags [S.], seq 2517428391, ack 2942898743, win 32768, options [mss 16396,sackOK,TS val 284979440 ecr 284979440,nop,wscale 7], length 0
E..<..@.@...
{..
.....i.7....KB....@....
..p...p.....
17:04:12.661251 IP 10.1.2.5.43789 > 10.1.2.5.10066: Flags [.], ack 1, win 257, options [nop,nop,TS val 284979440 ecr 284979440], length 0
E..4b.@.@...
{..
'R.i.7........K:.....
..p...p.
17:04:12.661302 IP 10.1.2.5.43789 > 10.1.2.5.10066: Flags [P.], seq 1:1441, ack 1, win 257, options [nop,nop,TS val 284979440 ecr 284979440], length 1440
E...b.@.@..H
{..
'R.i.7........P......
..p...p.POST /Air HTTP/1.1
Accept-Encoding: identity
Content-Length: 1245
Host: air:10066
User-Agent: DSMN/4.4/1.0
Connection: close
Content-Type: text/xml
Authorization: Basic dmFpbGE6c2V1dHJvdXhh
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<methodCall>
<methodName>UpdateOffer</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>originNodeType</name>
<value>
<string>EXT</string>
</value>
</member>
<member>
<name>originHostName</name>
<value>
<string>HELIO</string>
</value>
</member>
<member>
<name>originTransactionID</name>
<value>
<string>410</string>
</value>
</member>
<member>
<name>originTimeStamp</name>
<value>
<dateTime.iso8601>20130115T17:04:12+0000</dateTime.iso8601>
</value>
</member>
<member>
<name>subscriberNumber</name>
<value>
<string>5511912345678</string>
</value>
</member>
<member>
<name>offerID</name>
<value>
<int>11</int>
</value>
</member>
<member>
<name>offerType</name>
<value>
<int>0</int>
</value>
</member>
<member>
<name>expiryDate</name>
<value>
<dateTime.iso8601>20131027T12:00:00+0000</dateTime.iso8601>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
17:04:12.661312 IP 10.1.2.5.10066 > 10.1.2.5.43789: Flags [.], ack 1441, win 256, options [nop,nop,TS val 284979440 ecr 284979440], length 0
E..4.X@.@.WX
{..
.....i......K:.....
..p...p.
17:04:12.829800 IP 10.1.2.5.10066 > 10.1.2.5.43789: Flags [P.], seq 1:836, ack 1441, win 256, options [nop,nop,TS val 284979609 ecr 284979440], length 835
E..w.Y@.@.T.
{..
.....i......N}.....
..q...p.HTTP/1.1 200 OK
Content-Length: 681
Content-Type: text/xml
X-Powered-By: AIR-XmlRpc Server 3.2
Server: air
Date: Tue, 15 Jan 2013 19:04:24 GMT
<?xml version="1.0" encoding="utf-8"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>expiryDate</name>
<value><dateTime.iso8601>20131027T12:00:00+0000</dateTime.iso8601></value>
</member>
<member>
<name>offerID</name>
<value><i4>11</i4></value>
</member>
<member>
<name>offerType</name>
<value><i4>0</i4></value>
</member>
<member>
<name>originTransactionID</name>
<value><string>410</string></value>
</member>
<member>
<name>responseCode</name>
<value><i4>0</i4></value>
</member>
<member>
<name>startDate</name>
<value><dateTime.iso8601>20130115T12:00:00+0000</dateTime.iso8601></value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
17:04:12.829865 IP 10.1.2.5.43789 > 10.1.2.5.10066: Flags [.], ack 836, win 256, options [nop,nop,TS val 284979609 ecr 284979609], length 0
E..4b.@.@...
{..
'R.i..........K:.....
..q...q.
17:04:12.830228 IP 10.1.2.5.43789 > 10.1.2.5.10066: Flags [F.], seq 1441, ack 836, win 256, options [nop,nop,TS val 284979609 ecr 284979609], length 0
E..4b.@.@...
{..
'R.i..........K:.....
..q...q.
17:04:12.865118 IP 10.1.2.5.10066 > 10.1.2.5.43789: Flags [F.], seq 836, ack 1442, win 256, options [nop,nop,TS val 284979644 ecr 284979609], length 0
E..4.Z@.@.WV
{..
.....i......K:.....
..q...q.
17:04:12.865140 IP 10.1.2.5.43789 > 10.1.2.5.10066: Flags [.], ack 837, win 256, options [nop,nop,TS val 284979644 ecr 284979644], length 0
E..4b.@.@...
{..
'R.i..........K:.....
..q...q.
^C
10 packets captured
20 packets received by filter
0 packets dropped by kernel
Nesse caso é uma aplicação que roda na porta 10066 que foi criada pra atribuir "Offers", ou ofertas de serviços através de um servidor que se chama AIR, Account Information and Refilling.
E fechando o ano de 2012, um último artigo sobre hibernação no Ubuntu 12.10, que é pra lembrar de entrar 2013 bem descansado :-)
Escrevo um artigo sobre a utilização do laptop sem ficar desligando, a guerra dos 100 dias, e seus benefícios e então me deparo justamente com um upgrade de sistema que não funciona com a hibernação. E em menos de 6 meses.
Tudo começou quando decidi passar o laptop de 32 bits para 64 (processador Intel Core i3). Minha limitação para não realizar tal tarefa antes era o sistema de SSL VPN, da Juniper, usado pela empresa para conectar remotamente. O sistema de VPN inicia um applet java que instala e roda uma biblioteca de 32 bits.
Já fazia algum tempo, eu vinha testando rodar isso em um modo "híbrido", com a funcionalidade de multi-arch ou com chroot de um ambiente de 32 bits. Como tudo estava funcionando nos testes, resolvi mudar o sistema aproveitando as férias de fim de ano.
Eu estava com Ubuntu 12.04 para i386, LTS, e resolvi instalar o 12.10 para amd64. Eu poderia ter escolhido um upgrade do sistema, que aparentemente funcionaria, mas resolvi fazer uma instalação nova, o que acabou me gerando a perda de dados do /home, mas essa é outra história.
Ao finalizar a instalação do 12.10 (e recuperar minha partição perdida - mas não completamente, duh!), eu me deparei com um kernel mais novo: 3.5.0-21-lowlatency. Anteriormente eu estava rodando o 3.2.7-pf (post factum). Não consegui fazer funcionar a hibernação de jeito nenhum. Nem com pm-suspend, nem com pm-hibernate, nem com o novo método, o pm-suspend-hybrid. Em todos os casos o sistema travava logo no início da hibernação e me deixava com uma tela preta, sistema operacional travado, mas máquina ligada. Somente um procedimento de "dedo-off" conseguia desligar o laptop. E sem nenhum log de problema por parte do ACPI.
Tentei recompilar o kernel, instalar outra versão, a versão sem lowlatency, enfim de tudo. Mas sem resultados.
Por um acaso, notei um erro no sistema pelo "dmesg". No começo achei que era problema da minha memória RAM.
[ 5.974345] BUG: unable to handle kernel paging request at 0000000000ff1000
[ 5.974351] IP: [] memcpy+0xd/0x110
[ 5.974359] PGD 1b0dbc067 PUD 1b0db9067 PMD 0
[ 5.974363] Oops: 0000 [#1] SMP
[ 5.974366] CPU 2
[ 5.974367] Modules linked in: snd_page_alloc drm_kms_helper serio_raw drm
coretemp cfg80211 kvm_intel i2c_algo_bit kvm videobuf2_vmalloc videobuf2_memops
mxm_wmi wmi sony_laptop(+) intel_ips microcode mac_hid video mei lpc_ich btusb
bluetooth xfs firewire_ohci firewire_core crc_itu_t sdhci_pci sdhci atl1c
[ 5.974385]
[ 5.974387] Pid: 637, comm: modprobe Not tainted 3.5.0-17-generic #28-Ubuntu
Sony Corporation VPCS110GB/VAIO
[ 5.974390] RIP: 0010:[] [] memcpy+0xd/0x110
[ 5.974394] RSP: 0018:ffff8801b0d31c40 EFLAGS: 00010246
[ 5.974395] RAX: ffff8801b0d31c90 RBX: ffff8801ae9545c0 RCX: 0000000000000001
[ 5.974397] RDX: 0000000000000000 RSI: 0000000000ff1000 RDI: ffff8801b0d31c90
[ 5.974398] RBP: ffff8801b0d31c58 R08: ffff8801b2218200 R09: 000000018040003e
[ 5.974399] R10: 0000000000000000 R11: ffffffff813ad3e5 R12: ffff8801b0d31c90
[ 5.974401] R13: ffff8801b0d31caf R14: ffff8801b22f4800 R15: 0000000000000135
[ 5.974403] FS: 00007fb7feb92700(0000) GS:ffff8801bbc80000(0000) knlGS:0000000000000000
[ 5.974404] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 5.974405] CR2: 0000000000ff1000 CR3: 00000001b271d000 CR4: 00000000000007e0
[ 5.974407] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 5.974408] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 5.974410] Process modprobe (pid: 637, threadinfo ffff8801b0d30000, task ffff8801b0d8c500)
[ 5.974411] Stack:
[ 5.974413] ffffffffa01a8893 0000000000000009 0000000000000035 ffff8801b0d31ce8
[ 5.974416] ffffffffa01a9b69 ffff8801b16986a0 ffff8801b0067800 ffff8801b0d31c80
[ 5.974419] ffffffff00000000 0000000000000009 0000000000000000 0000000000000000
[ 5.974422] Call Trace:
[ 5.974430] [] ? sony_nc_buffer_call.constprop.12+0x43/0xa0 [sony_laptop]
[ 5.974435] [] sony_nc_function_setup+0x2f9/0xab0 [sony_laptop]
[ 5.974440] [] sony_nc_add+0x1f8/0x660 [sony_laptop]
[ 5.974446] [] ? sysfs_do_create_link+0xeb/0x200
[ 5.974451] [] acpi_device_probe+0x50/0x11d
[ 5.974457] [] driver_probe_device+0x7e/0x220
[ 5.974460] [] __driver_attach+0xab/0xb0
[ 5.974462] [] ? driver_probe_device+0x220/0x220
[ 5.974465] [] bus_for_each_dev+0x55/0x90
[ 5.974468] [] ? 0xffffffffa01b4fff
[ 5.974470] [] driver_attach+0x1e/0x20
[ 5.974473] [] bus_add_driver+0x198/0x270
[ 5.974475] [] ? 0xffffffffa01b4fff
[ 5.974478] [] driver_register+0x77/0x150
[ 5.974483] [] ? dmi_matches+0x53/0xc0
[ 5.974485] [] ? 0xffffffffa01b4fff
[ 5.974488] [] acpi_bus_register_driver+0x3e/0x47
[ 5.974492] [] sony_laptop_init+0x57/0x1000 [sony_laptop]
[ 5.974498] [] do_one_initcall+0x12a/0x180
[ 5.974502] [] sys_init_module+0xc2/0x230
[ 5.974508] [] system_call_fastpath+0x16/0x1b
[ 5.974509] Code: 2b 43 50 88 43 4e 48 83 c4 08 5b 5d c3 90 e8 eb fb ff ff
eb e6 90 90 90 90 90 90 90 90 90 48 89 f8 48 89 d1 48 c1 e9 03 83 e2 07
48 a5 89 d1 f3 a4 c3 20 4c 8b 06 4c 8b 4e 08 4c 8b 56 10 4c
[ 5.974539] RIP [] memcpy+0xd/0x110
[ 5.974542] RSP
[ 5.974543] CR2: 0000000000ff1000
[ 5.974545] ---[ end trace 67f7b54c3f5c5271 ]---
Como a danada da falha mostrava um erro com "memcpy+0xd/0x110", eu imaginei que era falha de cópia de dados pra alguma endereço da memória RAM, ou seja, o pente de memória que comprei no #DX estava com problemas, o que denota a máxima de que, na dúvida, culpe o fornecedor Chinês mais próximo de você.
Passei os restantes dos dias buscando por mais reclamações sobre problemas de hibernação no Ubuntu 12.10 ou algo parecido, e... nada. Comecei a desconfiar mesmo dos produtos chineses, a ponto de passar 2 dias rodando memtest pra verificar o estado da RAM, procedimento aliás que só causa expectativa seguida de frustração, e não tira o produto Chinês da mira de vilão da história.
Hoje, por um acaso muito grande, eu resolvi buscar pelo erro do bug, mas na verdade para buscar alguma ferramenta para bloquear o segmento de memória danificado. Então busquei pela linha:
BUG: unable to handle kernel paging request at
E encontrei umas referências sobre problemas em... Sony Vaio! Justamente a marca do meu laptop. Coincidência?
Então resolvi buscar diretamente o endereço de memória do meu problema:
BUG: unable to handle kernel paging request at 0000000000ff1000
E não é que peguei um problema reportado e bem descrito no Launchpad, o sistema de reporte de bugs do Ubuntu? Eu nunca tinha encontrado referências a esse bug porque a descrição fala de problema de Sony Vaio (outro duh!).
[SONY VAIO VPCS12L9E] Suspend doesn't work after dist-upgrade to Quantal 12.10
Felizmente a pessoa que abriu o bug report fez uma bela descrição do problema e também de uma solução. Apenas apliquei os seguintes passos para ter meu sistema funcionando corretamente:
sudo add-apt-repository ppa:shiba89/vaio-kernel sudo apt-get update sudo apt-get install linux-headers-generic sony-laptop-dkms
Com isso, no boot seguinte tive a comprovação de que meu laptop voltou à hibernar feito um bebê. E com isso fecho 2012 sem pendências, ao menos pessoais, para 2013.
E que venha 2013! Se sobrevivemos ao fim do mundo segundo os Maias, não é um problema de kernel que vai nos segurar!
Invariavelmente eu preciso trocar o hostid de uma máquina com Solaris para realizar testes. O objetivo não é pirataria, ou algo assim, mas testes de verificação de aplicativos com licença de uso, que são amarrados ao hostid da máquina.
Eu conhecia um programa para fazer isso, mas essa semana topei com uma explicação bem legal de como fazer manualmente a mudança, disponível aqui:
Baseado nessa explicação, montei um programa em perl pra conseguir fazer a mesma coisa de forma mais simplificada, o hostid.pl.
#! /usr/bin/perl
$HOSTID = "/usr/bin/hostid";
$SAVEORIG = "/etc/hostid.orig";
$ADB = "/usr/bin/adb";
$ADBOPTS = "-w -k /dev/ksyms /dev/mem";
sub Usage() {
print "Use: $0 \n";
print "\t note: hostid must be 8 chars long\n";
exit(1);
}
if ($ENV{"USER"} ne "root") {
print "This must be run as root.\n";
exit(1);
}
$newhostid = $ARGV[0];
if (length($newhostid) != 8) {
Usage();
}
if (! -f "$SAVEORIG") {
print "Saving original hostid into $SAVEORIG\n";
open(SAVE,">$SAVEORIG") or die "Impossible to save original hostid: $!\n";
print SAVE `$HOSTID`;
close SAVE;
}
$myhex = eval("0x".$newhostid);
$mystr = sprintf("%s", $myhex);
$i = 0;
$parts[$i] = substr($mystr, $i, 4);
$parts[$i + 1] = substr($mystr, $i + 4, 4);
$parts[$i + 2] = substr($mystr, $i + 8, 4);
for ($i = 0; $i <= 3; $i++) {
foreach $p (split(//,$parts[$i])) {
$hwserial[$i] .= ($p + 30);
}
}
$hwserial[2] .= "0000";
$msg = "$ADB $ADBOPTS << EOF > /dev/null
hw_serial/W 0x".$hwserial[0]."
hw_serial+4/W 0x".$hwserial[1]."
hw_serial+8/W 0x".$hwserial[2]."
END
EOF
";
print "Applying hostid change into memory\n";
system($msg);
print "Enforcing new hostid across system\n";
system("/etc/rc2.d/S20sysetup");
O calcanhar de Aquiles do Linux sempre foi o gerenciamento de memória. Por mais memória que se tenha disponível, ele vorazmente sempre quer mais. E nunca libera a memória livre.
E meus parcos 6 GB de memória do laptop tem sentido isso nesses últimos dias de 2012. E verificável pelos gráficos do Munin, que mostra o pedido de 10 GB de memória pra usar. Isso me faz pensar que talvez os Maias esteja certos.
Eu ainda não descobri qual programa (ou processo) está causando isso, e o kernel Linux não cuida de matar o processo comilão.
Então criei um pequeno daemon, em perl, para ficar lendo o /proc e matando os processos que mais consomem memória se a carga do sistema aumentar muito (atualmente marquei para load average maior de 10).
#! /usr/bin/perl
use POSIX;
$PROC = "/proc";
$MAXLOAD = 10; #loadaverage
$SLEEPTIME = 1; #seconds
if (getuid() != 0) {
print "Only root can run this program.\n";
exit(1);
}
if (! -d $PROC) {
print "Not possible to run. System not running with $PROC directory\n";
exit(1);
}
sub GetMem() {
$pid_dir = $_[0];
my $dir = $PROC."/".$pid_dir."/statm";
open(MEM, $dir) or die "Error:$dir $!\n";
@params = split(/ /, );
close MEM;
$memory = $params[0];
return $memory;
}
sub GetPID() {
my %MEM;
opendir(PROC,$PROC) or die "Not possible to run. System not running with $PROC directory\n";
foreach $dir (readdir PROC) {
# Just read higher processes
# avoid init (1) or non-pid
next if ($dir !~ m/^\d\d\d+/);
$mem = &GetMem($dir);
if ($mem) {
$MEM{$dir} = $mem;
}
}
closedir PROC;
return %MEM;
}
sub GetLoad() {
open(LOAD,$PROC."/loadavg") or die "Impossible to detect load average by $PROC:$!\n";
my $load = ;
close LOAD;
my @params = split(/ /, $load);
return $params[0];
}
sub GetCommand() {
my $pid = $_[0];
open(CMD, $PROC."/".$pid."/cmdline") or die "Impossible to read the source command: $!\n";
my $cmd = ;
close CMD;
return $cmd;
}
sub DaemonizeMe() {
print "Starting to memory control daemon\n";
POSIX::setsid or die "setsid: $!";
my $pid = fork ();
if ($pid < 0) {
die "fork: $!";
} elsif ($pid) {
exit 0;
}
chdir "/";
umask 0;
foreach (0 .. (POSIX::sysconf (&POSIX::_SC_OPEN_MAX) || 1024)) {
POSIX::close $_;
}
open (STDIN, "/dev/null");
#open (STDERR, ">&STDOUT");
}
&DaemonizeMe();
my $mypid = getpid();
my %DEATHCOUNTER;
while (! $SIG{TERM}) {
sleep($SLEEPTIME);
my $load = &GetLoad();
next if ($load < $MAXLOAD);
my %MEM;
%MEM = &GetPID();
$higher_m = 0;
$higher_pid = 0;
foreach $k (sort keys %MEM) {
next if ($k eq $mypid);
$mem = $MEM{$k};
if ($mem > $higher_m) {
$higher_m = $mem;
$higher_pid = $k;
$DEATHCOUNTER{$higher_pid}++;
}
}
if ($DEATHCOUNTER{$higher_pid} >= 5) {
print "Killing due higher memory usage: ".&GetCommand($higher_pid)." (".$higher_pid.") [".$higher_m." Bytes]\n";
%DEATHCOUNTER;
}
}
print "Exiting...";
exit(0);
Os Maias podiam até estar certos, mas isso não significa que precisamos ficar sentados olhando.
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).
Como é de se esperar, aumentei meus "skills" de apresentação junto com o MBA. Uma das ferramentas que conheci, mas acabei não usando durante o curso, foi Prezi.
As apresentações ficam simplesmente fanstásticas.
É feita toda via flash, via web, no modelo freemium (de graça com até certas features). Apesar disso, recomendo mais que qualquer outra ferramenta como Microsoft Powerpoint ou LibreOffice Presentation.
Minha primeira brincadeira com Prezi.
Já faz anos que compilo meus kernels e sistemas com a utilização do parâmetro "-j 8" ou "-j 12". Esse parâmetro, passado ao GCC, faz uso de multithreads em máquinas com mais de um processador ou processador multicore, como esse Intel Core i3 que tenho no laptop.
Mas sempre usei esse parâmetro quase que como dogma, sem muita certeza de sua eficiência. Aliás, com uma pequena idéia de eficiência já que, sem o uso do mesmo, o tempo de compilação era mais demorado. Mas tudo muito de "sentimento", sem nenhuma comprovação.
Então, num desses dias sem muita coisa pra fazer (pequena metira: estava lotado de coisas pra terminar, mas decidi fazer isso pra limpar um pouco a mente), resolvi verificar essa compilação com dados mais concretos e monitoração dos resultados. Fiz o seguinte programa em python pra ficar compilando um kernel que já estava configurado e que eu tinha certeza que compilava sem problemas, com as threads indo de 1 a 20:
#! /usr/bin/python
# make clean; time make-kpkg -j 4 --initrd kernel_image
import os
import time
#print time.time()
OUTPUT = "/tmp/kernel_results.csv"
FD = open(OUTPUT, "w")
for TH in xrange(1,21):
print "Threads:", TH
print "\tlimpando..."
os.system("make clean")
t_0 = time.time()
os.system("make-kpkg -j " + str(TH) + " --initrd kernel_image")
t_1 = time.time()
total_time = t_1 - t_0
msg = "Threads: %d in %0.2f s" %(TH, total_time)
print msg
FD.write(str(TH) + "," + str(total_time) + "\n")
FD.flush()
Então deixei o sistema rodando. Eu costumo usar o "make-kpkg", do pacote kernel package, que já gera para mim o pacote DEB para instalação.
Ao final, os resultados foram os seguintes:
A troca de contextos de processos realmente aumentou com o aumento de threads. Por isso o sistema fica tão lento.
O sistema ficou com uso de CPU intenso, mas sem crescimento gradual (isso eu já achei estranho).
As interrupções de mudança de contexto também ficaram iguais, onde eu esperava um valor em degraus.
Mas a carga do sistema, load average, aumentou realmente em degrau, acompanhando a quantidade definida no "-j". Isso era esperado e é sempre notado, pois o computador fica super lento.
Porém o melhor ficou pro final: a análise do tempo pela quantidade de threads.
O tempo diminuiu conforme a quantidade de threads que aumenta até... 3??? O processador Intel Core i3 é um multicore de 4 cores, eu esperava ao menos um melhor desempenho até 4 threads, mas dá pra ver bem claro que o sistema estabiliza em 3.
Ou seja, usando "-j 8" ou "-j 12" só serve para aumentar a carga da CPU, aumentando as trocas de contextos, mas não significam nem melhora nem otimização da compilação. Pelo contrário. Então o melhor é saber o máximo que a CPU realmente aguenta antes de aplicar cegamente parâmetros para *melhorar* o desempenho do sistema. E monitorar os resultados!
Atualização: Sun Feb 3 20:34:35 BRST 2013
Conforme pedido do Erick Tostes, @ericktostes no twitter, estou incluindo o meu /proc/cpuinfo.
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 37
model name : Intel(R) Core(TM) i3 CPU M 330 @ 2.13GHz
stepping : 2
microcode : 0x9
cpu MHz : 933.000
cache size : 3072 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36
clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc
arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor
ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm arat dtherm tpr_shadow
vnmi flexpriority ept vpid
bogomips : 4255.62
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 37
model name : Intel(R) Core(TM) i3 CPU M 330 @ 2.13GHz
stepping : 2
microcode : 0x9
cpu MHz : 933.000
cache size : 3072 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 2
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36
clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc
arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor
ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm arat dtherm tpr_shadow
vnmi flexpriority ept vpid
bogomips : 4255.62
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
processor : 2
vendor_id : GenuineIntel
cpu family : 6
model : 37
model name : Intel(R) Core(TM) i3 CPU M 330 @ 2.13GHz
stepping : 2
microcode : 0x9
cpu MHz : 933.000
cache size : 3072 KB
physical id : 0
siblings : 4
core id : 2
cpu cores : 2
apicid : 4
initial apicid : 4
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36
clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc
arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor
ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm arat dtherm tpr_shadow
vnmi flexpriority ept vpid
bogomips : 4255.62
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
processor : 3
vendor_id : GenuineIntel
cpu family : 6
model : 37
model name : Intel(R) Core(TM) i3 CPU M 330 @ 2.13GHz
stepping : 2
microcode : 0x9
cpu MHz : 933.000
cache size : 3072 KB
physical id : 0
siblings : 4
core id : 2
cpu cores : 2
apicid : 5
initial apicid : 5
fpu : yes
fpu_exception : yes
cpuid level : 11
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36
clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc
arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni dtes64 monitor
ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt lahf_lm arat dtherm tpr_shadow
vnmi flexpriority ept vpid
bogomips : 4255.62
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
Outro dia, durante o trabalho, fui perguntado sobre onde fazer cursos para certificação Linux LPI. Antes de dar recomendações, fiz a pergunta básica: qual o seu propósito com essa certificação?
Muitas pessoas buscam a certificação por vários motivos: status, melhoria salarial ou carreira, ou conhecimento. Mas será que é algo que vale a pena? Como resposta, ou melhor, opinião minha digo que depende da situação e do objetivo.
Certificação é uma forma mais rápida de adquirir um conhecimento e comprovar tal aprendizado.
Nada mais que isso. Cursos de certificação levam em média 6 meses (em geral menos), mas não são nada mais que isso. São cursos, e cursos não substituem uma boa faculdade. Alguns cursos ainda o preparam somente pra passar na prova de certificação. Caso ainda não seja formado ou seja um profissional autodidata, e queira comprovar no seu currículo que detém mesmo um certo conhecimento, então eu recomendo uma certificação na sua área de atuação. Muitas certificações não exigem uma quantidade mínima de aulas, mas apenas agendamento, pagamento e realização da prova (não necessariamente nessa ordem). Se aprovado, consegue-se a certificação.
Mas caso tenha uma faculdade, tentar engrossar o currículo com certificação pode significar que seu curso não prestou a que devia: ensinar. É bastante arriscado fazer isso. Não existe no mundo certificação que seja melhor que um curso de no mínimo de 2 anos (em relação às boas faculdades). Claro que é preciso "saber aprender" durante a faculdade, do contrário realmente foi um tempo jogado fora e nem mesmo a certificação vai ajudar.
Em termos de carreira, se deseja melhorar seu salário ou crescer na empresa, é melhor negociar com seu gerente antes, pois pode ser que a empresa precisa desse conhecimento mas... não tanto a ponto de pagar algo a mais por seu esforço. Então realmente converse com seu gerente sobre sua carreira, o que deseja, sobre a certificação, e tenha a certeza se vale a pena investir nele ou não.
Se o desejo for por um melhor emprego, certificação não é o que ajuda. O importante é o conhecimento. Mentir no currículo não pega bem e é descoberto logo, pela falta de conhecimento. Certificação não é diferente. De todas as entrevistas de emprego em que eu estava como empregador, em nenhum caso a certificação fez diferença já que eu perguntava aos candidatos sobre suas competências e pedia exemplos de como a usaram. Em alguns casos eu ainda fazia exemplos de problemas e perguntava como resolveriam.
Mas se o caso de busca for por conhecimento, eu acho que cursos gratuitos na Internet podem ajudar com isso sem necessariamente precisar da certificação. Existem os mais variados materiais disponíveis e o interessante seria aplicar seus conhecimentos, ao longo do aprendizado, em algum projeto que esteja trabalhando. Isso ajuda a fixar o conteúdo.
No exemplo do LPI, eu sugeri que buscassem as apostilas do Guia Foca Linux, que é um curso completo de Linux desenvolvido com várias contribuições e ao longo de vários anos. Eu mesmo administro os treinamentos internos da empresa baseados nessa apostilas. Sempre que me pedem referência sobre livros ou qualquer coisa de Linux, eu sempre recomendo o Guia Foca Linux.
Então quando pensar em certificação, pense antes qual o seu real objetivo com isso.
Após aproximandamente passado 1 mês do lançamento da pesquisa do MBA FGV, sobre perfil de consumidores de dispositivos móveis em frente da TV, finalmente é possível sumarizar e apresentar os resultados.
Antes de mais nada agradeço aos que participaram.
A pesquisa foi anônima, mas pelo perfil apresentado, é possível ver que a rede de contato não fugiu muito do perfil de T.I., pois a maioria é composta de homens entre 25 e 40 anos e atuantes na área de exatas. Tentei fazer o mais abrangente possível, mas... é impossível fugir do teorema dos grafos...
Vamos às respostas então.
Os resultados foram muito próximos daqueles já informados por pesquisas como IBOPE e até mesmo a ConsumerLabs da Ericsson.
A idéia da pesquisa era saber sobre o mercado de aplicativos second screen, onde os dispositivos móveis como smartphones e tablets tornam-se parte da programação de TV. A forma mais fácil de visualizar isso seria através do aplicativo participando online durante o debate político na TV. Imagine poder verificar online quem está indo melhor num debate, ou pior. Pode não ser significativo em termos de análise eleitoral, mas é no mínimo diverto.
Agora resta saber se algum dia conseguirei realmente montar uma empresa startup com isso :-)
No dia 13 de janeiro de 2012 eu resolvi experimentar um desses roteadores wireless que são vendidos no Dealextreme. O que mais me seduziu pra fazer isso foram dois fatores: preço (sempre barato) em torno de 70 reais e dizer que rodava o DD-WRT.
Então nessa data comprei o roteador WR3G01.
O roteador chegou exatamente dia 27 de junho do mesmo ano, praticamente 6 meses depois da compra. A entrega no Brasil foi rápida, quem atrasou tudo foi a receita federal. Mas não foi taxado já que a compra foi abaixo de 50 dólares.
Ao abrir o equipamento, foi uma grande decepção. Não pelo hardware, mas pelo software. É uma horrível interface escrita em pseudo-inglês com chinês.
E nada de carregar o DD-WRT ou Open-WRT facilmente, as versões alternativas de firmware de roteadores wireless que rodam puramente Linux. Pra conseguir tal façanha é necessário soldar os pinos de E/S serial na placa, conectar com um módulo de porta serial RS-232, e então habilitar um carregamento de firmware por tftp.
O Dealextreme já vende um kit para fazer esse tipo de aventura, como o "RS232 Serial Port To TTL Converter Module w/ Transmitting and Receiving Indicator - Blue", mas isso está longe do que sonhei, que era simplesmente realizar um upgrade via web GUI e carregar um firmware alternativo, como é feito pelo TP-Link 1043. Infelizmente na época da compra faltavam informações sobre isso.
Não existe interface de upgrade automática e somente uma informação de versão, que é 1.0.5.3. Conectando via telnet, é possível verificar a informação de revisão também, que dá mais algumas pistas sobre o equipamento.
Sem nenhuma outra informação. Buscando na Internet pelo número serial, modelo e versão de firmware, é possível encontrar referências como sendo um Widemac. O site é tão informativo quanto horário político.
O roteador tem acesso via telnet, mas as opções de comandos são extremamente limitadas:
Trying 192.168.0.1...
Connected to 192.168.0.1.
Escape character is '^]'.
Router login: admin
Password:
Welcome to Bococom Router Series
For detailed information, please check:
www.bococom.com
BusyBox v1.12.1 (2010-11-26 17:38:48 CST) built-in shell (msh)
Enter 'help' for a list of built-in commands.
# sh
Unknow command
# ls
Unknow command
# help
? ->Display help information.
help ->Display help information, same as '?' command.
clear ->Clear various talbes, type clear for help.
ping ->ping HOST, type ping for help.
traceroute ->route trace, type traceroute for help.
ipmac ->ip mac bind settings.
quit ->Close terminal session.
show ->Display various talbes information, type show for help.
restart_httpd ->Restart web server.
restore_defaults ->Restore the config to the default factory value.
run_ated ->Run ated for MS product.
O roteador funcionou pro básico que nada mais é que uma conexão WAN via DHCP com o Net Virtua, wireless interno com WPA2 e controle de acesso. Mas falta coisas mais avançadas como suporte à IPv6.
Tem também uma porta USB que eu esperava conseguir usar no Linux como NAS, conectando um HD externo, mas não deu certo com o firmware que veio por padrão.
Reza a lenda que vem com suporte para modems 3G nessa porta USB, mas não me dei o trabalho de testar.
Para quem tem filho adolescente, sabe que as traquitanas tecnológicas tornaram a vida um inferno quando o assunto é estudar. Controlar o acesso ao computador é fácil, criando regras de bloqueio após certos horários estabelecidos, ou mesmo permissão e filtragem de acessos à sites baseados em URL e squid.
Mas com a chegadas dos dispositivos móveis, como telefones Android e tablets, a coisa não ficou tão fácil.
Restou a opção de bloquear o acesso pelo MAC address nos horários de estudo (que em geral são transformados em horários de soneca durante a tarde ou televisão).
Então fiz um pequeno script em python que bloqueia os MACs já cadastrados, tanto do tablet quanto do smartphone, e libera nos horários em que o computador desktop também está liberado. Com certeza isso não resolve o problema, mas com adolescentes, em geral, quase nada resolve.
O programa funciona com meu roteador wifi, um WR3G01, que comprei no Dealextreme (mais informações aqui). É um roteador wireless que se diz compatível com DD-WRT, mas que pra isso exige soldar os contatos da conexão serial na placa e carregar o firmware por tftp (era mais fácil dizer que não suporta então).
O programa segue:
#! /usr/bin/python
import re, urllib2
from base64 import encodestring
from sys import argv
MACS = [ "94:63:AA:BB:CC:DD", "74:E1:AA:BB:CC:DD" ]
login = "admin"
password = "admin"
server = "192.168.0.1"
port = 80
URI = "/apply.cgi"
TAG =""
for mac in MACS:
mac = re.sub(":",'%3A', mac)
TAG += mac + '%3B'
def Usage():
print "Use: %s {block|allow}" % argv[0]
exit(1)
if (len(argv) < 2):
Usage()
elif (not re.search("allow|block",argv[1])):
Usage()
msg_body = "submit_button=wlan_access&" + \
"change_action=&" + \
"action=Apply&" + \
"AccessControlList0=" + TAG + "&"
if (argv[1] == "allow"):
msg_body += "AccessPolicy0=0&"
elif (argv[1] == "block"):
msg_body += "AccessPolicy0=2&"
msg_body += "mac=&mac=&mac=&mac=&mac=&mac=&"
if (argv[1] == "allow"):
msg_body += "selectMAC=1"
elif (argv[1] == "block"):
msg_body += " selectMAC=3"
http_pass = encodestring(login + ":" + password)
url = "http://" + server + ":" + str(port) + URI
my_headers = {
'User-Agent' : 'Python Client/1.0/1.0',
'Authorization' : 'Basic ' + http_pass,
'Content-Type' : 'application/x-www-form-urlencoded'
}
req = urllib2.Request(
url,
headers = my_headers,
data = msg_body
)
print "Sending: %s" % argv[1]
resp = urllib2.urlopen(req)
Desde a mudança pra Joomla 2.5 que meu site estava limpo de propaganda do Google AdSense. Apesar da interface mais limpa, isso afeta a parte de rentabilidade do site que, diga-se de passagem, não é lá essas coisas. Mas se um dia eu puder viver de blog como o vídeo do "vida de blogueiro", não vou achar ruim. Então é necessário ao menos tentar.
Então eu estava procurando por algum plugin ou módulo do Joomla para conseguir inserir essa propaganda quando encontrei o artigo:
Adicionar o AdSense ao seu Joomla! 2.5 do Site
Simplesmente fantástico! Ensina com um passo-a-passo como criar um módulo no Joomla 2.5 para adicionar o AdSense. É fácil, é rápido, e sem ficar dependendo de módulos ou plugins de terceiros.
Um amigo de trabalho, o @dancriv, publicou uma foto muito legal em seu Instagram nesse dia dos pais.
Essa foto me fez pensar que sou um pai desse tipo.
Page 21 of 35