No use la palabra "test" para designar un archivo ejecutable de
prueba. test
es un comando del shell.
Referencias:
/usr/share/doc/paquetes
Unix / Programming
Information
Una gran cantidad de extensos documentos con información se puede obtener del
proyecto GNU
.
Las siguientes 4 secciones contienen algunos scripts de ejemplo en diferentes
lenguajes de programación para crear un archivo de texto con información de las
cuentas para agregarse al archivo /etc/passwd
usando un procesador
por lotes como lo es el programa newusers
. Cada script requiere
como entrada de un archivo con una serie de líneas de la forma: nombre
apellido contraseña (estos scripts no crearán los directorios 'home' de
los usuarios)
Leer los scripts de shell es la mejor manera de entender cómo
funciona un sistema tipo Unix. Aquí, brindo algunos enlaces y recordatorios
para la programación del shell. Véase Shell
Mistakes
para aprender de los errores.
Referencias para Bash:
bash(1)
BASH
Programming - Introduction HOWTO
del LDP como documento
introductorio.
(Instale el paquete bash-doc
para ver archivos de ejemplo)
Pequeño programa de ejemplo (sirve como entrada para el comando
newusers
):
#!/bin/bash # (C) Osmu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain pid=1000; while read n1 n2 n3 ; do if [ ${n1:0:1} != "#" ]; then let pid=$pid+1 echo ${n1}_${n2}:password:${pid}:${pid}:,,,/home/${n1}_${n2}:/bin/bash fi done
En Debian diversos paquetes proporcionan un intérprete de comandos POSIX:
dash
(Sarge)
ash
(Woody)
bash
pdksh
Si desea escribir scripts de shell portables, resulta conveniente escribirlos
como script de shell POSIX . Use /bin/sh
enlazado con
ash
o (dash
) para comprobar su compatibilidad POSIX.
Evite escribir scripts usando la sintaxis propia del bash o
del zsh que es similar al del csh
). Por ejemplo,
evite usar:
La descripción de los intérpretes de comandos en el presente documento se
aplica únicamente a aquellos del tipo POSIX y no a csh
incluyendo
a tcsh
.
Diversos parámetros especiales para recordar:
$0 = nombre del shell o del script del shell $1 = primer argumento ... $9 = noveno argumento $# = cantidad de parámetros "$*" = "$1 $2 $3 $4 ... $n" "$@" = "$1" "$2" "$3" "$4" ... "$n" $? = estado de salida del comando más reciente $$ = PID del script de shell $! = PID del proceso en segundo plano más reciente
Expansiones de parámetros básicas para recordar:
Forma Si var está Si var inicializada no está inicializada ${var:-cadena} $var cadena ${var:+cadena} cadena null ${var:=cadena} $var cadena (y ejecute var=cadena) ${var:?cadena} $var (repite cadena y luego sale)
Aquí, en realidad, los `:' son opcionales para todos los operadores.
Sustituciones de parámetros básicas para recordar:
Forma Resultado ${var%sufijo} Elimina el patrón sufijo más pequeño ${var%%sufijo} Elimina el patrón sufijo más grande ${var#prefijo} Elimina el patrón prefijo más pequeño ${var##prefijo} Elimina el patrón prefijo más grande
Redireccionamiento básico para recordar (aquí el [n] es un número opcional para especificar el descriptor de archivo):
[n]> archivo Redirige stdout (o n) al archivo. [n]>> archivo Añade stdout (o n) al archivo. [n]< archivo Redirige stdin (o n) desde el archivo. [n1]>&n2 Redirige stdout (o n1) a n2. 2> archivo >&2 Redirige stdout y stderr al archivo. | comando Desvía stdout al comando. 2>&1 | comando Desvía stderr y stdout comando.
Aquí:
El intérprete de comandos le permite abrir archivos usando el comando propio
exec
con un descriptor de archivo arbitrario.
$ echo Hola >loquesea1 $ exec 3<loquesea1 4>loquesea2 # abrir archivos $ cat <&3 >&4 # redirigir stdin a 3, stdout a 4 $ exec 3<&- 4>&- # cerrar archivos $ cat loquesea2 Hola
Aquí n<&- y n>&- significan cerrar el descriptor de archivo n.
Todos los comandos devuelven un estado de salida que se pueden utilizar para expresiones condicionales:
Obsérvese que aquí el valor 0, contrariamente a la convención habitual en otras
áreas de la computación, significa "verdadero". Asimismo, `[' es
equivalente al comando test
, que evalúa sus argumentos hasta `]'
como expresión condicional.
Expresiones condicionales básicas para recordar:
comando && si_éxito_ejecutar_también_este_comando || verdadero comando || si_fracaso_ejecutar_en_cambio_este_comando if [ expresión_condicional ]; then si_éxito_ejecutar_este_comando else si_fracaso_ejecutar_este_comando fi
En este caso || verdadero se necesita para asegurarse que este script de shell no salga accidentalmente en esta línea al invocar el intérprete de comandos con la opción -e.
Los operadores de comparación de archivos en las expresiones regulares son:
-e archivo Verdadero si archivo existe. -d archivo Verdadero si archivo existe y es un directorio. -f archivo Verdadero si archivo existe y es un archivo normal. -w archivo Verdadero si archivo existe y se puede escribir. -x archivo Verdadero si archivo existe y es ejecutable. archivo1 -nt archivo2 Verdadero si archivo1 es más reciente que archivo2 (modificación) archivo1 -ot archivo2 Verdadero si archivo1 es más antiguo que archivo2 (modificación) archivo1 -ef archivo2 Verdadero si son el mismo dispositivo o tienen igual ínodo.
Los operadores de comparación de cadenas en las expresiones condicionales son:
-z str Verdadero si la longitud de str es igual a cero. -n str Verdadero si la longitud de str es distinta de cero. str1 == str2 Verdadero si las str son iguales. str1 = str2 Verdadero si las str son iguales. (debería usarse "=" en vez de "==" para una extricta compatibilidad POSIX) str1 != str2 Verdadero si las str son distintas. str1 < str2 Verdadero si str1 está antes que str2 (depende del local). str1 > str2 Verdadero si str1 está después que str2 (depende del local).
Los operadores de comparación aritmética entera en las expresiones condicionales son -eq, -ne, -lt, -le, -gt o -ge.
El intérprete de comandos procesa un script de la siguiente manera:
Las comillas simples dentro de las dobles no tienen ningún efecto.
Al ejecutar set -x en el intérprete de comandos o al invocar este último con la opción -x hará que se muestren todos los comandos ejecutados. Esto resulta bastante práctico para depurar.
Referencias para Awk:
mawk(1)
y gawk(1)
Pequeño programa de ejemplo (sirve como entrada para el comando
newusers
)
#!/usr/bin/awk -f # Script para crear un archivo que sirva para usar con el comando # newusers a partir de un archivo que contiene las IDs y contraseñas de # los usuarios de la siguiente manera: nombre apellido contraseña # Copyright (c) KMSelf Sat Aug 25 20:47:38 PDT 2001 # Distribuido bajo GNU GPL v 2 o cualquier versión posterior. # Este programa se distribuye SIN NINGUNA GARANTÍA. BEGIN { # Asignar UID, GID iniciales if ( ARGC > 2 ) { startuid = ARGV[1] delete ARGV[1] } else { printf( "Uso: newusers UIDinicial archivo\n" \ "...donde UIDinicial es el ID del primer usuario " \ "a agregar y 'archivo' es \n" \ "un archivo de entrada de la forma: \n"\ "'nombre apellido contraseña'\n" \ ) exit } infile = ARGV[1] printf( "Primer UID: %s\n\n", startuid ) } /^#/ { next } { ++record first = $1 last = $2 passwd = $3 user= substr( tolower( first ), 1, 1 ) tolower( last ) uid = startuid + record - 1 gid = uid printf( "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n", \ user, passwd, uid, gid, first, last, user \ ) }
En Debian dos paquetes proveen awk
POSIX:
mawk
gawk
Este es él intérprete interpreter on a Unix-like system.
Referencias para Perl:
perl(1)
Pequeño programa de ejemplo (sirve como entrada para el comando
newusers
)
#!/usr/bin/perl # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain $pid=1000; while (<STDIN>) { if (/^#/) { next;} chop; $pid++; ($n1, $n2, $n3) = split / /; print $n1,"_",$n2,":", $n3, ":",$pid, ":",$pid,",,,/home/",$n1,"_",$n2,":/bin/bash\n" }
Instalar el módulo Perl nombre módulo:
# perl -MCPAN -e 'install nombre_modulo'
Es un intérprete orientado a objetos muy agradable.
Referencias para Python:
python(1)
Pequeño programa de ejemplo (sirve como entrada para el comando
newusers
)
#! /usr/bin/env python import sys, string # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain # Adaptado del script awk por KMSelf Sat Aug 25 20:47:38 PDT 2001 # Este programa se distribuye SIN NINGUNA GARANTÍA. def usages(): print \ "Uso: ", sys.argv[0], " UID_inicial [nombre_archivo]\n" \ "\tUID_inicial es el ID del primer usuario a agregar.\n" \ "\tnombre_archivo es el nombre del archivo de entrada.\n" \ "Si no se especifica, se toma la entrada estándar.\n\n" \ "Formato del archivo de entrada:\n"\ "\tnombre apellido contraseña\n" return 1 def parsefile(startuid): # # filtrado principal # uid = startuid while 1: line = infile.readline() if not line: break if line[0] == '#': continue (first, last, passwd) = string.split(string.lower(line)) # lo anterior falla con un # equivocado de parámetros :-) user = first[0] + last gid = uid lineout = "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n" % \ (user, passwd, uid, gid, first, last, user) sys.stdout.write(lineout) +uid if __name__ == '__main__': if len(sys.argv) == 1: usages() else: uid = int(sys.argv[1]) #print "# UID empieza desde: %d\n" % uid if len(sys.argv) > 1: infilename = string.join(sys.argv[2:]) infile = open(infilename, 'r') #print "# Leer archivo desde: %s\n\n" % infilename else: infile = sys.stdin parsefile(uid)
Referencias for Make:
make(1)
Variables automáticas sencillas:
Sintaxis de las reglas:
Objetivo: [Prerequisito ... ] [TAB] comando1 [TAB] -comando2 # ignorar errores [TAB] @comando3 # evitar repetición
Aquí [TAB] es un TAB. Cada línea es interpretada por el shell
antes de la sustitución de variables por parte de make
. Utilice
la \ al final de la línea para continuar el script. Utilice
$$ para escribir el $ para las variables de entorno
para un script de shell.
Las reglas implícitas para el objetivo y los prerequisitos se pueden escribir, por ejemplo, así:
%: %.c header.h
o,
%.o: %.c header.h
En este caso, el objetivo contiene el carácter % (exactamente uno de ellos). El % puede corresponderse con cualquier subcadena no vacía en los nombres de los archivos objetivo actuales. Asimismo, los prerequisitos usan % para mostrar cómo se relaciones sus nombres con el nombre del objetivo actual.
Las reglas de sufijo son una forma obsoleta
de definir reglas implícitas para make
. Por compatibilidad, aún
son admitidas en el make
GNU pero, en lo posible, utilice las
reglas de patrón equivalentes:
antigua regla de sufijo --> nueva regla de patrón .c: --> % : %.c .c.o: --> %.o: %.c
Variables automáticas para las reglas anteriores:
foo.o: nuevo1.c nuevo2.c original1.c nuevo3.c $@ == foo.o (objetivo) $< == nuevo1.c (el primero) $? == nuevo1.c nuevo2.c nuevo3.c (los nuevos) $^ == nuevo1.c nuevo2.c original1.c nuevo3.c (todos) $* == `%' patrón correspondiente al patrón objetivo.
Referencia de las variables:
foo1 := bar # Expansión única foo2 = bar # Expansión recursiva foo3 += bar # Añade SRCS := $(wildcard *.c) OBJS := $(foo:c=o) OBJS := $(foo:%.c=%.o) OBJS := $(patsubst %.c,%.o,$(foo)) DIRS = $(dir directory/filename.ext) # Extrae "directory" $(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ...
Ejecute make -p -f/dev/null para ver las reglas automáticas internas.
Preparación:
# apt-get install glibc-doc manpages-dev libc6-dev gcc
Referencias para C:
gcc(1)
each_C_library_function_name(3)
gcc
)
Un simple ejemplo example.c
para compilar con la biblioteca
libm
y obtener el ejecutable run_example
:
$ cat > exemple.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); /* evita el desbordamiento del búfer */ y[10] = '\0'; /* para asegurar que la cadena termine con un '\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
Aquí, -lm se necesita para enlazar la biblioteca
libm y poder así usar sqrt(). La biblioteca
actual se encuentra en el directorio /lib
con el nombre
libm.so.6
que es un enlace lógico a libm-2.1.3.so
.
Observe el último parámetro del texto de salida. Existen más de 10 caracteres a pesar de haber especificado %10s.
El uso de funciones que efectuan operaciones con punteros sin verificar sus
limítes, tales como sprintf
y strcpy
, es censurado
pues no evita las vulnerabilidades que surgen por desbordamiento de búfer.
Utilice, en cambio, snprintf
y strncpy
.
gdb
Preparación:
# apt-get install gdb
Referencias para gdb
:
gdb(1)
http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html
Utilice gdb
para depurar un programa compilado con la opción
-g. Muchos de los comandos se pueden abreviar. La expansión del
tabulador funciona de igual manera que en el shell.
$ gdb programa (gdb) b 1 # coloca un punto de ruptura en la línea 1 (gdb) run arg1 arg2 arg3 # ejecuta programa (gdb) next # va a la siguiente línea ... (gdb) step # avanza un paso ... (gdb) p parm # imprime parámetro ... (gdb) p parm=12 # inicializa el valor del parámetro en 12
Para depurar dentro de Emacs, diríjase a Resumen de los comandos del editor (Emacs, Vim), Sección 11.3.4.
Utilice ldd
para averiguar las dependencias de un programa con
respecto a las bibliotecas:
$ ldd /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 ls
funcione en un entorno chroot
, deben esta
disponibles las mencionadas bibliotecas.
Pueden también resultar útiles los siguientes comandos.
strace
: rastrea las señales y llamadas al sistema
ltrace
: rastrea las llamadas a las bibliotecas
Existen diversas herramientas de detección de fugas de memoria disponibles en Debian.
njamd
valgrind
dmalloc
electric-fence
memprof
memwatch
(el paquete no existe, obténgalo de memwatch
.)
mpatrol
leaktracer
libgc6
Parasoft
. (propietario, commercial
for fee)
También consulte Herramientas
de depuración para la asignación de almacenamiento dinámico y administración de
memoria
.
flex
es un generador de analizadores sintácticos muy veloz.
Referencias para flex
:
flex(1)
Necesita proporcionar su propia main()
y yywrap()
, o
su programa.l
se vería así al compilar sin la biblioteca
(yywrap
es una macro; %option main activa en forma
implícita a %option noyywrap):
%option main %% .|\n ECHO ; %%
Alternativamente, puede compilar con la opción -lfl del enlazador
al final de la línea de comando de cc
(como ATT-Lex con
-ll). En este caso no se necesita la %option.
En Debian diversos paquetes proporcionan un generador de analizadores LALR compatible con Yacc:
bison
: generador de analizador LALR GNU
byacc
: el generador de analizador LALR de Berkeley
byyacc
: generador de analizador con backtracking basado en byacc
Referencias para bison
:
bison(1)
Necesita proporcionar su propia main()
y yyerror()
.
main()
llama a yyparse()
que llama a
yylex()
que ha sido generalmente creada con FleX.
%% %%
autoconf
es una herramienta para crear scripts de shell que
automáticamente configuran los paquetes con código fuente para adaptarlos a
distintos tipos de sistemas tipo UNIX que utilizan el sistema de compilación
GNU.
autoconf
crea el script de configuración configure
.
configure
crea automáticamente un Makefile
y un
Makefile.am
personalizados.
Debian no toca los archivos situados en /usr/local
(véase En apoyo a la diversidad, Sección 2.5).
Por lo tanto, si compila un programa a partir de sus fuentes, instálelo en
/usr/local
de modo que no interfiera con Debian.
$ cd src $ ./configure --prefix=/usr/local $ make $ make install # esto ubica los archivos en el sistema
SI cuenta con los fuentes, SI éstos utilizan
autoconf
/automake
y SI puede recordar cómo lo
configuró:
$ ./configure todas-las-opciones-que-eligió # make uninstall
Alternativamente, si está absolutamente sequro que el proceso de instalación
ubicó todos los archivos únicamente en /usr/local/
y que no hay
nada importante allí, puede borrar todo su contenido haciendo:
# find /usr/local -type f -print0 | xargs -0 rm -f
Si no está seguro dónde fueron instalados los archivos, considere el uso de
checkinstall
que permite desinstalaciones limpias.
Tradicionalmente, roff es el sistema de tratamiento de texto principal de Unix.
Véase roff(7)
, groff(7)
, groff(1)
,
grotty(1)
, troff(1)
, groff_mdoc(7)
,
groff_man(7)
, groff_ms(7)
, groff_me(7)
,
groff_mm(7)
e "info groff".
Existe un buen tutorial sobre macros -me
. Si tiene groff (1.18 o
posterior), busque /usr/share/doc/groff/meintro.me.gz
y haga lo
siguiente:
$ zcat /usr/share/doc/groff/meintro.me.gz | \ groff -Tascii -me - | less -R
Lo que sigue creará un archivo de texto:
$ zcat /usr/share/doc/groff/meintro.me.gz | \ GROFF_NO_SGR=1 groff -Tascii -me - | col -b -x > meintro.txt
Para imprimir use la salida PostScript.
$ groff -Tps meintro.txt | lpr $ groff -Tps meintro.txt | mpage -2 | lpr
Preparación:
# apt-get install debiandoc-sgml debiandoc-sgml-doc
Referencias de debiandoc-sgml
:
/usr/share/doc/debiandoc-sgml-doc
debiandoc-sgml(1)
DocBook:
The Definitive Guide
, de Walsh y Muellner, (O'Reilly) (paquete
docbook-defguide
)
SGML permite la creación de múltiples formatos de un mismo documento. Un sistema SGML sencillo es Debiandoc que es el que se usó aquí. Este requiere de pequeñas adaptaciones en los archivos de texto originales para los siguientes caracteres:
Para marcar una sección como comentario, escriba:
<!-- El tema empieza aquí ... -->
Para marcar una sección que necesita modificarse, escriba:
<![ %FIXME [ El tema empieza aquí ... ]]>
En SGML, la primer definición de una entidad gana. Por ejemplo:
<!entity % qref "INCLUDE"> <![ %qref [ <!entity param "Datos 1"> ]]> <!entity param "Datos 2"> ¶m;
Esto finaliza como "Datos 1". Si en la primer línea figurara "IGNORE" en vez de "INCLUDE" finalizaría como "Datos 2" (la segunda línea es una sentencia condicional). Asimismo, las frases que se repiten se pueden definir de antemano separadas del contexto.
<!entity esto "mi"> Hola &esto; amigo. Este es &esto; libro.
Esto resulta en lo siguiente:
Hola mi amigo. Este es mi libro.
Vea el pequeño ejemplo en SGML sample.sgml
en los ejemplos
.
Cuando los documentos SGML aumentan de tamaño TeX, que es utilizado como interfaz del procesador de texto, puede provocar,a veces, errores TeX/LaTeX, Sección 13.8.3.
Preparación:
# tasksel # seleccionar Miscelánea --> Entorno TeX/LaTeX
Referencias para LaTeX:
The teTeX HOWTO: The
Linux-teTeX Local Guide
tex(1)
latex(1)
Éste es el entorno más poderoso para la composición de documentos. Muchos
procesadores SGML lo utilizan como su procesador de texto. Lyx proporcionado
por lyx
, lyx-xforms
o lyx-qt
y GNU
TeXmacs, proporcionado por el paquete texmacs
, ofrecen un entorno
de edición WYSIWYG agradable para LaTeX mientras que muchos utilizan a Emacs y
Vim como editores de los archivos fuente.
Existen diversos recursos disponibles en Internet:
teTeX - A Documentation
Guide
(paquete tetex-doc
)
A Quick Introduction
to LaTeX
A Simple
Guide to Latex/Lyx
Word
Processing Using LaTeX
Local
User Guide to teTeX/LaTeX
Cuando los documentos SGML aumentan de tamaño TeX puede, a veces, provocar
errores. Debe incrementar el tamaño del repositorio en
/etc/texmf/texmf.cnf
(o mejor editar
/etc/texmf/texmf.d/95NonPath
y ejecutar update-texmf
)
para solucionarlo.
En vez de escribir código que contenga documentación, el programador ilustrado escribe documentación que contiene código. Este enfoque asegura una buena documentación del programa.
Para más información sobre programación ilustrada, véase Literate Programming
.
Preparación:
# apt-get install nowebm
Referencias para Noweb:
Esta herramienta de la programación ilustrada del tipo WEB es mucho más
sencilla ya que provee extensibilidad e independencia de lenguaje. [22] Cuando se invoca
noweb
, escribe el código fuente del programa en los archivos
mencionados en el archivo noweb y crea un archivo TeX para la composición de la
documentación.
El paquete Debian ifupdown
es un buen ejemplo.
$ apt-get source ifupdown $ cd ifupdown* $ make ifupdown.pdf ifupdown.ps
Preparación:
# apt-get install doxygen doxygen-doc doxygen-gui
Referencias para Doxygen (¡creado por doxygen
!):
Puede generar documentación HTML, RTF, páginas de manual Unix, PostScript y PDF
(usando LaTeX) para C++, C, Java, IDL y, con en cierto grado, para programas en
PHP y C#. Doxygen es compatible con JavaDoc (1.1), Qt-Doc, KDOC y fue
específicamente diseñado para ser usado en proyecto que utilizan el conjunto de
herramientas Qt
de Troll
Tech. Al crear incluye gráficos de dependencia, diagramas de colaboración y
gráficos jerárquicos incluso para programas no documentados. La salida es
similar a la de la documentación Qt.
Preparación:
# apt-get install debian-policy developers-reference \ maint-guide dh-make debhelper # apt-get install packaging-manual # en el caso de Potato
Referencias para la creación de paquetes:
dh-make(1)
Método rápido para empaquetar un único binario por Joey Hess.
# mkdir -p mi_pqt/usr/bin mi_pqt/DEBIAN # cp binario mi_pqt/usr/bin # cat > mi_pqt/DEBIAN/control Package: mi_paquete Version: 1 Architecture: i386 Maintainer: Joey Hess <joeyh@debian.org> Description: mi pequeño paquete No espere demasiado. ^D # dpkg-deb -b mi_pqt
Utilice dh_make
del paquete dh-make
para crear la
arquitectura del paquete. Luego, proceda de acuerdo a las instrucciones de
dh-make(1)
que utiliza debhelper
en
debian/rules
.
Otro enfoque consiste en usar deb-make
del paquete
debmake
que no utiliza los scripts de debhelper
y
depende únicamente del intérprete de comandos.
Para ejemplos de múltiples paquetes fuente, véase "mc"
(dpkg-source -x mc_4.5.54.dsc) que utiliza
"sys-build.mk" por Adam Heath (doogie@debian.org
) y
"glibc" (dpkg-source -x glibc_2.2.4-1.dsc) que utiliza
un sistema diferente de Joel Klecker (espy@debian.org
).
Guía de referencia Debian
CVS, lun abr 3 22:57:45 UTC 2005osamu@debian.org
wecharri@infovia.com.ar