28 oct 2010

Miscelánea: Límites por proceso y usuario, introduccion a la virtualización....

Tema final del curso

He dejado abierto el final del curso para preparar algun tema que interese a los asistentes.
Los asistentes me han comentado que les interesa:

- Limites por proceso y usuario
- Virtualización
- Monitorización del sistema operativo, especialmente de la memoria



Límites por proceso y usuario

Cuando un usuario se conecta a un sistema, el entorno tiene límites para varias cosas, de las cuales, algunos interesantes son:

- Tamaño máximo de stack (stack - kbytes): Necesario si recibimos un error de stack más pequeña.
- Número máximo de ficheros abiertos por proceso (nofiles - descriptors): Necesario para aplicaciones que soporten muchas conexiones
- Tamaño máximo de fichero (filesize - kbytes): En caso de que intentemos guardar un fichero más grande que el tamaño máximo

La shell de Linux tiene un límite interesante más:

- Número máximo de procesos por usuario (maxprocs): Interesante para evitar fork bombs.

El sistema tiene un límite "absoluto" que se llama "límite hard". El límite por defecto que impone la shell se llama "límite soft". La shell permite subir los límites "soft" al usuario hasta que llegan al límite "hard", que sólo se puede subir a nivel de superusuario, muchas veces tocando el kernel.
La sintaxis para subir el límite "soft" es distinta según la shell.

Operación

SH/KSH/BASH

CSH/TCSH

Ver límite soft


ulimit -a
o bien
ulimit -S -a

limit

Ver límite hard

ulimit -H -a

limit -h

Subir limite de stack size
a 128 MB (131072 kB)

ulimit -s 131072

limit stacksize 128m

Límite de descriptores
por proceso a 8192

ulimit –n 8192

limit descriptors 8192

Límite de fichero más grande a 4GB

ulimit -f 4194304

limit filesize 4194304

Número máximo de procesos por usuario (bash)

ulimit -u 1000

---

El administrador puede subir los "límites duros" según el sistema operativo.

Por ejemplo, para el número máximo de descriptores por proceso:

  • Solaris, hay que editar /etc/system y cambiar las siguientes entradas, después reiniciar el sistema.
set rlim_fd_max = 8192
set rlim_fd_cur = 1024

A los usuarios, entonces le aparecería por defecto un límite de 1024 y se podrían subir con ulimit -n/limit descriptors hasta 8192.

  • AIX, en /etc/security/limits
  • Linux, en /etc/security/limits.conf
Estos son, en Linux, los límites que se pueden configurar en limits.conf

# - core - limits the core file size (KB)
# - data - max data size (KB)
# - fsize - maximum filesize (KB)
# - memlock - max locked-in-memory address space (KB)
# - nofile - max number of open files
# - rss - max resident set size (KB)
# - stack - max stack size (KB)
# - cpu - max CPU time (MIN)
# - nproc - max number of processes
# - as - address space limit
# - maxlogins - max number of logins for this user
# - maxsyslogins - max number of logins on the system
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
# - sigpending - max number of pending signals
# - msgqueue - max memory used by POSIX message queues (bytes)
# - nice - max nice priority allowed to raise to
# - rtprio - max realtime priority


Conectividad TCP/IP

ifconfig, netstat -r, netstat -a, lsof, traceroute.

Virtualización

Zonas.
En Solaris, una zona es un entorno virtual del sistema operativo creada dentro de una instancia de Solaris. La meta de esta tecnología es una utilización eficiente de los recursos del sistema operativo. Cuando instalamos Solaris 10, nos viene una zona por defecto llamada zona global.
 % zoneadm list -v
ID NAME STATUS PATH
0 global running /
Si queremos crear una zona local, necesitamos
  • Al menos 2GB para copiar los ficheros esenciales a la zona local.
  • Una dirección IP para la nueva zona.
Por ejemplo, si tenemos 5GB disponibles en el filesystem /zones y nos han dado la IP 192.168.175.126, utilizaremos el comando zonecfg para crear una zona nueva.

% mkdir /zones/appserv % chmod 700 /zones/appserv % zonecfg -z appserv appserv: No such zone configured
 Use 'create' to begin configuring a new zone.
zonecfg:appserv>
create
zonecfg:appserv>
set zonepath=/zones/appserver
zonecfg:appserv>
set autoboot=true
zonecfg:appserv>
add net
zonecfg:appserv:net>
set physical=eri0
zonecfg:appserv:net>
set address=192.168.175.126
zonecfg:appserv:net>
end
zonecfg:appserv>
add fs
zonecfg:appserv:fs>
set dir=/repo2
zonecfg:appserv:fs>
set special=/dev/dsk/c2t40d1s6
zonecfg:appserv:fs>
set raw=/dev/rdsk/c2t40d1s6
zonecfg:appserv:fs>
set type=ufs
zonecfg:appserv:fs>
set options noforcedirectio
zonecfg:appserv:fs>
end
zonecfg:appserv>
add inherit-pkg-dir
zonecfg:appserv:inherit-pkg-dir>
set dir=/opt/csw
zonecfg:appserv:inherit-pkg-dir>
end
zonecfg:appserv>
info
zonepath: /zones/appserver
autoboot: true
pool:
inherit-pkg-dir:
dir: /lib
inherit-pkg-dir:
dir: /platform
inherit-pkg-dir:
dir: /sbin
inherit-pkg-dir:
dir: /usr
inherit-pkg-dir:
dir: /opt/csw
net:
address: 192.168.175.126
physical: eri0
zonecfg:appserv>
verify
zonecfg:appserv>
commit
zonecfg:appserv>
exit
En este enlace podemos seguir el proceso de creación explicado y detalles.

DLPAR

En AIX DLPAR significa Dynamic Logical Partitions.

Una partición lógica a nivel de hardware es una división de recursos hardware para formar sistemas lógicos. Se pueden instalar múltiples sistemas operativos que ejecuten en las CPUs de IBM (Power4) y niveles de AIX en las particiones logicas. Los recursos no se comparten entre las particiones, y cada partición tiene su interfaz de red, dirección IP, etc.
Se administran con la HMC, hardware management console.

Solamente se puede particionar en sistemas que tengan el soporte físico para ello.


27 oct 2010

Gestión de software

Instalación de software

Siendo la nuestra una compañía de software, tenemos un buen conocimiento de instalación de software en Windows (en realidad, algunos más que otros).

En el sistema operativo de Microsoft es prácticamente obligado mantener una política de instalación estándar para que un software sea aceptado en muchas de las organizaciones que lo despliegan. De hecho, Windows Installer y los archivos de instalación .msi son prácticamente exigidos por cualquier técnico de sistemas de cualquier organización.

En UNIX, no hay un estándar tan claro. Es más frecuente encontrarse las siguientes situaciones:

- Software distribuído como código fuente que hay que compilar. Hay que estar familiarizado con el comando configure, make (o más frecuentemente gmake) y tener instalado el compilador de C++ (gcc suele ser el que triunfa en estas cosas). Cuando tenemos un error, tendremos que recurrir a nuestro conocimiento de desarrollo C++ en UNIX multiplataforma para arreglarlo, lo que convierte en difícil cualquier esfuerzo de "portabilidad".

- Software del que se distribuyen los binarios "sueltos": Por ejemplo, Apache Tomcat. Se distribuye un fichero.tar.gz, que descomprimimos y desempaquetamos, como vimos en un capítulo anterior, y posteriormente configuramos manualmente, con nuestro editor. También es frecuente que el sofware venga acompañado por un script, Korn Shell, Perl o similar, para realizar una configuración básica de sus ficheros de configuración, etc.

- Software que se proporciona con los binarios empaquetados por un instalador que "emula" los de Windows (por ejemplo una interfaz Java). Este instalador puede ir desde a realizar una configuración sencilla en el software distribuido, a requerir instalarse como superusuario y hacer todo tipo de configuraciones, no sólo en el software, sino también en el sistema (como los instaladores de grandes productos de IBM tipo WebSphere).

- Software empaquetado con el estándar de paquetes del sistema. Desafortunadamente, el estándar de paquetes de sistema requiere la instalación como superusuario (cosa que no siempre es necesaria para un software). También hay que tener en cuenta que cada sistema UNIX ha decidido que la forma estándar de instalar paquetes es distinta.

Estándares de paquetes

Solaris:

En Solaris el sistema de instalación estándar de los paquetes se origina atrás en System V. Los comandos para instalar paquetes empiezan por pkg*. Para ejecutar los comandos pkg* que listan el software o que transfieren de formato comprimido a formato expandido no se requieren privilegios especiales, pero para instalar o desinstalar, es necesario ser superusuario.

El famosísimo sitio de software de libre distribución http://sunfreeware.com tiene los paquetes en este formato.

Cuando Solaris se ramificó en OpenSolaris, se inventaron un nuevo sistema de packages, porque el sistema clásico va un poco mal con el tema de instalaciones distribuidas o de control de las dependencias.

Ejercicio:
Instalar un paquete de sunfreeware en un sistema Solaris

Paso 1: Descargar top-3.6.1-sol10-sparc-local.gz en, por ejemplo, $HOME/download
Paso 2: Descomprimir en directorio propio: gunzip $HOME/download/top-3.6.1-sol10-sparc-local.gz
Paso 3: Hacernos superusuario
Paso 4: Desempaquetar con pkgrans al directorio /var/spool/pkg: pkgtrans $HOME/download/top-3.6.1-sol10-sparc-local /var/spool/pkg

The following packages are available:
1 SMCtop top
(sparc) 3.6.1

Select package(s) you wish to process (or 'all' to process
all packages). (default: all) [?,??,q]:

(si no queremos escribir en el spool, podemos hacerlo a cualquier otro directorio, no como root)

Paso 5: Instalar: pkgadd -d /var/spool/pkg

# pkgadd -d .

The following packages are available:
1 SMCtop top
(sparc) 3.6.1

Select package(s) you wish to process (or 'all' to process
all packages). (default: all) [?,??,q]:

Processing package instance from

top(sparc) 3.6.1
LeFebvre et al


AIX: Los paquetes de AIX están empaquetados en un formato de fichero con extensión .bff conocido como Backup File Format. El comando que los instala se llama installp. Como siempre, es mucho más fácil hacer cualquier cosa con el smit que directamente con el comando, por la miríada de opciones que hay que aprenderse (es decir, todo el mundo prefiere invocar smit easy_install o smit install_software). Para listar los paquetes instalados, podemos usar smit list_installed_software, mucha gente se sabe el comando lslpp -a.

Un sitio muy famoso de paquetes de AIX es http://www.bullfreeware.com


HP-UX: Para instalar software, se tiene una familia de comandos de utilización similar a la de Solaris, pero con mucha más complejidad. Los comandos empiezan por sw*. Listar el software con swlist nos produce una lista de todo lo que hay instalado. Los parches se instalan con estos comandos, y el sistema de gestión de sofware tenía una funcionalidad para conectarse a un repositorio de parches (software depot) y traérselos todos.

Linux: En el mundo Linux hay dos familias de empaquetamiento de software, la de Debian (ficheros .deb, se manejan con el comando dpkg) y la de Red Hat (Red Hat Package Manager, ficheros .rpm, se manejan con el comando rpm), que no sólo es utilizado por Red Hat, sino también por Fedora o SuSE.

Es relativamente fácil transformar un package de un formato a otro con herramientas como alien (k
itenet.net/programs/alien), aunque mejor usar los packages relativos a nuestra distribución.

Por encima de los ficheros .rpm y .deb hay herramientas de gestión de sofware que nos instalan y desinstalan, preguntan y actualizan.

Por encima de todo esto aún existen herramientas que analizan dependencias entre paquetes (las metaherramientas), y que son capaces de realizar actualizaciones de red. Los principales son yum, que funciona con el sistema RPM, RHN que es específico para Red Hat Linux, y Debian Advanced Package Tool (APT), que aunque empezó trabajando con packages Debian ahora trabaja con todo.

El comando rpm: Instala, verifica, y pregunta. Antiguamente también construía packages, pero ahora la funcionalidad se ha pasado a un comando adicional llamado rpmbuild. Dependiendo de si entramos en modo instalación o pregunta (--install o --query), el comando tiene un comportamiento específico (opciones a ver: --install, --upgrade, --erase, o --query)

El comando dpkg: Lo mismo pero en el mundo Debian. Las opciones a ver son --install, --remove, y -l para listar los packages. Si instalamos uno que ya está instalado, nos sobreescribe sin piedad el anterior. Por ejemplo, supongamos que tenemos instalado el paquete nvi, y hacemos esto:

# dpkg --install ./nvi_1.79-16a.1_i386.deb
(Reading database ... 24368 files and directories currently installed.)
Preparing to replace nvi 1.79-14 (using ./nvi_1.79-16a.1_i386.deb) ...
Unpacking replacement nvi ...
Setting up nvi (1.79-16a.1) ...
Checking available versions of ex, updating links in /etc/alternatives ...
(You may modify the symlinks there yourself if desired - see 'man ln'.)
Leaving ex (/usr/bin/ex) pointing to /usr/bin/nex.
Leaving ex.1.gz (/usr/share/man/man1/ex.1.gz) pointing to
/usr/share/man/man1/nex.1.gz.

Como vemos, se enrolla como las persianas. Podemos emplear el flag -l para buscar por un patrón.

$ dpkg -l nvi
Desired=Unknown/Install/Remove/Purge
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
| / Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
| | / Name Version Description
+++-===========-==============-================================
i i nvi 1.79-16a.1 4.4BSD re-implementation of vi.

Meta gestion de packages: Las herramientas de meta gestión de paquetes sirven para simplificar la localización de paquetes, automatizar la instalación o actualización y facilitar la gestión de interdependencias. Quedémonos con los dos nombres yum y APT, sepamos que en Fedora12 por defecto viene yum, aunque APT con rpms también funcionaría.


Ejercicio de este tema
Instalar el cluster de parches recomendados en Solaris
Instalar un package de Solaris
Instalar un package rpm en Fedora12



Bibliografía:
Recomiendo la lectura del capítulo 12 de Nemeth et al.

Instalar el sistema operativo
Installing Linux and OpenSolaris. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
Netbooting PCs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
Setting up PXE for Linux. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
Netbooting non-PCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 364
Using Kickstart: the automated installer for Red Hat Enterprise Linux. . . 365
Setting up a Kickstart configuration file . . . . . . . . . . . . . . . . . . . . . . . . . 365
Building a Kickstart server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
Pointing Kickstart at your config file. . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
Using AutoYaST: SUSE’s automated installation tool . . . . . . . . . . . . . . . . . 367
Automating installation with the Ubuntu installer . . . . . . . . . . . . . . . . . . . . 368
Installing Solaris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
Network installations with JumpStart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 371
Network installations with the Automated Installer . . . . . . . . . . . . . . . . . . . 375
Installing HP-UX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
Automating Ignite-UX installations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
Installing AIX with the Network Installation Manager . . . . . . . . . . . . . . . . . . . . 380

Gestión de paquetes

Managing packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 381
Managing Linux packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
rpm: manage RPM packages. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
dpkg: manage .deb packages in Ubuntu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 383
Using high-level Linux package management systems. . . . . . . . . . . . . . . . . . . . . 384
Package repositories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
RHN: the Red Hat Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
APT: the Advanced Package Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 387
apt-get configuration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 388
An example /etc/apt/sources.list file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389
Creation of a local repository mirror. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
apt-get automation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
yum: release management for RPM. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
Zypper package management for SUSE: now with more ZYpp! . . . . . . . . . 392

Managing packages for UNIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393
Solaris packaging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
HP-UX packaging. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
Software management in AIX. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396

Control de versiones, entornos de desarrollo

Revision control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
Backup file creation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
Formal revision control systems. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
Subversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399
Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401

Software localization and configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 404
Organizing your localization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405
Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 406
Compiling locally . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
Distributing localizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
Using configuration management tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
cfengine: computer immune system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 408
LCFG: a large-scale configuration system. . . . . . . . . . . . . . . . . . . . . . . . . . . . 409
Template Tree 2: cfengine helper. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
DMTF/CIM: the Common Information Model . . . . . . . . . . . . . . . . . . . . . . 410
Sharing software over NFS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
Package namespaces. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 411
Dependency management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 412
Wrapper scripts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413

10 oct 2010

Impresión

Introducción a la impresión

Las distintas implementaciones de UNIX soportan la impresión de forma distinta.

Históricamente, para imprimir un documento teníamos que saber si estábamos en un sistema tipo BSD, SystemV, o AIX.

El mundo era de las impresoras de línea de puerto serie y todos los trabajos de impresión eran trabajos que se enviaban a una cola, del que un daemon los sacaba.

Con el tiempo, algunos sistemas han pasado a soportar ambas familias de comandos de impresión. En especial AIX ha incorporado un sistema completo de impresión System V.

En Linux ha surgido un sistema moderno de impresión llamado CUPS que acepta la realidad de que ahora mismo la mayoría de impresoras son dispositivos complejos con su propia dirección de red, por las que comunicarse por un protocolo Cliente/Servidor.

Comandos BSD

El sistema BSD se basa en que hay un daemon llamado lpd, al que los usuarios llaman con el comando lpr.
  • Imprimir: Para imprimir un fichero en un sistema tipo BSD hay que usar el comando lpr.
lpr [argumentos] fichero
lpr [argumentos]

Si imprimimos a la impresora por defecto $lpr fichero.txt
Si imprimimos a otra impresora $lpr -Pprinter fichero.txt
Si no queremos que se imprima el banner $lpr -Pprinter -h fichero.txt

  • Para ver los trabajos de impresión: lpq -Pprinter
  • Para cancelar un trabajo: lprm -Pprinter 11042
  • Para ver las opciones e impresoras configuradas está el fichero /etc/printcap.
    Las impresoras se pueden definir como de texto o de postscript. Entonces si vamos a imprimir texto hay que elegir una impresora de texto
Yo tuve que configurar /etc/printcap en el difunto Digital UNIX y soportar una impresora local de línea para una máquina AlphaServer. Una impresora tenía una pinta como esta:

printer|PLJ-H1998:\       :lp=/dev/null:\       :sd=/var/spool/lpd/PLJ-H1998:\       :lf=/var/spool/lpd/PLJ-H1998/errores:\       :if=/var/spool/lpd/PLJ-H1998/filtro_entrada:\       :mx#0:\       :sh:\       :sf:

¿Qué significan los campos en /etc/printcap?

sd ------------ Spool directory sd=/var/spool/lpd/howler-lw
lf ------------ Error log file lf=/var/log/lpr
lp ------------ Device name lp=/dev/lp0
af ------------ Accounting file af=/usr/adm/lpr.acct
rm ------------ Remote machine name rm=beast.xor.com
rp ------------ Remote printer name rp=howler-lw
of ------------ Output filter of=/usr/libexec/lpr/lpf
if ------------ Input filter if=/usr/sbin/stylascii
mx ------------ Maximum file size mx#0
sh ------------ Suppress headers s

Comandos System V
  • Imprimir: Para imprimir en un sistema tipo System V (Solaris) hay que utilizar lp
lp [argumentos] fichero
lp [argumentos]

Si imprimimos a la impresora por defecto $lp fichero.txt
Si imprimimos a otra impresora $lp -dprinter fichero.txt.
Si no especificamos ninguna impresora con -d se mira la variable $LPDEST
Si no queremos que se imprima el banner $lp -dprinter -h fichero.txt

  • Ver las colas de impresión Para ver las cola de impresión, lpstat -a.
  • Cancelar un trabajo: cancel
  • Configurar la impresora. El comando a usar es lpadmin. Este comando modifica los ficheros en /var/spool/lp (que no hay que tocar directamente). En Solaris hay un fichero único tipo printcap, que está en /etc/printers.conf.
Un resumen de comandos System V
lp Encola los trabajos

accept Acepta los trabajos
cancel Cancela los trabajos
disable Deshabilita la cola
enable Habilita la cola

lpadmin Configura el sistema de impresión
lpshut Para el servicio de impresión
lpstat Informa sobre el estado de las colas

lpmove Cambia trabajos de cola
lpsched Planifica impresiones

Solaris
lpget Reads configuration settings
lpset Modifies configuration settings
lpfilter Controls print filters

¿De qué forma se define una impresora en Solaris?
En teoría habría que encontrar las opciones "correctas" de lpadmin, pero en la práctica, el administrador tiene más fácil recurrir a admintool o herramientas similares de ayuda.

El caso de AIX
AIX implementó un sistema de colas propietario que además de trabajos de impresión podía encolar cualquier cosa. El comando para interactuar con este sistema se llamaba enq. Para minimizar la confusión a usuarios provenientes de sistemas tipo BSD o SystemV, incluye los comandos lp y lpr, pero solamente como frontend de enq.

enq manda trabajos a una "cola", definida en el fichero /etc/qconfig, del siguiente estilo:

lp0:
device = pdev0
pdev0:
file = /dev/lp0
header = never
backend = /usr/lpd/piobe

En este fichero se ve que hay una cola lp0 asociada al dispositivo de impresora pdev0, que tiene tres parámetros de configuración (device file, header, backend - programa que envía realmente los trabajos a imprimir).

El daemon de impresión es qdaemon.
Para saber cómo van las colas: qchk, lpstat, or enq -A
La sintaxis del comando enq es complicada, los que venimos de imprimir en SystemV o BSD preferimos acordarnos de esto:
   lpr -P printer /etc/motd 
que de esto:
   enq -P printer -c -Bgn /etc/motd
Para crear la cola de impresión, los dispositivos, smit nos lo hace de una forma muy intuitiva.

CUPS

CUPS es el acrónimo de Common Unified Printing System y es lo que se viene usando en Linux como "servidor de impresión". A diferencia de los sistemas clásicos de impresión, CUPS se "encarga de todo".

CUPS reemplaza completamente los sistemas clásicos y consta de:
  • demonio de impresión (cupsd): Vigila los directorios spool buscando trabajos que imprimir.
  • cola de impresión (/var/spool/cups/): Directorio que almacena los trabajos a imprimir.
  • drivers PPD para impresoras postscript o filtro que traduzca el documento generado por la aplicación a un lenguaje entendible por la impresora (el fichero necesario para caracterizar a una impresora se llama PPD - Postscript Printer Description - y si no se puede encontrar en linuxprinting.org, se busca foomatic (paquete foomatic-db-engine), que proporciona el archivo PPD y los filtros necesarios para traducir los documentos (trabaja sobre GhostScript).
  • comandos de usuario de interfaz con el sistema: clonados de los clásicos (tanto SysV como BSD) por compatibilidad: lpr (o lp) para enviar a imprimir, lprm para borrar, etc.
  • comandos de administración: los clásicos lpstat, lpinfo...
  • una interfaz web de administración
En Linux, para instalar una impresora:
- Conectamos la impresora
- Conseguimos el archivo PPD
- Instalamos foomatic
- Reiniciamos el cupsd (/etc/init.d/cupsys restart)
- El interfaz web de administración está en el puerto 631


Bibliografía


Sistema X Windows

Introducción

El sistema X Windows (también conocido como X11, porque fue la versión 11 de este software desarrollado en el MIT a principios de los 80 la que alcanzó mayor estabilidad, en el año 87) está presente en la mayoría de interfaces gráficas de sistemas UNIX y Linux.

En sistemas Linux se hizo famosa la implementación de X11 proporcionada por XFree86, aunque recientemente se ha desplazado en favor de la ramificación mantenida por X.Org.

Conceptos básicos: display, screen, pointer, window

El sistema X11 se diseño para permitir que la salida gráfica de un programa se mostrara en otra máquina, posiblemente remota y de distinta arquitectura.

En el diseño de X11, se habla de "display" como la "máquina" en la que aparecerá la salida gráfica. Un "display" puede tener un ratón y un teclado pero muchos monitores (no es común pero puede suceder) o "screens".

Finalmente una "ventana" es un área rectangular de la pantalla que se usa para entrada y salida. El área rectangular no cubre la "screen" entera, sino que reside en memoria (una ventana es sólo un rectángulo, no tiene asociado ni barra de desplazamiento vertical y horizontal ni otras cosas que nos hemos familiarizado en otros sistemas operativos).

En la documentación original de X11 se habla de "pointer" en lugar de "ratón" porque aún no se sabía a ciencia cierta si el ratón iba a triunfar :)

El cliente y el servidor

En X11, el cliente es la aplicación que manda sus datos al servidor gráfico, que es un programa que corre en la máquina que tiene la pantalla. El servidor es un programa que maneja los recursos gráficos.

Esto causa confusión a veces, porque el "cliente X11" se ejecuta en la máquina "servidor UNIX" y el "servidor X11" en el "desktop".

Window Managers

X11 comprende un protocolo de red específico y una definición de primitivas gráficas, sin embargo no especifica nada de interfaz de usuario (botones, menús o barras de título). La componente que controla la interfaz de usuario que corre sobre X11 es un "Window Manager".

Prácticamente todo lo que aparece en una pantalla X11 es una ventana. El "Window Manager" controla su apariencia y su comportamiento.

Ejemplos de Windows Managers:

Desktop

Un desktop es otra cosa que un Window Manager. Un desktop es un conjunto de aplicaciones que dan una experiencia al usuario, pueden incluir (o no) un Window Manager.

Ejemplos de Desktop:
- CDE: (Common Desktop Environment) es el entorno gráfico en el que se pusieron de acuerdo un número importante de vendedores de sistemas operativos UNIX con el fin de estandarizar el aspecto del "escritorio" (en concreto, Sun, IBM y HP). Desde 1996 el CDE es responsabilidad del consorcio de estándares The Open Group. Se basa en el paquete de librerías Motif.

- KDE: Un entorno gráfico nacido a finales de los 90 (que yo conocí cuando estaba en beta) muy interesante y con herramientas adicionales. Aunque hay versiones para Solaris, MacOS X e incluso Windows, por lo que se ha hecho famoso ha sido por el "Plasma Desktop", que viene por defecto en algunas distribuciones de Linux como openSuSE. Ahora mismo KDE no sólo es el entorno gráfico, sino que es la marca que abarca también otro software como Amarok que es un famoso reproductor de música para Linux. Las librerías en las que se basa son las librerías Qt.

- GNOME: Diseñado originalmente para Linux, como alternativa a KDE porque en su momento las librerías no eran "libres", en Solaris empezó a distribuirse por defecto a partir de Solaris 9, discontinuándose un entorno anterior llamado OpenWindows (nacido en 1989). Sus librerías gráficas son las GTK+.


Ejecución de X11
Cuando abrimos una sesión gráfica, el gestor de ventanas X11 suele estar arrancado y no nos tenemos que preocupar de nada. Si entramos en línea de comandos, puede ser que tengamos que iniciar X11 (startx o xinit). Al inicio de X, se arranca lo que se conoce como "gestor de ventanas".

Abriendo un programa gráfico
El problema clásico de un usuario X es intentar abrir un programa remoto desde la máquina local, siendo la máquina local el "display". Supongamos que el programa es el famoso xeyes.

Los pasos a realizar son:

A - Averiguar el nombre de la máquina local o "display"
B - (Opcional) Dar permiso a la máquina "remota" para usar el "display".
C - Logarse a la máquina "remota"
D - Decirle a la máquina "remota" dónde anda el "display"
E - Abrir la aplicación
F - Salir

En más detalle:

A) Vamos a ejecutar la aplicación xeyes en la máquina luna (no es en la que estamos sentados) xeyes necesita saber en qué display abrirse. El nombre del display se puede elegir mediante una variable de entorno que se llama DISPLAY, en cuyo valor se emplea la sintaxis:

Si estamos sentados en una máquina llamada pluton y tenemos tcsh
setenv DISPLAY pluton:0.0

B) Si estamos sentados en una máquina UNIX (pluton), tendremos que dar permiso en el sistema pluton para que el sistema luna pueda emplear su consola. Esto en ciertos emuladores de ventanas Windows no es necesario porque "viene hecho" al establecer la conexión.

luna> xhost luna

Si queremos denegar el permiso de que la máquina plutón use la pantalla de luna:

luna> xhost -luna

Si queremos exponernos a que nos secuestren el display

luna> xhost +

C) Nos logamos a la máquina remota.
      1. El comando xterm crea una nueva ventana mediante un emulador de terminal estándar llamado xterm. Este emulador se ejecuta en local, pero lo primero que hará será invocar el programa ssh. Este programa encriptaría la comunicación entre luna y pluton. Si accedes por ssh a una máquina que nunca accediste antes, te pedirá que verifiques que el nombre es correcto, dí que sí con todas las letras: yes.


        rlogin es Remote Login y no tiene seguridad.
        slogin es un rlogin más seguro, que encripta las comunicaciones.
        ssh sirve para hacer slogin, pero tiene funcionalidades de protección ante más ataques.





D) Ahora que ya estamos en la máquina remota, luna, le decimos dónde estamos sentados.


setenv DISPLAY pluton:0.0


E) Ya podemos ejecutar cualquier aplicación. Si ejecutamos la aplicación "gráfica" xeyes aparecerá en nuestra máquina pluton.

Si ejecutamos aplicaciones "de texto", lo harán en el emulador de terminal. Dichas aplicaciones de texto puede que necesiten, para saber cómo comportarse, saber a qué emulador de terminal se enfrentan. Para eso se puede hacer con la variable:


setenv TERM xterm


El más estándar de los emuladores de terminal es el vt100 o el vt220, así que en muchos entornos se entra con

setenv TERM vt100


F) Ya podemos salir, para ello hacemos exit, logout... etc

Configuración de un servidor X


Esta es una tarea para el administrador del sistema. Tengo que confesar que nunca he configurado un servidor X. Siempre he utilizado lo que por defecto venía en cada sistema.
En un sistema Linux moderno vamos a encontrar toda la información en /etc/X11/xorg.conf







6 oct 2010

Curso de Korn Shell scripting

Shell Scripting

Se denomina scripting a la habilidad de encadenar expresiones interpretadas por la shell.

Es una forma de programación esencial para quien quiera dedicarse a la administración de sistema, o para quien trabaje programando o desarrollando tareas de cierta complejidad con archivos y directorios en un sistema UNIX.

La sección se llama Korn Shell scripting porque la mayoría de scripts de mi vida los he escrito en Korn Shell, pero habrá quien se decante por programar en Bash que es actualmente ubicua en los sistemas Linux.

Antes de empezar, decir tres cosas:
  • que a programar en shell sólo se aprende escribiendo scripts, aunque ayuda mucho leer scripts de otros bien hechos y comentados.
  • que no se requieren más herramientas que un editor, y que este, en sistemas UNIX, debe ser el vi, aunque para mayor productividad, viene bien tener un editor gráfico como nedit.
  • que además de la shell, se asume que el programador debe conocer ciertos comandos del sistema, como sed, grep o awk que permiten que los scripts hagan cosas realmente interesantes.

El editor vi

Aunque existen en UNIX editores con interfaz gráfica de usuarios, un técnico de sistemas debe saber utilizar el editor vi. El vi es un editor que pese a su nombre muy visual no es, pero hay que tener en cuenta su fecha de nacimiento: 1976.

¿Qué editores hay en UNIX?

vi - todo técnico de sistemas debería saber usarlo
e, ed, o ex - un editor que sólo gestionaba una línea cada vez
emacs - un editor que se creó para programar en lisp y era más fácil que el vi
gráficos - nedit, xedit, gedit, kedit, etc. Si quieres ser productivo, y no está ya instalado uno de ellos, pide a tu administrador que te instale uno de estos en los que el copiar/pegar se haga con el ratón :)

Lo que más choca al principio de usar el vi es que no se puede editar directamente, que hay que "entrar" en un modo u otro según estemos dando comandos, editando, o ejecutando:
  • modo comando: es el modo en que se entra por defecto cuando se comienza la sesión de vi, cualquier cosa que se escriba se interpreta como un comando
  • modo inserción: cualquier cosa que se escriba en él, se interpreta como que se quiere meter al fichero, menos la tecla ESC que interpreta que queremos irnos al modo comando.
  • modo ejecución: cualquier cosa que se escriba en el se interpreta como que se quiere ejecutar algo. Se invoca con el :
Si queremos entrar en el vi escribimos simplemente el comando vi o

$ vi fichero

Para salir del vi, tendremos que escribir en el modo comando (ESC para asegurarnos de que estamos en él) el comando

:q! ---> salir sin grabar
:q ---> salir grabando, igual que :wq!

Meternos en el modo inserción requiere elegir si nos metemos en la línea que estamos o no:

a -> insertamos donde está el cursor
A -> idem pero al final de la linea
i -> insertamos debajo del cursor
I -> idem pero al final de la línea
o -> por encima
O -> al final

Vamos a escribir algo

luciag@luna.acme.com:~> vi fichero.txt
(a ---> hola ---> ESC ---> :wq!)

Ha sido fácil, vamos a aprendernos algunos comandos.

Para mover el cursor por la pantalla, hay que aprenderse h, j, k, l, que son los comandos para moverse a la izquierda, derecha, arriba, abajo, aunque algunos teclados nos dejan usar las flechas normales. Irse moviendo de palabra en palabra requiere usar la w o la b, para ir alante o atrás.

Para borrar, está la x, que borra el carácter que está donde el cursor, y la d, que borra la línea actual, como por ejemplo en dd, que borra la línea, también podemos dw (borrar el resto de la palabra), dG (borrar el resto del fichero), d$ (borrar hasta el final de la línea). Podemos 4dd para borrar 4 líneas.

El copia pega es un poco más complicado. Básicamente yy (yank) y p (paste por delante del cursor) y P (paste por detrás).

Un comando bastante intereante es el u. Y el . repite el último cambio.

En modo ejecución podemos hacer búsquedas, si hacemos
/texto --> Buscamos el texto
n -> Siguiente ocurrencia

Y también cambiar texto
;1,$s/algo/otracosa/g

A continuación vamos a ver una "chuleta" completa del editor

OperatorsDescription
d operanddelete the operand into the (delete) buffer
ppaste the contents of the (delete) buffer after the cursor
y operandyank the operand into the (delete) buffer
i operandinserts the operand (before current character)
a operandappends the operand (insert after current character)
r operandreplaces current character with operand
s operandsubstitute the operand with typed-in text
c operandchange the operand to typed-in text
! operandpass the operand to a (Unix) shell as standard input;
standard output replaces the operand.
Common MacrosDescription
Iinsert at beginning of line (same as ^i)
Aappend at end of line (same as $a)
Ddelete to end of line (same as d$)
Cchange to end of line (same as c$)
xdelete one character (same as dl)
ZZsave and exit
:w filenamesave as filename without exiting
:q!quit immediately (without save)
Miscellaneous
Renter replace (overstrike) mode
oopen line below current line
Oopen line above current line
" nn is 0-9: delete buffers
" xx is lowercase a-z: replace user buffer
" xx is uppercase A-Z: append to user buffer
.perform last change again
uundo last change
Uundo all changes to current line
OperandsDescription
h j k lleft, down, up, right; one character/line at a time
w b enext word, back word, end of word
W B E(same as above, but ignores punctuation)
/stringsearch for string (use ? for reverse search)
nsearch for string again (see /, above)
%find matching ( ), { }, or [ ]
( )beginning of current/previous sentence and beginning of next sentence
{ }beginning of current/previous paragraph (two adjacent newlines) and beginning of next paragraph (see also set paragraphs)
[[ ]]beginning of current/previous section and beginning of next section (mostly user-defined; see also set sections)
line Ggoto particular line number (defaults to end-of-file)
0 ^ $move to column 0, move to first non-whitespace, move to end of line
f xforward to character x on same line (inclusive)
t xto character x on same line (not inclusive)
;last f or t again in the same direction
,last f or t again in the opposite direction
m xset mark x at current position
' xmove to line containing mark x
` xmove to exact position of mark x
''move to line of last jump point
``move to exact position of last jump point


Interesting examples of numeric prefixes would be 36i-*, 8i123456789-, and 20r_.


Ex (colon-mode) commands

In the following commands, file may be either a filename, or a shell command if prefixed with !. Filenames are globbed by the shell before vi uses them (shell wildcards are processed before the filenames are used). Address ranges may be used immediately after the colon in the commands below. Example address ranges are:

RangeDescription
1,$From line 1 to the end of the file.
10,20From line 10 to line 20, inclusive.
.,.+10From the current line to current line + 10 (11 lines total).
'a,'dFrom the line containing mark a to the line containing mark d.
/from/,/to/From the line containing "from" to the line containing "to", inclusive.
Commands which change the file being edited.
:e filenameChange from the current file being edited to filename. "%" means current file, and "#" means alternate file.
Use :e # to edit the file most recently edited during the same session.
:n [filename(s)]Edits the next file from the command line. With optional list of filenames, changes command parameters and edits the first file in the list. Filenames are passed to the shell for wildcard substitution. Also consider command substitution:
:n `grep -l pattern *.c`
:argsLists the files from the command line (possibly as modified by :n, above).
:rewRestarts editing at the first filename from the command line.
Commands which modify the text buffer or disk file being edited.
:g/RE/cmdGlobally search for regular expression and execute cmd for each line containing the pattern.
:s/RE/string/optSearch-and-replace; string is the replacement. Use opt to specify options c (confirm), g (globally on each line), and p (print after making change).
:w fileWrite the contents of the buffer to file. If file starts with an exclamation mark, the filename is interpreted as a shell command instead, and the buffer is piped into the command as stdin.
:r fileReads the contents of the file into the current buffer. If file starts with an exclamation mark, the filename is interpreted as a shell command instead, and the stdout of the command is read into the buffer.
These commands control the environment of the vi session.
:set optTurns on boolean option opt.
:set nooptTurns off boolean option opt.
:set opt=valSets option opt to val.
:set opt?Queries the setting of option opt.
Miscellaneous commands.
:abbr string phraseCreates abbreviation string for the phrase phrase. Abbreviations are replaced immediately as soon as recognized during text or command input. Use :unab string to remove an abbreviation.
:map key stringCreates a mapping from key to string. This is different from an abbreviation in two ways: abbreviations are recognized as complete units only (for example, a word with surrounding whitespace) while mappings are based strictly on keystrokes, and mappings can apply to function keys by using a pound-sign followed by the function key number, i.e. #8 would map function key 8. If the terminal doesn't have an key, the mapping can be invoked by typing "#8" directly (doesn't work in the AIX 5L version of vi).


Comandos típicos para usar en scripts

Los siguientes comandos manipulan líneas, y en general cadenas.

head, tail - listan respectivamente el comienzo y el final de un fichero al stdout. Por defecto 10 líneas, pero con -n se puede cambiar.

Ejercicio: Obtener las 10 últimas alertas que se registraron en el fichero /var/adm/messages (Solaris, Linux).

cut, paste, join -
cut sirve para extraer campos de una línea (veremos que awk se usa mucho para eso también). Las opciones importantes son -d (delimitador de campos) y -f (campos que queremos)

Ejemplo: Sacar con el comando uname una cadena que sólo tenga el sistema operativo y la versión

luciag@luna.acme.com:~> uname -a
Linux luna.acme.com 2.6.18-128.el5 #1 SMP Wed Dec 17 11:41:38 EST 2008 x86_64 x
86_64 x86_64 GNU/Linux
luciag@luna.acme.com:~> uname -a |cut -d" " -f1,3
Linux 2.6.18-128.el5

Ejemplo: Sacar los usuarios y las UIDs
luciag@luna.acme.com:~> cat /etc/passwd | cut -d: -f1,3
root:0
bin:1

tr: El tr viene de "translation filter", pero yo durante mucho tiempo pensé que era tr de trocear.
Sirve para muchas cosas.

Por ejemplo, convertir a mayusculas

luciag@luna.acme.com:~> cat /etc/passwd |tr a-z A-Z
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
BIN:X:1:1:BIN:/BIN:/SBIN/NOLOGIN

Cambiar todas las letras por asteriscos
luciag@luna.acme.com:~> cat /etc/passwd | tr "[a-z][A-Z]" "*"
****:*:0:0:****:/****:/***/****
***:*:1:1:***:/***:/****/*******


wc: Hace una "cuenta de palabras" (word count) sobre un fichero o I/O stream

luciag@luna.acme.com:~> wc /etc/passwd
35 56 1619 /etc/passwd

Se muestran palabras, líneas y bytes.
Si sólo queremos estas por separado sacamos opciones -w, -l, -c.

Un ejemplo típico:

luciag@luna.acme.com:~> who
pepe pts/1 2010-10-18 15:32 (pepepc.dominio.com:0.0)
luciag pts/4 2010-10-20 14:49 (pluton)
luciag@luna.acme.com:~> who | wc -l
2

Hay tres comandos que me dejo explícitamente para el final: grep, sed, awk


"Hola mundo" en Korn Shell

Escribiremos un primer script que saludará al mundo en general, como siempre que se aprende a programar. Iniciaremos el editor escribiendo a continuación el nombre del fichero que contendrá el script.

$ vi helloworld.ksh

El llamar helloworld.ksh al script es por manías propias, en UNIX como todo el mundo sabe, no hace falta una extensión para que el script se ejecute.

La primera línea en todo script comienza por el carácter #, seguido de una admiración ! (a esta combinación de caracteres se le conoce como shabang o sharp+bang) y la ruta a la shell con la que se ejecutará.

#!/bin/ksh

El carácter "comentario" en Korn Shell es el #, y podemos utilizarlo para crear una cabecera que explique lo que hace el script.

El carácter @(#) es opcional, sirve para que una utilidad de programación llamada "what" (no estándar en todos los sistemas) nos dé información sobre el script.

#!/bin/ksh
#
# @(#)FileDescription: Mi primer script 
# @(#)Language:        Korn Shell
# @(#)Version:         1.0

Ahora decir hola mundo es tan fácil como usar el comando echo.

#!/bin/ksh
#
# @(#)FileName:        helloworld.ksh
# @(#)FileDescription: Mi primer script
# @(#)Language:        Korn Shell
# @(#)Version: 1.0
#
echo "Hello world"

Se guarda el script y para ejecutarlo o bien le damos permisos de ejecución y escribimos su path completo, o bien indicamos la shell seguida del nombre del script.

Es decir:

$ chmod +x helloworld.ksh
$ ./helloworld.ksh

donde como se puede observar, el directorio actual (.) no está en el PATH (en algunos entornos muy confiados sí se incluye . en el PATH, pero esto no es así por defecto en la mayoría de los sistemas).

$ ksh helloworld.ksh

Más sintaxis de Korn Shell

En un script de Korn shell podemos utilizar la siguiente sintaxis:

- Ejecución de comandos en serie: $ who -l; df -v; ps aux
- Ejecución de comandos en paralelo: $ who & df -k & ps -ef &
- Ejecución de comandos en tubería: $ who | sort | lp
- Sustitución de metacaracteres: $ ls f*
- Definición de variables: export OPCION=a (sin espacios)
- Consulta de variables: echo $OPCION

- Usar acentos graves para ejecutar comandos

#!/bin/ksh
echo "Hay `who | grep $u | wc -l` usuarios conectados"

- Modos de la shell: El verboso: set -x (set -o xtrace)

#!/bin/ksh
# Descomentar si tenemos problemas con el script
# set -x


- Sustitución de comandos: expr
- Variables leidas de la linea: read var

Ejemplo

#!/bin/ksh
#
# @(#)FileName:        exprsample.ksh
# @(#)FileDescription: Uso de expr
# @(#)Language:        Korn Shell
# @(#)Version:         1.0

echo Dime un numero 
read a 
echo Dime otro 
read b 
echo He leido primero 
echo $a 
echo He leido después 
echo $b echo 
La suma es echo suma='expr $a+$b'

- Declarar enteros para usar aritmética de enteros

#!/bin/ksh
#
# @(#)FileName:        integers.ksh
# @(#)FileDescription: Uso de expr
# @(#)Language:        Korn Shell
# @(#)Version:         1.0

typeset -i i=12            integer j=44



- Manejar los argumentos del script con las variables tipo dólar:

$0nombre del script
$1...$nargumentos de 1 a n
$#número de argumentos
$?código de salida (exit)

- Terminar la ejecución
exit [n]

- Escapar caracteres utilizando metacaracteres de escape como La \ y el --
Ejemplo: Cómo crear un fichero llamado *
Ejemplo: Cómo borrar un fichero llamado -i

Sentencias de control en la programación de la shell
Las cuatro más famosas: if case while y for

1) if comandos then comandos else comandos fi
2) case valor in
1) comandos;;
2) comandos;;
*) comandos;;
esac
3) while comandos do comandos done
4) for variable in argumentos do comandos done

Se pueden necesitar read y shift.

El comando test

Para empezar un if siempre hay que poner una condición que se comprueba con el comando test o simplemente []
Las condiciones sobre cadenas de caracteres pueden ser

[ string1 = string2 ]
[ string1 != string2 ]

Hay que tener cuidado con la cadena vacía, que no se puede testear así

Si son enteros

[ int1 -eq int2 ] [-ne ] [- gt ][ -ge ][ -lt ][ -le ]

Si son ficheros
-r fichero (legible) -w fichero (escribible) -x fichero (ejecutable) -f fichero (regular) -d fichero (directorio) -s fichero (no vacío) -t fichero (abierto en una terminal)

Condiciones lógicas
[ algo -a algo ]
[ algo -o algo ]

La sentencia while
Ejercicio: Escribir un programa que le pasas un número y saca algo por la pantalla ese número de veces

La sentencia for
Ejercicio: Crear un programa que saluda a todos los usuarios del sistema por su nombre de usuario

El comando grep y expresiones regulares

El comando grep es una herramienta de búsqueda que nos permite usar expresiones regulares (de ahi su nombre, global regular expresion printer).

luciag@luna.acme.com:~> ps -ef| grep luciag
luciag 27421 27420 2 14:49 pts/4 00:00:00 -tcsh
luciag 27451 27421 0 14:49 pts/4 00:00:00 ps -ef
luciag 27452 27421 0 14:49 pts/4 00:00:00 grep luciag

luciag@luna.acme.com:~> grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

Opción -i: case insensitive
Opción -w: Palabras completas
Opción -l: Sólo lista los ficheros donde encontró
Opción -n: Saca la línea donde lo encontró

Una expresión regular es un conjunto de caracteres que especifican patrones de búsqueda o de sustitución. Tienen una sintaxis un poco compleja y la única forma de saber si una expresión regular busca lo que queremos es comprobarla con un ejemplo.

Caracteres utilizados en la sintaxis de las expresiones regulares:

El asterisco -- * -- busca cualquier número de repeticiones de la cadena que le precede
El punto -- . -- busca 1 carácter
El gorrito -- ^ -- busca el comienzo de la línea
El signo dólar -- $ -- busca al final de una línea

"[xyz]" busca uno de los tres caracteres x, y, or z.
"[c-n]" busca caracteres en el rango de c a n.
"[a-z0-9]" busca minúsculas o alfanuméricos.

Los angulitos escapados buscan palabras enteras -- \<...\> --

Ejemplos:

grep luciag /etc/passwd {busca la cadena luciag en el fichero /etc/passwd}
grep '^ luciag' files {'luciag' al principio de una linea}
grep 'luciag$' files {'luciag' al final}
grep '^smug$' files {lineas que empiezan y terminan por 'luciag', sólo contienen eso}
grep '\^l' files {lineas que empiezan por '^l', "\" es para escapar ^}
grep '[Ll]ucia' files {busca 'Lucia' or 'lucia'}
grep 'B[oO][bB]' files {busca BOB, Bob, BOb or BoB }
grep '^$' files {busca líneas que no tienen nada}

Otros patrones
[0-9] un dígito del 0 al 9
[0-9][0-9] dos dígitos
[0-9][0-9]* n dígitos

Ejemplos de expresiones regulares:
1) Vamos a sacar la máquina desde la que hemos abierto nuestra sesión (el servidor X):

luciag@luna.acme.com:~/> who -m
luciag pts/4 2010-11-03 09:45 (tpbasexp)
luciag@luna.acme.com:~/> who -m | sed 's/.*(:*0*\.*0*\(.*\))/\1/'

sed & awk

Las utilidades sed y awk sirven para procesar texto:

sed: editor no interactivo. Se usa sobre todo para "aplicar expresiones regulares".
awk: lenguaje de procesamiento de patrones. Se usa sobre todo para conversión de unas cosas en otras.

Las dos utilidades tienen una invocación similar y usan expresiones regulares, leyendo del stdin y escribiendo al stdout.

Funciones, e includes, en los scripts

Cuando un script se convierte en algo muy grande, podemos escribir "funciones" como en C.

Funcion()
{
echo "aqui mi funcion"
}

Para llamarla, simplemente

Funcion

Las funciones pueden tener argumentos, se usa la numeracíon a partir del 1

CheckSomething()
{
thing_to_check=$1
}

Para llamarla: CheckSomething ARGUMENTO

Cuando un script se nos hace muy grande podemos dividirlo en ficheros. Luego "sourceamos" el trocito pequeño desde el trocito grande

InitializeScript()
{
Init_Filename="file_to_include.ksh"
. ./$Init_Filename

# Add here specific variables
}


Scripting by example

Esta sección pretende ser un recopilatorio de ejemplos resueltos y ejercicios

Ejemplos resueltos
  • En este ejemplo quería saber todos los ficheros jar que había en un directorio para ponerlo en un classpath
for file in $APP_HOME/WEB-INF/lib/*.jar
do
JAVA_CP=`echo $JAVA_CP`:$file
done
  • En este ejemplo quería saber un número de versión de java para compararlo con otro
luciag@luna.acme.com:~/> java -version
java version "1.4.2"
gij (GNU libgcj) version 4.1.2 20080704 (Red Hat 4.1.2-44)

luciag@luna.acme.com:~/> java -version |head -1|awk '{print $3}' | sed -e 's/.//g' | tr -d \"
142

El resultado es 142, obviamente ;)

  • Aquí quería saber si el número de descriptores de archivo era 1024 por lo menos

CheckFileDescriptors()
{

sSOFT=`ulimit -n`
sHARD=`ulimit -nH`

if [ "${sSOFT}" = "unlimited" ]; then
typeset -i CURRENT_NOFILES_SOFT=1024
else
typeset -i CURRENT_NOFILES_SOFT=`echo $sSOFT`
fi

if [ "${sSOFT}" = "unlimited" ]; then
typeset -i CURRENT_NOFILES_HARD=`echo $CURRENT_NOFILES_SOFT`
else
typeset -i CURRENT_NOFILES_HARD=`echo $sSOFT`
fi

if [ ${CURRENT_NOFILES_SOFT} -lt 1024 ]; then
echo ""
echo "$0 ERROR:"
echo
echo "This application needs a file descriptors per-process limit of at least 1024"
echo "Before you install, you must set"
echo " (ksh) ulimit -n 1024 in the users .profile"
echo " (csh) limit descriptors 1024 in the users .cshrc"
echo ""
if [ ${CURRENT_NOFILES_HARD} -lt 1024 ]; then
echo ""
echo "Check with your system administrator for system wide limits"
echo ""
fi
exit
else
:
# -- all ok
fi

}

Bibliografía
El arte del bash scripting de Mendel Cooper: http://tldp.org/LDP/abs/html/
La página oficial de la Korn Shell: http://www.kornshell.com/