O shell |
O shell no Linux é o nome genérico de uma classe de programas
que servem ao mesmo propósito: fornecer uma interface interativa, mas
não visual, ao usuário ou operador, aonde comandos podem ser
digitados, tarefas podem ser controladas e manipuladas, mantendo um ambiente
(environment) aonde a configuração da aparência e
parêmetros de alguns programas podem ser modificadas interativamente.
Por outro lado, os shells também funcionam como linguagem de
programação (interpretadas) e são uma forma relativamente
eficiente mas menos custosa de se executarem tarefas complexas, sem a
necessidade das fases clássicas de
edição-compilacão-depuração. Concentraremos
nossos esforços no bash
, que é indubitavelmente o
shell mais popular no Linux, mas grande parte desses conceitos se aplicam a
outros shells igualmente.
Cada shell tem um environment (ambiente, em portugues) que
é um simples banco de dados em forma de texto, relacionando nomes de
variáveis com os seus valores. Algumas variáveis são
muito importantes, pois controlam aonde o bash irá procurar programas
para executar, qual o tipo de terminal que estamos usando, e outras
propriedades realacionadas com o nosso ambiente particular. No login, o
bash
executa inicialmente /etc/profile, e depois algum dos
arquivos[18] ~/.profile
,
~/.bash_profile
ou ~/.bash_login
, definindo assim o
ambiente inicial do usuário. Se o shell é interativo, isto
é, ele está conectado a um terminal (em oposição a
um shell em batch-mode), ele lerá também o arquivo
~/.bashrc
.
|
o environment
As variáveis ao lado são as mais comuns, mas não de
maneira exuastiva. Muitos programas se comunicam com outros através
deste mecanismo bastante simples. PATH indica o local aonde o
bash deverá procurar por programas executáveis.
SHELL deverá conter |
Outras variáveis do environment são PPID, UID, EUID,
correspondendo aos valores de id de usuário e "programa-pai" que
já discutimos. Algumas variáveis têm significado especial,
e são modificadas diretamente pelo bash
: RANDOM mostra um
número aleatório (inteiro) cada vez que é referenciada;
SECONDS mostra o número de segundos desde o início do presente
processo (bash
) foi criado; LINENO mostra um número
sequencial da linha corrente, mas não linha do terminal e sim a
n-ésima linha de comando solicitada ao bash
.
Para visualizar quaisquer das variáveis do environment, usamos a
substituição de parâmetros do bash e o
comando echo
para nos mostrar esse valor substituido, por
exemplo:
echo $RANDOM
nos mostrará números aleatórios a cada vez que é executado. Para modificar um destes valores, simplesmente uma atribuição com o sinal de = é suficiente, exceto que o seu valor só permanece durante o comando presente. Usualmente queremos que "de agora em diante" o valor seja modificado, seja persistente. Para isso o comando export é necessário:
export CURSO=sysadmin
ou em outra forma mais explícita (separando os dois comandos):
CURSO=sysadmin export CURSO
O bash tem comandos builtins (já incorporados ao programa
bash) que são de outra forma indistinguíveis dos comandos que
discutimos em capítulos anteriores. Um comando builtin,
entretanto, não abre nenhum arquivo executável, e assim é
bem mais rápido a sua execução. Outra diferença
sutil, é que não haverá manpage para um
builtin. No seu lugar, usaremos o (builtin também,
evidentemente) help
seguido do nome do comando que desejamos
obter informação. No caso de comandos externos, o
(programa) man
faz esse papel.
Podemos executar comandos externo e retornar imediatamente, mesmo sem esperar que o comand termine, colocando um "&" no final da linha de comando:
comando &
Podemos também executar vários comandos em sequência, separando-os com um ponto-e-vírgula:
comando1 ; comando2
Outras formas de controlar logicamente a execução de comandos
é através de operadores lógicos && e
||:
comando1 && comando2
comando1 || comando2
A primeira destas formas executa comando2 somente se o comando1 for bem sucedido (não der erro). A segunda executa o comando2 somente se o comando1 falhar. (&& corresponde a um AND, || corresponde a um OR lógico)
cdtroca o diretório corrente. Usado sem parâmetros vai para o diretório $HOME (contido na variável HOME) Colocando os diretórios mais usados na variável CDPATH (separados por ":") podemos trocar para qualquer subdiretório dos contidos nessa lista sem introduzir os seus paths completos. |
pwdmostra o diretório corrente, de forma absoluta, isto é, sem o "~" que indica o nosso home dir. |
echoecoa os argumentos no terminal, após fazer as expansões (substituições) de variáveis, comandos, etc. |
umaskdefine (ou mostra, sem argumentos) a máscara que será usada na criação de novos arquivos. Essa máscara contém as permissões (rwx) que vimos anteriormente. Usando umask -S a mesma coisa se processa simbolicamente, ao inves de ser em octal (default). |
exit, byeesses comandos terminam o shell, opcionalmente retornando um número que seja dado como parãmetro. (no caso exit 3, por exemplo o status retornado será 3) |
helpum dos mais úteis comandos (principalmente para que é principiante!) para fornecer informações sobre os comandos builtins do bash. |
O bash efetua uma série de substituições nos argumentos que lhes são fornecidos. As mais comuns são até familiares para quem já é usuário do MsDos, que é a substituição de wildcards em nomes de arquivos. Mas o bash vai bem além, permitindo o uso de classes de caracteres e múltiplos "*" nos nomes de arquivos. Outras substituições não tão familiares também existem, com alguns exemplos introdutórios [19]:
substituição de chaves
É expandida como a combinação de todos os elementos entre
as chaves, separados por vírgulas. O segundo exemplo mostra um simples
"gerador de pronomes" brasileiros. Observe que em |
~$ echo ago{r,ni}a agora agonia
|
substituição de comandos
O resultado da execução do comando é colocado no lugar do
argumento. Esta subsituição vem em dois formatos:
|
~$ echo o path para ls é `which ls` o path para ls é /bin/ls
|
expansão de wildcards
É a já familiar expansão dos "*" (asteriscos) por
qualquer número de caracteres; "?" por um único caracter;
adicionalmente "[abc]" é substituido por "um destes" e "[^abc]" por "um
exceto estes" caracteres. |
~$ echo *.htm* cap01.html politica.htm
|
substituição do til "~"
O til é expandido somente quando está no início de uma
palavra, sendo substituido pelo conteúdo da variável HOME (o
diretório home do usuário). Além disso, os prefixos
|
~$ echo ~ , ~-
|
expansão de variáveis e
parâmetros
É o desdobramento do nome de variável, prefixado por "$" no seu
valor, contido no environment, mas outras formas de usar este mecanismo
existem. Mostraremos só algumas mais comuns. |
~$ export CURSO="Administração de Sistemas"
|
expansão aritmética
O bash permite fazer alguns cálculos simples (para cálculos com
precisão infinita, use |
~$ echo $((3*5))
|
Outras substituições serão vistas posteriormente, mas
aconselhamos brincar um bocado com estas, pois existem nuances que só a
utilização (e a consulta da manpage: man bash
)
revelam.
Algumas vezes queremos evitar a substituição de
variáveis ou remover o significado especial de caracteres. Isso
é chamado dequoting, e pode
ser feito de várias maneiras.
No segundo caso, as substituições de variáveis (prefixo $), comandos (entre acentos graves `) e caracteres prefixados com a barra invertida, continuarão sendo efetuadas. Observe que o último caso ecoará apenas um asterisco, e não todos os arquivos, o que seria resultada da expansão de wildcards como vimos acima.
|
O bash usa a biblioteca readline (mais outra excelente
herança GNU), que lhe dá uma potência considerável
na edição de linhas, tratamento da historia (history, comandos
previamente executados), e para complementação de palavras
parcialmente digitadas. Para o principiante, entretanto, é uma
miríade de comandos novos, nem sempre muito amigáveis para
memorizar. Todavia, o bash tem um builtin muito especial para nos
socorrer nesse caso, o comando fc
. Com ele re-editamos uma linha
introduzida anteriormente usando o editor da nossa preferência
(joe, tão bom que não precisei mostrar os
comandos dele. São triviais para quem já usou algum
WordStar-like anteriormente). Para abrir a edição de uma linha
previamente introduzida, entre fc <parte da linha>
e ele vai
buscá-la. Quando saimos do editor, a linha editada é executada.
Simples, não?
Mesmo assim, há vezes em que voce precisará realmente editar a linha de comando, portanto eis aqui um resumo dos principais controles de edição:
Ctrl-B | move para trás um caracter sem apagá-lo |
Ctrl-F | move à frente um caracter |
Del | apaga um caracter (digitado antes) |
Ctrl-D | apaga o caracter à frente do cursor |
Ctrl-A | move para o início da linha |
Ctrl-E | move para o final da linha |
Ctrl-P | move para a linha anterior (já executada) |
Ctrl-N | move para a próxima linha |
Esc ? | tenta completar o nome do comando (dado parcialmente) |
Ctrl-C | aborta o comando que está sendo executado |
Ctrl-Z | suspende, mas não aborta, o comando sendo executado |
Ctrl-S | suspende a saida para o terminal do programa executando |
Ctrl-Q | restaura a sida para o terminal (vide comando anterior) |
Os quatro últimos controles na verdade se relacionam mais com controle
de tarefas que edição de linhas, mas preferimos
mostrá-los aqui. Muitos desses comandos podem ser executados
também pelas teclas com setas do terminal, mas é bom
conhecê-los pois muitas vezes o terminal está mal configurado.
Além desses, outros controles indispensáveis são so que
permitem revisar o texto (saida) quando passa do tamanho da tela
(Ctrl-PgUp
e Ctrl-PgDown
), e os que mudam de
terminal virtual (Alt-F1 a Alt-F10
, dependendo do número
de terminais configurados). Se voce estiver em X-Windows, o certo é
Ctrl-Alt-F1
no lugar de Alt-F1
.
O bash possui alguns builtins para controle de processos:
jobs
lista os jobs atualmente executando, kill
%n
termina o job de número n
, bg
põe um job em background, fg
põe um
job em foreground. Os jobs são processos controlados
pelo shell corrente, mas com uma numeração localizada, diferente
da obtida com o comando ps
.
No Linux existem três arquivos pré-definidos para um programa, inclusid\ve para o próprio shell: stdin, stdout e stderr, abreviaturas de standard input, output, e error. Este comportamento se confunde com o da linguagem C, que foi criada exatamente para re-escrever o Unix (no final da década de 70) numa forma mais portável para várias arquiteturas (CPUs) diferentes.
Quando um programa "conversa" com o seu terminal, ele recebe caracteres do
stdin, que corresponde aos dados introduzidos no teclados
dele, e envia caracteres para o stdout, que corresponde
à tela deste terminal. Se todos os programas só funcionassem
assim, teríamos que estar constantemente digitando
informações para obter respostas, que não seriam
armazenadas em lugar algum!
Evidentemente, precisamos de uma forma melhor de reutilizar programas prontos,
como pro exemplo o programa sort, que lê o que é introduzido na
sua entrada (stdin) e escreve em ordem alfabética na
sua saida (stdout). Quando um programa encontra um erro de
sintaxe, usualmente ele escreve no stderr (saida de erro) o
que está errado. O bash nos fornece vários comandos para
controlar efetivamente para onde vai essa entrada e saida, permitindo
também concatenar vários programas, literalmente "conectados"
entre si, de acordo com uma metáfora que lembra encanamentos
(pipes) de uma distribuição de água, por
exemplo.
redireção de I/O
Os comandos podem ter suas entradas/saidas redirecionadas para arquivos. Na
figura, cmd é o nome de algum comando (qualquer) que estamos
considerando; saida, entrada, erro, são arquivos. O primeiro caso
redirige a saida (o que seria impresso no terminal) para o arquivo
|
|