Zoom de uma tela exibindo a saída do comando top do Unix em um terminal com fundo preto

Coisas que você talvez não saiba sobre Linux, Unix e OS X

Já faz bastante tempo que trabalho com Linux e outros unices ao lado de gente muito foda. Ao longo desse período fui aprendendo algumas dicas e macetes que, quando uso na frente de alguns amigos, deixam eles espantados.

São coisas simples que talvez vocês já conheçam, mas que vou colocar aqui como referência para as “futuras gerações” 😀

Matando um processo que não quer ser interrompido

Você executa um comando na linha de comando e ele fica travado. Você dá ^C (CTRL-C) e ele não morre? Tente ^\ (CTRL-\).

Complementação enviada pelo meu amigo Rudá Moura: ^C envia um SIGINT, ^\ envia um SIGQUIT, o kill (sem argumentos) envia um SIGTERM e o kill -9 (que deve ser usado somente se você já tentou o SIGTERM) envia um SIGKILL que é o único sinal não interceptável pelo processo.

Sessão SSH travou? Chame o ~

Você deu ssh para um servidor e por algum motivo a sessão ficou pendurada?

Tecla “<ENTER>~.” e a sessão será encerrada imediatamente. Lembre-se que se você usa um teclado com acentuação dead-keys você precisará digitar “<ENTER>~<SPACE>.“.

Esse é o comando-til mais legal mas existem outros:

$ man ssh  # procure por "ESCAPE CHARACTERS"

Arquivos com - no início do nome?

Uma brincadeirinha que a gente fazia com a molecada que chegava pra trabalhar era criar um arquivo chamado “-rf ~” em algum lugar na máquina do cara e desafiar: “apague esse arquivo na linha de comando”.

Tem algumas respostas certas para esse desafio, mas rm -rf ~ (CUIDADO COM ISSO!) certamente não é uma delas 😀 Tentar fazer escape do “-” ou fazer rm "-rf ~" também não vai funcionar. Os comandos vão interpretar esse sinal como uma opção do próprio comando e não como um argumento do tipo nome de arquivo.

Solução?

rm -- "-rf ~"

Quando colocamos o -- informamos pro comando que todos os parâmetros passados a partir daquele ponto são argumentos para o comando e não opções do comando.

O meu amigo Elvis (EPx) e o Fedalto conhecem outra forma que também permite remover esse diretório:

$ rm -rf ./-rf\ ~

Debugando problemas em software alheio

Você tem um software que simplesmente não está funcionando direito e não dá nenhuma mensagem que te ajude a resolver o problema? Esse software não é seu; foi feito em C; você só tem o binário; etc?

Na minha experiência de vida quase sempre esses problemas acontecem por causas “bobas” como um arquivo de configuração que não está no lugar certo ou está com as permissões incorretas, um processo tentando alocar um recurso que já está sendo usado por outro, etc. Mas como saber disso se a única coisa que aparece pra mim é um enigmático “Segmentation Fault”?

# strace [-p PID|software] [-f]

O strace mostra todas as syscalls que um processo está executando no console. Como é muita informação é sempre legal redirecionar essa saída para um arquivo e analisar depois.

Quando o software caiu você abre o arquivo de log e procura (de trás para frente) por mensagens de erro logo antes do programa morrer. Já resolvi dezenas de problemas assim.

Vale lembrar que essa ferramenta deve ser encarada como um tipo de “último recurso” quando outras técnicas de resolução de problemas já não estiverem funcionando mais.

No OSX o utilitário que imita o strace se chama dtruss e o jeito de usar é bem similar.

Pausando o console

Você executou um tail -f arquivo.log mas os logs chegam numa velocidade que te impedem de analisar as mensagens?

Faça um Pause no terminal: ^S (CTRL-S). Para liberar o Pause: ^Q (CTRL-Q).

Alternando entre jobs

Executou um comando e deu ^Z. Executou outro comando e deu ^Z novamente. Ficou com dois jobs parados, certo? (execute o comando jobs para ver os dois processos parados).

Para trazer um deles devolta para o primeiro plano use o comando:

$ %N  # onde N é o número do job

O Aristeu pediu pra lembrar que esse comando é uma espécie de atalho para o comando fg:

$ fg N

E que, fazendo par com o fg tem o comando bg N que “despausa” o processo e coloca ele pra funcionar em segundo plano.

Se você quer executar um processo direto em segundo plano é só colocar um & no fim da linha:

$ find / > lista_de_arquivos.txt &

É o mesmo que fazer ^Z e bg.

Reexecute comandos

Você digitou um comando grande e chato na linha de comando, precisa reexecutar ele mas ele tá lááá atrás no histórico? Não precisa ficar com a setinha pra cima até cansar. É só usar a !:

$ find . -type f | while read i; do mv "$i" "$i.bak"; done  # ok, eu sei que dá pra melhorar isso mas queria uma linha grande, ok? :D
$ ...
$ ...
$ ...
$ # vamos reexecutar o find|while
$ !fin

Buscando no histórico de comandos

O Thiago Santos, o Aristeu e o toti pediram pra eu acrescentar a busca no histórico. Eu acho que muita gente já sabia desta dica e por isso não coloquei na primeira versão desse artigo. Mas… como tem gente que talvez não conheça aí vai.

Eu uso o modo VI no console (próximo tópico) e para fazer buscas no histórico de comandos eu uso os comandos de busca do próprio vi: <ESC>/string_de_busca. Para repetir a busca basta ir acionando a tecla N.

Por padrão a maioria das distribuições Linux (e alguns Unix) usam o modo emacs e para fazer a mesma busca usa-se o comando CTRL+R. Agora é só digitar a string de busca e <ENTER>. Para repetir a busca use o comando CTRL+R novamente.

Modo VI no console

Tive um amigo que dizia que você não pode se considerar um usuário de VI se usa o modo emacs (default) no console.

Para alternar para o modo VI (erroneamente chamado de modo que bipa pelos detratores do VI) é só digitar:

$ set -o vi

Ou acrescentar as linhas abaixo ao teu ~/.inputrc:

set editing-mode vi
set keymap vi

Nesse modo você usa os comandos do VI navegar no histórico, fazer busca dos comandos, etc. Exemplo: para buscar o comando find no histórico você digita <ESC>/find<ENTER> e para procurar as próximas ocorrências é só ir apertando N. Encontrando o comando é só dar <ENTER> para executar o comando ou I para entrar no modo de edição e alterar o conteúdo da linha.

Mas o mais legal desse modo é que você pode chamar a linha de comando no VI a qualquer momento. Vamos supor que você digitou uma mega linha comprida na linha de comando e começou a ficar complicado de edita-la. No modo VI basta você digitar <ESC>vi e o editor VI será carregado com todo o conteúdo da sua linha de comando.

Se você gravar e sair (:wq) a linha será executada. Se você só sair sem gravar a linha será ignorada.

Usando o comando history

O Gustavo Straube também sugeriu usar o comando history em conjunto com o grep:

$ history | grep 'comando'

Resetando o terminal

Você estava lá trabalhando na linha de comando e acidentalmente deu um cat num arquivo binário achando que lá só tinha texto. Teu terminal ficou todo zoado com símbolos irreconhecíveis no lugar dos caracteres? É só resetar o terminal:

$ reset

Funciona na imensa maioria das vezes. Mas se não funcionar… aí é só matando esse terminal mesmo 😀

Agradecimentos para o toti por ter feito me lembrar dessa dica 😀

Limpando a tela do console

O comando para limpar a tela do console e posicionar o prompt na primeira linha do terminal é:

$ clear

Mas você também pode usar uma combinação de teclas essa função:

  • CTRL-L no Linux
  • CMD-K no Mac OS X

você pode acionar essa combinação de teclas a qualquer momento. Mesmo depois de já ter digitado alguma coisa no prompt. Exemplo:

$ ls <CTRL+L>

Vai limpar a tela e manter o comando ls que já foi digitado.

Eu já conhecia e usava isso, mas o Adrian C. Miranda me lembro nos comentários.

Último argumento

Essa eu não conhecia e foi passada pelo meu colega Vinicius Assef:

$ git diff path/para/meu/arquivo_que_mudou.py
$ git add !$

O !$ pega o último argumento do último comando digitado no shell.

Para saber mais sobre essa e outras expansões possíveis:

$ man bash  # procure por ^HISTORY EXPANSION

Voltando para o diretório anterior

Essa eu imaginava que todos soubessem, mas descobri que muita gente desconhece. O comando cd que altera o diretório corrente aceita o parâmetro - (cd - que faz você voltar para o diretório onde você estava anteriormente.

~/Work/x$ cd ../y
~/Work/y$ cd -
~/Work/x
~/Work/x$ 

Dica: Você também pode usar “git checkout -” no git para voltar para o branch anterior.

Usando o make sem um Makefile

É possível utilizar o utilitário make sem a necessidade de criar um Makefile quando você quer fazer alguma compilação de programas escritos em C/C++.

Se você tem um programa.c e quer compilar ele basta fazer make programa (make [nome-do-programa-sem-extensão):

$ ls
programa.c

$ cat programa.c
#include <stdio.h>

int main(int argc, char *argv[]) {
	printf("Hello World!\n");
	return 0;
}

$ make programa
cc programa.c -o programa

$ ./programa
Hello World!

Sabe algum macete que não está aqui?

Eu sei de mais alguns outros vários mas não consegui lembrar pra colocar aqui. Conforme for lembrando vou atualizando esse artigo. E você sabe algum? Mande para blog @ osantana (dot) me.