Índice
Disponibilizo algumas dicas para as pessoas aprenderem programação no sistema Debian o suficiente para rastrear o código fonte do pacote. Aqui estão pacotes notáveis e pacotes de documentação correspondentes para programação.
Estão disponíveis referências online ao escrever "man
nome
" após instalar os pacotes manpages
e
manpages-dev
. As referências online ás ferramentas GNU
está disponíveis ao escrever "info nome_do_programa
" após
instalar os pacotes de documentação pertinentes. Poderá ter de incluir os
arquivos contrib
e non-free
adicionalmente ao arquivo main
pois algumas documentações
GFDL não são consideradas compatíveis com DFSG.
Considere a possibilidade de utilizar ferramentas do sistema de controlo de versões. Ver Secção 10.5, “Git”.
![]() |
Atenção |
---|---|
Não use " |
![]() |
Cuidado |
---|---|
Deve instalar os programas compilados directamente a partir da fonte em
" |
![]() |
Dica |
---|---|
Os Exemplos de código da criação de "Song 99 Bottles of Beer" devem dar-lhe uma boa ideia de praticamente todas as linguagens de programação. |
O script de shell é um ficheiro de texto com o bit de execução definido e contém os comandos no seguinte formato.
#!/bin/sh ... command lines
A primeira linha especifica o interpretador shell que lê e executa o conteúdo deste ficheiro.
Ler scripts de shell é a melhor maneira de compreender como um sistema tipo Unix funciona. Aqui, Dou alguns apontamentos e lembranças para programação de shell. Veja "Erros de Shell" (https://www.greenend.org.uk/rjk/2001/04/shell.html) para aprender a partir de erros.
Ao contrário do modo interativo de shell (veja Secção 1.5, “O comando simples da shell” e Secção 1.6, “Processamento de texto estilo Unix”), os scripts de shell usam frequentemente parâmetros, condicionais e ciclos.
Muitos scripts de sistema podem ser interpretados por qualquer uma das shells POSIX (ver Tabela 1.13, “Lista de programas da shell”).
A shell POSIX não-interactiva predefinida "/usr/bin/sh
" é
uma ligação simbólica que aponta para /usr/bin/dash
e é
utilizada por muitos programas de sistema.
A shell POSIX interactiva predefinida é /usr/bin/bash
.
Evite escrever um script de shell com bashisms ou zshisms para fazê-loportável entre todas as shells
do POSIX. Pode verificar isto a usar o checkbashisms
(1).
Tabela 12.1. Lista dos 'bashisms' típicos
Bom: POSIX | Evitar: 'bashism' |
---|---|
if [ "$foo" = "$bar" ] ; then … |
if [ "$foo" == "$bar" ] ; then … |
diff -u file.c.orig file.c |
diff -u file.c{.orig,} |
mkdir /foobar /foobaz |
mkdir /foo{bar,baz} |
funcname() { … } |
function funcname() { … } |
formato octal: "\377 " |
formato hexadecimal: "\xff " |
O comando "echo
" tem de ser usado com os seguintes
cuidados porque a implementação dele difere entre o integrado na shell e os
comandos externos.
Evite usar quaisquer opções de comando excepto "-n
".
Evite usar sequências de escape na cadeia porque o manuseamento dele varia.
![]() |
Nota |
---|---|
Apesar da opção " |
![]() |
Dica |
---|---|
Use o comando " |
Parâmetros de shell especiais são frequentemente usados no script shell.
Tabela 12.2. Lista de parâmetros da shell
parâmetro da shell | valor |
---|---|
$0 |
nome da shell ou script de shell |
$1 |
primeiro(1) argumento shell |
$9 |
nono(9) argumento shell |
$# |
quantidade de parâmetros de posição |
"$*" |
"$1 $2 $3 $4 … " |
"$@" |
"$1" "$2" "$3" "$4" … |
$? |
estado de saída do comando mais recente |
$$ |
PID deste script shell |
$! |
PID da tarefa de fundo iniciada mais recentemente |
As expansões de parâmetro básicas a lembrar são as seguintes.
Tabela 12.3. Lista de expansões de parâmetros de shell
formato da expressão do parâmetro | valor se var estiver definido |
valor se var não estiver definido |
---|---|---|
${var:-cadeia} |
"$var " |
"cadeia " |
${var:+cadeia} |
"cadeia " |
"null " |
${var:=cadeia} |
"$var " |
"cadeia " (e corra "var=cadeia ") |
${var:?cadeia} |
"$var " |
echo "cadeia " para stderr (e termina com erro) |
Aqui, o símbolo ortográfico dois pontos ":
" em todas
estas operações é na realidade opcional.
com ":
" = teste de
operador para existe e não nulo
sem ":
" = teste de
operador para apenas existe
Tabela 12.4. Lista de substituições de parâmetros de shell chave
formato de substituição de parâmetro | resultado |
---|---|
${var%suffix} |
remover o modelo de sufixo menor |
${var%%suffix} |
remover o modelo de sufixo maior |
${var#prefix} |
remover o modelo de prefixo menor |
${var##prefix} |
remover o modelo de prefixo maior |
Cada comando retorna um estado de saída que pode ser usado para expressões condicionais.
Sucesso: 0 ("True")
Erro: não 0 ("False")
![]() |
Nota |
---|---|
"0" no contexto condicional da shell significa "Verdadeiro", enquanto "0" no contexto condicional de C significa "Falso". |
![]() |
Nota |
---|---|
" |
Os idiomas condicionais básicos a lembrar são os seguintes.
"comando &&
se_sucesso_corre_também_este_comando || true
"
"comando ||
se_não_sucesso_corre_também_este_comando ||
true
"
Um fragmento de script de multi-linhas como o seguinte
if [ conditional_expression ]; then if_success_run_this_command else if_not_success_run_this_command fi
Aqui o "|| true
" final foi necessário para assegurar que
estes script de shell não termina acidentalmente nesta linha quando a shell
é invocada com a flag "-e
".
Tabela 12.5. Lista de operadores de comparação de ficheiros na expressão condicional
equação | condição para retornar o verdadeiro lógico |
---|---|
-e ficheiro |
ficheiro existe |
-d ficheiro |
ficheiro existe e é um diretório |
-f ficheiro |
ficheiro existe e é um ficheiro normal |
-w ficheiro |
ficheiro existe e pode-se escrever nele |
-x ficheiro |
ficheiro existe e é executável |
ficheiro1 -nt
ficheiro2 |
ficheiro1 é mais recente que ficheiro2 (modificação) |
ficheiro1 -ot
ficheiro2 |
ficheiro1 é mais antigo que ficheiro2 (modificação) |
ficheiro1 -ef
ficheiro2 |
ficheiro1 e ficheiro2 estão no mesmo aparelho e no mesmo número de inode |
Tabela 12.6. Lista de operadores de comparação de cadeias na expressão condicional
equação | condição para retornar o verdadeiro lógico |
---|---|
-z str |
o comprimento de str é zero |
-n str |
o comprimento de str não é zero |
str1 = str2 |
str1 and str2 são iguais |
str1 != str2 |
str1 and str2 não são iguais |
str1 < str2 |
str1 ordena antes de str2 (dependente do locale) |
str1 > str2 |
str1 ordena após str2 (dependente do locale) |
Os operadores de comparação Aritmética de
inteiros na expressão regular são "-eq
",
"-ne
", "-lt
",
"-le
", "-gt
" e
"-ge
".
Existem vários idiomas de ciclo para usar na shell POSIX.
"for x in foo1 foo2 … ; do command ; done
" faz ciclos ao
atribuir itens da lista "foo1 foo2 …
" à variável
"x
" e a executar o "comando
".
"while condition ; do command ; done
" repete o
"comando
" enquanto a "condição
" for
verdadeira.
"until condition ; do command ; done
" repete o
"comando
" enquanto a "condição
" não
for verdadeira.
"break
" permite sair do ciclo.
"continue
" permite resumir a próxima interacção do ciclo.
![]() |
Dica |
---|---|
A interacção numérica tipo linguagem C pode ser
realizada a usar |
Algumas variáveis de ambiente populares para a linha de comandos normal da shell podem não estar disponíveis no ambiente de execução do seu script.
Para "$USER
", use "$(id -un)
"
Para "$UID
", use "$(id -u)
"
Para "$HOME
", use "$(getent passwd "$(id
-u)"|cut -d ":" -f 6)
" (isto também funciona em Secção 4.5.2, “O moderno sistema de gestão centralizado”)
A shell processa um script rudemente como a seguinte sequência.
A shell lê uma linha.
A shell agrupa uma parte de uma linha como um
testemunho se estiver dentro de "…"
ou
'…'
.
A shell divide a outra parte de uma linha em testemunhos como o seguinte.
Espaços em branco: espaço
tab nova-linha
Meta-caracteres: < > | ; & ( )
A shell verifica a palavra reservada para
cada testemunho para ajustar o comportamento dele se não dentro de
"…"
ou '…'
.
palavra reservada: if then elif
else fi for in while unless do done case esac
A shell expande o alias se não estiver
dentro de "…"
ou '…'
.
A shell expande o til se não dentro de
"…"
ou '…'
.
"~
" → diretório home do utilizador atual
"~utilizador
" → diretório home do
utilizador
A shell expande o parâmetro ao seu valor
se não dentro de '…'
.
parâmetro:
"$PARAMETER
" ou "${PARAMETER}
"
A shell expande a substituição do comando
se não dentro de '…'
.
"$( comando )
" → o resultado do
"comando
"
"` comando `
" → o resultado do
"comando
"
A shell expande o glob nome_de-caminho
aos nomes de ficheiros correspondentes se não dentro de
"…"
ou '…'
.
*
→ quaisquer caracteres
?
→ um caractere
[…]
→ qualquer um dos caracteres em
"…
"
A shell procura o comando a partir do seguinte e executa-o.
definição de função
comando builtin
ficheiro executável em
"$PATH
"
A shell vai à próxima linha e repete este processo outra vez a partir do topo desta sequência.
Citações singulares (') dentro de aspas não têm efeito.
Executar "set -x
" na shell ou invocar a shell com a opção
"-x
" faz a shell escrever todos os comandos
executados. Isto é muito útil para depuração.
De modo a tornar o seu programa de shell o mais portável possível entre os sistemas Debian, é uma boa ideia limitar os programas utilitários àqueles disponibilizados pelos pacotes essenciais.
"aptitude search ~E
" lista os pacotes essenciais.
"dpkg -L nome_do-pacote |grep
'/man/man.*/'
" lista as manpages (manuais) para comandos
oferecidos pelo pacote
nome_do_pacote
.
Tabela 12.7. Lista de pacotes que contém programas utilitários pequenos para scripts de shell
pacote | popcon | tamanho | descrição |
---|---|---|---|
dash
|
V:884, I:997 | 191 | shell pequeno e rápido compatível com POSIX para sh |
coreutils
|
V:880, I:999 | 18307 | utilitários de núcleo GNU |
grep
|
V:782, I:999 | 1266 | GNU grep , egrep e
fgrep |
sed
|
V:790, I:999 | 987 | GNU sed |
mawk
|
V:442, I:997 | 285 | awk pequeno e rápido |
debianutils
|
V:907, I:999 | 224 | utilitários variados específicos do Debian |
bsdutils
|
V:519, I:999 | 356 | utilitários básicos do 4.4BSD-Lite |
bsdextrautils
|
V:596, I:713 | 339 | utilitários extras do 4.4BSD-Lite |
moreutils
|
V:15, I:38 | 231 | utilitários Unix adicionais |
![]() |
Dica |
---|---|
Apesar de |
Ver Secção 1.6, “Processamento de texto estilo Unix” exemplos.
Tabela 12.8. Lista de pacotes relacionados com o interpretador
pacote | popcon | tamanho | documentação |
---|---|---|---|
dash
|
V:884, I:997 | 191 | sh: shell pequena e rápida compatível com POSIX
para sh |
bash
|
V:838, I:999 | 7175 | sh: "info bash " fornecido por
bash-doc |
mawk
|
V:442, I:997 | 285 | AWK: awk pequeno e rápido |
gawk
|
V:285, I:349 | 2906 | AWK: "info gawk " proporcionado
por gawk-doc |
perl
|
V:707, I:989 | 673 | Perl: perl (1) e páginas html
fornecidas por perl-doc e
perl-doc-html |
libterm-readline-gnu-perl
|
V:2, I:29 | 380 | Extensão Perl para a Biblioteca GNU ReadLine/History:
perlsh (1) |
libreply-perl
|
V:0, I:0 | 171 | REPL para Perl: reply (1) |
libdevel-repl-perl
|
V:0, I:0 | 237 | REPL para Perl: re.pl (1) |
python3
|
V:718, I:953 | 81 | Python: python3 (1) e
páginas html fornecidas por python3-doc |
tcl
|
V:25, I:218 | 21 | Tcl: tcl (3) e páginas de
manual detalhadas fornecidas por tcl-doc |
tk
|
V:20, I:211 | 21 | Tk: tk (3) e páginas de manual
detalhadas fornecidas por tk-doc |
ruby
|
V:86, I:208 | 29 | Ruby: ruby (1),
erb (1), irb (1),
rdoc (1), ri (1) |
Quando deseja automatizar uma tarefa em Debian, deve primeiro fazer o script com uma linguagem interpretada. A linha de orientação para a escolha da linguagem interpretada é:
Utilize dash
, se a tarefa for simples e combinar
programas CLI com um programa shell.
Utilize python3
, se a tarefa não for simples e se a
estiver a escrever de raiz.
Use perl
, tcl
,
ruby
, ... se houver um código existente usando uma dessas
linguagens no Debian que precisa ser retocado para fazer a tarefa.
Se o código resultante for demasiado lento, pode reescrever apenas a parte crítica para a velocidade de execução numa linguagem compilada e chamá-la a partir da linguagem interpretada.
A maioria dos intérpretes oferece funcionalidades básicas de verificação da sintaxe e de rastreio do código.
"dash -n script.sh" - Verificação da sintaxe de um script Shell
"dash -x script.sh" - Rastreia um script de shell
"python -m py_compile script.py" - Verificação da sintaxe de um script Python
"python -mtrace --trace script.py" - Rastreia um script Python
"perl -I ../libpath -c script.pl" - Verificação da sintaxe de um script Perl
"perl -d:Trace script.pl" - Traça um script Perl
Para testar o código para dash
, tente Secção 9.1.4, “Revestimento da linha de leitura” o que acomoda o ambiente interativo semelhante
ao bash
.
Para testar código para perl
, tente o ambiente REPL para
Perl que acomoda o ambiente REPL (=READ
+ EVAL + PRINT + LOOP) semelhante ao Python para Perl.
O script shell pode ser melhorado para criar um programa GUI atrativo. O
truque é usar um dos chamados programas de diálogo em vez de uma interação
monótona usando comandos echo
e read
.
Tabela 12.9. Lista de programas de diálogo
pacote | popcon | tamanho | descrição |
---|---|---|---|
x11-utils
|
V:192, I:566 | 651 | xmessage (1): mostra uma mensagem ou questão numa janela
(X) |
whiptail
|
V:284, I:996 | 56 | mostra caixas de diálogo amigas do utilizador a partir de scripts de shell (newt) |
dialog
|
V:11, I:99 | 1227 | mostra caixas de diálogo amigas do utilizador a partir de scripts de shell (ncurses) |
zenity
|
V:76, I:363 | 183 | exibir caixas de diálogo gráficas a partir de scripts de shell (GTK) |
ssft
|
V:0, I:0 | 75 | Ferramenta Frontend de Scripts de Shell (revestimento para o zenity, kdialog e dialog com o gettext) |
gettext
|
V:56, I:259 | 5818 | "/usr/bin/gettext.sh ": traduz mensagem |
Aqui está um exemplo de um programa GUI para demonstrar como é fácil apenas com um script de shell.
Este script usa zenity
para selecionar um ficheiro (por
defeito /etc/motd
) e mostrá-lo.
O lançador GUI para este script pode ser criado da seguinte forma Secção 9.4.10, “Arrancar um programa a partir da GUI”.
#!/bin/sh -e # Copyright (C) 2021 Osamu Aoki <[email protected]>, Public Domain # vim:set sw=2 sts=2 et: DATA_FILE=$(zenity --file-selection --filename="/etc/motd" --title="Select a file to check") || \ ( echo "E: File selection error" >&2 ; exit 1 ) # Check size of archive if ( file -ib "$DATA_FILE" | grep -qe '^text/' ) ; then zenity --info --title="Check file: $DATA_FILE" --width 640 --height 400 \ --text="$(head -n 20 "$DATA_FILE")" else zenity --info --title="Check file: $DATA_FILE" --width 640 --height 400 \ --text="The data is MIME=$(file -ib "$DATA_FILE")" fi
Este tipo de abordagem ao programa GUI com o script de shell é útil apenas para casos de escolha simples. Se for escrever qualquer programa com complexidades, por favor considere escrevê-lo numa plataforma mais capaz.
Os programas de arquivamento GUI podem ser alargados para executar algumas ações populares em ficheiros selecionados utilizando pacotes de extensão adicionais. Também podem ser feitos para executar ações personalizadas muito específicas, adicionando os seus scripts específicos.
Para o GNOME, consulte NautilusScriptsHowto.
Para o KDE, veja Criando menus de serviço do Dolphin.
Para o Xfce, consulte Thunar - Acções personalizadas e https://help.ubuntu.com/community/ThunarCustomActions.
Para LXDE, consulte Ações personalizadas.
Para processar dados, sh
precisa gerar sub-processos
executando cut
, grep
,
sed
, etc., e é lento. Por outro lado, o
perl
tem capacidades internas para processar dados, e é
rápido. Por isso muitos scripts de manutenção do sistema na Debian usam
perl
.
Vamos pensar no seguinte trecho de script AWK de uma linha e seus equivalentes em Perl.
awk '($2=="1957") { print $3 }' |
Isto é equivalente a qualquer uma das seguintes linhas.
perl -ne '@f=split; if ($f[1] eq "1957") { print "$f[2]\n"}' |
perl -ne 'if ((@f=split)[1] eq "1957") { print "$f[2]\n"}' |
perl -ne '@f=split; print $f[2] if ( $f[1]==1957 )' |
perl -lane 'print $F[2] if $F[1] eq "1957"' |
perl -lane 'print$F[2]if$F[1]eq+1957' |
Este último é um enigma. Aproveitei-me das seguintes funcionalidades do Perl.
O espaço em branco é opcional.
Existe a conversão automática de números para cadeia.
Truques de execução do Perl através de opções de linha de comando:
perlrun
(1)
Variáveis especiais do Perl: perlvar
(1)
Esta flexibilidade é o ponto forte do Perl. Ao mesmo tempo, isto permite-nos criar códigos crípticos e emaranhados. Por isso, é preciso ter cuidado.
Tabela 12.10. Lista de pacotes relacionados com o compilador
pacote | popcon | tamanho | descrição |
---|---|---|---|
gcc
|
V:167, I:550 | 36 | Compilador GNU C |
libc6-dev
|
V:248, I:567 | 12053 | Biblioteca GNU C: Bibliotecas de desenvolvimento e ficheiros de cabeçalho |
g++
|
V:56, I:501 | 13 | Compilador GNU C++ |
libstdc++-10-dev
|
V:14, I:165 | 17537 | GNU Standard C++ Library v3 (ficheiros de desenvolvimento) |
cpp
|
V:334, I:727 | 18 | Pré-processador GNU C |
gettext
|
V:56, I:259 | 5818 | Utilitários de internacionalização GNU |
glade
|
V:0, I:5 | 1204 | Construtor de interfaces de utilizador GTK |
valac
|
V:0, I:4 | 725 | Linguagem semelhante ao C# para o sistema GObject |
flex
|
V:7, I:73 | 1243 | Gerador de analisador léxico rápido compatível com LEX |
bison
|
V:7, I:80 | 3116 | YACC-compatible gerador de análise |
susv2
|
I:0 | 16 | buscar "The Single UNIX Specifications v2" |
susv3
|
I:0 | 16 | buscar "The Single UNIX Specifications v3" |
susv4
|
I:0 | 16 | baixar "As especificações únicas UNIX v4" |
golang
|
I:20 | 11 | Compilador de linguagem de programação Go |
rustc
|
V:3, I:14 | 8860 | Linguagem de programação de sistemas Rust |
haskell-platform
|
I:1 | 12 | Bibliotecas e ferramentas Haskell padrão |
gfortran
|
V:6, I:62 | 15 | Compilador GNU Fortran 95 |
fpc
|
I:2 | 103 | Pascal livre |
Aqui, Secção 12.3.3, “Flex — um Lex melhor” e Secção 12.3.4, “Bison — um Yacc melhor” são incluídos para indicar como um programa semelhante a um compilador pode ser escrito em linguagem C, compilando uma descrição de nível superior em linguagem C.
Pode configurar um ambiente apropriado para compilar programas escritos na linguagem de programação C com o seguinte.
# apt-get install glibc-doc manpages-dev libc6-dev gcc build-essential
O pacote libc6-dev
, isto é, a biblioteca C GNU,
disponibiliza uma biblioteca standard
C a qual é uma colecção de ficheiros cabeçalho e rotinas de
biblioteca usadas pela linguagem de programação C.
Veja referências para C nos seguintes.
"info libc
" (Referência de funções da biblioteca C)
gcc
(1) e "info gcc
"
cada-nome_de_função_da_biblioteca_C
(3)
Kernighan & Ritchie, "A Linguagem de Programação C", 2ª edição (Prentice Hall)
Um simples exemplo, "example.c
" pode ser compilado com
uma biblioteca "libm
" num executável
"run_example
" com o seguinte.
$ cat > example.c << EOF #include <stdio.h> #include <math.h> #include <string.h> int main(int argc, char **argv, char **envp){ double x; char y[11]; x=sqrt(argc+7.5); strncpy(y, argv[0], 10); /* prevent buffer overflow */ y[10] = '\0'; /* fill to make sure string ends with '\0' */ printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]); return 0; } EOF $ gcc -Wall -g -o run_example example.c -lm $ ./run_example 1, 2.915, ./run_exam, (null) $ ./run_example 1234567890qwerty 2, 3.082, ./run_exam, 1234567890qwerty
Aqui, o "-lm
" é necessário para ligar a biblioteca
"/usr/lib/libm.so
" do pacote libc6
para o sqrt
(3). A biblioteca real está em
"/lib/
" com o nome de ficheiro
"libm.so.6
", o qual é uma ligação simbólica para
"libm-2.7.so
".
Olhe ao último parâmetro no texto resultante. Existem mais de 10 caracteres
mesmo com "%10s
" especificado.
O uso de funções de operação de memória de ponteiro sem verificações de
limites como em sprintf
(3) e
strcpy
(3), está descontinuado para prevenir exploits de
sobrelotação do buffer que influenciam os efeitos de transbordo em cima. Em
vez disso, use snprintf
(3) e
strncpy
(3).
O Flex é um gerador rápido de análise léxica compatível com o Lex.
O tutorial do flex
(1) encontra-se em "info
flex
".
Muitos exemplos simples podem ser encontrados em
"/usr/share/doc/flex/examples/
". [7]
Vários pacotes disponibilizam um gerador LR parser ou LALR parser compatível em frente com o Yacc em Debian.
O tutorial para o bison
(1) encontra-se em "info
bison
".
Tem de disponibilizar as suas próprias chamadas "main()
"
e "yyerror()
". "main()
" chama
"yyparse()
" que chama "yylex()
",
geralmente criada com Flex.
Aqui está um exemplo para criar um programa simples de calculadora de terminal.
Vamos criar example.y
:
/* calculator source for bison */ %{ #include <stdio.h> extern int yylex(void); extern int yyerror(char *); %} /* declare tokens */ %token NUMBER %token OP_ADD OP_SUB OP_MUL OP_RGT OP_LFT OP_EQU %% calc: | calc exp OP_EQU { printf("Y: RESULT = %d\n", $2); } ; exp: factor | exp OP_ADD factor { $$ = $1 + $3; } | exp OP_SUB factor { $$ = $1 - $3; } ; factor: term | factor OP_MUL term { $$ = $1 * $3; } ; term: NUMBER | OP_LFT exp OP_RGT { $$ = $2; } ; %% int main(int argc, char **argv) { yyparse(); } int yyerror(char *s) { fprintf(stderr, "error: '%s'\n", s); }
Vamos criar, example.l
:
/* calculator source for flex */ %{ #include "example.tab.h" %} %% [0-9]+ { printf("L: NUMBER = %s\n", yytext); yylval = atoi(yytext); return NUMBER; } "+" { printf("L: OP_ADD\n"); return OP_ADD; } "-" { printf("L: OP_SUB\n"); return OP_SUB; } "*" { printf("L: OP_MUL\n"); return OP_MUL; } "(" { printf("L: OP_LFT\n"); return OP_LFT; } ")" { printf("L: OP_RGT\n"); return OP_RGT; } "=" { printf("L: OP_EQU\n"); return OP_EQU; } "exit" { printf("L: exit\n"); return YYEOF; } /* YYEOF = 0 */ . { /* ignore all other */ } %%
Em seguida, execute o seguinte a partir do prompt do shell para tentar isso:
$ bison -d example.y $ flex example.l $ gcc -lfl example.tab.c lex.yy.c -o example $ ./example 1 + 2 * ( 3 + 1 ) = L: NUMBER = 1 L: OP_ADD L: NUMBER = 2 L: OP_MUL L: OP_LFT L: NUMBER = 3 L: OP_ADD L: NUMBER = 1 L: OP_RGT L: OP_EQU Y: RESULT = 9 exit L: exit
As ferramentas do tipo Lint podem ajudar automaticamente a análise de código estático.
As ferramentas do tipo indentação podem ajudar as revisões de código humano, reformatando os códigos-fonte de forma consistente.
As ferramentas do tipo Ctags podem ajudar nas revisões humanas de código, gerando um ficheiro de índice (ou tag) de nomes encontrados nos códigos fonte.
![]() |
Dica |
---|---|
Configurar o seu editor favorito |
Tabela 12.12. Lista de ferramentas para análise de código estático
pacote | popcon | tamanho | descrição |
---|---|---|---|
vim-ale
|
I:0 | 2591 | Mecanismo assíncrono Lint para Vim 8 e NeoVim |
vim-syntastic
|
I:3 | 1379 | Truques de verificação de sintaxe para o vim |
elpa-flycheck
|
V:0, I:1 | 808 | verificação de sintaxe moderna em tempo real para o Emacs |
elpa-relint
|
V:0, I:0 | 147 | Localizador de erros de regexp do Emacs Lisp |
cppcheck-gui
|
V:0, I:1 | 7224 | ferramenta para análise estática de código C/C++ (GUI) |
shellcheck
|
V:2, I:13 | 18987 | ferramenta lint para scripts shell |
pyflakes3
|
V:2, I:15 | 20 | verificador passivo de programas Python 3 |
pylint
|
V:4, I:20 | 2018 | Verificador estático de código Python |
perl
|
V:707, I:989 | 673 | interpretador com verificador de código estático interno:
B::Lint (3perl) |
rubocop
|
V:0, I:0 | 3247 | Analisador de código estático Ruby |
clang-tidy
|
V:2, I:11 | 21 | ferramenta de verificação de formato de regras C++ baseada em Clang |
splint
|
V:0, I:2 | 2320 | ferramenta para verificação estática de programas C por bugs |
flawfinder
|
V:0, I:0 | 205 | ferramenta para examinar código fonte C/C++ e procurar por fraquezas na segurança |
black
|
V:3, I:13 | 660 | formatador de código Python sem compromissos |
perltidy
|
V:0, I:4 | 2493 | Indentador e reformatador de scripts Perl |
indent
|
V:0, I:7 | 431 | Programa de formatação de código fonte em linguagem C |
astyle
|
V:0, I:2 | 785 | Indentador de código-fonte para C, C++, Objective-C, C# e Java |
bcpp
|
V:0, I:0 | 111 | Embelezador C(++) |
xmlindent
|
V:0, I:1 | 53 | Reformatador de fluxo XML |
global
|
V:0, I:2 | 1908 | Ferramentas de pesquisa e navegação de código-fonte |
exuberant-ctags
|
V:2, I:20 | 341 | criar índices de ficheiros de etiquetas de definições de código-fonte |
universal-ctags
|
V:1, I:11 | 3386 | criar índices de ficheiros de etiquetas de definições de código-fonte |
A depuração é uma parte importante das atividades de programação. Saber como depurar programas faz de si um bom utilizador de Debian capaz de produzir relatórios de bugs significantes.
O depurador principal em Debian é o
gdb
(1) que lhe permite inspeccionar um programa enquanto
ele é executado.
Vamos instalar o gdb
e programas relacionados com o
seguinte.
# apt-get install gdb gdb-doc build-essential devscripts
Pode ser encontrado um bom tutorial do gdb
:
“info gdb
”
"Depurando com GDB" em
/usr/share/doc/gdb-doc/html/gdb/index.html
Aqui está um exemplo simples de utilização do gdb
(1) num
"program
" compilado com a opção "-g
"
para produzir informação de depuração.
$ gdb program (gdb) b 1 # set break point at line 1 (gdb) run args # run program with args (gdb) next # next line ... (gdb) step # step forward ... (gdb) p parm # print parm ... (gdb) p parm=12 # set value to 12 ... (gdb) quit
![]() |
Dica |
---|---|
Muitos comandos do |
Uma vez que todos os binários instalados devem ser despojados no sistema
Debian por defeito, a maioria dos símbolos de depuração são removidos no
pacote normal. De modo a depurar pacotes Debian com
gdb
(1), os pacotes *-dbgsym
precisam
de ser instalados (e.g. coreutils-dbgsym
no caso do
coreutils
). Os pacotes fonte geram pacotes
*-dbgsym
automaticamente juntamente com os pacotes
binários normais e esses pacotes de depuração são colocados separadamente no
arquivo debian-debug. Por favor, consulte
os artigos no Debian Wiki para
mais informações.
Se um pacote a ser depurado não fornecer o seu pacote
*-dbgsym
, é necessário instalá-lo depois de o reconstruir
através do seguinte.
$ mkdir /path/new ; cd /path/new $ sudo apt-get update $ sudo apt-get dist-upgrade $ sudo apt-get install fakeroot devscripts build-essential $ apt-get source package_name $ cd package_name* $ sudo apt-get build-dep ./
Corrigir bugs se necessário.
Mude a versão de pacote para uma que não colida com as versões oficiais de
Debian, por exemplo, uma adicionada com "+debug1
" quando
se recompila uma versão de pacote existente, ou uma adicionada com
"~pre1
" quando se compila uma versão de pacote ainda não
lançada com o seguinte.
$ dch -i
Compilar e instalar pacotes com símbolos de depuração com o seguinte.
$ export DEB_BUILD_OPTIONS="nostrip noopt" $ debuild $ cd .. $ sudo debi package_name*.changes
Necessita verificar os scripts de construção do pacote e assegurar o uso de
"CFLAGS=-g -Wall
" para compilar binários.
Quando encontrar uma falha num programa, é uma boa ideia enviar um relatório de bug com informação de rastreio copiada-e-colada.
O backtrace pode ser obtido pelo gdb
(1) utilizando uma
das seguintes abordagens:
Abordagem às falhas em GDB:
Execute o programa a partir do GDB.
Falha no programa.
Digite "bt
" no prompt da GDB.
Abordagem falhas primeiro:
Actualize o ficheiro "/etc/security/limits.conf" para incluir o seguinte:
* soft core unlimited
Escreva "ulimit -c unlimited
" na prompt da shell.
Execute o programa a partir desta janela de comandos.
Colapsa o programa para produzir um ficheiro de despejo do núcleo.
Carregar o ficheiro core dump para GDB como
"gdb gdb ./program_binary core
" .
Digite "bt
" no prompt da GDB.
Para uma situação de loop infinito ou de teclado congelado, pode forçar o
encerramento do programa premindo Ctrl-\
ou
Ctrl-C
ou executando "kill -ABRT
PID
". (Ver Secção 9.4.12, “Matar um processo”)
![]() |
Dica |
---|---|
Muitas vezes, vê um backtrace onde uma ou mais linhas do topo estão em
" $ MALLOC_CHECK_=2 gdb hello |
Tabela 12.14. Lista de comandos gdb avançados
comando | descrição dos objetivos do comando |
---|---|
(gdb) thread apply all bt |
obter um backtrace para todos os processos de um programa de multi-processo |
(gdb) bt full |
obter parâmetros que vêm na pilha das chamadas de função |
(gdb) thread apply all bt full |
obtém um backtrace e parâmetros como a combinação das opções precedentes |
(gdb) thread apply all bt full 10 |
obter um backtrace e parâmetros para as 10 chamadas do topo para cortar resultados irrelevantes |
(gdb) set logging on |
escreve um relatório dos resultados do gdb para um
ficheiro (a predefinição é "gdb.txt ") |
Use o ldd
(1) para encontrar uma dependência de um
programa em bibliotecas com o seguinte.
$ ldd /usr/bin/ls librt.so.1 => /lib/librt.so.1 (0x4001e000) libc.so.6 => /lib/libc.so.6 (0x40030000) libpthread.so.0 => /lib/libpthread.so.0 (0x40153000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Para que o ls
(1) funcione num ambiente 'chroot', as
bibliotecas em cima têm de estar disponíveis no seu ambiente 'chroot'.
Existem várias ferramentas de rastreio de chamadas dinâmicas disponíveis em Debian. Veja Secção 9.4, “Monitorizar, controlar e iniciar as atividades de programas”.
Se o programa do GNOME preview1
recebeu um erro do X,
deverá ver a mensagem que a seguir.
The program 'preview1' received an X Window System error.
Neste caso, pode tentar correr o programa com "--sync
" e
quebrar a função "gdk_x_error
" de modo a obter um
backtrace.
Aqui estão várias ferramentas de detecção de fugas de memória em Debian.
Tabela 12.15. Lista de ferramentas de detecção de fugas de memória
pacote | popcon | tamanho | descrição |
---|---|---|---|
libc6-dev
|
V:248, I:567 | 12053 | mtrace (1): funcionalidades de depuração do malloc em
glibc |
valgrind
|
V:6, I:37 | 78191 | depurador e perfilador de memória |
electric-fence
|
V:0, I:3 | 73 | o depurador malloc (3) |
libdmalloc5
|
V:0, I:2 | 390 | biblioteca de depuração de alocação de memória |
duma
|
V:0, I:0 | 296 | biblioteca para detetar "overruns" e "under-runs" de buffer em programas C e C++ |
leaktracer
|
V:0, I:1 | 56 | rastreador de fugas de memória para programas C++ |
Tabela 12.16. Lista de pacotes de ferramentas de compilação
pacote | popcon | tamanho | documentação |
---|---|---|---|
make
|
V:151, I:555 | 1592 | "info make " disponibilizado por
make-doc |
autoconf
|
V:31, I:230 | 2025 | "info autoconf " disponibilizado por
autoconf-doc |
automake
|
V:30, I:228 | 1837 | "info automake " disponibilizado por
automake1.10-doc |
libtool
|
V:25, I:212 | 1213 | "info libtool " fornecido por
libtool-doc |
cmake
|
V:17, I:115 | 36607 | cmake (1) sistema make multiplataforma e de código aberto |
ninja-build
|
V:6, I:41 | 428 | ninja (1) pequeno sistema de construção mais próximo em
espírito do Make |
meson
|
V:3, I:22 | 3759 | meson (1) sistema de construção de alta produtividade no
topo do ninja |
xutils-dev
|
V:0, I:9 | 1484 | imake (1), xmkmf (1), etc. |
O Make é um utilitário para manutenção de grupos
de programas Após a execução do make
(1), o
make
lê o ficheiro de regras,
"Makefile
" e atualiza um alvo se depender de ficheiros
pré-requisitados que foram modificados desde que o alvo foi modificado por
último, ou se o alvo não existir. A execução destas atualizações pode
ocorrer concorrentemente.
A regra de sintaxe do ficheiro é a seguinte.
target: [ prerequisites ... ] [TAB] command1 [TAB] -command2 # ignore errors [TAB] @command3 # suppress echoing
Aqui "[TAB]
" é um código TAB. Cada linha é interpretada
pela shell após fazer a substituição da variável. Utilize
"\
" no final de uma linha para continuar o script. Use
"$$
" para inserir "$
" para valores de
ambiente para um script de shell.
Podem ser escritas regras implícitas para o destino e pré-requisitos, por exemplo, com o seguinte.
%.o: %.c header.h
Aqui, o alvo contém o caractere "%
" (exatamente um
deles). O "%
" pode corresponder a qualquer subcadeia não
vazia nos nomes de ficheiros do próprio alvo. Os pré-requisitos usam
igualmente "%
" para mostrar como os seus nomes estão
relacionados ao próprio nome do alvo.
Tabela 12.17. Lista de variáveis automáticas do make
variável automática | valor |
---|---|
$@ |
alvo |
$< |
primeiro pré-requisito |
$? |
todos os novos pré-requisitos |
$^ |
todos os pré-requisitos |
$* |
"% " estaminal correspondente no modelo de destino |
Tabela 12.18. Lista de expansões da variável do make
expansão da variável | descrição |
---|---|
foo1 := bar |
expansão de uma vez |
foo2 = bar |
expansão recursiva |
foo3 += bar |
acrescentar |
Corra "make -p -f/dev/null
" para ver as regras internas
automáticas.
O Autotools é um conjunto de ferramentas de programação concebido para ajudar a tornar os pacotes de código-fonte portáveis para muitos sistemas do tipo Unix.
O Autoconf é uma ferramenta para produzir um
script shell "configure
" a partir de
"configure.ac
".
O "configure
" é utilizado mais tarde para produzir
o"Makefile
" a partir do modelo
"Makefile.in
".
Automake é uma ferramenta para produzir
"Makefile.in
" a partir de
"Makefile.am
".
Libtool é um script shell para resolver o problema de portabilidade de software ao compilar bibliotecas partilhadas a partir do código fonte.
![]() |
Atenção |
---|---|
Não substitua ficheiros do sistema com os seus programas compilados quando os instalar. |
Debian não toca nos ficheiros em "/usr/local/
" ou em
"/opt
". Portanto se compilar um programa a partir do
código-fonte, instale-o em "/usr/local/
" para que não
interfira com o Debian.
$ cd src $ ./configure --prefix=/usr/local $ make # this compiles program $ sudo make install # this installs the files in the system
Se tiver o código original, se ele utiliza
autoconf
(1)/automake
(1) e se você
lembrar como o configurou, execute como segue para desinstalar o programa.
$ ./configure all-of-the-options-you-gave-it
$ sudo make uninstall
Em alternativa, se tiver a absoluta certeza que o processo de instalação
apenas coloca ficheiros sob "/usr/local/
" e não há lá
nada importante, pode apagar todos os seus conteúdos com o seguinte.
# find /usr/local -type f -print0 | xargs -0 rm -f
Se não tiver a certeza de onde os ficheiros estão instalados, deve
considerar usar o checkinstall
(8) do pacote
checkinstall
, que disponibiliza um caminho limpo para a
desinstalação. Agora suporta criar um pacote Debian com a opção
"-D
".
O sistema de construção de software tem vindo a evoluir:
Autotools no topo do Make tem sido o padrão de facto para a infraestrutura de compilação portátil desde os anos 1990. Isso é extremamente lento.
O CMake, inicialmente lançado em 2000, melhorou significativamente a velocidade, mas foi originalmente construído sobre o inerentemente lento Make. (Agora Ninja pode ser seu backend.)
O Ninja, lançado inicialmente em 2012, destina-se a substituir o Make para melhorar a velocidade de construção e foi concebido para que os seus ficheiros de entrada sejam gerados por um sistema de construção de nível superior.
O Meson, lançado inicialmente em 2013, é o novo sistema de construção de nível superior popular e rápido que usa o Ninja como backend.
Ver documentos encontrados em "O sistema de construção Meson" e "O sistema de construção Ninja".
Páginas web dinâmicas interactivas podem ser feitas conforme a seguir.
As questões são apresentadas ao explorador do utilizador a usar formulários HTML.
Preencher e clicar nas entradas do formulário envia uma das seguintes cadeias de URL com parâmetros codificados do explorador para o servidor web.
"https://www.foo.dom/cgi-bin/program.pl?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3
"
"https://www.foo.dom/cgi-bin/program.py?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3
"
"https://www.foo.dom/program.php?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3
"
O "%nn
" no URL é substituído por um caractere com valor
hexadecimal nn
.
A variável de ambiente está definida como: "QUERY_STRING="VAR1=VAL1
VAR2=VAL2 VAR3=VAL3"
".
O programa CGI (qualquer um de
"program.*
") no servidor web executa-se a si próprio com
a variável de ambiente "$QUERY_STRING
".
O stdout
do programa CGI é enviado ao explorador web e é
apresentado como uma página web dinâmica e interactiva.
Por razões de segurança é melhor não embarcar em novos hacks para analisar parâmetros CGI. Existem módulos definidos para eles em Perl e Python. O PHP vem com estas funcionalidades. Quando é necessário o armazenamento de dados no cliente, usam-se cookies HTTP. Quando é necessário o processamento de dados no lado do cliente, usa-se frequentemente Javascript.
Para mais, veja Common Gateway Interface, The Apache Software Foundation e JavaScript.
Procurar "CGI tutorial" no Google ao escrever diretamente o URL codificado https://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial no endereço do explorador é uma boa maneira de ver o script CGI em acção no servidor da Google.
Existem programas para converter código-fonte.
Se desejar criar um pacote Debian, leia o seguinte.
Capítulo 2, Gestão de pacotes Debian para compreender o sistema básico de pacotes
Secção 2.7.13, “Portar um pacote ao sistema stable” para compreender o processo básico de portar
Secção 9.11.4, “Sistema chroot” para compreender as técnicas de chroot básicas
debuild
(1), e sbuild
(1)
Secção 12.5.2, “Depurar o pacote Debian” para recompilar para depuração
Guia dos Novos Maintainers da
Debian (o pacote debmake-doc
)
Referência de Programadores da
Debian (o pacote developers-reference
)
Manual de Políticas Debian (o
pacote debian-policy
)
Existem pacotes como os debmake
,
dh-make
, dh-make-perl
, etc., que
auxiliam no processo em empacotamento.