SS-0101 - Resumo de Shell Script

SS-0101 - Resumo de Shell Script
Publicado em 24/02/2023 15h17
Visualizações: 95

Resumo Geral

1 - Básico de Shell Script

1.1 - Introdução:

Arquiterura em camadas do sistema operacional Linux:

SS-0101 - Resumo de Shell Script

Componentes da variável PS1 (Prompt String One): usuário@host:diretorio atual tipo de usuário (# ou $).

SS-0101 - Resumo de Shell Script

Estrutura da linha de comando: comando -opção argumento/parâmetro.

SS-0101 - Resumo de Shell Script

1.2 - Comandos básicos:

  • cd: altera o diretório de trabalho do shell;
  • pwd: mostra o nome do diretório de trabalho atual;
  • ls: lista o conteúdo de diretório;
  • cp: copia arquivos e diretórios;
  • mv: movimenta ou renomeia arquivos e diretórios;
  • rm: apaga arquivos e diretórios;
  • echo: imprime na tela;
  • which: encontra o PATH de um comando;
  • date: mostra ou configura a data e hora;
  • man: interface para manuais de referência on-line;
  • help: ajuda para comandos built in;
  • nano: editor de texto simples;
  • cat: concatena arquivos mostra seu conteúdo na tela;
  • tail: lê as últimas linhas de um arquivo;
  • head: lê as primeiras linhas de um arquivo;
  • stat: mostra os atributos de um arquivo ou diretório no sistema de arquivos;
  • touch: altera o MACtime de um arquivo; e
  • w: mostra os usuários que estão logados no sistema.

1.3 - Variávies

Um parâmetro é uma entidade que armazena valores. Ele pode ser um nome, um número, ou um dos caracteres especiais utilizados pelo shell. Uma variável tem um valor e zero ou mais atributos. Atributos são definidos utilizando o comando declare. Elas também são case sensitive e não podem ter seu nome começando com um número.

1.3.1 - Manipulando uma variável local

Uma variável pode ser definida da seguinte forma:

$ nome=[valor]

Para exibir na tela o valor de uma variável, utilizamos o comando echo:

$ echo $nome

Para excluir uma variável podemos utilizar o comando unset:

$ unset nome

SS-0101 - Resumo de Shell Script

No exemplo acima a variável nome foi criada como LOCAL, isso significa que ela vai existir apenas no shell em execução, não acessível por um subshell. Para tornar uma variável GLOBAL, acessível por subshells se utiliza o comando export:

$ export nome="Rodrigo Brito"

1.3.2 - Variáveis de ambiente

Uma variável de ambiente contém dados utilizados por uma ou mais aplicações no sistema. Esse tipo de variável é comumente utilizado para definir configurações do sistema operacional. Exemplos:

  • HOME: contém o caminho completo do diretório HOME do usuário;
  • OLDPWD: diretório anterior acessado pelo comando cd;
  • PATH: contém uma lista de diretórios separados por dois pontos que o sistema utilizará para procurar arquivos executáveis;
  • PWD: contém o caminho completo do diretório atual; e
  • SHELL: contém o caminho do shell preferido pelo usuário.

Pode-se modificar as configurações definidas pelas variáveis de ambiente apenas modificando seu valor. EX: adicionar o diretório /home/domingues como um diretório válido na variável PATH:

SS-0101 - Resumo de Shell Script

Após a modificação, o shell buscará por executáveis também no diretório /home/kali.

1.3.3 - FHS (Filesystem Hierarchy Standard)

O FHS é o documento que define os principais diretórios e seus conteúdos para sistemas Linux/Unix:

SS-0101 - Resumo de Shell Script

  • /bin/: comandos executáveis essenciais para todos os usuários (ex: cat, ls, cp), especialmente arquivos necessários para funcionamento mínimo do sistema;
  • /boot/: boot loader, kernels e arquivos initrd;
  • /dev/: arquivos de dispositivos (ex: /dev/sda);
  • /etc/: arquivos de configuração do sistema específicos do host;
  • /home/: diretórios home dos usuários;
  • /lib/: bibliotecas essenciais para os binários no /bin e /sbin;
  • /lost+found/: alguns arquivos e fragmentos que foram “recuperados” durante o fsck (NÃO faz parte do FHS);
  • /mnt/: sistemas de arquivos montados temporariamente;
  • /media/: ponto de montagem para dispositivos removíveis como CD-ROMs;
  • /opt/: pacotes de software de aplicativos complementares;
  • /proc/: sistema de arquivos virtual que documenta o status do kernel e dos processos;
  • /root/: diretório home do usuário root;
  • /sbin/: binários administrativos do sistema (binários do root) para recuperação do sistema;
  • /tmp/: arquivos temporários;
  • /selinux/: SE-Linux configurações de tempo de execução (não faz parte do FHS);
  • /srv/: dados específicos do site que são servidos pelo sistema (não faz parte do FHS);
  • /sys/: o sistema de arquivos para exportar objetos do kernel;
  • /usr/: hierarquia secundária para dados compartilháveis e somente leitura (arquivos que não são necessários para inicializar ou resgatar o sistema); e
  • /var/: dados variáveis, como logs, bancos de dados, site e arquivos temporários de spool.

1.4 -Permissões

O modelo de permissões utilizado no GNU/Linux é baseado na posse de arquivo ou diretório. Cada arquivo ou diretório tem um dono, um grupo e os outros usuários.

SS-0101 - Resumo de Shell Script

Para cada classe dono, grupo e outros temos um conjunto de permissões que podem ser leitura(r), escrita(w) e execução(x).

  • r (4) - leitura (2**2);
  • w (2) - escrita (2**1); e
  • x (1) - execução (2**0).

É possível checar a permissão de um arquivo utilizando o comando ls com a opção -l:

SS-0101 - Resumo de Shell Script

No exemplo acima, o arquivo flag.txt tem como saída as permissões onde o primeiro grupo é permissões do arquivo (rw-r--r--), o segundo é o dono do arquivo (kali) e o terceiro é o grupo (kali). Quanto as permissões, de forma fatiada, o dono possui as permissões rw- (leitura e escrita), o grupo possui as permissões r-- (leitura) e outros usuários possui também somente a de leitura.

1.4.1 - Permissões de diretório

A permissão de diretório tem uma diferença em relação as permissões de arquivo. A permissão x para diretório não significa execução e sim permissão para entrar no diretório. Lembrando que escrever (w) no diretório significa apagar ou criar arquivos no diretório. Se você tiver permissão de escrita no diretório, você será capaz de apagar qualquer arquivo dentro desse diretório, mesmo os que você não tiver permissão de leitura ou escrita. Para listar as permissões de um diretório sem listar o seu conteúdo é utilizado  o comando ls -ld:

SS-0101 - Resumo de Shell Script

1.4.2 Modificando permissões

Para modificar as permissões de um arquivo é utilizado o comando chmod. Apenas o usuário root pode alterar as permissões de qualquer arquivo ou diretório, os demais usuários só podem modificar as permissões dos arquivos que são donos.

Alterando as permissões utilizando o formato octal:

$ chmod 640 flag.txt

Alterando as permissões utilizando o formato por extenso:

$ chmod u=rw,g=r,o=--- flag.txt

Também é possível atribuir apenas uma permissão por vez utilizando o formato por extenso, por exemplo, para adicionar a permissão de escrita (w) para o grupo (g):

$ chmod g+w flag.txt

Para remover apenas a permissão de escrita para o grupo:

$ chmod u-x arquivo.txt

SS-0101 - Resumo de Shell Script

1.5 - Redirecionamentos

Segundo o manual do programador Linux, todo programa Unix em circunstâncias normais possuí três fluxos abertos para ele quando é inicializado, um para entrada padrão, um para saída padrão e outro para saída de erros.

SS-0101 - Resumo de Shell Script

Todas as operações de redirecionamento vão manipular esses descritores, por exemplo, quando a saída de um comando é redirecionada para um arquivo o apontamento de stdout é modificado, que era tela do computador, e apontando esse descritor para um arquivo.

1.5.1 - Redirecionamentos básicos

  • comando > arquivo: redireciona a saída padrão (stdout) para o arquivo arquivo. Esse redirecionamento apaga o conteúdo existente no arquivo, caso ele exista, se ele não existir um arquivo ele será criado;
  • comando >> arquivo: redireciona a saída padrão (stdout) para o final do arquivo. Se o arquivo existir, ele apenas adicionará o resultado do comando ao arquivo, caso o arquivo não exista, ele será criado;
  • comando 2> arquivo: redireciona a saída de erros (stderr) para o arquivo. Esse redirecionamento apaga o conteúdo existente no arquivo, caso ele exista, se ele não existir um arquivo será criado;
  • comando 2>> arquivo: redireciona a saída de erros (stderr) para o final do arquivo. Se o arquivo existir, ele apenas adicionará o resultado do comando ao arquivo, caso o arquivo não exista, ele será criado;
  • comando &> arquivo: redireciona o stdout e sterr para arquivo;
  • comando1 | comando2: conecta a saída padrão do comando1 a entrada padrão do comando2;
  • comando < arquivo: redireciona o conteúdo do arquivo para entrada padrão;
  • comando << FIM: conhecido como Here Documents, esse tipo de redirecionamento faz o shell receber dados do usuário até que a palavra FIM seja encontrada;
  • comando <<< STRING: redireciona a string STRING para a entrada padrão de um comando.

1.5.2 - Redirecionamentos avançados

  • comando &> arquivo: redireciona o stdout e sterr para arquivo;
  • i >& j: redireciona o descritor i para j. Todas as saídas do arquivo apontado para i são enviadas para o arquivo apontado por j;
  • >& j: redireciona a stdout para j. Todas as saídas para stdout irão para o arquivo apontado por j; e
  • j <> arquivo: abre o arquivo para leitura e gravação e associa a ele o descritor j.

1.5.3 - Executando vários comandos na mesma linha

No shell interativo o padrão é a execução de um comando por linha, mas fazendo o uso do ponto e vírgula é possível executar vários comandos na mesma linha:

$ ls;date; pwd; cd /tmp; pwd

SS-0101 - Resumo de Shell Script

1.6 - Operadores de encadeamento condicional && e ||

Existem alguns operadores especiais que são chamados de operadores de encadeamento condicional. Eles são utilizados com base no resultado da saída de um comando.

O operador "e comercial duplo" && é executado caso a execução do último comando seja concluída com sucesso:

$ comando1 && comando2

Já o operador "pipe duplo" || é executado quando o último comando executado retorne uma situação de erro, ou seja, o comando2 só vai ser executado se o comando1 não for executado com sucesso.

$ comando1 || comando2

1.7 - Expansão do Shell

Antes do shell executar uma linha de comando, ele divide essa linha em partes e realiza as substituições necessárias antes de executar o todo comando. Por exemplo, para atribuir um valor em uma variável ele executa uma estrutura de subshell, $((comando)), entre outros tipos de expansão. Somente após realizar todas as expansões o shell vai executar o comando.

1.7.1 Brace expansion

Por meio da brace expansion, pode-se gerar strings aleatórias. Os padrões que serão expandidos são inseridos entre colchetes ({}), podendo ter um PREÂMBULO (uma string fixa que precede os padrões entre os colchetes) e um POSTSCRIPT (uma string fixa ao final dos colchetes). Por exemplo, vamos gerar uma lista de senhas iniciadas pela string Brasil19 (preâmbulo), acompanhadas de todos os anos do século 20, seguidos pelo caractere * (postscript):

$ echo Brasil19{0..9}{0..9}\*

SS-0101 - Resumo de Shell Script

No exemplo acima, antes de executar o comando echo, o shell substitui os valores entre colchetes ({0..9}{0..9}). Nesse caso, esses valores representam o intervalo numérico de 0 a 9. Quando combinados os dois pares de colchetes, o shell faz uma combinação com  preâmbulo (Brasil19) + a combinação de todas as possibilidades de 00 a 99 + postscript (*).

Expandindo todos os números de 0 a 100:

$ echo {0..100}

Expandindo todos os números de cinco algarismos:

$ echo {0..9}{0..9}{0..9}{0..9}{0..9}

Expandindo uma lista de todas as palavras de cinco letras:

$ echo {a..z}{a..z}{a..z}{a..z}{a..z}

1.7.2 Substituição de comandos $(...) e ` `

Muitas vezes é preciso passar para uma linha comando informações que virão de resultados de outros comandos. Para essas situações, existe a substituição de comandos. Essa substituição é realizada durante a expansão do shell. Ex:

SS-0101 - Resumo de Shell Script

Quando utilizamos um comando dentro da estrutura $(...), o shell sabe que deve executar esse comando e substituí-lo pelo seu resultado antes de executar o comando principal, nesse caso o ls. O comando que vai ser substituído também pode ser colado entre crases (`...`), mas é prefirível a construção $(...) devido a sua melhor visualização em relação a crase, que pode ser confundida com aspas simples.

SS-0101 - Resumo de Shell Script

2 – Tratamento de conteúdo

O tratamento de conteúdo envolve a utilização de comandos com a capacidade de extrair de um conjunto de dados ou informação desejada de arquivos, páginas ou saídas de comandos.

2.1 - Expressões Regulares

Expressão regular é um método formal de se especificar um padrão de texto, sendo uma composição de símbolos, caracteres com funções especiais, que, agrupados entre si e com caracteres literais, formam uma sequência, uma expressão que é interpretada como uma regra, que indicará sucesso se uma entrada de dados qualquer coincidir com a regra.

2.1.1 - Meta caracteres

As expressões regulares são formadas por símbolos e caracteres literais. Esses símbolos são chamados de meta caracteres, pois possuem funções especiais.

  • . - ponto;
  • [] - lista;
  • [^...] - lista negada;
  • ? - opcional;
  • * - asterisco;
  • + - mais;
  • {} - chaves;
  • ^ - circunflexo;
  • $ - cifrão;
  • \b - borda;
  • \ - escape;
  • | - ou;
  • () - grupo;
  • \1 - retrovisor.

Além destes, existem outros meta caracteres estendidos que foram criados posteriormente, pois tarefas mais complexas requisitavam funções mais específicas ainda. Importante dizer que a sintaxe de utilização não é a mesma para todos os programas que suportam expressões regulares.

Os meta caracteres estão divididos em quatro grupos distintos, de acordo com características comuns entre eles.

2.1.1.1 - Representantes

Representam um ou mais caracteres.

SS-0101 - Resumo de Shell Script

2.1.1.2 - Quantificadores

Definem a quantidade de vezes que um caractere pode se repetir.

SS-0101 - Resumo de Shell Script

2.1.1.3 - Âncoras

Esses caracteres marcam uma posição específica na linha.

SS-0101 - Resumo de Shell Script

2.1.1.4 - Diversos

SS-0101 - Resumo de Shell Script

2.1.2 - Classes POSIX

Existem também as Classes POSIX, que são conjuntos predefinidos de caracteres válidos ou proibidos em dada posição do padrão.

SS-0101 - Resumo de Shell Script

2.1.3 - Diferenças de meta caracteres entre aplicações

SS-0101 - Resumo de Shell Script

2.2 - A família GREP

2.1 - Comando grep

O comando grep no Linux é muito usado no dia a dia, seja tarefas administrativas, de segurança ou ofensivas. O grep filtra as linhas de um determinado arquivo procurando por uma expressão regular como padrão. Pode ler um ou mais arquivos que são passados como argumento ou pode receber como entrada a saída de outro comando.

Se o grep receber mais de um arquivo ou um wildcard (curinga) como argumento para efetuar a sua busca, ele vai indicar o nome do arquivo seguido de dois pontos e a linha encontrada.

O grep utiliza o padrão de Expressões Regulares POSIX BRE (Basic Regular Expressions, do inglês, expressões regulares básicas). Sendo assim, os caracteres ? + { } | ( ) não tem significado especial. No padrão BRE, esses caracteres somente são interpretados com significado especial se precedidos com a contra barra: \? \+ \{ \} \| \( \).

As principais opções do comando grep são:

  • -c: mostra somente a contagem das ocorrências nos arquivos e não as linhas onde as ocorrências foram encontradas;
  • -h: mostra somente as linhas encontradas, sem a indicação do nome dos arquivos;
  • -i: procura as ocorrências ignorando se as letras estão em maiúsculas ou minúsculas;
  • -v: mostra todas as linhas do arquivo procurado menos as ocorrências encontradas. Tem o efeito inverso;
  • -n: mostra, além do texto das linhas encontradas, o número das linhas dentro dos arquivos;
  • -B n: mostra n linhas antes da linha encontrada;
  • -A n: mostra n linhas depois da linha encontrada;
  • -E: muda o padrão POSIX BRE para POSIX ERE; e
  • -F: não interpreta nenhum meta-caractere.

Exemplos:

  • Procurar a palavra brito no arquivo /etc/passwd:
grep brito /etc/passwd

SS-0101 - Resumo de Shell Script

  • Procurar todas as linhas começadas com a letra u no arquivo /etc/passwd. O acento circunflexo (^) simboliza o início de uma linha:
grep "^u" /etc/passwd

SS-0101 - Resumo de Shell Script

  • Procurar todas as linhas terminadas com a palavra false no arquivo /etc/passwd. O símbolo cifrão ($) representa o fim de uma linha:
grep "false$" /etc/passwd

SS-0101 - Resumo de Shell Script

  • Procurar todas as linhas que iniciam com vogais no arquivo /etc/passwd. A expressão regular chamada lista procura qualquer um dos caracteres dentro do colchete:
grep "^[aeiou]" /etc/passwd

SS-0101 - Resumo de Shell Script

  • Procurar por todas as linhas em que o primeiro caracter seja qualquer um e o segundo caracter seja uma vogal. O ponto na expressão regular simboliza um caractere qualquer:
grep "^.[aeiou]" /etc/passwd

SS-0101 - Resumo de Shell Script

  • Procurar por linhas que contenham uma sequência de pelo menos quatro números consecutivos:
grep "[0-9][0-9][0-9][0-9]" /etc/passwd

SS-0101 - Resumo de Shell Script

  • Procurar em todos os arquivos do diretório atual a ocorrência da palavra brito.

grep brito *

SS-0101 - Resumo de Shell Script

  • Para procurar uma ocorrência em todos os subdiretórios, utiliza-se a opção de recursividade -r:
grep -r brito *

SS-0101 - Resumo de Shell Script

  • Para listar somente as linhas com endereços de e-mail válidos:
grep -Eiorha '([[:alnum:]_.-]+@[[:alnum:]_.-]+?\.[[:alpha:].]{2,6})' "$@" * 2> /dev/null

SS-0101 - Resumo de Shell Script

  • Para listar todos os endereços IPs únicos que acessaram um servidor web:
grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" /var/log/apache2 -r | sort | uniq 

SS-0101 - Resumo de Shell Script

  • É possível também usar expressões com OU para fazer buscas de mais de um termo:
grep -E 'brito|programador' flag.txt

SS-0101 - Resumo de Shell Script

  • O comando grep faz distinção de maiúsculas e minúsculas. Para fazer uma busca independente se o texto está em caixa alta ou baixa, pode-se usar a opção -i (buscas com a opção -i demoram mais tempo):
grep -i ProGramadOr flag.txt

SS-0101 - Resumo de Shell Script

  •  É possível usar as chaves para especificar ocorrências de algum caracter da busca em maiúsculo ou minúsculo:
grep -i [Pp]rogramador flag.txt

SS-0101 - Resumo de Shell Script

  • Para mostrar a linha de uma determinada ocorrência:
grep -n brito flag.txt

SS-0101 - Resumo de Shell Script

  • Para mostrar uma linha antes e depois do termo, pode-se usar a opção -C n, onde n é o número de linhas:
grep -C 1 programador flag.txt

SS-0101 - Resumo de Shell Script

2.2.2 - Comando egrep

O comando egrep funciona como a opção -E do grep. Ele utiliza o padrão POSIX de Expressões Regulares ERE (Extended Regular Expression, do inglês, expressões regulares estendidas) na busca. Isto significa que a contra barra deve ser usada para definir que o próximo caractere é um caractere literal e não um meta caractere como no padrão POSIX BRE.
Isto significa que os caracteres ? + { } | ( ) não precisam da contra barra para funcionar como meta-caracteres.

É importante a diferença do uso das contra barras entre o grep (que necessita delas para indicar meta caracteres) e o egrep (cujo efeito das contra barras é inverso, indicando um caractere
comum).

2.2.3 - Comando fgrep

O comando fgrep também é parecido com o grep, mas ele não suporta expressões regulares, procurando somente uma chave de busca ou um texto comum nos arquivos. Por este motivo, é mais rápido que o grep porém, menos versátil. Ele equivale à opção -F do grep.

3 - CUT

O comando cut é um utilitário de linha de comando que permite cortar seções de um arquivo específico ou de uma saída de um comando e imprimir o resultado na saída padrão. O comando corta partes de uma linha por campo, delimitador, posição de byte e caractere.

  • -f (--fields=LIST): seleciona usando um campo especificado, um conjunto de campos ou um intervalo de campos;
  • -b (--bytes=LIST): seleciona usando um byte especificado, um conjunto de bytes ou um intervalo de bytes;
  • -c (--characters=LIST): seleciona usando um caractere especificado, um conjunto de caracteres ou um intervalo de caracteres;
  • -d (--delimiter): usado para especificar um delimitador a ser usado em vez do delimitador padrão (TAB);
  • --complement: quando especificada, esta opção instrui o cut a exibir todos os bytes, caracteres ou campos, exceto o selecionado;
  • -s (--only-delimited): a configuração padrão é imprimir as linhas que não contêm caracteres delimitadores. A opção -s instrui cut a não imprimir as linhas que não contêm
    delimitadores;
  • --output-delimiter: por padrão, cut usa o delimitador de entrada como delimitador de saída. Especificar a opção --output-delimiter permite especificar um delimitador de saída diferente.

Podemos determinar um delimitador de campos (neste caso pelo caractere “:”) e que sejam impressos apenas os campos de número 1 e 7, com o comando abaixo:

cut -d: -f1,7 /etc/passwd

SS-0101 - Resumo de Shell Script

A opção -c, podemos listar caracteres específicos, como no exemplo do comando abaixo:

cat /etc/passwd | cut -c 1-5

SS-0101 - Resumo de Shell Script

Repare que, nesse caso, não houve limitação por colunas, sendo pego caracteres de 1 a 5 de cada linha.

A opção --complement, exibe todos os dados, exceto os dados explicitados por outras opções (-f, -b e -c), invertendo, na prática, o resultado exibido na saída padrão:

cat /etc/passwd | cut -d: -f2-6 --complement

SS-0101 - Resumo de Shell Script

2.4 - SED – Stream EDitor

O Stream EDitor (SED) pode ser utilizado para filtrar ou fazer transformações básicas no texto lido de um arquivo ou pipe. O resultado é enviado para a saída padrão (stdout). A sintaxe do comando sed não possui especificação de um arquivo de saída, mas os resultados podem ser salvos utilizando redirecionamento (> ou >>).

O sed não altera a entrada original, a menos que seja explicitado essa opção (-i). O que distingue o sed de outros editores, como vi e nano, é sua capacidade de filtrar texto obtido de um
feed de pipeline. Não há a necessiade de interagir com o editor enquanto estiver em execução. É por isso que sed é, às vezes, chamado de editor em lote. Esse recurso permite o uso de comandos de edição em scripts, facilitando muito as tarefas de edição repetitiva. Ao enfrentar a substituição de texto em um grande número de arquivos, sed é uma grande ajuda. Dentre muitas possibilidades, cabe destacar que o sed pode ser usado para:

  • Buscar por um padrão de texto e substituí-lo (localizar e substituir);
  • Buscar por um padrão de texto e apagá-lo;
  • Filtrar textos entre intervalos de palavras. Ex: INICIO – Texto....... - FIM;
  • Filtrar linhas de um texto. Ex: Mostrar apenas a linha 5000 de um arquivo de texto; e
  • Buscar por um padrão e inserir linhas após esse.

Normalmente o sed é invocado com a seguinte sintaxe: sed OPÇÕES... [SCRIPT] [INPUTFILE...].

  • -b, --binary: abre os arquivos de entrada no modo binário;
  • --debug: muda para o modo de depuração;
  • --follow-symlinks: edita o destino final se o arquivo especificado for um link simbólico. Funciona apenas quando combinado com a opção -i;
  • --help: exibe as informações de uso;
  • --i, --in-place [=SUFFIX]: realiza edições substituindo o arquivo original;
  • --version: exibe a versão do sed em execução no sistema;
  • -E, -r, --regexp-extended: usa expressões regulares estendidas;
  • -e script, --expression=script: adiciona um script especificado para executar com os comandos;
  • -f script-file: adiciona o conteúdo de um arquivo de script especificado para executar com os comandos;
  • -l N, --line-length=N: define o comprimento de quebra de linha desejado para o comando l (o valor padrão é 70);
  • -n, --quiet, --silent: desativa a impressão de saída;
  • -s, --separate: visualiza os arquivos especificados como separados, não como um único fluxo longo e contínuo;
  • --sandbox: desativa a execução de programas externos e opera apenas em arquivos de entrada na linha de comando;
  • -u, --unbuffered: diminui o buffer de entrada e saída;
  • -z, --null-data, --zero-terminated: visualiza a entrada como um conjunto de linhas onde cada uma termina com um byte zero.

2.4.1 - Localizar e substituir

Sintaxe do sed para localizar e substituir:sed 's/PADRAO1/PADRAO2/g' arquivo.

Por exemplo, vamos substituir todas as ocorrências de "o" para "0":

sed 's/o/0/g' flag.txt

SS-0101 - Resumo de Shell Script

2.4.2 - Trabalhando com linhas específicas

Para imprimir uma linha, a sintaxe é sed -n ‘NUMEROp’ arquivo, onde o número corresponde ao número da linha. Imprimindo a linha 10 do arquivo:

$ sed -n '2p' flag.txt

Para imprimir um intervalo de linhas, a sintaxe é sed -n 'NUMERO,NUMEROp' arquivo. Imprimindo a linha de 1 a 5:

$ sed -n '1,5p' flag.txt

Para imprimir a última linha de um texto, a sintaxe é sed -n '$p' arquivo. Imprimindo a última linha:

$ sed -n '$p' flag.txt

Para apagar uma linha específica, a sintaxe é sed 'NUMEROd' arquivo, onde o número corresponde ao número da linha que será apagada. Apagando a linha 1:

$ sed '1d' flag.txt

2.4.3 - Filtrando o intervalo de textos

Para filtrar as linhas no intervalo das palavras Cybersecurity e extorting:

$ sed -n '/Cybersecurity/,/extorting/p' arquivo.txt 

2.4.4 - Outros exemplos úteis

Apagando o primeiro caractere de qualquer linha:

$ sed -n 's/^.//' arquivo.txt

Apagando o último caractere de qualquer linha:

$ sed -n 's/.$//' arquivo.txt

Apagando qualquer ocorrência de um caractere na linha:

$ sed 's/\"//g' arquivo.txt

2.5 - AWK

O awk, assim como o sed, é uma ferramenta para manipulação de texto. No entanto, ele também é considerado uma linguagem de programação. Com ele é possível pesquisar palavras num arquivo, identificar padrões e realizar substituições, entre outras funcionalidades. Além disso, o awk suporta expressões regulares, o que permite realizar matches de padrões complexos.

Será utilizada a saída do comando ps u (que lista os usuários e detalhes de sua utilização) para a realização dos exemplos a partir de agora:

SS-0101 - Resumo de Shell Script

2.5.1 - Utilizações básicas

2.5.1.1 - Exibir colunas determinadas

Para selecionar apenas a primeira coluna, utiliza-se o comando abaixo:

ps u | awk '{print $1}'

SS-0101 - Resumo de Shell Script

Para selecionar múltiplas colunas:

ps u | awk '{print $1,$2,$3}'

SS-0101 - Resumo de Shell Script

Utilizando \t é possível separar as colunas com Tab:

ps u | awk '{print $1 "\t" $2 "\t" $3}'

SS-0101 - Resumo de Shell Script

Para remover a primeira linha de um arquivo, basta utilizar o comando abaixo:

ps u | awk 'NR!=1'

Para substituir um texto, podemos utilizar a função sub(), conforme o exemplo abaixo, que substitui a string debian por outro-usuario:

ps u | awk 'sub(/brito/, "xxx")'

SS-0101 - Resumo de Shell Script

OBS: A função sub() substitui apenas a primeira ocorrência, uma vez por linha. Para substituir mais de uma ocorrência, utiliza-se a função gsub().

5.1.2 - Utilizando um outro delimitador

Por padrão, o delimitador do awk é o espaço ou TAB. No entanto, para utilizar um outro delimitador, pode-se utilizar a opção -F seguida do delimitador:

echo 'brito/2023/Brasil' | awk -F '/' '{print $3}'

SS-0101 - Resumo de Shell Script

2.5.2 - Utilizando REGEX

2.5.2.1 - Exemplos com REGEX

Para selecionar a linha inteira, caso a segunda coluna se inicie com o número 1:

ps u | awk '$2 ~ /^1/ {print $1,$2}'

SS-0101 - Resumo de Shell Script

Para selecionar todas as linhas cuja coluna 2 não comecem com o número 1:

ps u | awk '$2 !~ /^1/ {print $1,$2}'

2.5.2.3 - Selecionar linhas entre dois padrões

Para imprimir todas as linhas entre brit0 e segurança:

awk '/brit0/{flag=1;next}/segurança/{flag=0}flag' flag.txt

SS-0101 - Resumo de Shell Script

Caso queira que brit0 e segurança também sejam impressos:

awk '/brit0/{a=1}/segurança/{print;a=0}a' flag.txt

SS-0101 - Resumo de Shell Script

3 - Shell Scritpt

Shell script é uma sequência de comandos armazenados em um arquivo. Todo script em shell deve começar com o shebang, escrito na primeira linha do script, que define qual será o programa utilizado para interpretar o conteúdo do arquivo. Quando executado pelo bash deverá ser #!/bin/bash. Para executar script é necessário que o mesmo tenha permissão de execução.

SS-0101 - Resumo de Shell Script

SS-0101 - Resumo de Shell Script


3.1 - Parâmetros especiais

Sãp parâmetros podem ser apenas referenciados, não sendo possível atribuir valores diretamente para esses parâmetros:

  • $0: nome do comando ou programa;
  • $1: primeiro parâmetro recebido na linha de comando;
  • $2: segundo parâmetro recebido na linha de comando;
  • $3: terceiro parâmetro recebido na linha de comando;
  • ${10}: décimo parâmetro recebido na linha de comando;
  • $#: mostra a quantidade de parâmetros recebida pelo programa;
  • $*: expande o conjunto de todos os parâmetros recebidos. (OBSOLETO);
  • $@: expande o conjunto de todos os parâmetros recebidos pelo programa; e
  • $?: expande o status de saída do último comando ou função executado.

3.2 - Recebendo parâmetros do usuário

Um script pode receber parâmetros passados pela linha de comando ou interagir com o usuário por meio de perguntas.

3.2.1 - Parâmetros posicionais

Parâmetros posicionais são os parâmetros passados como argumento de um script no momento de sua execução: programa.sh parm1 parm2 parm3 parm4 parm5 ... parmn. Os parâmetros passados parm1, parm2, parm3, ..., parmn são recebidos pelo programa.sh e dão origem dentro do programa as variáveis $1, $2, $3.....$n.

3.3 - Perguntando ao usuário

É possível interagir com o usuário para receber dados. Isso é feito utilizando o conjunto echo/read. O comando echo vai imprimir na tela a pergunta e o comando read vai receber dados do usuário e armazenar numa variável.

SS-0101 - Resumo de Shell Script

SS-0101 - Resumo de Shell Script

3.4 - Estrutura de controle de fluxo IF

A estrutura de decisão if nos permite tomar rumos diferentes dependendo do resultado de um teste ou comando.

3.4.1 - Sintaxe

Sua sintaxe pode variar conforme a necessidade, porém a sintaxe completa é a seguinte if, then, elif e else, terminado com fi (if ao contrário):

Algumas considerações importantes:

  • As palavras reservadas if e elif avaliam o estado de saída de comandos;
  • Todo if e elif deve ser seguidos de um bloco iniciado pela palavra reservada then;
  • Podemos utilizar tantos blocos elif/then quanto forem necessários;
  • Apenas o bloco if/then é obrigatório na estrutura; e
  • Só pode haver um bloco else e ele é opcional.

O comando if do shell não testa o resultado de uma expressão, mas sim o estado de saída de um comando (variável especial $?). Na estrutura acima, caso o estado de retorno do comando seja 0 (verdadeiro), ele executará o Bloco de Código IF, caso retorne um valor diferente de 0 (falso), ele irá direto para o fi, ignorando o Bloco de Código IF:

SS-0101 - Resumo de Shell Script

O elif permite aninhar vários if no mesmo bloco de teste. Ou seja, caso o primeiro if retorne falso, é possível testar novamente utilizando o elif, caso não dê certo é possível testar novamente com outro elif e assim sucessivamente. Se o estado do retorno de todos
os testes for falso, ele executará o Bloco de Código ELSE.

3.4.2 - Testes no shell

O comando test pode checar atributos de arquivos e comparar valores. Se a expressão ou comparação for verdadeira, o comando test retornará 0 para variável de retorno ($?), caso contrário, retornará 1 para variável de retorno.

SS-0101 - Resumo de Shell Script

Na figura acima verificamos com o comando test se o teste.sh existe (flag -f), como existe, a saída é zero; no segundo teste realizado em um arquivo inexistente o retorno é um.

3.4.2.1 - Tabela de operadores de arquivos

  • [ -a ARQUIVO ] Verdadeiro se ARQUIVO existe;
  • [ -b ARQUIVO ] Verdadeiro se ARQUIVO é um arquivo de bloco;
  • [ -c ARQUIVO ] Verdadeiro se ARQUIVO é um arquivo de caractere;
  • [ -d ARQUIVO ] Verdadeiro se ARQUIVO é um diretório;
  • [ -e ARQUIVO ] Verdadeiro se ARQUIVO existe;
  • [ -f ARQUIVO ] Verdadeiro se ARQUIVO existe e é um arquivo regular;
  • [ -g ARQUIVO ] Verdadeiro se o bit SGID está ativado;
  • [ -h ARQUIVO ] Verdadeiro se ARQUIVO é um link simbólico;
  • [ -L ARQUIVO ] Verdadeiro se ARQUIVO é um link simbólico. Mesmo que -h;
  • [ -G ARQUIVO ] Verdadeiro se ARQUIVO existe e é de propriedade do ID do grupo;
  • [ -O ARQUIVO ] Verdadeiro se ARQUIVO existe e é de propriedade do ID do usuário;
  • [ -w ARQUIVO ] Verdadeiro se ARQUIVO existe e permissão de escrita é garantida;
  • [ -x ARQUIVO ] Verdadeiro se ARQUIVO existe e tiver permissão de execução garantida; e
  • [ -u ARQUIVO ] Verdadeiro se ARQUIVO existe e tem o set-user-ID setado.

SS-0101 - Resumo de Shell Script

3.4.2.2 - Tabela de operadores de string

  • [ -z STRING ] Verdadeiro se a string é vazia;
  • [ -n STRING ] Verdadeiro se a string não é vazia;
  • [ STRING1 = STRING2 ] Verdadeiro se as strings forem iguais;
  • [ STRING1 != STRING2 ] Verdadeiro se as strings não forem iguais;
  • [ STRING1 < STRING2 ] Verdadeiro se STRING1 for ordenada primeiro em ordem alfabética que STRING2; e
  • [ STRING1 < STRING2 ] Verdadeiro se STRING1 for ordenada depois que STRING2.

3.4.2.3 - Operadores aritméticos

  • [ arg1 -eq arg2 ] Verdadeiro se arg1 for igual a arg2;
  • [ arg1 -ne arg2 ] Verdadeiro se arg1 for diferente de arg2;
  • [ arg1 -lt arg2 ] Verdadeiro se arg1 for menor que arg2;
  • [ arg1 -le arg2 ] Verdadeiro se arg1 for menor ou igual a arg2;
  • [ arg1 -gt arg2 ] Verdadeiro se arg1 for maior que a arg2; e
  • [ arg1 -ge arg2 ] Verdadeiro se arg1 for maior ou igua a arg2.

3.5 - Estrutura de controle de fluxo CASE

O case é uma estrutura alternativa ao if/elif, podemos dizer que é uma maneira de simplificar uma construção com vários if/elif. Se a expressão ou variável testada estiver em algum caso listado na construção do case, o bloco de código referentes a esse caso é executado.

SS-0101 - Resumo de Shell Script

SS-0101 - Resumo de Shell Script

3.6 Aritmética básica com SHELL

3.6.1 - Expansão $((...))

O Bash tem a funcionalidade de expansão aritmética. Essa funcionalidade ocorre na mesma etapa das expansões de parâmetros e substituições de comandos e implementa, entre outras operações, as quatro operações básicas da matemática, além do módulo e exponenciação.

A estrutura básica para utilizar a expansão aritmética é $((NUM1 OP NUM2)), onde NUM1 e NUM2 são os operandos e OP é o sinal que representa a operação matemática. É importante frisar alguns pontos:

  • Essa expansão trabalha apenas com dados numéricos inteiros;
  • Nomes de variáveis não precedidos por $ expressam o valor de seus dados;
  • Strings expandidas a partir de parâmetros e variáveis são tratadas como nomes de variáveis;
  • Se uma string não corresponder a uma variável definida ou se o dado associado não for um número inteiro, sua avaliação será zero (0); e
  • Variáveis ou dados literais que resultem em números com ponto flutuante causarão erros.

SS-0101 - Resumo de Shell Script

3.6.2 - Comando LET

O comando let é um comando interno usado para avaliar expressões aritméticas. Ao contrário de outros comandos de avaliação e expansão aritmética, let é um comando simples com seu próprio ambiente. Sua sintaxe é: let [expression]. Ele é capaz de avaliar expressões que contêm os operadores aritméticos citados anteriormente, além de outras comparações.

SS-0101 - Resumo de Shell Script

3.7 - Estruturas de repetição

Todo programa tem uma entrada de dados, um processamento e uma saída. Esse processamento é quase sempre feito em ciclos que normalmente chamamos de loop.

As estruturas de laço permitem que uma ação seja repetida enquanto uma determinada condição for verdadeira, ou repetir uma ação para um conjunto de itens. Para implementar repetições
no shell, utilizaremos as estruturas FOR, WHILE ou UNTIL.

3.7.1 - Laço FOR

O comando for é muito útil quanto temos um conjunto de itens e precisamos que, para cada item do conjunto, seja executado um grupo de comandos. A sintaxe do for é: for var [in lista ]; do comandos; done, onde "var" pode ser qualquer nome de variável, o mais comum é utilizar i, "lista" pode ser uma lista de palavras, números ou strings e "comandos" serão executados a cada iteração, podendo ser qualquer instrução de shell script.

3.7.1.1 - Exemplo 1: laço com uma lista de palavras

No exemplo abaixo, temos um conjunto de seis palavras {Alice, Bob, Charlie} que serão iterados pelo laço for, para cada item do conjunto o for executará o bloco de código entre o do e done. Ou seja, a cada iteração a variável palavra receberá o valor de um item do conjunto e o bloco de código do laço será executado, nesse caso o será executado o comando echo:

SS-0101 - Resumo de Shell Script

3.7.1.2 Exemplo 2: laço com o conteúdo de um arquivo

No exemplo abaixo, vamos pegar o conteúdo do arquivo hosts.txt que contém alguns IPs e vamos executar um ping para cada IP e verificar se o host está UP ou DOWN:

SS-0101 - Resumo de Shell Script

3.7.1.3 - Exemplo 3: laço com o conteúdo de uma variável

Dependendo do caso, pode ser necessário salvar o conteúdo do arquivo que será iterado em uma variável. Nesses casos, pode-se passar a variável como lista no for:

SS-0101 - Resumo de Shell Script

A variável passada para o laço deve estar sem aspas. Caso sejam colocadas aspas, a variável será interpretada como um único elemento.

3.7.1.4 - Exemplo 4:laço no estilo C

O shell também aceita a utilização do for de maneira crescente ou decrescente implementando um contador assim como é feito na linguagem C. Ex:

SS-0101 - Resumo de Shell Script

No laço for ((i=1;i<10;i++)), a variável i será igual a 1 na primeira iteração do laço. A condição para que o laço continue executando, é que i seja menor que 10 e após cada iteração, i será incrementado, ou seja, será adicionado 1 ao valor de i a cada iteração, então, o for percorrerá todos os números de 1 a 9 e, a cada vez, executará os comandos definidos no bloco do/done.

3.7.2 - Laço WHILE

A estrutura while permite a execução repetitiva de uma lista de comandos, enquanto o comando de controle for executado com sucesso. A sintaxe do while é: while condicao_verdadeira; do comandos; done.

3.7.2.1 - Exemplo 1: while incremental

No exemplo abaixo, o while vai executar os comandos entre do/done enquanto a variável "i" for menor que cinco e a cada iteração,esta variável que tem valor inicial um será incrementada em uma unidade:

SS-0101 - Resumo de Shell Script

3.7.2.2 - Exemplo 2: while read

O comando read executa a leitura de um arquivo linha a linha. Cada vez que o read lê uma linha do arquivo, ele termina com estado de sucesso e o while permite a execução do bloco de código. ao mesmo tempo, o ponteiro interno do arquivo muda para a linha seguinte, e esta será a linha lida quando o read for novamente invocado. Os ciclos continuam até que o read encontre o fim do arquivo e termine com erro:

SS-0101 - Resumo de Shell Script

3.7.2.3 - While infinito

O comando interno true não faz nada e termina sempre com sucesso, o que faz com que o while sempre permita uma nova repetição do bloco de código. Nesta situação, ou terminamos o loop manualmente, com o atalho Ctrl+C, ou escrevemos alguma estrutura de controle no bloco de código para interromper o loop
(comando break) condicionalmente. O comando true também pode ser substituído por dois pontos (:).

3.7.3 - Laço UNTIL

O comando until tem o mesmo comportamento do loop while, exceto pelo fato de só permitir a execução do bloco de código se o comando testado terminar com erro. Ex:

SS-0101 - Resumo de Shell Script

3.8 - Comando BREAK e CONTINUE

Além dos controles das próprias estruturas de repetição, o Bash possui comandos internos para controlar loops:

  • break: interrompe a execução do bloco de comandos e sai do loop; e
  • continue: interrompe a execução do bloco de comandos e segue para o próximo loop.

4.1 - Funções

No shell, funções são implementadas na forma de comandos compostos identificados por um nome seguido por abertura e fechamento de parênteses. Alternativamente, pode ser utilizada a palavra reservada function e neste caso, os parênteses são dispensáveis. Alguns pontos importantes:

  • Funções devem ser definidas antes do ponto onde são chamadas;
  • Funções podem chamar outras funções definidas antes ou depois de suas próprias definições; e
  • Funções podem ter definições de outras funções nos seus corpos.

4.1.1 - Criando funções com agrupamentos

É possível transformar qualquer comando composto em uma função, mas o agrupamento com chaves é a opção mais comum.

Muitos dos conceitos difundidos sobre funções no shell são apenas consequências do uso do agrupamento com chaves, como:

  • Variáveis de escopo global;
  • Execução na mesma sessão do shell.

Contudo, uma função criada com um agrupamento com parênteses é perfeitamente válida, mas é preciso lidar com comportamentos diferentes:

  • Variáveis de escopo restrito à função;
  • Execução em um subshell.


4.1.2 - Nomeando funções

As regras para o nomear funções são muito mais flexíveis do que as que limitam os nomes de variáveis. Em geral, qualquer conjunto de caracteres é válido, porém, é sempre uma boa ideia adotar alguns critérios, como:

  • Utilizar apenas caracteres não acentuados minúsculos;
  • Separar nomes compostos com o sublinhado;
  • Escolher nomes significativos; e
  • Utilizar o sublinhado como primeiro caractere do nome quando o nome coincidir com algum comando existente.

4.1.3 Passagem de argumentos para funções

O shell substitui temporariamente o conteúdo dos parâmetros posicionais da sessão pelos valores dos argumentos passados na chamada de uma função, de modo que, no interior da função, podemos utilizar qualquer uma de suas expansões. Quando a execução da função termina, os parâmetros posicionais da sessão são restaurados.

SS-0101 - Resumo de Shell Script

No exemplo acima, foi definido o parâmetro posicional $1 como "host" dentro do laço until. Dentro da função, esse parâmetro posicional assume o valor repassado na chamada da função, porém ao ser encerrada essa função, os parâmetros voltam a assumir o valore origiinal,que foi o IP passado após a execução do script (192.168.0.2).

SS-0101 - Resumo de Shell Script

Este é o ponto mais importante, porque, como todas variáveis têm escopo global numa mesma sessão do shell, o esperado seria que os parâmetros posicionais expandissem o mesmo valor da sessão mãe, mas este é um comportamento exclusivo de funções.

Os parâmetros especiais *, @ e # também passam a fazer referência aos parâmetros posicionais passados para a função, mas o parâmetro especial script $0 continua contendo o nome do shell ou do script.

4.1.4 - Escopo de variáveis em funções

Além do caso especial dos parâmetros posicionais, o escopo das variáveis dependerá da estrutura utilizada na formação da função. Ou seja, se o comando composto não abrir um subshell (como um agrupamento com parênteses, por exemplo), nós podemos generalizar e dizer que a função tem acesso a todos os parâmetros da sessão do shell e a sessão enxerga todas as variáveis na função. Eventualmente, pode não ser interessante criar situações em que uma variável na função possa ser acessada fora dela. Nesses casos, pode-se contar com o comando interno local, que torna restrito ao contexto da função os escopos das variáveis que forem definidas com ela com o uso da palavra-chave local para o parâmetro dentro da função:

SS-0101 - Resumo de Shell Script

4.1.5 Retorno de funções no shell

No shell, não existe o conceito de funções retornando dados processados, limitando-se à ideia de devolver o controle da execução para o fluxo principal do programa entregando um
estado de saída.

4.1.6 - O comando interno 'return'

O comando interno return equivale ao exit, só que para funções. Quando utilizado, seu papel é interromper a função e devolver o controle de execução para o comando seguinte no script. Opcionalmente, podemos passar um valor inteiro entre 0 e 255 como argumento para especificar o estado de saída da função. Se não for passado nenhum valor, a função sairá com o mesmo estado de saída do último comando executado.

4.1.7 Variáveis, apelidos e funções

Na customização da linha de comandos, é muito comum nós criarmos apelidos para abreviar a digitação ou padronizar as opções de um comando. Isso pode ser feito tanto com o comando alias quanto com variáveis:

SS-0101 - Resumo de Shell Script

SS-0101 - Resumo de Shell Script

Tanto apelidos quanto a variáveis expandem para a string do comando, mas ambos os métodos carecem de uma coisa que pode ser bem mais útil numa linha de comandos: a capacidade de receber e processar argumentos de fato. Isso só é possível com scripts ou funções.

Às vezes, não vale a pena passar por todo o processo de criação de scripts e gerenciamento de arquivos para fazer essas pequenas customizações. Nesses casos, pode ser mais interessante criar funções. Se for necessário, por exemplo, um comando para calcular o quadrado de um inteiro qualquer, basta criar uma função chamada quadrado e salvá-la no final de um arquivo de início, como o arquivo ~/.bashrc, assim, a função estará sempre disponível.

Este website utiliza cookies próprios e de terceiros a fim de personalizar o conteúdo, melhorar a experiência do usuário, fornecer funções de mídias sociais e analisar o tráfego. Para continuar navegando você deve concordar com nossa Política de Privacidade

Sim, eu aceito. Não, eu não aceito.