Arquivo da tag: artigos

Ansible is one of the best tools in DevOps that I like, he just need a simply configuration and can help you with a lot of tasks in your day by day on your infrastructure, today I will show to you how to configure him to work with a lot of servers and how to automate some simple tasks.

Advantages of Ansible

  • Easy to use and fast response
  • Highly configurable to almost every task you need to do
  • SSH based, just use ssh-keygen, ssh-copy-id and ssh-add
  • Free software sponsored by Red Hat
  • Playbooks to make complex tasks

So how we begin use this tool?

The very first thing you need to do is obviously install Ansible on your system. You can do this by typing on linux

# yum install ansible # (redhat)
# apt-get install ansible # (debian/ubuntu)

Or on your OSX:

$ /usr/bin/ruby -e "$(curl -fsSL \"
$ brew install ansible

The inventory file

Ansible needs a file to specify all servers you want to control, you can use a tag name to make an group  to all servers you want by category, below we set two groups: appservers and databases, note that you don’t need to specify one by one in a line, you can use regex to simplify (this is awesome!)



After that, or perhaps before that, as told before Ansible needs a SSH master key that need to be added on ~/.ssh/authorize_keys file into each of your slave servers, to do that you just need to proceed like this:

$ ssh-keygen -t rsa # (to generate your key, enter until finish)

And you will get a ~/.ssh/ public key file in your $HOME directory; So now you need to distribute your public-key to all servers you need control, this can be easy if you have only ten servers to administer or a pain if you have to do this in more than 100+ servers, so here’s a tip:

  1. Create a file with all your servers like this:

    (I will not show to you how to make this with inventory file as input, but you can!)

  2. Use this command-line to copy your keys to each server and insert root-password
    $ while read LINE; do ssh-copy-id $LINE; done < /tmp/servers

Using Ansible in command-line

All set? So lets try do something really cool here. This is the most basic syntax of ansible:

$ ansible :target: -i inventory-file :actions:

Where :target: is the group of servers in your inventory file or just an string all to contemplate all servers in your inventory, the :actions: can be a simply command like below or a more complex command-line using ansible modules.

  • Get all kernel versions of our servers
    $ ansible all -i yourcompany.conf -u root -a "uname -a" | SUCCESS | rc=0 >>
    Linux 3.13.0-92-generic #139-Ubuntu SMP Tue Jun 28 20:42:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux | SUCCESS | rc=0 >>
    Linux 3.13.0-92-generic #139-Ubuntu SMP Tue Jun 28 20:42:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux | SUCCESS | rc=0 >>
    Linux 3.13.0-92-generic #139-Ubuntu SMP Tue Jun 28 20:42:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux | SUCCESS | rc=0 >>
    Linux 3.13.0-92-generic #139-Ubuntu SMP Tue Jun 28 20:42:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

    (Note that all servers responded with your kernel)

  • Use a default module ping to check if databases are alive
    $ ansible databases -i yourcompany.conf -m ping | SUCCESS => {
        "changed": false, 
        "ping": "pong"
    } | SUCCESS => {
        "changed": false, 
        "ping": "pong"
  • Use a default module apt to install a mysql database
    $ ansible databases -i yourcompany.conf \
    -m apt -a "name=mysql-server state=latest"

So how can I know what modules are available?

They are listed here ->

Playbooks: The real thing

Okay, now you know that you can send commands and use modules to process in all your servers with just one command line, thats cool! But what really amazing in Ansible are the playbooks! A playbook is just a file with a template engine called YAML and Jinja to apply some filters, variables and others, with that you can do a lot of automate complex tasks in your servers. Lets take a look into a sample file called ‘install_apache.yml‘:

- hosts: appservers
    http_port: 80
    max_clients: 200
  remote_user: root
  - name: install or upgrade apache to latest version
    yum: name=httpd state=latest
  - name: write the apache config file
    template: src=./httpd.j2 dest=/etc/httpd.conf
    - restart apache
  - name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
    - name: restart apache
      service: name=httpd state=restarted

There’s a lot of information and process automation here.

  1. hosts -> means that all these tasks will only be executed in the group defined after the word, here appservers, defined by our inventory file in the begin of this post.
  2. vars -> are variables you define to process tasks with it, note that variables are defined line by line.
  3. remote_user -> another way to use -u root without need to put in cmd.
  4. name -> is just a name you define to implement a task
  5. template -> in this case is just a way to say, copy my source file defined as ./httpd.j2 to destination server on /etc/httpd.conf
  6. notify -> is a tag that call a job (restart apache) in handlers block at the end of execution of the current block

Or, to resume this playbook will:

  1. Install the latest version of httpd apache on all your appservers
  2. Copy your local httpd.j2 file to remote server on /etc/httpd.conf
    1. Put your variables where you set in httpd.j2 file
    2. Restart apache after that
  3. Set apache to run automatically after a boot/reboot

As you see you can do a lot with this, without this you would need to enter in each server and make these tasks one by one without any human mistake, with ansible you just need to type this:

$ ansible-playbook -i yourcompany.conf install_apache.yml

On next time we will show to you how to do more complex examples, best practices and directory structure to help on your day tasks.

Thats it for now! What are you waiting for? Use ansible to automate your tasks now!! 🙂

Hello friends!

Look on the internet a alternative way to upload files on Amazon S3 without AWS-SDK and then you will know that is a dificult thing for many; Wait a second, why someone will need to use S3 without the Amazon SDK? That’s the problem! We all know that sometimes you can’t do simple a import/require in some lib written by another guy/girl to turn things to into a easy way. That’s the beauty of an challenge.

So to win that, all you need to do is read two docs of Amazon:

The first documentation describes how you handle the HTTP PUT using simple REST and the second describes how to implements the Amazon signature based on AWS_ACCESS_KEY and AWS_SECRET_KEY;

Backing to the problem, days ago in my work we need to face this problem: the development version of a framework that we use can’t import AWS-SDK into project and after the mess that this problem caused, it make me think in do this post on blog;

I was already do it a year ago using shell-script when I need to automatize a build process of MacOS to send the .IPA into S3, so I start to do some changes in code and finally written two new version: one in shell script and other in node.js; The principal problem found, the root of many problems to some guys is the signature process, as described on Amazon docs all you need to sign is:

  • MD5_BASE64_HASH is one of the tricks of Amazon Doc (bad trick)
  • mimetype i just use application/octet-stream works for all types of file
  • DateInIsoUTCTime like -> Wed, 26 Oct 2016 12:09:45 +0000
  • someHeadersOfAmazon extra header of Amazon that you need to pass
  • fullPathOfObjectFile /yourBucketName/dir1/subdir2/yourFile.jpg

Or in resume:

Fri, 25 Nov 2016 14:27:42 +0000

If you type one character byte wrong then your signature will receive the error below when you try to send your file:

<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>AKIAIJ5QILNVUULONEGQ</AWSAccessKeyId>

So, later I will post more details here if someone needs and also the node.js code using just the builtin libs: crypto, fs, https and buffer; until then that’s the cURL version

And the node.JS version, using just native modules;

Hope it helps someone! 🙂

O GIT é um controlador de versão criado por Linus Torvalds, na minha opinião um dos maiores ‘integradores’ de código do mundo, afinal ele tee que fazer merge de milhões de linhas de código durante vários anos, então rapaziada o GIT é fera mesmo. Depois de anos usando o Subversion como alternativa ao CVS me rendi a simplicidade e facilidade de uso do git por uma série de razões, então abaixo mostro o meu dia a dia usando o GIT em várias situações diferentes afim de mostrar para vocês como é fácil de resolver seus problemas de versionamento.

Clona (faz checkout ou baixa) um repositório remoto para a máquina local:
$ git clone
Verifica e informa as mudanças feitas no diretório local:
$ git status
Atualiza repositório local com as modificações do repositório original:
$ git pull
Mostra todas as diferenças feitas no arquivo “libsmb.c”:
$ git diff libsmb.c
Faz commit (atualiza arquivo no repositório) com uma mensagem, entre aspas, do arquivo “libsmb.c”:
$ git commit -m ‘Adicionando funcao principal para DEBUG enquanto biblioteca nao esta pronta’ libsmb.c
Envia suas modificações ao repositório remoto (por padrão “origin” no Git):
$ git push origin master
Lista branchs criadas:
$ git branch
Cria branch “cpp-list” com base na branch “fix2”:
$ git checkout -b cpp-list fix2
Lista todas as tags do repositório:
$ git tag -l
Baixa a tag “v3.8.8” do repositório e cria um arquivo “../linux-3.8.8” com seu conteúdo localmente:
$ git archive –format=tar –prefix=linux-3.8.8/ -o ../linux-3.8.8.tar v3.8.8
Faz merge do branch “fix2” na linha base raiz
$ git checkout master
$ git merge fix2

Gostou!? Que tal vermos um exemplo prático? Primeiro vamos baixar um repositório, no caso o repositório aqui vai ser o do SFM que estamos desenvolvendo para exemplificar o uso de C e a biblioteca GTK:

$ cd $HOME/repo/github
$ git clone
Cloning into 'sfm'...
remote: Counting objects: 74, done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 74 (delta 35), reused 51 (delta 14)
Unpacking objects: 100% (74/74), done.
$ cd sfm && ls -lh
total 72K
-rw-r--r-- 1 mulatinho mulatinho 2.4K May  9 16:48 ChangeLog
-rw-r--r-- 1 mulatinho mulatinho  397 May  9 16:48 INSTALL
-rw-r--r-- 1 mulatinho mulatinho  753 May  9 16:48 LICENSE
-rw-r--r-- 1 mulatinho mulatinho  945 May  9 16:48 Makefile
-rw-r--r-- 1 mulatinho mulatinho  296 May  9 16:48
-rw-r--r-- 1 mulatinho mulatinho  319 May  9 16:48 TODO
-rw-r--r-- 1 mulatinho mulatinho 5.9K May  9 16:48 action.c
-rw-r--r-- 1 mulatinho mulatinho 3.6K May  9 16:48 libsmb.c
-rw-r--r-- 1 mulatinho mulatinho 4.3K May  9 16:48 main-list.c
-rw-r--r-- 1 mulatinho mulatinho 4.3K May  9 16:48 main.c
-rw-r--r-- 1 mulatinho mulatinho 3.2K May  9 16:48 main.h
drwxr-xr-x 2 mulatinho mulatinho 4.0K May  9 16:48 picz/
-rw-r--r-- 1 mulatinho mulatinho 1.5K May  9 16:48 strkey.c
-rw-r--r-- 1 mulatinho mulatinho 5.8K May  9 16:48 util.c

Pronto! Note que o que eu fiz acima foi uma clonagem (uma cópia do estado mais atual) do repositório criado no GitHub. Agora vamos modificar algumas linhas de código e pedir ao git para mostrar o que foi modificado.

.... algumas edições nos códigos ...
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#	modified:   libsmb.c
#	modified:   util.c
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#	libsmb
no changes added to commit (use "git add" and/or "git commit -a")

Hummm! Atente para a mensagem, o GIT está te informando que existem três mudanças: os arquivos ‘libsmb.c’, ‘util.c’ foram modificados e o arquivo ‘libsmb’ não está sendo versionado. Vamos ver o que mudou no arquivo ‘libsmb.c’:

$ git diff libsmb.c
diff --git a/libsmb.c b/libsmb.c
index c9a3662..bc93ede 100644
--- a/libsmb.c
+++ b/libsmb.c
@@ -140,3 +140,18 @@ int sfm_smb_exec(char *line)
        return 0; 
+#ifdef DEBUG
+int main(void) {
+       sfm_smb_exec("list smb://");
+       fprintf(stdout, "nn");
+       sfm_smb_exec("list smb://MULATINHO");
+       fprintf(stdout, "nn");
+       sfm_smb_exec("list smb://FORREST");
+       fprintf(stdout, "nn");
+       sfm_smb_exec("list smb://FORREST/multimedia");
+       fprintf(stdout, "nn");
+       sfm_smb_exec("recv smb://FORREST/multimedia/");
+       return 0;

Notemos que só as linhas que começam com ‘-‘ e ‘+’ significam respectivamente uma remoção ou modificação numa linha, podemos ver aí então que a função principal da biblioteca foi adicionado ao código (afim de testar a biblioteca enquanto não está completamente pronta).

Certo!! E se quisermos fazer um commit (enviar as modificações para o repositório) das nossas alterações para todo mundo do repositório vêr?

$ git commit -m 'Adicionando funcao principal para DEBUG enquanto biblioteca nao esta pronta' libsmb.c
[master c577a9c] Adicionando funcao principal para DEBUG enquanto biblioteca nao esta pronta
 1 file changed, 15 insertions(+)

Note que o GIT está dizendo a você que o seu arquivo foi modificado no seu repositório local (o master acima), você precisa ainda dizer que o que estiver no seu repositório deve ir para o repositório remoto.

$ git push origin master
Counting objects: 5, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 528 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
   3fb2123..c577a9c  master -> master

A sintaxe do push é simples, o primeiro argumento após o comando push é a origem (por padrão o GIT utiliza a palavra ‘origin’ como sendo o repositório clonado) e a segunda opção o branch que você quer enviar (no nosso caso o ‘master’ mas poderia ser qualquer outro).

O GIT é roots porque é muito dinâmico, você não tem mais aqueles conceitos de seguir um único baseline, você pode seguir vários! Veja como listar branchs é fácil:

$ git branch
* master

Vêmos que estamos trabalhando aí com duas branches diferente, um desenvolvedor colocou sua branch com o nome ‘v0.0.5’, E como faz para podermos criar uma nossa?

$ git branch cpp-list # cria branch 'cpp-list'
$ git branch
* master

Difícil para caramba né? Mas vêmos que o ‘*’ (asterisco) está na branch master, isso significa que ainda estamos trabalhando no nosso repositório principal e quando fazermos modificações elas vão estar no master, então como mudamos para outro repositório?

$ git checkout cpp-list
Switched to branch 'cpp-list'

Muito difícil né? Agora vamos terminando por aqui mostrando só mais algumas coisas legais que podem ser feitas utilizando o GIT, eu por exemplo gosto de acompanhar o desenvolvimento do GCC (GNU C Compiler), então vamos vêr se existe alguma atualização no repositório e copia-la para a nossa máquina local

$ cd $HOME/repo/gcc
$ git pull
From git://
   43bf72f..b6de2ea  master     -> origin/master
   43bf72f..b6de2ea  trunk      -> origin/trunk
Updating 43bf72f..b6de2ea
 gcc/cp/ChangeLog                                   | 20 +++++
 gcc/cp/call.c                                      |  9 ++-
 gcc/cp/cp-tree.h                                   |  1 +
 gcc/cp/decl.c                                      |  1 +
 gcc/cp/error.c                                     | 28 ++++---
 gcc/cp/except.c                                    | 11 +++
 gcc/cp/init.c                                      | 46 +++++++++--
 gcc/cp/parser.c                                    |  3 -
 gcc/cp/semantics.c                                 |  2 -
 gcc/testsuite/g++.dg/cpp0x/bad_array_new1.C        | 20 +++++
 gcc/testsuite/g++.dg/cpp0x/bad_array_new2.C        | 21 ++++++
 gcc/testsuite/g++.dg/cpp0x/initlist21.C            |  1 -
 gcc/testsuite/g++.dg/ext/vla4.C                    |  2 +-
 gcc/testsuite/g++.dg/init/new40.C                  |  2 +
 gcc/testsuite/g++.dg/parse/ref-qual1.C             | 29 +++++++
 libstdc++-v3/ChangeLog                             | 20 +++++
 .../config/abi/pre/gnu-versioned-namespace.ver     |  3 +
 libstdc++-v3/config/abi/pre/gnu.ver                |  4 +                                                   
 libstdc++-v3/include/bits/atomic_base.h            | 88 +++++++++++-----------
 libstdc++-v3/libsupc++/                 | 14 +++-
 libstdc++-v3/libsupc++/            | 36 +++++++++
 libstdc++-v3/libsupc++/cxxabi.h                    |  3 +
 libstdc++-v3/libsupc++/           |  4 +
 libstdc++-v3/libsupc++/new                         | 15 ++++
 24 files changed, 315 insertions(+), 68 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/bad_array_new1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/bad_array_new2.C
 create mode 100644 gcc/testsuite/g++.dg/parse/ref-qual1.C
 create mode 100644 libstdc++-v3/libsupc++/

Alguns arquivos foram modificados e baixados para o nosso computador local! E se quisessemos listar as tags de um repositório linux afim de baixar versões!?

$ cd $HOME/repo/linux-stable
$ git tag -l

Ainda omiti bastante coisa pois senão ficaria extenso! Veja aí que todas as baselines da versão estável do Linux estão aí, agora o pulo do gato, e tem como baixar uma versão de uma tag dessa em específico? Com certeza! Veja abaixo:

$ git archive --format=tar --prefix=linux-3.8.8/ -o ../linux-3.8.8.tar v3.8.8
$ cd .. && ls -l linux*tar
-rw-r--r--  1 mulatinho mulatinho 505743360 May  9 17:19 linux-3.8.8.tar

É isso rapaziada! O GIT é fera!!!

Texto de 2006, adicionado ao blog.

Há muito tempo eu escrevi uma introdução ao bash script e olhando ontem, resolvi fazer uma adaptação aqui no blog e colocar pra o pessoal ler, quem sabe alguém que esteja iniciando no mundo unix se interesse 🙂 Este texto contém uma visão introdutória sobre o que é uma shell e como a manipular, mas especificamente a Bourne-Again SHell (BASH).


1.1 – O que é uma shell?
1.2 – Principais tarefas da shell.

2.1 – Conectivos padrões e retornos lógicos.
2.2 – A matemática na shell.
2.3 – Tipos de parametros.

3.1 – Variáveis ambiente.
3.2 – Atribuindo comandos à variáveis.

4.1 – Usando loops.
4.2 – Fazendo condições.

5.1 – Redirecionando entrada/saída de dados.
5.2 – Usando comandos em background e adcionando interrupções.
5.3 – Alguns comandos: sed, cut, wc, od.
5.4 – Cores no terminal.

6.1 – .bashrc
6.2 – .bash_history

Programação Shell Linux, Júlio Cezar Neves, Brasport.
The GNU Bash Reference Manual

1. A shell no Linux

A shell está no Linux desde o início e serve justamente para executar os comandos com mais eficiência do que seriam executados se estivessem sem a organização que ela oferece. O Linux desde o início foi desenvolvido em partes que formam um todo utilizando um núcleo que chamamos de KERNEL, essas partes são pequenos ou grandes programas que utilizam chamadas do kernel para realizar a maioria de suas tarefas em conjunto ou separados.

Digamos que se quisessemos copiar um arquivo para outro usariamos algo como o comando cp ou se quisessemos apenas modificar seu nome usariamos o comando mv. Para que tudo fosse mais prático os seus desenvolvedores pensaram em algo que pudesse interpretar e unir com mais facilidade esses comandos/programas, foi aí que originou-se a shell com o intuito de organizar estes comandos, interpretando-os e também com uma poderosa linguagem de programação com o conjunto de seus programas. O sistema operacional UNIX e seus derivados como no nosso caso, o Linux, é composto por várias “camadas”. A mais interna de todas elas é a que chamamos de KERNEL ou núcleo, ele é responsável por interagir diretamente com o HARDWARE simplesmente fornecendo o controle total para que o resto do sistema funcione, por exemplo quando escrevemos algo em um arquivo ou mesmo quando estamos lendo, o KERNEL envia sinais para que o processador procure na trilha e no setor certo do disco onde está sendo gravado/lido certo dado que foi processado.

Os programas por sua vez quando são executados as vezes precisam que o usuário forneça dados como argumentos ou opções, no nosso terminal então precisamos de algo que entenda o que está sendo pedido e é finalmente aí onde entramos com a SHELL.

1.1 O Que é uma shell?

Pra começo de conversa, no momento em que você se loga no sistema você já está numa SHELL. A SHELL é um meio pelo qual o usuário entra com dados para o sistema fazendo com que o sistema identifique esses dados e os converta para o sistema operacional poder lê-los sem ter que resolvê-los, diminuindo assim o tempo que seria gasto se a SHELL não interpretasse esses dados e o deixasse para que o kernel também fosse resolvê-lo. Tendo em vista esses dados podemos dizer que a SHELL é uma ferramenta poderosa que usamos para interpretar nossos comandos antes de roda-los fazendo com que seja possível o uso de parametros, substituição de strings, modificação de variáveis ambiente, etc. Também vale ressaltar que a shell vem com uma linguagem poderosa, chamada shell script, que nos permite utilizar laços de condição e processamento de certos dados, principalmente os de entrada e saída.

1.2 Principais tarefas da Shell.

As principais tarefas da nossa shell são compreender e organizar a linha de comando que o usuário envia na entrada de dados, fazendo assim com que
os comandos executados rodem com mais performance e de um jeito muito mais estruturado, depois de feito isso a shell ordena de ESPAÇO em ESPAÇO cada comando e argumento enviado, procurando-os na variável $PATH que contém os caminhos onde o usuário em questão pode executar programas. A shell também é capaz de agir como um interpretador de linguagem estruturada, permitindo-nos fazer scripts com a mistura de comandos que o sistema nos fornece. Podemos resumir então estes processos desta forma:

  1. A shell pega os dados e os interpreta antes de serem executados.
  2. Usa variáveis ambiente como o $PATH, que nos mostra os diretórios aos quais o usuário tem acesso para execução de comandos.
  3. Processa como os dados vão sair e entrar corretamente (input/output).
  4. A nível de programação ela executa laços, condições, etc.

2. O básico do básico.

Este capítulo é chamado de básico do básico porque relaciona coisas bem iniciantes a nível de noções da shell no Linux, para obtermos uma visão
correta é preciso ter noção de como funciona alguns comandos do linux que estão diretamente ligados ao uso da nossa shell, por exemplo para listarmos
o conteúdo de um diretório não precisamos entrar nele para ver seus arquivos, basta que usemos o comando de listagem com o diretório como
parametro, por exemplo:

$ ls /home/alexandre/txtz/y0/
bash.txt  plantz.txt  provas.txt  userfile.txt


$ cd /home/alexandre/txtz/y0
$ pwd
$ ls
bash.txt  plantz.txt  provas.txt  userfile.txt

Como podemos ver isso tudo é muito básico mas é necessário ter uma idéia que estamos trabalhando com um interpretador de comandos que nos oferece além de qualidade para entender o que está sendo digitado também praticidade e velocidade. Vejamos como seria se eu quisesse me movimentar um diretório abaixo:

$ cd ..
$ pwd
$ ls -lh
-rw-r--r--    1 alexandr users        307k Dec 22  2003 focalinux.txt
drwxr-xr-x    2 alexandr users         200 Sep  3 12:01 y0

Vemos que descemos um diretório abaixo de onde estávamos usando o comando cd seguido de 2 pontos finais, a shell interpreta isso fazendo com que nós voltemos um diretório do orignal a qual estávamos. Uma observação interessante a se comentar é que o diretório y0 nada mais é do que um
arquivo assim como todos os diretórios do linux, a diferença é a flagzinha ‘d’ na sua permissão.

Outra coisa que devemos observar é que como na matemática a shell da preferência a opções que estejam entre parenteses, por exemplo:

$ ls txtz/y0/
bash.txt  file.txt  plantz.txt  provas.txt  userfile.txt
$ pwd
$ ( cd txtz/y0/ ; cat file.txt )
voce esta me lendo! ohh :~
$ pwd

Ué ? por que eu não fui pro diretorio txtz/y0/ ? e como eu li o arquivo file.txt se ele estava dentro desse diretório e eu ainda continuo no $HOME
CALMA! Não foi nenhuma macumba.. o que aconteceu foi que a shell deu preferência ao comando entre parenteses, executou o comando em uma shell filho e retornou a shell normal matando a shell filho. Outro tipo de forma pra mostramos como o parenteses está em preferência com a shell é usando um comando qualquer entre parenteses:

$ echo "A versão do meu kernel é: $(uname -r)"
A versão do meu kernel é: 2.4.26

Para saber como funciona essa interpretação de comandos nós temos que
voltar a coisas bem iniciais por isso chamamos essa parte de básico do
básico, imaginemos então:

$ ls
eu.txt voce.txt nos.txt vos.txt eles.txt

Temos um comando simples ‘ls’ que quando executado na shell
retorna os arquivos do diretorio em que estamos. Agora vejamos:

$ ls e*
eu.txt eles.txt

Digitamos novamente o ‘ls’ sendo que com um argumento, a primeira letra
‘e’ seguida de um ASTERISCO, a shell então retorna todos os arquivos do
diretório que contém a primeira letra que indicamos mais TODO O RESTO, que
é o que significa o asterisco. Vemos agora a utilidade das aspas no echo:

$ echo 1 2 3...    VOCE  EH ESTA  APRENDENDO  BASH
$ echo "1 2 3...    VOCE  EH ESTA  APRENDENDO  BASH"

OBS: Veja que a mudança ocorre na saída do texto quando usamos às aspas.

Resumindo, ela interpretou o comando antes de executa-lo, isso se faz
muito útil para que você as vezes não tenha que fazer vários comandos com
um objetivo só ou as vezes queira obter mais performance. Por exemplo no
caso de interagir com um ou mais comandos, deve-se usar conectivos.

2.1 Conectivos padrões e retornos lógicos.

+-----------+---------------------------------+   +---+---+------+
| CONECTIVO | DESCRIÇÃO                       |   | A | B |A && B|
+-----------+---------------------------------+   +---+---+------+
|     &&    | AND (E) lógico.                 |   | 0 | 0 |  0   |
|     ||    | DOUBLE PIPE (OU) lógico.        |   | 0 | 1 |  0   |
|     |     | PIPE (OU) lógico.               |   | 1 | 0 |  0   |
+-----------+---------------------------------+   | 1 | 1 |  1   |
$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/hda1             9.8G  2.9G  6.9G  29% /
/dev/hda4              14G  3.2G   10G  23% /mnt
$ echo $?

O duplo caracter $? (dólar,interrogação) retorna o valor do resultado do
comando digitado na entrada, fornecendo 0 se o comando retornar OK e 1 se
ele retornar com algum erro (observemos que é o inverso da tabela verdade
usada na lei de Boole). Com isso podemos usar os conectivos e colocar dois
comandos numa linha apenas, por exemplo:

$ cd /
$ echo "Arquivos do diretório atual ($PWD):" && ls
Arquivos do diretório atual (/):
bin  boot  dev  etc  home  lib  mnt  opt  proc  root  sbin  tmp  usr  var

*OBS: Como o resultado do comando echo e do ls são 0 (e na tabela verdade
da shell o 0 representa LIGADO), indicando que eles retornaram VERDADEIRO
os dois comandos são colocados na tela. O $PWD é uma variável do sistema
que será explicada depois 😉

Então já podemos dizer que a tabela VERDADE da nossa shell ficaria da
forma inversa da tabela original da lei de Boole.


| A | B | A&&B |          RETORNO:
+---+---+------+          --------
| 0 | 0 |  0   |          0 = OK.
| 0 | 1 |  1   |          1 = ERRO.
| 1 | 0 |  1   |
| 1 | 1 |  1   |

Ou seja, os dois comandos só seriam impressos na tela juntos se ambos os
termos fossem 0 quanto ao seu resultado. Agora vejamos se no primeiro
argumento o resultado fosse maior que ou igual a 1, e o próximo fosse 0
usando o AND condicional ficaria:

$ ls /root && echo "Fim do /root"
ls: /root: Permission denied
$ echo $?

*OBS: O 1° argumento retorna um numero diferente de 0 fazendo com que o
2° comando nao seja executado porque de acordo com a tabela verdade
do AND condicional o 2° comando só executado se houvesse uma verdade
lógica ou um retorno 0;.


$ ls /root
ls: /root: Permission denied
$ echo $?

$ echo "Fim do /root"
Fim do /root
$ echo $?


!(1 && 0) =>; 1 (ERRO/DESLIGADO)

Já no caso do PIPE (|), a prioridade dos argumentos sempre estão do lado
direito(ou 2° argumento) é muito útil quando estamos lendo algo no console
quando o texto é muito grande e precisamos realizar pausas pra leitura:

$ cat /usr/doc/Linux-HOWTOs/Bash-Prompt-HOWTO | grep PS1

O comando cat é executado fazendo com que todo o arquivo seja impresso na tela embora com uma diferença, todo o texto é enviado para o comando grep, que por sua vez procura por strings no arquivo e entrada retornando apenas as linhas que contenham o argumento passado no comando ‘grep’ ;]

2.2 A matemática da shell.

Temos várias formas para realizarmos calculos matemáticos na shell,
podemos simplesmente usar o comando ‘expr’ ou usar cálculos entre
parenteses com as definições de operadores da shell.

| VALOR | SIGNIFICADO                                   |
|   +   | Como na matemática, serve para somar números. |
|   -   | Também como na matemática, subtrair.          |
|   /   | Este é o operador para divisão de números.    |
|   *   | Operador de multiplicação.                    |
|   %   | Resto de uma divisão.                         |
| == != | Igual e diferente.                            |
| <= >= | Menor igual que, maior igual que.             |

Podemos realizar operações usando o comando expr mais os números e que
tipo de operadores queremos para realizar cálculos, ou simplesmente usar o
echo $((CALCULO MATEMATICO)), onde dentro desses DOIS parenteses, faremos
o cálculo para ser armazenado ou impresso na tela. Exemplos:

Fazer a soma de 4 + 5:

$ expr 4 + 5

A média aritmética de 20+15+10:

$ echo $(( (20+15+10) / 3 ))

Multiplicar 3 por 5:

$ expr 3 * 5
expr: syntax error

Ué!? O que houve de errado? bom, relembrando o início a shell interpreta os comandos antes de executa-los, ela entendeu o ASTERISCO como usamos anteriormente significando QUALQUER COISA, só que isso numa operação matemática não faz sentido. O que fazer então? temos que proteger o asterisco da shell pra dar prioridade ao operador e não a interpretação
que a shell faz do asterisco normal.

Novamente, protegendo o asterisco, multiplicando 3 por 5:

$ expr 3 * 5

Há também outra forma de fazermos cálculos, usando a cálculadora padrão do GNU a bc. Como vimos, usando o PIPE odemos jogar uma informação no 2° argumento de um comando:

$ echo "(4 * 27) + 21" | bc

Usamos às aspas para proteger o parenteses da shell e jogamos a operação
na calculadora bc que nos retorna o resultado rapidamente.

2.3 Tipos de parâmetros.

O uso de parametros é quase constante em uma linha de comando de uma
pessoa que esteja acostumada à shell, eles tornam tudo mais fácil e as
vezes se fazem extremamente necessários.

o> parametro de substituição de comando

para a shell saber onde executar os comandos é necessário uma forma de
procura por programas para executar no sistema, a variável $PATH indica
onde o usuário em questão verá os diretorios separados por ‘:’ do
sistema aos quais ele obterá acesso à comandos.

podemos utilizar um parametro para executar comandos na shell fazendo
com que seu output saia na tela ou seja armazenado em alguma variável,
a shell bash vai entender o que estiver entre os parenteses como um
comando de algum diretório do $PATH.


$(COMANDO) => Abre uma subshell e executa o comando retornando a
shell pai e saindo da subshell.


`comando` => Executa um comando normal do sistema.

$ echo -e "todays fortune:n $(fortune)"
todays fortune:
"All flesh is grass"
-- Isiah
Smoke a friend today.

$ SYSTEM=`uname -s`
$ echo "Sistema: $SYSTEM"
Sistema: Linux

voce pediu pra a shell imprimir uma frase, seguida de um comando
‘fortune’ que faz parte de um pacote chamado bsdgames, ele é bem
interessante, é composto de milhares de frases e pensamentos de
filósofos, autores de livros, etc. já no segundo exemplo usamos uma
variável SYSTEM para armazenar o retorno do comando ‘uname -s’ depois
imprimimos na tela.

o> parametros com chaves

as vezes queremos nos referir a um nome de arquivo em vários tipos de
extensão, ou fazer coisas do tipo, para isso podemos ao inves de ter
que escrever toda a linha de comando repetidamente usamos as chaves.

$ echo m{a,e,o}ngo          ou         $ ls *.{bz2,txt}
mango mengo mongo                      IAO-paper.txt focalinux.txt
gcc-3.3.tar.bz2 retlib.txt

evitamos ter que fazer repetições na linha de comando colocando as
sequencias necessarias entre chaves.

o> outros parametros

podemos trocar strings de um parametro, declaramos ele desta forma:
${PARAMETRO/STRING/NEWSTRING} , onde STRING é a ocorrência que você
deseja modificar e o NEWSTRING é a nova string que vai ficar.

$ STR="estou aprendendo a errar"
$ echo ${STR/errar/viver}
estou aprendendo a viver

ou se quisessemos ver o tamanho de caracteres de uma string, fariamos
assim ${#STRING}, onde STRING seria a variavel ou palavra/frase.

$ echo $STR
estou aprendendo a errar
$ echo ${#STR}

para pegarmos um argumento da linha de comando usamos o carácter
dólar seguido da ordem do seu argumento, exemplo:

$ ./comando arg1 arg2 arg3
$1 -> arg1
$2 -> arg2
$3 -> arg2

3. Variáveis.

Uma coisa muito útil na shell é a possibilidade de armazenamento de
dados na memória, fazendo isso podemos atribuir à variaveis saídas de
comandos, calculos aritméticos e strings. Para setar uma variável na
shell basta fazer:

$ A=1

$ echo $A $B $C

Veja que dessa vez não usamos o DÓLAR para setar a variável A,B,C esse
dólar só vai ser colocado quando quisermos que a shell retorne o valor
da variável. Para remover a variável do sistema é só fazer:

$ unset C
$ echo $C

3.1 Variáveis ambiente.

Há uma série de variáveis padrões definidas pela SHELL quando você se
loga nela, estas servem para organizar de forma mais eficiente tudo que
o usuário tem acesso, pode fazer e quer saber. Vamos ver algumas delas:

$HOME => Indica o diretório raiz do usuário que esta logado na shell.
$PATH => Diretórios aos quais o usuário tem acesso à comandos.
$PWD => Diretório onde o usuário se encontra.
$USER => Usuário logado na shell.

Para vermos todas elas usamos o comando ‘export’ que serve também para
setar as variáveis ambiente na shell. Para ver todas:

$ export

Para setar:

$ export VAR="Conteúdo"
$ echo $VAR

3.2 Atribuindo comandos à variáveis.

Podemos utilizar as variáveis também para armazenar saída de comandos
do sistema, para isso colocamos o comando entre crases, vejamos exemplos:

$ cd txtz/y0/
$ pwd
$ var=`ls`
$ echo $var
bash.txt file.txt plantz.txt provas.txt slides.txt userfile.txt

Entramos no diretório e setamos uma variável ‘var’ com o valor da saída
do comano ‘ls’, depois imprimimos o valor com o comando echo.

$ proc=`cat /proc/cpuinfo | grep "model name" | cut -d" " -f4-10`
$ echo "PROCESSADOR: $proc"
PROCESSADOR: Athlon(tm) XP 1700+

4. Estrutura de loops e condições.

Podemos elaborar processos repetidas vezes de acordo com a condição que
desejarmos, usando as estruturas de loop e condições começamos a falar de
shell script que nada mais é do que uma forma estruturada de organizar os
comandos do sistema utilizando tudo que aprendemos em conjunto(variáveis,
comandos, retornos de comandos, etc).
Há diferença entre eles é que os loops executam uma certa sequencia de
comandos digitados pelo programador até que aconteça algo que será
processado e de acordo com o tipo de loop, terminado ou continuado,
enquanto as condições esperam que o programa receba algo e de acordo com
um teste que foi previsto pelo programador anteriormente execute um bloco
de códigos ou não.
Para setar um arquivo como shell script deve-se coloca-lo com uma
permissão de execução, fazendo:

$ chmod +x arquivo
$ ./arquivo

Tendo em vista isto, temos também que entender que no shell script os
operadores para condições matemáticas tambem mudam, exemplo:

| OPERADOR | SIGNIFICADO                                 |
|   -lt    | less than (menor que).                      |
|   -le    | less or equal than (menor ou igual que).    |
|   -gt    | greater than (maior que).                   |
|   -ge    | greater or equal than (maior ou igual que). |
|   -eq    | equal than (igual que).                     |
|   -ne    | not equal (diferente de).                   |

Também é bom lembrar que num arquivo shell script, a primeira linha
deverá sempre ser a declaração da shell em que estamos programando:


4.1 Usando loops.

Os loops servem entre outras coisas para executar um bloco de códigos
até que um teste seja atingido, vejamos alguns tipos de loop:

o> until


until [ 'TESTE' ] ; do

O comando until serve para executar um laço até o seu TESTE retorne
um valor diferente diferente de 0 (ou seja, até que o teste seja falso)


until [ $IN -lt 4 ] ; do
echo "LOOP: $IN"
IN=`expr $IN - 2`

$ ./until

o> while


while [ 'TESTE' ] ; do

Fazendo o inverso do until, o comando while executa o CÓDIGO até que
o retorno de seu TESTE seja igual a 0 (ou seja verdadeiro), exemplo:


while [ $IN -lt 4 ] ; do
echo "LOOP: $IN"
IN=`expr $IN + 1`

$ ./while

o> for


for (( expr1 ; expr2; expr3 )) ; do

Onde temos o primeiro modo de utilizar o for na shell, o expr1 é um valor que será atribuido à uma variável, o expr2 é um teste que será feito até que seu resultado seja verdadeiro, fazendo com que o bloco de código seja executado repitidamente e expr3 será o que será feito quando o teste for verdadeiro, poucos usam o for desta forma embora na minha opnião seja mais eficiente. Por exemplo:

for (( i=0 ; i<5 ; i++ )); do
echo "loop: $i"

$ ./for
loop: 0
loop: 1
loop: 2
loop: 3
loop: 4

4.2 Fazendo condições.

É necessário fazer condições quando recebemos algo da entrada de um
usuário e queremos realizar um TESTE com esses dados para ver qual rumo
o programa deve tomar. Vamos usar dois tipos de comandos básicos para
execução de condições, são eles:

o> if-then-else


if [ 'TESTE' ] ; then

Executa o TESTE, se ele for verdadeiro executa o bloco de CÓDIGO senão sai sem executar nada dentro do if.

if [ 'TESTE' ] ; then
elif [ 'TESTEDOIS' ] ; then

Executa o TESTE, aciona o bloco de CÓDIGO se o resultado do teste for verdadeiro.. depois executa o TESTEDOIS e se for verdadeiro ele executa o bloco de CÓDIGO DOIS.

if [ 'TESTE' ] ; then

Aqui ele executa o TESTE, entra no bloco de CÓDIGO se o resultado
do teste for verdadeiro, senão ele entre no bloco de CÓDIGO DOIS.


if [ "$1" == "Mulher" ] ; then
echo "Olá senhorita :)~"
elif [ "$1" == "Homem" ] ; then
echo "Como vai meu bom homem?"
echo "Escolha sua opção sexual rapaz!"

$ ./ifthenelse
Escolha sua opção sexual rapaz!
$ ./ifthenelse Homem
Como vai meu bom homem?
$ ./ifthenelse Mulher
Ola senhorita :)~

o> case


case ARG in


Aqui o teste ocorre em cima de ARG, o case explode várias possíveis alternativas que podem ser PS1, PS2, PS3, …, PSN. Uma boa função do case é poder fazer essas possibilidades usando meta-caracteres.


case $IN in
echo "Tu és homem!"
echo "Tu és mulher!"
echo "Tá confuso?"

$ ./case b
Tu és homem!
$ ./case 3
Tá confuso?

5. Avançando.

Nesta parte vamos começar a complicar mais um pouquinho pra descomplicar bem muito, hã? é isso mesmo, aqui vamos mostrar alguns comandos que a maioria nem chega perto mas que são úteis demais para um shell scripter.

5.1 Redirecionando entrada/saída de dados.

Podemos direcionar como os dados irão entrar e como irão sair em nossa shell usando operadores, para começarmos a fazer isso devemos lembrar os 3 tipos padrões de entrada/saída de dados, são eles:

(0 ou STDIN) => Standard Input (Entrada Padrão).
(1 ou STDOUT) => Standard Output (Saída Padrão).
(2 ou STDERR) => Standard Error (Saída de erro padrão).

Tendo em mente isso, usamos operadores para o redirecionamento que são parecidos com os símbolos da matemática:

| N> | Onde N, é o valor da saída de dados (1 ou 2), fazendo com que |
| | o redirecionamento da saída seja feito há direita do operador. |
| > | Envia os dados para arquivo, criando-o caso não existe ou |
| | apagando seu conteúdo anterior e adcionando novo, caso exista. |
| >> | Aqui há o redirecionamento de dados para o FINAL do arquivo |
| | caso exista, ou uma criação de arquivo, caso não exista. |
| < | Setamos na shell que a entrada padrão não irá vir do teclado |
| | e sim do arquivo em questão. |
| << | Indicamos um LABEL para o começo de uma linha fazendo com que |
| | a linha só termine quando houver a proxima ocorrência do LABEL |

$ echo "Ohh! voce me leu :~" > file.txt
$ cat file.txt
Ohh! voce me leu :~

$ echo "Que trágico!" >> file.txt
$ cat file.txt
Ohh! voce me leu :~
Que trágico!

$ tr e i < file.txt
Ohh! voci mi liu :~
Qui trágico!

$ mount /dev/cdrom /mnt/cdrom 2> error.txt
$ cat error.txt
mount: only root can do that

5.2 Usando comandos em background e adcionando interrupções

Podemos rodar comandos em modo background., que significaria mais ou
menos que executamos um comando deixando-o numa file de espera, então
ele em alguns programas que precisam de entrada de dados só irá
executar suas funções quando agente o chamar no sistema.

$ vim file.txt &
[1] 22956
Î   Î
`---|-------- 1 = First Job (Primeiro trabalho.)
'--- 22956 = PID (Process ID).

Vêmos que ele carregou o programa numa subshell, mas não executou a sua função que era de editar o arquivo, para fazermos isso, digitamos

$ fg 1

E então o ID do processo em background sairá da subshell e virá para nossa shell principal, podemos fazer isso várias vezes. Outra coisa muito útil é que podemos adcionar interrupções ou simplesmente modifica-las de acordo com o nosso interesse, para agente começar a mecher nos sinais devemos é claro, entendê-los:

0 => Saída normal do programa.
1 => Sinal de quando se recebe um kill -HUP
2 => Interrupção forçada pelo teclado CTRL+C.
15 => Sinal de interrupção de programa quando se é kilado. (kill PID).

Isso é muito útil quando fazemos um programa e queremos ter certeza
que o usuário não fará a besteira de termina-lo usando CTRL+C ou se
fizer nós termos como ajeitar sua trapalhada, por exemplo:

$ trap “echo THE POWER OF TRAP” 2

5.3 Alguns comandos: sed, cut, wc, od.

Aqui vamos ver alguns comandos que são muito úteis quando se esta
trabalhando com arquivos, é importante domina-los para uma maior
velocidade e eficiência.

o> sed






Usando sed podemos substituir FRASE(strings, números, frases)
por uma NOVA palavra ou frase, vejamos um exemplo simples:

$ cat file.txt
batatinha quando nasce, esparrama pelo chão.
$ sed 's/esparrama/cai/' file.txt
batatinha quando nasce, cai pelo chão.



sed ‘X,Yd’ <ARQUIVO>

Não imprime linhas de X à Y.


Não imprime linhas que contém PALAVRA.

$ cat file.txt
Linux comanda o mundo.
Windows comanda o mundo.
Freebsd comanda o mundo.

$ sed ‘2,3d’ file.txt
Linux comanda o mundo.

$ sed ‘/Windows/d’ file.txt
Linux comanda o mundo.
Freebsd comanda o mundo.



sed -n …. <ARQUIVO>

$ sed -n '/Windows/!p'
Linux comanda o mundo.
Freebsd comanda o mundo.

o> cut

Serve para separar de acordo com o seu DELIMITADOR as palavras e
imprimir apenas o que é pedido.




-d => Usado para definir qual vai ser o delimitador.
-fN => De acordo com o delimitador, a Nª palavra.

$ cat /etc/passwd | cut -d":" -f1

o> wc

Este comando serve para imprimir a quantidade de bytes, palavras
e linhas de um arquivo, é geralmente usado depois de um PIPE.




-l => quantidade de linhas
-w => quantidade de palavras
-c => quantidade de bytes (caracteres).

$ wc -l file.txt
2 file.txt
$ wc -c file.txt
34 file.txt

o> od

O comando od serve para imprimir um arquivo de acordo com uma
especificação dada pelo usuário, podemos imprimir um arquivo texto
com suas letras em formato hexadecimal, octal, etc.




-h => imprime letras e números em hexadecimal.
-o => imprime letras e números em octal.

$ od -h file.txt
0000000 684f 2168 7620 636f 2065 656d 6c20 7565
0000020 3a20 0a7e 7551 2065 7274 67e1 6369 5c6f
0000040 0a21

5.4 Cores no terminal.

Podemos sim adcionar cores para dar ênfase a alguma frase ou enfeitar nossos programas shell, usamos então uma definição especial para isso, um caracter ESC seguido de uma [ mais códigos de cores e terminando por uma barra invertida seguida de um m, ‘]m’, vejamos a lista de códigos para suas cores:

| TEXTO | FUNDO | COR               |   | CÓDIGO | SIGNIFICADO   |
+-------+-------+-------------------+   +--------+---------------+
|   30  |   40  | Preto (cinza).    |   |   0    | Desliga tudo. |
|   31  |   41  | Vermelho.         |   |   1    | Negrito.      |
|   32  |   42  | Verde.            |   |   5    | Pisca pisca.  |
|   33  |   43  | Marrom (amarelo). |   |   7    | Reverso.      |
|   34  |   44  | Azul.             |   +--------+---------------+
|   35  |   45  | Roxo.             |
|   36  |   46  | Ciano.            |   *OBS: ESC == 33 (Octal)
|   37  |   47  | Cinza (branco).   |

$ echo -e “33[40;31;1mSPORT RECIFE33[m”
$ echo -e “33[42;32;1mLOL33[m”

6. Arquivos de configuração.

Estes arquivos servem para quando iniciarmos a shell, carregarmos ou
executarmos váriaveis/programas, mudarmos o prompt, adcionarmos aliases
e várias outras opções.

o> .bashrc / .bash_profile

Este arquivo é executado assim que logamos na shell, podemos então
utiliza-lo para setar o prompt, adcionar aliases padrões, etc.

o> .bash_history

Este é o arquivo onde ficama a história dos processados pela shell
no sistema, ele fica no diretório $HOME do usuário.

É lastimável como a sociedade Brasileira trata o lixo, e mais recentemente o lixo eletrônico, na era da tecnologia moderna aonde os relacionamentos são iniciados em salas de bate papo via internet o ser humano ainda não aprendeu a enamorar-se pela natureza.

O lixo eletrônico, peças de computador contendo problemas no hardware ou simplesmente esquecidas por serem consideradas ultrapassadas (ex.: Pentium MMX, AMD K6-II 500Mhz, 486, etc.) estão cada vez mais sendo descartadas pela sociedade na natureza mas alguns jovens em Recife estão se unindo em torno de uma solução, o LTSP, que em português significa Projeto de Servidores de Terminais Linux, e tem como objetivo básico utilizar máquinas interconectadas via redes ethernet (e em breve wireless) a uma série de computadores, centralizando os dados em apenas um computador.

O LTSP pode ser usado para recuperar as máquinas que dispõem de hardwares mais antigos e não tem processamento ou capacidade de armazenamento dos computadores nos dias atuais. Usando apenas um computador de grande potência operacional pode se replicar a computadores de baixa potência uma boa porcentagem de seu processamento, memória RAM e armazenamento de dados sem perda de performance significativa, além de fornecer todo um sistema operacional e softwares complementares juntos. Então, pode-se dizer que com um computador velho: apenas a placa mãe antiga com suporte a rede e vídeo, uma memória mínima para o computador poder iniciar, um teclado, um mouse e sem HD (que já economiza bastante energia) é possível “recuperá-lo” e utilizá-lo com o dobro ou o triplo de sua performance bastando apenas ter uma máquina potente do outro lado, um bom esquema de redes (switchs, cabos, etc) e o LTSP.

A figura do início deste post expressa bem como funciona o LTSP, além de ser útil para recuperar as máquinas antigas ele serve perfeitamente para formar um firewall (afinal todos os computadores interconectados devem passar por um servidor LTSP antes de ir pra rede legada ou internet) e centralizar os dados e os softwares de um determinado departamento em apenas um computador fazendo com que se padronizem as ferramentas utilizadas no departamento e não haja muita redundância de dados armazenados.

Para quem desejar implementar este software em sua casa ou empresa, segue abaixo um link do texto que fiz baseado no Fedora/Red Hat, da instalação do LTSP dentro de uma rede corporativa: CLIQUE AQUI. E antes de pensar em jogar uma máquina fora (envie-a pra mim, hehehe) novamente pense na situação em que nossa natureza se encontra além da economia que vocë irá fazer.

%d blogueiros gostam disto: