Documente Academic
Documente Profesional
Documente Cultură
Volumen 1
LIBROS PARA EL FUTURO QUE ESTÁ PRESENTE
RESPONSABLE EDITORIAL:
Tomás Fernández Cuesta
AUTOEDICIÓN:
Tomás Fernández Cuesta
DISEÑO DE CUBIERTA:
Tomás Fernández Cuesta
REALIZACIÓN DE CUBIERTA:
Tomás Fernández Cuesta
Volumen 1
Febrero 2011
Tomás Fernández Cuesta
Ingeniero Superior de Telecomunicaciones
Unix, del cero al infinito Febrero-2.011
eulalyl SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSYL
EloOxoErloxGpUGAtAGpxopxaparBul SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS3L
1 EloExeTlGpFUotAMxoTAaxGpGlBuxpGrGTxMAGplexuATrOlG SSSSSSSSSSSSSSSS31
Y FrEHxulGSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSgL
3 txGAuulaalpHrGTÓurElptxpUorX SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSg9
4 EloExeTlGptxapGrGTxMApGlaAurG SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS67
g xapUGUAurlpFuxoTxpAapGrGTxMApUorXSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS7Y
6 yxoxuAartAtxGpGlBuxpuxtxGp(MltxalplGr) SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS84
7 roTxueuxTxptxpElMAotlGp(GHxaa)ptxapGrGTxMA SSSSSSSSSSSSSSSSSSSSSSSSSSSS91
8 GrGTxMAptxpFrEHxulGptxapGrGTxMAplexuATrOlpUorXSSSSSSSSSSSSSSSSSSSSSSS1LL
9 aAGpxXeuxGrloxGpuxyUaAuxGSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS131
1L alGpxtrTluxGptxapGrGTxMAp“xt”pYp“Or” SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS147
11 oUEaxlptxapGrGTxMApUorX SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS161
1Y EloTulaptxpeulExGlG SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS166
13 GxyUurtAtptxapUGUAurlSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS173
14 exuMrGlGptxpFrEHxulG SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS184
1g ElMAotlGptxapGrGTxMAplexuATrOl SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS191
16 axoyUAJxp“E”pBÁGrElp(r) SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSY1g
17 eulyuAMAErÓopxopxapaxoyUAJxpGHxaa SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSY47
18 MAoUAapUorXptxpGH,pJGHpYpuGH SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSY8g
19 EAuAETxurGTrEAGptxpaApEpGHxaapYpKluopGHxaaSSSSSSSSSSSSSSSSSSSSSSSSSSS3L6
YL MAoUAapUorXptxpaApGHxaapE SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS3YL
Y1 AtMrorGTuAErÓoptxpeulExGlG SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS343
YY eulExGlptxpAuuAoQUxptxpGlaAurGSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS3g4
Y3 orOxaxGptxpxJxEUErÓoSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS368
Y4 ElMAotlGptxpAtMrorGTuAErÓoptxpeAQUxTxGptxpGlFTWAux SSSSSSSSSSSSS373
Yg FrEHxulGptxprorErAarZAErÓoptxpUGUAurl SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS383
rotrExptxpraUGTuAErloxGSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS394
BrBarlyuAFrA SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS39g
EloTuAeluTAtASSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS399
PROLOGO
UNIX son las siglas de identificación de uno de los mejores sistemas operativos de aplicación general
que se encuentran en el mercado desde hace mucho tiempo, incluyendo todos los derivados (SCO-
Unixware, Solaris, AIX, HP-UX, DEC-Ultrix, Linux, etc). Y hemos dicho uno de los mejores por no decir el
mejor. Me explicaré, UNIX es ante todo un sistema operativo de uso general que posee herramientas y
utilidades capaces de efectuar aplicaciones de gestión, control industrial, comunicaciones, cálculo
científico, diseño gráfico, etcétera. UNIX no está limitado a una aplicación o entorno concreto, y además
nos pone en las manos las funciones básicas de su control y funcionamiento.
Uno de los objetivos fundamentales que se propusieron los creadores de UNIX fue su portabilidad y
facilidad de implementación en diversos tipos de hardware, lo que a la larga ha propiciado su
disponibilidad en las plataformas de todos los fabricantes. Esto se consiguió mediante la creación de un
lenguaje de programación denominado “C”, y la escritura de gran parte del núcleo del sistema UNIX en
dicho lenguaje, con lo que únicamente se debe poseer un compilador de lenguaje “C” en la máquina
donde se desea implementar el sistema operativo UNIX. Los manejadores de dispositivos (discos, cintas,
terminales, impresores, módems, tarjetas de red, etcétera) estaban escritos en código máquina o bien en
ensamblador, con lo que se debían rescribir para cada tipo de hardware. Hoy en día casi todos estos
manejadores están escritos en lenguaje “C” y para numerosos tipos de hardware que pueda soportar
UNIX, con lo que se reafirma su portabilidad de una máquina a otra. El lenguaje “C” está íntimamente
ligado al sistema operativo UNIX y prácticamente no se puede entender uno sin el otro. Hoy en día
existen otros sistemas operativos que implementan el lenguaje “C”. Debido a que dicho lenguaje posee
una sintaxis de alto nivel, tiene potencia para manejar el sistema a muy bajas capas o niveles (todas las
funciones del sistema están disponibles en el lenguaje), y está profundamente relacionado con todo
UNIX, se consiguió un sistema operativo con potencia para poder desarrollar cualquier tipo de aplicación.
UNIX posee gran cantidad de complejos comandos, funciones, programas y aplicativos, pero más que
nada ofrece unas posibilidades de programación, control de procesos, multitarea, comunicaciones y
control de flujos, que lo hacen ideal para cualquier tipo de aplicación, no estando limitado como muchos
sistemas operativos a gestionar un tipo concreto de aplicaciones.
Hay otra palabra básica que define a UNIX, robustez. Es un sistema robusto en dos sentidos, por un lado
posee una fiabilidad de diseño excelente, y por otro lado, está absolutamente controlado por el
administrador, siempre que sus conocimientos se lo permitan. Lo bueno no es sencillo en UNIX.
Veamos dos aspectos prácticamente contradictorios de UNIX. Por un lado es un sistema operativo de
muy pocos conceptos básicos, muy claros, y bastante fáciles de entender, que una vez dominados nos
ofrecen unas posibilidades inmensas de trabajo. Por otro lado, se tiene la impresión de que es un
sistema operativo demasiado complejo. Es un sistema complejo pero en absoluto difícil de dominar con
unas explicaciones claras y muy concretas. A UNIX lo hacen todavía mas complejo los usuarios que
pueden acceder a la CONSS, o los administradores que montan recursos de NFS sin dominar la política de
usuarios / permisos / propietarios / red, y no digamos los programadores que dejan consciente o
inconscientemente puertas abiertas en los programas. Evidentemente han existido y existen numerosas
versiones de UNIX, que han ido mejorando con el tiempo y nunca se podrá decir de UNIX ni de ningún
otro sistema operativo, que está creada la versión definitiva e inmejorable del mismo. UNIX es un
sistema operativo muy estable incluso ante fallos en los programas de usuario, el sistema sigue
funcionando a la perfección sin alterar las tareas de otros usuarios. Se puede argumentar que UNIX
nunca pide confirmación para ejecutar el comando que se le ha solicitado, y por este motivo se pueden
producir casos de alteración importante de la información, pero todo ello es debido a la falta de
preparación de los usuarios, incluso de los administradores (siempre es posible adaptar nuestro entorno
de trabajo para hacer que determinados comandos soliciten la conformidad del usuario). Quizá se le
pueda achacar a UNIX algo más de control en estos aspectos, pero no se puede desvirtuar un sistema
como UNIX por un detalle de ese tipo; UNIX deja las puertas abiertas, es labor del programador y
administrador del sistema el desarrollar los aspectos de seguridad y funcionalidad de las aplicaciones.
UNIX también carece de una documentación clara y sencilla para el usuario, los manuales originales de
UNIX son demasiado extensos y poco claros para usuarios de nivel bajo y medio.
UNIX posee una extensa biblioteca de programas especiales para muy diversas tareas y cada vez
existen más en el mercado. Es un sistema que tiene sentadas las bases de su estructura y
funcionamiento. Se irá mejorando con el incremento de la potencia del hardware que incorporen las
máquinas u ordenadores. Quizá la mayor tarea que le queda a UNIX sea el aprendizaje de los usuarios
finales del mismo, e incluso del personal técnico trabajando en entornos UNIX. Existe un numeroso
conglomerado de libros y publicaciones sobre el tema, pero que no hacen más que contribuir a la
confusión general. Nuestra opinión como usuarios de UNIX y en tiempos y aun hoy en día estudiosos del
mismo, es que se deberán recalcar mucho las ideas y estructuras básicas de UNIX durante el tiempo
que haga falta, y no continuar por el resto del sistema hasta el dominio total de estos conceptos UNIX.
Una vez que se tenga la confianza propia de poder seguir adelante continuaremos navegando por la
extensa carrera de UNIX, acudiendo siempre, y en último termino, a los manuales originales.
De una forma muy genérica, los programas del sistema UNIX están funcionalmente clasificados de la
siguiente forma:
El sistema UNIX se puede complementar o modificar por todo aquel que disponga de licencia de acceso
a los códigos fuente del mismo. Un elevado número de programadores han ido incorporando al sistema
nuevos programas. Estos programas, y los que irán apareciendo, incrementaran la amplia biblioteca
existente de software en UNIX.
Por todo esto, el libro que presentamos a continuación no pretende ser ni una sustitución de los
manuales originales, ni una pequeña iniciación al sistema. Pretendemos recalcar y poner ejemplos del
pequeño número de los conceptos básicos de UNIX, de tal forma que el usuario pueda llegar a adquirir la
confianza necesaria para continuar el estudio en otros niveles. La claridad y a la vez complejidad de
UNIX y el lenguaje “C”, nos han llevado a la idea de crear una obra de UNIX, que a la vez de servir como
introducción al sistema, profundice en numerosas partes, que si no se tratan desde un principio, después
pueden llegar a ser totalmente oscuras para el usuario final del sistema. Cuando el usuario continúa
adelante con el sistema, sin esa fuerte base en los conceptos UNIX, llegara a decir que el sistema "falla".
Debemos hacer notar que seria muy conveniente compaginar la lectura del presente libro con el de
Lenguaje “C”, al que dedicamos un amplio capítulo, pues como dijimos anteriormente, no se pueden
entender el uno sin el otro.
La estructura de este libro comienza con una reseña histórica de UNIX. A continuación explicaremos lo
que se va a encontrar el usuario cuando entre en el sistema. Seguiremos con el desarrollo de los
conceptos básicos sobre ficheros UNIX y los comandos para manejarlos, el apartado más extenso del
libro. Mas tarde nos adentraremos en un comando básico, el editor de ficheros (ed). Avanzaremos en el
estudio del resto de conceptos fundamentales de la CONSS del sistema, finalizando con unas nociones
sobre la estructura interna del núcleo del sistema. Finalizaremos con una completa tabla de comandos
de UNIX (excepto aquellos que sobrepasen el nivel de un usuario medio), con todas sus opciones
posibles. Esta tabla servirá de guía para el usuario, una vez dominados el resto de los capítulos del libro.
Como todo libro de desarrollo de un sistema operativo, conviene leerlo mas de una vez, por la sencilla
razón de que la complejidad de un sistema operativo, no solamente de UNIX, requiere el manejo de
tantos conceptos y definiciones, que es imposible seguir un orden totalmente coherente en el desarrollo
de los temas. Así, podemos encontrar al principio del libro, conceptos que son ampliamente
desarrollados posteriormente y que en una segunda lectura nos darían una visión mucho más completa y
clara del tema tratado.
Esperamos con esto poder sentar las bases de un buen usuario y posterior administrador o programador
en UNIX.
Pretendo solo mostrar, y no comparar. Todos tenemos nuestras preferencias, avaladas por la
experiencia y motivadas por la evolutiva inteligencia del ser humano. Este libro solo pretende formar a
verdaderos conocedores del sistema UNIX, que puedan ir creciendo poco a poco, pero a los que
presento una base muy sólida. Es un libro de iniciación y también es un libro para los que se creen
expertos. Haber nacido al mundo informático con este sistema me da derecho a mostrar cierta
prepotencia que solo espero se traduzca en mas ansias de enseñar.
CLAVES
Es vital mantener una política de claves (E CCDAMIC) robusta. Usar claves de 8 caracteres, combinando
números y letras mayúsculas y minúsculas aleatoriamente, y sin significado alguno. Memorizar 4 o 5 de
esas claves en nuestro cerebro y no anotarlas en ningún soporte, manteniéndolas ocultas a cualquier
otra persona y bajo cualquier concepto. Tener en cuenta que el único usuario con acceso a nuestra
información es el súper usuario del sistema.
USUARIOS
Entidad que tiene acceso al sistema mediante un nombre y una clave de acceso. No es necesario tener
más de un usuario por persona en el sistema. Todas las acciones pueden ser desarrolladas dentro del
mismo usuario, manteniendo una buena lógica de distribución de los ficheros por directorios. Lo mismo
es aplicable a los usuarios de aplicativos que no tienen acceso a la CONSS, sino que solamente la usan
como vehículo para conducirlos a su aplicación.
Súper usuario. Administrador primario del sistema. Posee todos los permisos y puede realizar
acciones sobre el resto de usuarios del sistema. Es conocedor de la contraseña el usuario root.
Pueden existir varios administradores en el sistema. La mejor política es asignarles un usuario
común a cada uno, y obligarlos a acceder a los privilegios de súper usuario mediante el comando su.
Evitar en todo lo posible el acceso al sistema con SATJR de root.
Usuarios desarrolladores de aplicaciones. Son usuarios que suelen tener unos conocimientos
medios o altos del sistema, desarrollando aplicaciones de cualquier tipo y sobre diversos entornos, y
que en muchos casos requieren acciones sobre el propio sistema operativo, para gestionar y evaluar
los procesos que ellos ejecutan. No deben realizar tareas de administración del sistema.
Usuario de aplicaciones. Son usuarios que se limitan a ejecutar las aplicaciones disponibles y a las
que tienen acceso. Nunca deben tener un acceso a la CONSS, y deben ser redirigidos de forma
automática hacía los menús que posibiliten el acceso a las aplicaciones o la salida del sistema. No
necesitan tener ningún conocimiento del sistema.
DIRECTORIOS
Todos los ficheros de un sistema UNIX residen en un árbol de directorios a partir del directorio raíz /
(MAAÓ). Conocer esta estructura de forma completa y exhaustiva no es necesario, pero si es indispensable
conocer de forma clara ciertos (bastantes) directorios tanto del sistema como de los usuarios o
aplicaciones de terceros. Podemos enumerar una serie de directorios que debemos conocer, aunque
existen algunos más:
Posicionados en esos directorios podemos realizar búsquedas de ficheros relevantes que nos permitan
obtener información deseada como administradores del sistema.
DIRECTORIO ACTUAL
Es muy importante conocer en cada momento el directorio en el que estamos posicionados. Al realizar
SATJR al sistema, este nos posiciona en el directorio de usuario (home). Desde ese momento nos
podemos mover por diversos puntos del árbol de directorios (comando cd) para realizar las tareas
propias del usuario. Una buena recomendación es colocar el nombre del directorio actual en el EMAUEÓ de
la CONSS.
PERMISOS DE FICHEROS
El sistema de permisos asociados a ficheros es vital para el funcionamiento del sistema y de posibles
aplicaciones que vayamos a desarrollar o estemos utilizando. Las entidades de usuario propietario,
grupo, resto de usuarios, junto con los permisos de lectura, escritura y ejecución (búsqueda en
directorios) forman un pilar básico de los permisos de UNIX y su seguridad. Si a los anteriores permisos
añadimos el SUID, el SGID y el CÓJXLV bit, tendremos todas las herramientas para proteger, tanto a los
ficheros, como a los procesos generados por esos ficheros. Dominar estos conceptos, juntos con la
utilización de los comandos umask, chmod, chown y chgrp, nos facilitará mantener la integridad de los
ficheros de los que somos responsables.
USUARIOS Y PROCESOS
Conocer que un proceso pertenece al usuario que lo lanza, pero que también puede adquirir la identidad
de otro usuario (incluso la del súper usuario), y que existe un tercer nivel de identidad correspondiente al
usuario guardado, es una información que debemos tener siempre en cuenta para garantizar la robustez
de los procesos y su relación con la seguridad.
EXPRESIONES REGULARES
Dominar las expresiones regulares, tanto las básicas, como las extendidas, nos va a permitir manejar el
contenido de ficheros con una flexibilidad tremenda, realizando búsquedas y transformaciones complejas
con comandos relativamente simples. Son una entidad bastante complicada, pero merece la pena llegar
a dominarlas, siendo incluso muy utilizadas en otros entornos fuera del sistema operativo UNIX.
LENGUAJE SHELL
Como administradores de sistemas UNIX, debemos dominar uno de los lenguajes CONSS del sistema; y
volvemos a repetir: dominar es dedicarle muchas horas y utilizar la técnica de repeticiones exhaustivas
para que nuestro cerebro asimile la lógica y sintaxis del lenguaje. Recomiendo el lenguaje de CXMJEÓC de
la Bourne CONSS, debido a su condición de estándar, y a su compatibilidad total con la Korn CONSS. Como
shell de login puede utilizarse, tanto la Korn shell, como la C shell, dependiendo de los gustos del
usuario, pero no recomiendo usar la Bourne shell como shell de login, salvo para usuarios que solamente
ejecuten una aplicación guiada.
SHELL DE LOGIN
Para proteger nuestros propios ficheros, y todos aquellos a los que tengamos acceso de escritura, es
muy importante utilizar una CONSS de SATJR que nos permita protegernos contra estas situaciones. Más
concretamente, debemos utilizar una CONSS donde el comando de borrado de ficheros (rm) pida
confirmación unitaria por cada fichero a borrar. Además, es muy conveniente que la shell disponga de un
mecanismo que permita que los comandos que utilicen redirección de salida (> o >>), no se ejecuten si
el fichero de salida existe previamente (caso de >) o no existe (caso >>). Estas características se
consiguen utilizando una CONSS que disponga de alias. Se creará un alias con el mismo nombre del
comando, pero que incluya las opciones de petición de confirmación. En este caso, un alias de este tipo:
alias rm=”rm -i", producirá el efecto deseado; al ejecutar un comando del tipo rm *, nos pedirá
confirmación por cada fichero encontrado, puesto que rm será sustituido previamente por el alias rm -i.
Ciertas CONSSC dispones de estas funcionalidades, como la FAMR CONSS y la C CONSS.
Entrada estándar (stdin). Corresponde al fichero desde donde el proceso podrá recibir entrada de
datos. Corresponde al descriptor de fichero 0.
Salida estándar (stdout). Corresponde al fichero hacia donde el proceso podrá enviar salida de
datos. Corresponde al descriptor de fichero 1.
Error estándar (stderr). Corresponde al fichero hacia donde el proceso podrá enviar mensajes de
error. Corresponde al descriptor de fichero 2.
Todos los procesos tienen acceso a estos ficheros, pudiendo ser obviados, utilizados directamente, o
redirigidos a otros ficheros o dispositivos especiales. Este concepto es básico para comprender el
funcionamiento de los procesos y su iteración con ficheros estándar del sistema.
ENTONO DE TRABAJO
Como administradores del sistema debemos disponer de un entorno de trabajo limpio, optimizado y lo
suficientemente potente para permitirnos realizar las tareas de mantener el funcionamiento y rendimiento
del sistema. Describo una serie de consejos útiles para crear un entorno óptimo de trabajo, que
evidentemente deberá ir evolucionando con nuestra formación, y adaptándose a las necesidades del
sistema administrado:
Crear un usuario normal para el administrador del sistema; realizar SATJR sobre dicho usuario; y
utilizar el comando su para realizar tareas propias del súper usuario. Evitar el realizar SATJR como
usuario root.
Elegir una CONSS de SATJR Korn o C CONSS. Existen muchos entornos de CONSS, pero por razones
históricas y de rendimiento nos decantamos por unas de las dos, teniendo en cuenta que el
desarrollo de CXMJEÓC debería ser realizado con la CONSS estándar Bourne.
Diseñar un fichero de inicialización depurado (.profile o .login), que incluya todas las variables de
entorno necesarias, los controles a realizar antes del EMAUEÓ, y el conjunto de alias (muy importante)
que vayamos preparando en el trabajo diario y nos resulten de una alta utilidad.
Programar todos los CXMJEÓC en lenguaje de la Bourne CONSS, el estándar de UNIX. Si tenemos
experiencia en lenguaje C, podemos utilizar la C CONSS para la realización de CXMJEÓC.
Disponer de una buena colección de CXMJEÓC que nos permitan realizar tareas complejas y repetitivas
en el sistema, incluso con labores de análisis de los datos recogidos. Es muy importante ir
depurando y comentando dichos scripts a lo largo del tiempo, de tal forma que llegaremos a disponer
de una gran cantidad de utilidades que nos facilitarán el trabajo diario, utilidades que siempre
podemos mejorar y adaptar a los nuevos entornos.
Guardar toda la información que vayamos generando, en directorios sobre nuestro directorio de
residencia, evitando la inclusión de información en sistemas de ficheros que no nos pertenezcan.
Es vital mantener una copia de seguridad de todo este entorno, para poder ser replicado en otros
sistemas, o ante posibles desastres.
CONTROL DE PROCESOS
Para llevar al sistema a un buen grado de afinamiento (tunning) del sistema es necesario conocer qué
procesos se están ejecutando en el mismo, su estado y su consumo de recursos. Saber diferenciar los
procesos del sistema de los procesos de usuario, conocer las prioridades con las que se ejecutan, así
como el consumo de memoria virtual o swap, de recursos de I/O, de terminal, o de bloqueos por espera
de otros recursos, nos va a proporcionar una visión clara del rendimiento del sistema.
No todos los sistemas tienen el mismo propósito, unos están dedicados a servir transacciones de bases
de datos, otros soportan entornos de desarrollo para varios programadores, otros se utilizan como
servidores Web, otros ejecutan una aplicación a la que se conectan cientos de usuarios, etc. Además del
propósito del sistema, debemos analizar las necesidades de memoria y disco en el sistema.
Debemos consultar el manual de cada sistema pare verificar los parámetros configurables del núcleo.
Por ejemplo, PRJYG MN permite parametrizar el máximo de ficheros abiertos en el sistema, y el máximo
de ficheros abiertos por usuario. Son dos parámetros importantes que muchas veces se han llegado a
consumir, siendo necesaria una recreación del LNMRNS para ampliar las tablas de descriptores de ficheros
abiertos y solucionar el problema.
Cuando seamos capaces de afrontar un afinamiento de un sistema UNIX, y llevarlo a unos buenos
niveles de rendimiento para el hardware disponible y las aplicaciones ejecutadas, podremos decir que
somos unos verdaderos especialistas en sistemas UNIX, hemos alcanzado la cima como
administradores de UNIX.
PRIMEROS PENSAMIENTOS
La mejor forma de empezar a desarrollar un programa es idearlo como un simple pensamiento cerebral,
lo que nos va a permitir abstraernos y reforzar los planteamientos básicos. Verlo en conjunto, para poder
dividirlo en partes.
Los primeros años iremos cambiando de ideas, lo que antes hacíamos de una forma, ahora lo hemos
mejorado y automatizado en nuestro buffer de memoria, lo hemos optimizado. El aprendizaje es un
proceso de optimización que nos llevará a procesos mentales consolidados, si lo aplicamos a la
programación, involucramos los mismos aspectos: estudio, memorización, repetición, práctica y
resultados.
TAREAS DE UN PROGRAMA
Que hace la programación:
Recibir datos. Los datos pueden proceder de diversas fuentes (no es una lista exhaustiva):
o Desde un fichero que contiene los datos a procesar
o Desde otro proceso
o Desde un formulario de captura de datos, normalmente mediante teclado y ratón.
o Desde un servicio de mensajes, tipo cliente – servidor.
o Desde un puerto serie
Almacenar datos. Los datos finales pueden ser almacenados en diversos objetivos (no es una
lista exhaustiva):
o Hacia uno o varios ficheros del sistema de ficheros
o Hacia un entorno de bases de datos
o Hacia otro proceso
o Hacia un servicio de mensajes, tipo cliente – servidor.
o Hacia un puerto serie.
PLANTEAMIENTOS DE DISEÑO
Para abordar los diferentes problemas planteados por el diseño y desarrollo de algoritmos en los
programas debemos seguir una serie de consejos:
En una aproximación inicial debemos utilizar la abstracción, es decir, buscar las generalidades y no
las particularidades.
Realizar un diagrama o tablas de casos de ejemplo con el resultado final que se debería obtener.
Nos ayudará a buscar una solución para el proceso y poder comprobar su funcionamiento.
Dominar los procesos lógicos, entre ellos los más importantes son las sentencias condicionales y los
bucles.
CONTROL DE ERRORES
Una de las labores más extensas e ingratas de la programación es el control de errores. Al manejar tanta
cantidad de posibilidades, dispositivos, eventos del sistema y situaciones posibles, es necesario realizar
un exhaustivo control de errores, teniendo en cuenta que siempre son predecibles y posibles. Debemos
proteger al programa de errores de tecleo del usuario, de eventos del sistema, de acciones imposibles, y
en general de cualquier situación que no sea normal en su ejecución. Muchos programadores realizan el
control de errores cuando estos se producen, lo que ante la falta de pruebas exhaustivas, dejan
programas con posibilidad de errores no controlados y posibles efectos colaterales no deseados. Ante un
error, podemos y debemos actuar con alguna de las siguientes posibilidades:
DEMASIADOS LENGUAJES
Si somos capaces de dominar un lenguaje de programación, seremos capaces de dominar cualquier otro
lenguaje en un corto espacio de tiempo. Pero dominar un lenguaje es como el idioma, hay que pensar en
ese lenguaje, debe ser un proceso cerebral absolutamente natural, y la mayor eficiencia se consigue con
la repetición, práctica de aprendizaje que ofrece los mejores resultados. Es decir, programar es pensar
con un conjunto muy estrecho de normas, pero donde nuestra imaginación puede ampliarlas hasta
límites impensables, y repetirlo muchas veces, hasta que resulte un proceso automático.
Recomendamos el Lenguaje C como base primordial de formación. Dominando ese lenguaje, se puede
abordar otro tipo, como puede ser Java.
ENTORNO DE TRABAJO
Para escribir programas es básico disponer de un editor especializado y ágil, adaptado para la
programación estándar, y preferentemente sin necesidad de utilizar el ratón. Uno de los mejores es el
editor “vi” (y sus derivados) del sistema operativo UNIX.
Cualquier programa o proceso puede ser realizado mediante el uso de variables, sentencias
condicionales (if) y bucles controlados (while, for, do-while).
Los programas, en cada momento tienen accesibles unas variables con cierto contenido; mantener
descontrolado ese contenido es la mayor fuente de fallos en los programas.
Las instrucciones que se ejecutan solo tienen disponible el entorno de instrucciones ejecutadas o
escritas anteriormente, no teniendo acceso al bloque de código que van a continuación de ellas.
EXPRESIONES CONDICIONALES
Es básico dominar la creación de expresiones condicionales complejas que combinen operadores
relacionales y lógicos, para crear condiciones de sentencias condicionales if, que realicen la bifurcación
del programa según las normas funcionales deseadas. Veamos un ejemplo: tenemos un formulario de
registro de base de datos que contiene un campo contador del número de imágenes asociadas al
registro num_imag (de 1 a 3), un campo booleano que indica si mostrar la imagen o no mostrarla
mues_imag, y un campo booleano que indica si mostrarla en fondo blanco o negro tipo_fondo. Si
deseamos que el programa actúe de forma inteligente a la hora de visualizar, por ejemplo la primera
imagen con fondo negro, deberíamos establecer una condición del tipo:
if (num_imag>0)&&(mues_imag==1)&&(tipo_fondo==1)
mostrar imagen 1 con fondo negro
DOCUMENTACIÓN
Es muy importante documentar cada paso que realiza el programa, incluso los más obvios. Según
vamos adquiriendo experiencia en programación, intentamos evitar la inclusión de muchos comentarios,
al considerarlo una pérdida de tiempo. Mientras estamos enfrascados en el desarrollo de un programa,
todo en él nos resulta familiar, y su comprensión es casi tan natural como el lenguaje hablado. Pero
cuando pasa cierto tiempo y volvemos a revisar el programa, muchos de sus caminos nos resultarán
difíciles de comprender sin prestarle una elevada atención y tiempo, incluso para los programadores más
experimentados. En este caso nos habría resultado vital el haber incluido comentarios exhaustivos del
programa.
NORMAS DE ESCRITURA
Debemos buscar formas para intentar evitar errores de programación que el compilador no puede
detectar, lo que nos dificultará la búsqueda del error. Veamos un ejemplo: en lenguaje C es muy común
el uso del operador de comparación de igualdad (==) para comparar dos expresiones. Como podemos
observar consta de dos signos igual, y muchas veces, más de las que podemos desear, escribimos un
solo signo igual. Si la comparación es del tipo:
if (a == 1)
Y, equivocadamente, escribimos:
if (a = 1)
El compilador no detectará ningún error, puesto que estamos usando una expresión que asigna a la
variable a el valor 1, lo que es completamente correcto. Como la variable a siempre contendrá el valor 1
(ÓMHN), la sentencia if siempre se cumplirá. La situación creada es bastante indeseable, puesto que
encontrar el error en programas grandes puede ser una tarea larga o una depuración costosa, debido a
que no sabemos donde se produce el error. Como mucho, podemos intuir que se ha colado en las
últimas instrucciones añadidas al programa desde el momento que funcionaba correctamente. Pero todo
esto puede ser todavía mucho peor de lo reseñado, puesto que los efectos colaterales pueden no ser
descubiertos fácilmente, pasando un tiempo hasta que se detecta el error, seguramente después de
haber escrito numerosas sentencias en el programa.
Existe un truco para resolver este problema, escribir la expresión al revés, es decir, colocar la constante
como primera parte de la comparación, quedando de la siguiente forma:
if (1 == a)
if (1 = a)
El compilador producirá un error, puesto que estamos intentando asignar a una constante el contenido
de una variable, lo que está prohibido por el lenguaje. Con este sencillo truco, podemos evitarnos
muchos quebraderos de cabeza en la utilización del operador de comparación de igualdad.
lee_campo_texto(fichero, texto);
while (!eof) {
for (i=0; i < strlen(texto); i++)
procesa(texto[i]);
lee_campo_texto(fichero, texto);
}
El trozo de código mostrado lee un campo cadena texto de un fichero, y entra en un bucle que se repite
mientras no se detecte un final de fichero. Dentro del bucle, ejecuta una función por cada carácter de la
cadena texto, mediante un bucle for. Si lo ejecutamos con un fichero de 1.000 registros que contenga
cadenas de caracteres de una longitud media de 100 caracteres, funcionará correctamente y en un
tiempo estimado correcto. En cambio, si ejecutamos el proceso con un fichero de 1.000.000 de registros
que contienen cadenas de caracteres de una longitud media de 500, el proceso puede llegar a tardar
tiempos no tan razonables. Sin entrar en temas de optimización de disco, o de sistemas más o menos
rápidos, o en gestión de punteros, al revisar el código anterior detectamos que estamos realizando una
llamada a la función strlen en cada ejecución del bucle, es decir, si la cadena a procesar tiene una
longitud de 200 caracteres, se llama 200 veces a la función strlen sin necesidad alguna, puesto que
asumimos que es un valor que no cambia durante la ejecución del bucle for. Con la simple corrección
siguiente, el proceso tendría una limpieza mucho mayor, y estaría mucho más optimizado:
lee_campo_texto(fichero, texto);
while (!eof) {
lon_tex = strlen(texto);
for (i=0; i < lon_tex; i++)
procesa(texto[i]);
lee_campo_texto(fichero, texto);
}
Para intentar normalizar la sintaxis de todos los términos y ejemplos, utilizaremos las siguientes
convenciones
Ejemplos desarrollados sobre un terminal aparecen en un tipo de letra proporcional y sin resalte de
negrita o cursiva:
$ wc fich1.c
12 34 456 fich1.
$
Comandos del sistema operativo UNIX, junto con sus opciones, aparecen en negrita, o en cursiva.
El comando ls -l proporciona ...........
El comando VECNMÍ,se utiliza ...........
El texto a sustituir en las opciones dentro de la sintaxis de los comandos o programas explicados en
el libro, aparece entre los signos mayor y menor <>, y a veces en cursiva:
wc <opciones> <ficheros>
Nombres de ficheros, nombres usados para hacer referencia a algún ejemplo, o en general nombres
que no corresponden a comandos u opciones de los mismos, aparecen en cursiva:
El fichero ÓNYÓA ha sido editado ...........
Términos técnicos que aparecen por primera vez en el texto son resaltados en un tipo de letra
distinto y en negrita:
Podemos definir inodo como el ..........
Este modo de operación podría denominarse proceso en serie porque refleja el hecho de que los
usuarios tenían que acceder al computador en serie.
La idea central que está detrás del esquema sencillo de proceso por lotes es el uso de un elemento SW
conocido como monitor. Para entender cómo funciona este esquema, se va a ver desde dos puntos de
vista: el del monitor y el del procesador.
Desde el punto de vista del monitor, él es quien controla la secuencia de sucesos. Para que esto sea
posible, gran parte del monitor debe estar siempre en memoria principal y disponible para su ejecución.
Esta parte del monitor se conoce como monitor residente. El resto del monitor consta de utilidades y
funciones comunes que se cargan como subrutinas en los programas de los usuarios al comienzo de
cualquier trabajo que las necesite.
El monitor lee los trabajos uno a uno del dispositivo de entrada y, a medida que los lee, el trabajo actual
se ubica en la zona del programa de usuario y toma el control. Cuando el trabajo termina, se devuelve el
control al monitor, quien lee el siguiente trabajo. Los resultados de cada trabajo se imprimen y entregan
al usuario.
Consideremos ahora desde el punto de vista del procesador. El procesador ejecuta las instrucciones del
programa de usuario hasta que encuentre una condición de finalización o de error, tras lo cual va en
búsqueda de la instrucción siguiente del programa monitor.
Debe quedar claro que es el monitor el que gestiona el problema de la planificación. Con respecto a la
preparación de los trabajos, también el monitor se encarga de ello. Con cada trabajo se incluyen
instrucciones de una forma primitiva de lenguaje de control de trabajos (JCL - ÑAB,1ARÓMAS,2 RTH TN),
que es un tipo especial de lenguaje de programación empleado para dar instrucciones al monitor.
Durante la ejecución del programa de usuario, cada instrucción de entrada origina la lectura de una
tarjeta de datos. La instrucción de entrada en el programa del usuario hace que se invoque una rutina de
entrada, que forma parte del sistema operativo. La rutina de entrada se asegura de que el programa de
usuario no ha leído accidentalmente una tarjeta JCL; si esto sucede, se produce un error y el control se
transfiere al monitor.
Los sistemas sencillos por lotes también poseen las siguientes características:
Protección de memoria: mientras el programa del usuario esté ejecutándose, no debe modificar la
zona de memoria en la que está el monitor. Si se hace un intento tal, el HW del procesador deberá
detectar el error y transferir el control al monitor, quien abortará entonces el trabajo, imprimirá el
mensaje de error y cargará el siguiente trabajo.
Uso de temporizador: impide que un solo trabajo monopolice el sistema. El temporizador se larga al
comenzar cada trabajo y si expira el tiempo, se producirá una interrupción y el control volverá al
monitor.
Instrucciones privilegiadas: ciertas instrucciones son designadas como privilegiadas y pueden ser
ejecutadas sólo por el monitor. Si el procesador, al ejecutar el programa del usuario, encuentra una
instrucción tal, entonces se produce una interrupción de error.
Esta ineficiencia no es necesaria. Se sabe que hay memoria suficiente para almacenar el SO (el monitor
residente) y un programa de usuario. Supóngase que hay espacio suficiente para el sistema operativo y
dos programas de usuarios. Ahora, cuando un trabajo necesite esperar una E/S, el procesador puede
cambiar al otro trabajo que probablemente no estará esperando a la E/S. Además se podría ampliar la
memoria para almacenar tres, cuatro o más programas y conmutar entre todos ellos. Este proceso es
conocido como multiprogramación o multitarea. Éste es el punto central de los sistemas operativos
modernos.
Al igual que la multiprogramación permite al procesador manejar varias tareas por lotes al mismo tiempo,
también puede utilizarse para manejar varias tareas interactivas. En este último caso, la técnica se
conoce como tiempo compartido, porque refleja el hecho de que el tiempo del procesador es compartido
entre los diversos usuarios. La técnica básica de un sistema de tiempo compartido es tener a varios
usuarios utilizando simultáneamente el sistema mediante terminales, mientras que el sistema operativo
intercala la ejecución de cada programa de usuario en ráfagas cortas de cómputo (quantum). De esta
manera si hay n usuarios que solicitan el servicio a la vez, cada usuario sólo dispondrá, en promedio, de
1 / n de la atención efectiva del computador, sin contar con la sobrecarga del sistema operativo.
Uno de los primeros sistemas de tiempo compartido que se desarrollaron fue el Sistema Compatible de
Tiempo Compartido (CTSS, 1AUE ÓJBSN,3JUN45O MJRT,5VCÓNU) en 1961. Su funcionamiento básico es
fácil de explicar. El sistema se ejecutaba en una máquina con una memoria de 32 K, palabras de 36 bits,
y con un monitor residente que consumía 5 K del total. Cuando había que asignar el control a un usuario
interactivo, el programa del usuario y los datos eran cargados en los restantes 27 K de la memoria
principal. Un reloj del sistema generaba interrupciones a razón de aproximadamente una cada 0,2
segundos. En cada interrupción del reloj, el SO se adueñaba del control y le podía asignar el procesador
a otro usuario. De esta manera, a intervalos regulares, el usuario en curso era expulsado y se cargaba
otro usuario en su lugar. Para conservar el estado del usuario anterior, para su reanudación posterior, los
programas del usuario anterior y sus datos eran escritos en el disco antes de leer los programas del
nuevo usuario y sus datos. En consecuencia, el espacio de memoria del usuario anterior debía ser
restaurado cuando le llegara de nuevo su turno.
En cambio, un procesamiento distribuido es aquel en que se ejecutan los procesos en distintos nodos,
dispersos geográficamente, interconectados mediante una red. Las características principales de un
sistema distribuido son:
Fragmentación de los elementos que componen una aplicación, en dos o más sistemas
interconectados, de igual o diferente arquitectura operativa.
La relación entre ambos sistemas puede tomar diferentes formas. Por ejemplo: Client-Server y Peer
to Peer (Un nodo es par de otro y ambos nodos ofrecen los mismos servicios).
Según sus funciones: "Un programa o conjunto de programas es llamado SO si cumple las funciones
de:
o Inicialización de la máquina
SO MONO-USUARIO
Son sistemas que se basan en máquinas que admiten a un solo usuario, el cual utiliza todos los recursos
sin compartirlos con otros. Éste es el caso de las computadoras personales (PC) o estaciones de
trabajos específicas (Workstation). El énfasis de su diseño está puesto en una interfase amigable entre el
usuario y el equipo, un lenguaje de control sencillo y periféricos.
SO MULTI-USUARIO
Los SO Multiusuario son aquellos que aceptan más de un usuario trabajando simultáneamente con el
computador.
SO DE PROPÓSITO GENERAL
Están diseñados para mantener un flujo constante de trabajo (GAML46SAD) en forma de tareas a ser
ejecutadas por la máquina. Debido al gran número (y diversidad) de trabajos, el sistema debe proveer
utilidades y facilidades para soportar una gran cantidad de unidades periféricas.
Se clasifican en Sistemas ( ÓXO y Sistemas de accesos múltiples ()HSÓJ XXNCC). Los Sistemas ( ÓXO se
caracterizan por el hecho de que una vez introducida una tarea en la máquina, el usuario no mantiene
contacto con la misma hasta que concluye su ejecución. Hay dos modos de trabajar proponiendo las
tareas al sistema:
A través del operador: el operador recibe el trabajo y lo pone a ejecutar. Al finalizar la ejecución,
devuelve los resultados al usuario.
En los Sistemas )HSÓJ XXNCC el usuario puede iniciar, vigilar, controlar o suspender la ejecución de su
programa desde cualquier terminal del sistema.
SO DE PROPÓSITO ESPECIAL
Están diseñados para aplicaciones y/o arquitecturas especiales. Se clasifican en: Tiempo real, Fault
Tolerance (Tolerancia a Fallos) y de Virtualización.
Sus parámetros más importantes son los tiempos de espera, procesamiento y almacenamiento.
Pueden tener un tiempo de respuesta crítico (Ej: control de procesos industriales) o no crítico (Ej:
reserva de pasajes).
Detecta y corrige errores, y recupera el sistema habilitando reemplazos de los componentes en mal
funcionamiento o vuelve atrás operaciones que motivaron pérdidas de datos.
Todos los SO trabajan en modo usuario respecto al SO virtual, pero están en modo privilegiado con
respecto a los programas que corren bajos ese SO.
Crea procesos
Una provee una interfase basada en comandos u órdenes llamadas CLI (1AUU RI,2JRN,9RÓNM6 XN)
que permite ingresar un conjunto de caracteres que el SO interpretará como comandos u órdenes.
Conocido como GUI (0M EOJX S,PCNM,9RÓNM6 XN) que permite accesos a través de entornos gráficos.
Se encarga de:
Interfases con el HW
Multiprogramación (2AD,5XONIHSNM)
Gestión del HW
Las características de sus funciones (del nivel cero de la estructura de un SO) son:
1.4.3 ADMINISTRADORES
Administración del procesador: consta de dos módulos:
o Dispatcher. Decide a qué procesador asignar el proceso que tiene que ser ejecutado
Administración de periféricos (I/O 5VCÓNU): posee todos los módulos necesarios para la utilización
de los periféricos.
1.5.1 INICIALIZACIÓN
Esta tarea es llevada a cabo por el Kernel, con rutinas residentes en memoria más otras residentes en el
disco del sistema. La inicialización tiene por objetivo preparar la máquina real y llevarla a un estado tal
que pueda ejecutar el primer trabajo.
Inicialización Total: es un proceso que se ejecuta al encender la máquina. Los pasos en que se
realiza son los siguientes:
o iMAUEÓ en pantalla
o Máquina utilizable
Inicialización Parcial: no crea ni localiza las tablas generadas por el proceso de Verificación de
Recursos en el instante del arranque (BAAÓ).
La comunicación con el usuario es a través de algún lenguaje de comandos. Esta interfase con el
usuario presenta dos visiones del SO:
Visión del usuario: para el usuario común. Provee una interfase que proporciona el ocultamiento de
HW, cuyos objetivos principales son la abstracción (para ocultar la complejidad) y seguridad
(proteger uso de recursos entre los usuarios y el sistema)
Visión del gestor del sistema: para el administrador del sistema (super usuario). El gestor del sistema
es el responsable de que el SO funcione en forma adecuada y lo configura para que los usuarios
compartan los recursos en forma eficiente.
Para ello, el SO controla todos los recursos de un sistema en cuanto a quién usa cuál recurso y su
respectiva planificación del reparto. De esta forma va asignando y desasignando recursos según
considere conveniente, transformándose en un árbitro imparcial en los conflictos generados entre
programas o usuarios. Para ser un árbitro imparcial, el SO implementa:
Autoridad: debe recuperar los recursos otorgados a los procesos y ordenar su uso.
Protección: brinda seguridad a los usuarios entre sí y preserva la integridad de los recursos.
Documentación de interfases
Portabilidad
Confiable: debe resolver todos los conflictos que se generan y debe estar libre de errores y fallos
Cada módulo no conoce la implementación de los otros módulos, sólo conoce las interfases.
Esta estructura puede representarse mediante anillos concéntricos (MJRTC). Cada anillo tiene una
apertura (ÓM E) por donde accede a otras capas (niveles). Las capas internas son las de mayor
privilegio.
Sistemas altamente modulares. Los módulos del sistema no tienen acceso directo al HW.
2. El LNMRNS recibe el mensaje, toma las decisiones de planificación y envía el mensaje al proceso
servidor.
3. El proceso servidor ejecuta la función solicitada y devuelve al LNMRNS un mensaje con el resultado de
la operación.
Acceso a los dispositivos de E/S: cada dispositivo de E/S requiere un conjunto propio y peculiar de
instrucciones o de señales de control para su funcionamiento. El SO tiene en cuenta todos estos
detalles.
Acceso controlado a los archivos: en el caso de archivos, el control debe incluir una comprensión,
no sólo de la naturaleza del dispositivo de E/S sino del formato de los archivos y del medio de
almacenamiento. Una vez más, es el SO el que se encarga de los detalles.
OPERATIVO
Cargadores (SA INM): SW que coloca las instrucciones del programa a ejecutar con sus datos en la
memoria principal.
Editores de enlaces (SJRL,NIJÓAMC): son los responsables de ubicar en el programa ejecutable las
rutinas de librerías (SJBM MV).
Depuradores (INBHTTNM): son programas que permiten encontrar y depurar fácilmente errores en los
programas.
La arquitectura SMP corre su kernel en cualquier procesador. El kernel es construido como múltiples
procesos o múltiples hilos. Esta arquitectura debe garantizar que dos procesadores no elijan el mismo
proceso ya que ocurriría un fallo. En SMP hay múltiples procesadores y cada uno de ellos tiene una
unidad de control, una unidad aritmética-lógica y sus registros propios. Cada procesador tiene acceso a
la memoria compartida y a dispositivos de I/O a través de un bus compartido. En maquinas modernas, el
procesador tiene generalmente un nivel de memoria cache privada.
1.11 MICROKERNELS
La filosofía del microkernel es que solamente las funciones esenciales del sistema operativo deben estar
en el kernel. Los componentes del sistema operativo externos al microkernel son implementados como
procesos servidores; estos interactúan entre ellos sobre una misma base, mediante mensajes a través
del microkernel. La función del microkernel con respecto al intercambio de mensajes, es la de validarlos,
pasarlos entre componentes y conceder acceso al hardware. (El microkernel pasa a tener una
arquitectura del tipo cliente/servidor).
Los beneficios del microkernel son, entre otros, extensibilidad, portabilidad, flexibilidad y fiabilidad, siendo
recomendado para sistemas operativos orientado a objetos. Una de las principales desventajas es el
rendimiento. Cuesta tiempo de proceso el crear y enviar un mensaje, aceptarlo, decodificarlo y
responderlo, entre otras cosas.
1.12 PROCESOS
Debe intercalar la ejecución de un conjunto de procesos para maximizar la utilización del procesador
ofreciendo a la vez un tiempo de respuesta razonable.
Debe asignar los recursos a los procesos en conformidad con una política específica
Podría tener que dar soporte a la comunicación entre procesos y la creación de procesos por parte
del usuario
El procesador ejecutará instrucciones de entre un repertorio, en una secuencia dictada por los valores
cambiantes de la comunicación entre procesos. A lo largo del tiempo, este contador puede apuntar a
códigos de programas diferentes que son parte de diferentes aplicaciones. Desde el punto de vista de un
programa individual, su ejecución involucra una secuencia de instrucciones del programa. La ejecución
de un programa individual se conoce como proceso o tarea.
Cuando se añade un proceso a los que ya está administrando el sistema operativo, hay que construir las
estructuras de datos que se utilizan para administrar el proceso y asignar el espacio de direcciones que
va a utilizar el proceso.
En un entorno de trabajo por lotes, un proceso se crea como respuesta al envío de un trabajo.
Por una aplicación. Por ejemplo, si un usuario solicita la impresión de un archivo, el SO creará un
proceso que gestionará dicha impresión.
Cuando un proceso es creado por el sistema operativo tras la solicitud explícita de otro proceso, la
acción se conoce como generación de procesos (EMAXNCC,CE DRJRT). Cuando un proceso genera otro, el
proceso generador se conoce como proceso padre y el proceso generado es el proceso hijo.
Jerárquica: cada proceso que se crea es hijo del proceso creador y hereda el entorno de ejecución
de su padre. Un proceso durante su ejecución puede crear varios procesos hijos a través de
llamadas al sistema para creación de procesos. Al restringirse un proceso hijo a un subconjunto de
recursos del padre, se evita que éste sature al sistema creando demasiados procesos hijos. Al crear
procesos hijos, el padre continúa ejecutando concurrentemente con sus hijos o espera a que todos
sus hijos hayan terminado y luego continúa él.
En un entorno de trabajo por lotes, inclusión de una instrucción de detención (HALT). Esta
instrucción generará una interrupción para avisar al SO que el proceso ha concluido.
En un entorno de trabajo por lotes, puede finalizarse por la llamada explícita a un servicio del SO
para su terminación.
En una aplicación interactiva, es la acción del usuario la que indica su terminación. Por ejemplo, en
un sistema de tiempo compartido, el proceso de un usuario particular terminará cuando éste se
desconecte del sistema o apague el terminal y en GAML5Ó ÓJAR cuando el usuario abandona una
aplicación.
Un proceso puede ser eliminado por el proceso que lo creó o al terminar el proceso padre.
Bloqueados: proceso que no se puede ejecutar hasta que se produzca un cierto suceso, como la
terminación de una operación de E/S.
Nuevo: proceso que se acaba de crear, pero que aún no ha sido admitido por el sistema operativo
en el grupo de procesos ejecutables.
Terminado: un proceso que ha sido excluido del grupo de procesos ejecutables, porque se detuvo o
porque fue abandonado por alguna razón.
Si un nuevo usuario intenta conectarse a un sistema de tiempo compartido o si un nuevo trabajo por
lotes es remitido para su ejecución, el sistema operativo puede definir un nuevo proceso en dos pasos:
Primero, el proceso termina cuando llega al punto normal de terminación, cuando se abandona
debido a un error irrecuperable o cuando otro proceso con la debida autoridad hace que el proceso
abandone.
A medida que se admiten procesos en el sistema, se sitúan en la cola de Listo. Cuando llega el
momento de que el SO escoja otro proceso para ejecutar, se selecciona uno de la cola de Listos. En
ausencia de un esquema de prioridades, ésta puede ser una simple cola FIFO. Cuando un proceso que
está ejecutándose es apartado de la ejecución, se le da por terminado o se le pone en la cola de Listos
o Bloqueados, dependiendo de las circunstancias.
Por último, cuando se produce un suceso, todos los procesos de la cola de Bloqueados que están
esperando a dicho suceso se pasan a la cola de Listos. Esta última medida significa que, cuando se
produce un suceso, el sistema operativo debe recorrer toda la cola de Bloqueados, buscando aquellos
que esperaban al suceso. En un SO grande, puede haber demasiada cantidad de procesos en dichas
colas y, por lo tanto, sería más eficiente tener varias colas de Bloqueados, una por cada suceso.
Consideremos un sistema que no utiliza memoria virtual. Cada proceso que va a ejecutarse debe ser
cargado por completo en la memoria principal. La memoria contiene varios procesos y el procesador
puede dedicarse a otro proceso cuando uno esté esperando. Pero si el procesador es tan rápido en
comparación con E/S, todos los procesos de memoria estarán esperando este recurso. Así pues, incluso
con multiprogramación, el procesador podría estar desocupado la mayor parte del tiempo.
Una solución es el intercambio (CD E), que significa mover una parte o toda la memoria principal del
proceso a disco. Cuando ninguno de los procesos en memoria está en estado Listo, el sistema operativo
expulsa a disco a uno de los procesos que esté Bloqueado y lo pasa a una cola de Suspendidos. Al
realizar la transferencia del proceso a disco, entonces el espacio que se libera de la memoria principal
puede ser utilizado para traer otro proceso. En este modelo vemos que se ha agregado un estado
Suspendido.
Hemos visto dos conceptos independientes: si un proceso está esperando un suceso (bloqueado o no) y
si un proceso ha sido expulsado de la memoria principal (suspendido o no). Para realizar las
combinaciones de estos conceptos, hacen falta los cuatro estados siguientes:
Listo y suspendido: el proceso está en la memoria secundaria pero está disponible para su
ejecución tan pronto como se cargue en la memoria principal.
Atributos de protección de segmentos de memoria, tales como qué procesos pueden acceder a
ciertas regiones compartidas de memoria.
Las tablas de E/S son utilizadas por el sistema operativo para administrar los dispositivos y canales de
E/S del sistema computacional.
Las tablas de archivos ofrecen información sobre la existencia de los archivos, su posición en la memoria
secundaria, su estado actual y otros atributos. Gran parte de esta información (o toda) puede ser
mantenida y utilizada por un sistema de gestión de archivos, en cuyo caso el sistema operativo tendrá
poco o ningún conocimiento de los archivos.
Todas estas tablas deben estar enlazadas o disponer de referencias cruzadas de alguna manera. La
memoria, E/S y los archivos son administrados en nombre de los procesos, por lo que debe haber alguna
referencia directa o indirecta a estos recursos en las tablas de procesos.
Espacio de direcciones privadas del usuario: incluye los datos del usuario (la parte modificable
del espacio de usuario que puede guardar datos del programa, una zona para una pila del usuario y
programas que pueden modificarse) y el programa del usuario (programa a ejecutar).
Pila del sistema: cada proceso tiene una o más pilas LIFO asociadas a él. Una pila se utiliza para
almacenar los parámetros y las direcciones de retorno.
Bloque de control del proceso: información necesaria para que el sistema operativo controle al
proceso.
Para que el sistema operativo pueda administrar el proceso, al menos una pequeña parte de su imagen,
que contiene la información a usar por el sistema operativo, debe mantenerse en memoria principal. Para
ejecutar el proceso, la imagen completa debe cargarse en la memoria principal. Por tanto, el sistema
operativo necesita conocer la ubicación de cada proceso en el disco y también la ubicación de los
procesos que estén en memoria principal.
Hay una tabla principal de procesos con una entrada para cada proceso. Cada entrada contiene, al
menos, un puntero a la imagen de un proceso. Si la imagen del proceso contiene varios bloques,
entonces esta información estará guardada directamente en la tabla principal o con referencias cruzadas
a entradas de las tablas de memoria.
Una serie de rutinas del SO intentarán acceder a la información de los PCB. La dificultad no está en el
acceso, sino en la protección; existen dos problemas:
Un error en una sola rutina, como la de tratamiento de interrupciones, puede dañar los PCB, lo que
destruiría la capacidad del sistema para administrar los procesos afectados.
Un cambio de diseño en la estructura o en la semántica del PCB podría afectar a varios módulos del
SO
Estos problemas planteados se pueden abordar exigiendo a todas las rutinas del SO que pasen a través
de una rutina de manejo, cuya única tarea sería la de proteger los PCB y que se constituiría en el único
árbitro para leer y escribir en estos bloques.
La información del bloque de control del proceso puede agruparse en tres categorías generales:
Identificación del proceso: incluye el identificador del proceso, el identificador del proceso que lo
creó (proceso padre) y el identificador del usuario. A cada proceso se le asigna un identificador
único, que puede ser tan simple como un índice en la tabla principal de procesos. Si no hay
identificadores numéricos, entonces debe existir una correspondencia que permita al SO ubicar las
tablas apropiadas a partir del identificador del proceso.
Información del estado del procesador: está formada por los registros del procesador, que son los
registros visibles al usuario (a los que puede hacerse referencia mediante el lenguaje de máquina),
los Registros de Control y de Estado (IP – EFLAGS – Identificadores de habilitación/inhabilitación) y
los Punteros de Pila (las pilas almacenan los parámetros y las direcciones de retorno de los
procedimientos y de las llamadas al sistema; el puntero de pila apunta siempre a la cima de la pila).
Por supuesto, mientras un proceso está ejecutándose, utiliza los registros de la CPU. Cuando se
interrumpe el proceso, toda la información de los registros debe salvarse de forma que pueda
restaurarse cuando el proceso reanude su ejecución.
o Estructuración de Datos: un proceso puede estar enlazado con otros procesos en una
cola, anillos u otra estructura. El PCB puede contener punteros a otros procesos para dar
soporte a estas estructuras.
o Gestión de Memoria.
1. Asignar un único identificador al nuevo proceso. En ese momento se añade una nueva entrada a la
tabla principal de procesos, que contiene una entrada por proceso.
2. Asignar espacio para el proceso. Esto incluye todos los elementos de la imagen del proceso.
3. Debe inicializarse el PCB. La parte de información del estado del procesador normalmente se
inicializa con la mayor parte de las entradas a cero, excepto para el proceso inicial (que se prepara
con el punto de entrada del programa) y los punteros a las pilas del sistema (que establecen los
límites de la pila del proceso). La parte de información de control del procesador se inicializa a partir
de los valores estándares por omisión y los atributos que se han solicitado para el proceso. La
prioridad puede asignarse por omisión al valor más bajo, a menos que se haya hecho una solicitud
explícita de un valor mayor.
Interrupción: originada por algún suceso externo e independiente del proceso que está
ejecutándose. El control se transfiere primero a un gestor de interrupciones, quien lleva a cabo
algunas tareas básicas y luego se salta a una rutina del sistema operativo que se ocupa del tipo de
interrupción que se produjo. Algunos ejemplos son:
o Interrupción de E/S: cuando el SO reconoce que se produjo una acción de E/S, y la acción
constituye un suceso que están esperando uno o más procesos, entonces el SO traslada
todos los procesos bloqueados al estado Listo y decide si reanuda la ejecución del proceso
que está actualmente en estado de Ejecución o se expulsa a dicho proceso en favor de un
proceso Listo de mayor prioridad.
Cepo: tiene que ver con una condición de error o de excepción generada dentro del proceso que
está ejecutándose, como un intento ilegal de acceso a un archivo. El sistema operativo determina si
el error ocurrido es fatal. Si lo es, el proceso que estaba ejecutándose pasa al estado de Terminado
y se produce un cambio de proceso. Si no es fatal, se puede intentar algún procedimiento de
recuperación o, simplemente, notificarlo al usuario. Se puede hacer un cambio de proceso o,
simplemente, reanudar el mismo proceso que se estaba ejecutando.
Llamada del supervisor: se producen desde el programa que estaba ejecutándose. Por ejemplo, se
está ejecutando un proceso de usuario y se llega a una instrucción que solicita una operación de
E/S, tal como abrir un archivo. Esta llamada provoca la transferencia a una rutina que forma parte del
código del sistema operativo. Por lo general, el uso de una llamada al sistema hace que el proceso
de usuario pase al estado Bloqueado.
Si hay alguna interrupción pendiente, el procesador salva el contexto del programa que está
ejecutándose y asigna al IP el valor de la dirección de comienzo de un programa de tratamiento de la
interrupción. El procesador continúa entonces con el ciclo de lectura de instrucción y trae la primera
instrucción del programa de tratamiento de interrupciones, que atenderá a la interrupción. Al salvar el
contexto, se debe incluir cualquier información que pueda alterarse por la ejecución de la rutina de
tratamiento de la interrupción y que pueda ser necesaria para reanudar el programa que fue
interrumpido. Así pues, deberá salvarse la parte de información de estado del procesador del PCB. El
resto de la información del PCB depende de la influencia del tratamiento de la interrupción en el proceso.
Está claro que el cambio de contexto es un concepto distinto del cambio de proceso. En los cambios de
estado del proceso, por ejemplo, si el proceso que estaba ejecutándose pasa a otro estado (Listo,
Bloqueado, etc.) los pasos que se llevan a cabo son:
2. Actualizar el PCB que estaba en estado de Ejecución. Esto implica cambiar el estado del proceso a
alguno de los otros estados.
5. Actualizar el PCB del proceso seleccionado. Esto incluye cambiar el estado del proceso a
Ejecución.
7. Restaurar el contexto del proceso a aquél que existía en el momento en el que el proceso
seleccionado dejó por última vez el estado de Ejecución.
Un enfoque bastante tradicional y habitual en muchos de los sistemas operativos más antiguos es
ejecutar el núcleo del sistema operativo fuera de cualquier proceso. Cuando el proceso en ejecución es
interrumpido o hace una llamada de supervisor, se salva el contexto del procesador para este proceso y
se pasa el control al núcleo. El SO tiene su propia región de memoria y su propia pila del sistema para
controlar las llamadas y retornos de procedimientos. El SO puede llevar a cabo cualquier función
deseada y luego restaurar el contexto del proceso interrumpido para reanudarlo.
El punto clave es que se considera que el concepto de proceso se aplica sólo a los programas de
usuario. El código del SO se ejecuta como una entidad separada que opera en modo privilegiado.
Cuando se produce una interrupción, un cepo o una llamada del supervisor, el procesador se pone en
modo del núcleo y el control pasa al SO. Con tal fin, se salva el contexto del procesador y tiene lugar un
cambio de contexto hacia una rutina del SO. Sin embargo, la ejecución continúa dentro del proceso de
usuario en curso.
Si el sistema operativo, al completar su trabajo, determina que el proceso en curso debe continuar
ejecutándose, entonces se lleva a cabo un cambio de contexto para reanudar el programa interrumpido
del proceso en curso.
En la mayoría de los sistemas operativos, estas dos características son, de hecho, la esencia de un
proceso. Para distinguir estas dos características, la unidad de expedición es llamada thread y la unidad
de propiedad de los recursos, task. Un ÓOMN I (también llamado hilo, hebra o proceso liviano) es,
básicamente, la unidad de utilización de la CPU.
1.12.7.1 MULTI-THREADING
Algunos sistemas operativos soportan múltiples hilos en la ejecución dentro de un proceso simple. Esto
es conocido como multi-threading. Los procesos continúan teniendo un PCB y una cantidad de
memoria para el usuario, pero cada hilo que pertenece a dicho proceso tiene un bloque de control de
hilos, una pila de usuario y una pila de LNMRNS propias.
Hilos de nivel usuario: en este nivel todo el trabajo de los hilos es realizado por la aplicación y el
LNMRNS no se percata de la existencia de dichos hilos. Una aplicación (que puede ser programada
para ser UHSÓJÓOMN I usando bibliotecas de hilos) comienza con un hilo simple. La aplicación y su hilo
son localizados en un proceso simple administrado por el LNMRNS. La generación de nuevos hilos es
realizada invocando las utilidades que se encuentran en la biblioteca de hilos.
Hilos de nivel kernel: tiene la desventaja de que el cambio de hilos requiere siempre la intervención
del LNMRNS. No hay un código de administración de hilos en el área de la aplicación, sino simplemente
una interfase de una aplicación programada (API) para el LNMRNS. El LNMRNS mantiene la información
del contexto del proceso entero y de cada uno de los procesos hilos que se encuentran dentro del
mismo. La ventaja que presenta es que si uno de estos procesos hilos se encuentra en estado
bloqueado, el LNMRNS puede ejecutar otro proceso hilo del mismo padre.
Un ÓOMN I individual tiene su propio registro de estado y generalmente su propia pila (CÓ XL).
Los hilos pueden estar en uno de los siguientes estados: listos, bloqueados, ejecutando o
terminados. O sea, igual que un proceso tradicional. Los hilos comparten CPU, por lo que un solo
hilo puede estar ejecutándose.
Un hilo puede leer o escribir sobre cualquier otra pila de otro hilo. No se provee protección porque no
es necesaria, ya que solo un usuario puede tener una tarea individual con múltiples hilos.
Una tarea no hace nada sin hilos y un hilo debe estar en una tarea
Un hilo único a nivel usuario ejecutando un 5VCÓNU,1 SS causará a la tarea entera esperar hasta que
el 5VCÓNU,1 SS sea devuelto.
2 FICHEROS
2.1 CONCEPTOS DE FICHEROS
Un fichero o archivo es un conjunto de bits almacenado en un dispositivo.
Un fichero es identificado por un nombre y la descripción de la carpeta o directorio que lo contiene dentro
del sistema operativo. Los ficheros informáticos se llaman así porque son los equivalentes digitales de
los ficheros en tarjetas, papel o microfichas del entorno de la oficina tradicional. Los ficheros informáticos
facilitan una manera de organizar los recursos usados para almacenar permanentemente datos en un
sistema informático.
Los datos de un fichero normalmente consisten en paquetes de datos más pequeños (llamados registros
o líneas) que son individualmente diferentes pero que comparten algún rasgo en común. Por ejemplo, un
fichero de nóminas puede contener datos sobre todos los empleados de una empresa y los detalles de
su nómina; cada registro del fichero de nóminas se refiere únicamente a un empleado, y todos los
registros tienen la característica común de estar relacionados con las nóminas. Esto es muy similar a
colocar todos los datos sobre nóminas en un archivador concreto en una oficina que no tenga ninguna
computación. Un fichero de texto puede contener líneas de texto, correspondientes a líneas impresas en
una hoja de papel.
La manera en que se agrupan los datos en un fichero depende completamente de la persona que diseñe
el fichero. Esto ha conducido a una gran cantidad de estructuras de ficheros más o menos
estandarizadas para todos los propósitos imaginables, desde las más simples a las más complejas. Los
ficheros son usados por programas de computación. Estos programas crean, leen, modifican y borran
ficheros para su propio uso bajo demanda. Los programadores que crean los programas deciden qué
ficheros necesitan, cual será su estructura, cómo se van a usar, y (a menudo) sus nombres.
En algunos casos, los programas de computación manipulan los ficheros que se hacen visibles al
usuario. Por ejemplo, en un programa de procesamiento de texto, el usuario manipula ficheros-
documentos a los que él mismo da nombre. El contenido del fichero-documento está organizado de una
manera que el programa de procesamiento de texto entiende, pero el usuario elige el nombre y la
ubicación del fichero, y proporciona la información (como palabras y texto) que se almacenará en el
fichero.
Muchas aplicaciones empaquetan todos sus datos en un único fichero, usando marcadores internos para
discernir los diferentes tipos de información que contienen.
Notar la diferencia entre el contenido de un fichero y la forma en que puede ser visualizado dicho
contenido. Muchos ficheros contienen información que no puede ser visualizado mediante los formatos
estándar (pantalla, papel u otros soportes). La interpretación del contenido depende del tipo de fichero y
de la estructura del mismo. El objetivo del fichero siempre será el almacenamiento de información
relevante y permanente.
Los ficheros se pueden crear, leer, mover, grabar y modificar su contenido, aumentar o reducir su
tamaño, y borrar. En la mayoría de los casos, los programas de computación se encargan de estas
operaciones, pero el usuario también puede manipular los ficheros si es necesario. Por ejemplo, los
ficheros de Microsoft Office Word son normalmente creados y modificados por el programa Microsoft
Word en respuesta a las órdenes del usuario, pero el usuario también puede mover, renombrar o borrar
estos ficheros directamente usando un programa gestor de ficheros como Windows Explorer (con
sistema operativo Windows).
Ficheros binarios. Son ficheros que contienen una lista de bits que solamente son reconocibles por
la aplicación que los gestiona, que puede ser un programa propio del sistema operativo, o una
aplicación concreta. Por ejemplo, la compilación de un programa escrito en lenguaje C produce un
fichero con un determinado nombre, ese fichero es comprensible por el núcleo del sistema operativo,
y será capaz de ejecutarlo. Otro ejemplo, si se quiere almacenar una gran cantidad de datos
numéricos en un fichero, lo más óptimo sería grabarlo en formato binario, y no en formato texto,
puesto que su procesamiento sería mucho más rápido, utilizando las primitivas correspondientes a la
grabación binaria del lenguaje utilizado.
Ficheros de texto. Son ficheros que contienen una lista de bits que siguen una codificación
determinada, como puede ser ASCII o Unicode, normalmente en grupos de 1 o 2 bytes, y que son
reconocibles por múltiples programas y aplicaciones que los gestionan, que pueden ser programas
propios del sistema operativo, o aplicaciones concretas. Por ejemplo, la mayor parte de los ficheros
de configuración de un sistema operativo son ficheros de texto que pueden ser gestionados con
cualquiera de los editores de ficheros del sistema. Otro ejemplo, si se desea almacenar un registro
de los pasos que va siguiendo un programa escrito, junto con ciertos valores de sus variables, lo
normal es grabarlo en un fichero de texto que puede ser verificado con múltiples comandos del
sistema operativo. En este caso no tendría mucho sentido almacenarlo en un fichero binario, por la
complejidad de su tratamiento posterior.
Directorios o Carpetas. Son ficheros especiales, sin un contenido manejable por el usuario, que
sirven para crear la estructura jerárquica de árbol que define las rutas o nombres completos de los
ficheros. Se pueden crear, borrar y renombrar.
Ficheros especiales y de dispositivos. Son ficheros que crea o gestiona el sistema operativo, y
que se utilizan para la gestión de determinados recursos como puede ser los discos, bloqueos,
procesos, memoria, área de swap, etc. Esta tipología de ficheros será vista en otra sección del
capítulo, y desarrollada en otros capítulos.
#include <protos.h>
main()
{
printf("Hello world\n");
exit(0);
}
La estructura completa del fichero está organizada en líneas, y cada línea está terminada en un
carácter especial (nueva línea o RNDSJRN).
Dentro de cada línea puede haber caracteres especiales, como puede ser un tabulador, que es
almacenado como un carácter más, y que puede producir efectos especiales a la hora de visualizar
dicho carácter; en este caso el tabulador será transformado en un cierto número de espacios en
blanco.
El sistema operativo marca el final del fichero con un carácter especial (ASCII CTRL-D) para indicar
el final del mismo. Este carácter nunca será visualizado al mostrar el contenido de un fichero.
Todos los caracteres del fichero están almacenados secuencialmente dentro del mismo, cada uno en un
byte. Veamos el contenido del fichero, para ello vamos a utilizar un comando del sistema operativo que
nos muestra el contenido en caracteres ASCII (visible) y en su equivalente hexadecimal:
Podemos notar que en la notación hexadecimal, los bytes están intercambiados, lo que nos puede llevar
a error. Para solucionarlo podemos usar otro formato del comando, que además nos muestra los
caracteres especiales mediante su notación ASCII:
Los caracteres especiales, como saltos de línea, tabuladores, etc. se muestran con una notación
especial, mediante una barra inclinada “\” y un símbolo que denota el tipo de carácter. La lista de
caracteres especial se muestra a continuación:
Si realizamos la compilación del programa fuente anterior para obtener un programa ejecutable,
obtenemos un fichero binario en código máquina, solamente comprensible por el sistema operativo.
Mediante el mismo comando anterior, y filtrando las primeras líneas del fichero, vamos a visualizar el
contenido de los primeros bytes del fichero ejecutable, cuyo nombre podría ser EMHNB :
7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
0000020 stx nul etx nul soh nul nul nul h eot eot bs 4 nul nul nul
02 00 03 00 01 00 00 00 68 84 04 08 34 00 00 00
0000040 ` ff nul nul nul nul nul nul 4 nul sp nul enq nul ( nul
60 0c 00 00 00 00 00 00 34 00 20 00 05 00 28 00
0000060 nak nul dc3 nul ack nul nul nul 4 nul nul nul 4 nul eot bs
15 00 13 00 06 00 00 00 34 00 00 00 34 80 04 08
0000100 nul nul nul nul sp nul nul nul sp nul nul nul enq nul nul nul
00 00 00 00 a0 00 00 00 a0 00 00 00 05 00 00 00
Como podemos observar el resultado no es nada significativo, puesto que el compilador traduce el
programa fuente a una serie de bytes que sólo son reconocibles por el núcleo del sistema operativo o por
determinadas herramientas de trabajo con programas compilados o ejecutables. En resumen, no tiene
mucho sentido la visualización del contenido de los ficheros binarios, salvo para los programas
específicos que sepan interpretarlos.
Veamos otro ejemplo del contenido de un fichero de texto, que corresponde a una descarga de datos
desde una BD, con la intención de ser procesado en otro sistema. El nombre del fichero es ÓJEACsJÍ , y
en estos ejemplos el directorio de residencia del fichero no es relevante. Su contenido es el siguiente
(mostrado en caracteres ASCII formateados sobre una pantalla):
Sobre el contenido de este fichero podemos observar una estructura especial en su contenido. Además
de tener la información diferenciada en líneas (cada línea hace referencia a un tipo de IVA determinado),
contiene una estructura dentro de cada línea, de forma uniforme en todas las líneas, y que podríamos
denominar campos dentro de la línea. Como vemos, cada campo esta separado del siguiente por un
carácter especial (~), incluso el final de cada línea está marcado por dicho carácter especial. Este
carácter de separación puede ser cualquiera, solamente debemos tener mucho cuidado de que dicho
carácter no esté contenido en los valores de cualquiera de los campos, lo que produciría que esa línea
tendría más campos que los definidos.
Como podemos observar, la primera línea del fichero es una pequeña descripción de los campos que
conforman cada línea, lo que no es propiamente una línea de datos descargados. El programador la ha
incluido para disponer de una ayuda relativa a la estructura del fichero, y será el programa que lo
procese, el encargado de obviar esa primera línea en el proceso del fichero.
0000000 C o d ~ D e s ~ T i p ~ R e c ~
43 6f 64 7e 44 65 73 7e 54 69 70 7e 52 65 63 7e
0000020 F e c ~ S / R ~ C t 1 ~ C t 2 ~
46 65 63 7e 53 2f 52 7e 43 74 31 7e 43 74 32 7e
0000040 C t 3 ~ \n 0 ~ I . V . A E X E
43 74 33 7e 0a 30 7e 49 2e 56 2e 41 20 45 58 45
0000060 N T O ~ 0 , 0 0 ~ 0 , 0 0 ~ 3 1
4e 54 4f 7e 30 2c 30 30 7e 30 2c 30 30 7e 33 31
0000100 - 1 2 - 2 0 5 0 ~ D ~ 4 . 7 . 2
2d 31 32 2d 32 30 35 30 7e 44 7e 34 2e 37 2e 32
0000120 . 0 0 0 0 9 9 ~ 4 . 7 . 2 . 0 0
2e 30 30 30 30 39 39 7e 34 2e 37 2e 32 2e 30 30
0000140 0 0 9 9 ~ 4 . 7 . 2 . 0 0 0 0 0
30 30 39 39 7e 34 2e 37 2e 32 2e 30 30 30 30 30
0000160 8 ~ \n N ~ F A C T U R A S I N
38 7e 0a 4e 7e 46 41 43 54 55 52 41 53 20 49 4e
0000200 V E R S I O N ~ 1 6 , 0 0 ~ 0 ,
56 45 52 53 49 4f 4e 7e 31 36 2c 30 30 7e 30 2c
0000220 0 0 ~ 3 1 - 1 2 - 2 0 0 9 ~ D ~
30 30 7e 33 31 2d 31 32 2d 32 30 30 39 7e 44 7e
eY Ch Hx Ch Hx Ch Hx Ch Hx Ch Hx Ch Hx Ch Hx Ch
00 nul 01 soh 02 stx 03 etx 04 eot 05 enq 06 ack 07 bel
08 bs 09 ht 0a nl 0b vt 0c np 0d cr 0e so 0f si
10 dle 11 dc1 12 dc2 13 dc3 14 dc4 15 nak 16 syn 17 etb
18 can 19 em 1a sub 1b esc 1c fs 1d gs 1e rs 1f us
20 sp 21 ! 22 " 23 # 24 $ 25 % 26 & 27 '
28 ( 29 ) 2a * 2b + 2c , 2d - 2e . 2f /
30 0 31 1 32 2 33 3 34 4 35 5 36 6 37 7
38 8 39 9 3a : 3b ; 3c < 3d = 3e > 3f ?
40 @ 41 A 42 B 43 C 44 D 45 E 46 F 47 G
48 H 49 I 4a J 4b K 4c L 4d M 4e N 4f O
50 P 51 Q 52 R 53 S 54 T 55 U 56 V 57 W
58 X 59 Y 5a Z 5b [ 5c \ 5d ] 5e ^ 5f _
60 ` 61 a 62 b 63 c 64 d 65 e 66 f 67 g
68 h 69 i 6a j 6b k 6c l 6d m 6e n 6f o
70 p 71 q 72 r 73 s 74 t 75 u 76 v 77 w
78 x 79 y 7a z 7b { 7c | 7d } 7e ~ 7f del
En los sistemas informáticos modernos, los ficheros siempre tienen nombres. Los ficheros se ubican en
directorios. El nombre de un fichero debe ser único en ese directorio. En otras palabras, no puede haber
dos ficheros con el mismo nombre en el mismo directorio.
El nombre de un fichero y la ruta de directorio que lo contiene, lo identifica de manera unívoca entre
todos los demás ficheros del sistema. No puede haber dos ficheros con el mismo nombre y ruta, o con el
mismo nombre completo. El aspecto del nombre depende del tipo de sistema operativo que se use. Los
primeros sistemas sólo permitían unas pocas letras o dígitos en el nombre de un fichero, pero los
sistemas modernos permiten nombres largos que contengan casi cualquier combinación de caracteres
Unicode, haciendo más fácil entender el propósito de un fichero con la sola visualización de su nombre.
Algunos sistemas operativos permiten nombres de fichero que contengan espacios; otros no. La
distinción entre mayúsculas y minúsculas en los nombres de fichero está determinada por el sistema
operativo. Los sistemas de ficheros UNIX distinguen normalmente entre mayúsculas y minúsculas, y
permiten a las aplicaciones a nivel de usuario crear ficheros cuyos nombres difieran solamente en si los
caracteres están en mayúsculas o minúsculas. Microsoft Windows reconoce varios sistemas de ficheros,
cada uno con diferentes políticas en cuanto a la distinción entre mayúsculas y minúsculas. El popular
antiguo sistema de ficheros FAT puede tener varios ficheros cuyos nombres difieran únicamente en las
mayúsculas y minúsculas si el usuario utiliza un editor de ficheros para editar los nombres de fichero en
las entradas de directorio. Las aplicaciones de usuario, sin embargo, normalmente no permitirán al
usuario crear varios ficheros con el mismo nombre pero con diferentes letras en mayúsculas y
minúsculas.
La mayoría de los sistemas operativos organizan los ficheros en jerarquías llamadas carpetas, directorios
o catálogos. El concepto es el mismo independientemente de la terminología usada. Cada carpeta puede
contener un número arbitrario de ficheros (limitado por el sistema), y también puede contener otras
carpetas. Las otras carpetas pueden contener todavía más ficheros y carpetas, y así sucesivamente,
construyéndose un estructura en árbol en la que una «carpeta raíz» (el nombre varía de un sistema a
otro) puede contener cualquier número de niveles de otras carpetas y ficheros. A las carpetas se les
puede dar nombre exactamente igual que a los ficheros (excepto para la carpeta raíz, que a menudo no
tiene nombre). El uso de carpetas hace más fácil organizar los ficheros de una manera lógica.
Cuando un sistema permite el uso de carpetas, cada fichero y carpeta no sólo tiene un nombre propio,
sino también una ruta, que identifica la carpeta o subcarpetas en las que reside un fichero o carpeta. En
la ruta, se emplea algún tipo de carácter especial -como una barra- para separar los nombres de los
ficheros y carpetas. Por ejemplo, en la ilustración mostrada en este artículo, la ruta
/Clientes/Pedidos/1AR6JMU IAC identifica unívocamente un fichero llamado 1AR6JMU IAC que está en una
carpeta llamada iNIJIAC que a su vez está contenida en una carpeta llamada 1SJNRÓNC. En este ejemplo,
los nombres de las carpetas y ficheros están separados por barras; la superior o carpeta raíz no tiene
nombre, y por ello la ruta comienza con una barra (si la carpeta raíz tuviera nombre, precedería a esta
primera barra).
Muchos (pero no todos) los sistemas operativos usan extensiones en los nombres de fichero para ayudar
a identificar qué contienen. En sistemas Windows, las extensiones consisten en un punto al final del
nombre del fichero, seguido de unas pocas letras para identificar el tipo de fichero. Una extensión .txt
identifica un fichero de texto; la extensión .doc identifica cualquier tipo de documento o documentación,
comúnmente en el formato de fichero de Microsoft Office Word; etc. Incluso cuando se utilizan
extensiones en un sistema informático, el grado con el que un sistema informático los reconoce y trata
puede variar; en algunos sistemas son obligatorias, mientras que en otros sistemas se ignoran
completamente si están presentes.
No se ha podido escribir en el dispositivo toda la información del fichero por falta de espacio en el
dispositivo de almacenamiento.
Otro mecanismo de protección implementado en muchos sistemas operativos es una marca de sólo
lectura. Cuando esta marca está activada en un fichero (lo que puede ser realizado por un programa o
por un usuario), el fichero puede ser examinado, pero no puede ser modificado. Esta marca es útil para
información crítica que no debe ser modificada o borrada, como ficheros especiales que son usados
solamente por partes internas del sistema informático. Algunos sistemas incluyen también una marca
oculta para hacer que ciertos ficheros sean invisibles; esta marca la usa el sistema informático para
ocultar ficheros de sistema esenciales que los usuarios nunca deben modificar.
Algunos países han creado organismos que se encargan del tema y de legislar respecto del acceso, uso
y confidencialidad de los datos. Para España, revisar la LOPD.
Hace unos años solían usarse cintas magnéticas para realizar las copias de seguridad. También se
usaban otros medios de almacenamiento como discos compactos grabables, unidades Zip, etc.
No obstante en la actualidad han cobrado mucho auge las memorias flash, dispositivos con mucha
capacidad de almacenamiento que tienen la ventaja de ser pequeños y portátiles; suelen usarse para
guardar ficheros en dispositivos pequeños como teléfonos móviles o reproductores de audio portátiles
Hay muchas maneras de hacer copias de respaldo de ficheros. La mayoría de los sistemas informáticos
proporcionan utilidades para ayudar en el proceso de respaldo, que puede llegar a consumir mucho
tiempo si hay muchos ficheros a salvaguardar. Copiar los ficheros a otro disco duro en el mismo sistema
protege contra el fallo de un disco, pero si es necesario protegerse contra el fallo o destrucción del
sistema entero, entonces de deben hacer copias de los ficheros en otro medio que pueda sacarse del
sistema y almacenarse en una ubicación distante y segura.
Dada la lentitud del proceso, Multics supuso un importante avance, sin embargo, este sistema operativo
carecía de características importantes para los programadores.
En 1969, Ken Thompson y Dennis Ritchie crearon un sistema operativo con el fin de paliar algunos
problemas de complejidad que se derivaban de la utilización de grandes ordenadores. A este sistema se
le llamó UNIX y supuso la simplificación del dialogo entre el hombre y la máquina. Thompson y Ritchie
consideraron que la mayor parte del desarrollo de programas (mas del 50%) se empleaba en crear
ficheros fuente y compilarlos. Para tales tareas no es necesario la utilización de una gran maquina, sino
que basta con un ordenador pequeño que disponga de gran memoria en periféricos, donde almacenar
los ficheros.
Aspecto importante a considerar era que el programador disponía de un método sencillo para la
creación, actualización y gestión de los ficheros, y esta es una de las características esenciales de UNIX:
un sistema de ficheros con estructura jerárquica en forma de árbol. Esta herramienta permite la creación
de un fichero sin necesidad de definir parámetros del mismo (extensión, formato, etc.), y se puede
localizar de forma automática cualquier fichero en cualquier directorio del sistema.
Una vez que se ha creado el fichero fuente es necesario compilarlo y para tal tarea tampoco se requiere
un gran ordenador, que únicamente será necesario a la hora de ejecutar grandes programas. Se
desarrollaron por tanto, en Bells Labs, una serie de programas de utilidad para facilitar las
comunicaciones entre los grandes y pequeños ordenadores. Estas utilidades forman parte del sistema
UNIX y son accesibles por el usuario. Estos programas permiten la traducción del código interno utilizado
por los pequeños PDP-11 de Digital, al código EBCDIC usado par los grandes ordenadores IBM.
Concluyendo, con UNIX se logró dotar a maquinas pequeñas de un sistema interactivo comparable al de
los grandes ordenadores de la época.
Ken Thompson, un programador informático de AT&T Bell Laboratories, y un equipo de expertos que
colaboraron con él, desarrollaron un sistema operativo flexible y totalmente compatible con las distintas
necesidades de los programadores. Cuenta la leyenda que Ken, que se encontraba desarrollando el
sistema operativo MULTICS, le puso el nombre de UNIX a este proyecto cuando se encontraba
bromeando con el resto del equipo. Ironizando sobre el sistema operativo multiusuario MULTICS
(MULTICS se pronuncia igual que MULTIX) decidió ponerle el nombre de UNIX, es decir un término
derivado de “uni”, que significa un o único, seguido de la letra homófona X. Lo más paradójico de este
hecho es que pocos usuarios recuerdan hoy MULTICS como un sistema operativo multiusuario viable
mientras que UNIX se ha convertido en el estándar multiusuario de facto para sistemas operativos
multiusuario y multitarea.
Thompson desarrolló un lenguaje basado en el "BCPL" con la finalidad de que fuera transportable y lo
denominó "Lenguaje B"'. En el mismo año 1971 D. Ritchie lo modificó y el nuevo resultado se llamó
"Lenguaje C".
Hasta el nacimiento de la versión V6 de UNIX, su uso era interno y restringido a los laboratorios Bell.
Estaba extendido por los distintos departamentos que le fueron incorporando modificaciones de acuerdo
con sus respectivas necesidades (MERT, PWD/UNIX).
En 1975 el sistema UNIX comienza a ser difundido. Su comercialización se limita al envío de una cinta
magnética y un ejemplar de cada manual. Los laboratorios Bell no garantizan por entonces ni la
instalación ni el mantenimiento del sistema. El PWD ("Programmer's Workbech") se desarrolló a la vez
que la versión V7 de UNIX para un equipo diferente al utilizado por Thompson y Ritchie. Se utilizó para
centros de cálculo donde el desarrollo se hacia con PWD/UNIX en mini ordenadores PDP-11 y la
ejecución se realizaba en sistemas IBM 370 y UNIVAC 1100. Las innovaciones que conlleva el PWD con
respecto a la versión V6 de UNIX son:
Creación de utilidades para gestión de los fuentes ("SCCS") y el envío de trabajos a distancia.
En los laboratorios Bell el sistema PWD/UNIX se puso a disposición del servicio B.I.S.P. que poseía una
red de PDP-11/45 y PDP-11/70 conectados con IBM 370/168, XDS SIGMA5 y UNIVAC 1100 utilizados
por gran cantidad de usuarios.
La versión V7 supuso un cambio importante con respecto a la V6, introduciendo una serie de
modificaciones que se pueden resumir en:
Hasta entonces UNIX solo se había instalado en maquinas PDP-11, sin embargo se llega a la conclusión
de que es necesario transportarlo a otras maquinas. El primer transporte se realizó en el año 1977 sobre
un ordenador INTERDATA 8/32. El hecho de que fuera necesaria la transportabilidad supuso llevar a
cabo una serie de modificaciones.
Debido al aumento de potencia y al abaratamiento del coste de los mini ordenadores, el sistema
operativo UNIX se ha hecho rápidamente popular. Estas máquinas se han utilizado inmediatamente para
el control de experimentos de laboratorio, soporte de diseño asistido por computador, supervisión de
redes de telecomunicaciones y ejecución de funciones comerciales. El desarrollo de un software que
cumpliera estas aplicaciones específicas supuso para los programadores un nuevo reto, y el sistema
UNIX se ofrecía como una herramienta efectiva para conseguirlo. Hacia 1978 estaban funcionando en
universidades, departamentos gubernamentales y en los laboratorios Bell más de 500 instalaciones del
sistema UNIX.
A nivel del lenguaje “C” se realizaron los cambios oportunos para que los programas se
independizaran en la medida de lo posible de las características físicas de la maquina.
A nivel del compilador se introdujeron técnicas que facilitaban la adopción del mismo a distintas
maquinas.
A nivel del sistema se pretendió aislar las partes más dependientes de la arquitectura de la maquina
del resto.
Con las modificaciones descritas anteriormente surge en 1978 la versión séptima de UNIX (UNIX/V7)
para los ordenadores PDP-11 UNIX/V32 y VAX 11/780.
Una distribución para maquinas de la gama de Digital Equipment (del PDP-11/23 al VAX 11/780.
El sistema V que surge en 1983 ofrece además de lo anterior, la licencia de uso, instalación,
mantenimiento y actualizaciones del sistema. En la actualidad es importante destacar el sistema UNIX
desarrollado por la Universidad de Berkeley (versión 4.1. BSD) que gestiona memoria virtual. Estos
programas han sido adoptados por los laboratorios Bell y se incluyen en las nuevas versiones de UNIX.
Una de estas importantes contribuciones es el editor de textos “vi”.
3.2.1 BSD
Berkeley Software Distribution (BSD), de la Universidad de Berkeley en California, desarrolló la primera
versión de UNIX basándose en la Versión 7 de AT&T, en 1978. BSD UNIX, que es como se conoce en el
sector informático, incluía una serie de mejoras desarrolladas por los círculos académicos de Berkeley,
diseñadas para que UNIX fuera más accesible para el usuario. Las mejoras que incorporaba BSD UNIX
fueron pensadas para atraer a un mayor número de usuarios, así como a expertos programadores que
apreciaran la flexibilidad de este sistema para adaptarse a sus exigencias. Aunque su compatibilidad con
el UNIX original de AT&T no alcanzaba el 100%, esta nueva versión consiguió el objetivo que se había
fijado: atraer a un mayor número de usuarios gracias a sus características añadidas.
BSD se ha convertido desde entonces en el estándar académico de UNIX. Los creadores originales de
BSD lanzaron posteriormente una versión para la plataforma Intel denominada, igualmente, BSD. Esta
versión tiene también una distribución limitada en Internet y en CD-ROM. Sus autores escribieron hace
unos años algunos artículos en la revista informática Dr. Dobb's Journal, detallando el diseño e
implementación del BSD386 o FreeBSD. Actualmente, la versión comercial de FreeBSD se ha
convertido, al igual que Linux, en uno de los sistemas operativos utilizados del mercado.
En definitiva, había dos opciones posibles en la elección de UNIX como herramienta de trabajo:
Sistemas que trabajan con UNIX transportado a una maquina en particular. En este caso era
necesario el pago de una licencia y de un canon a los laboratorios Bell.
Sistemas que poseen los mismos servicios que UNIX pero que han sido lo suficientemente
modificados como para que se los considere ajenos a los laboratorios Bell.
La historia continuó de forma vertiginosa. NCR se constituyó en uno de los impulsores de sistemas
UNIX, implementando System V en numerosas plataformas, lo que hizo que otros fabricantes le
acompañasen. Otros optaron por implementar sus propias versiones del sistema.
3.2.2 USL
UNIX System Laboratories (USL) era una empresa filial de AT&T que llevaba desarrollando el sistema
operativo UNIX desde principios de la década de los 80. Antes de que fuera adquirida por Novell en
1993, USL desarrolló el código fuente para todas las variantes de UNIX System V. Sin embargo, en
aquel momento USL no vendió ni uno solo de sus productos.
La última versión de UNIX que realizó USL fue UNIX System V versión 4.2 (SVR4.2). El SVR4.2 supuso
la primera tentativa comercial de USL en el mercado de UNIX. Asociado a Novell, que fundó
temporalmente una empresa llamada Univel, USL desarrolló una versión comercial de SVR4.2 con el
nombre de UnixWare.
Con la adquisición de USL por parte de Novell, la empresa dejó de producir códigos fuente para
concentrarse en el desarrollo de UnixWare. Posteriormente Novell vendió su versión de UNIX a la
compañía Santa Cruz Operation (SCO).
Recientemente, SCO realizó una licencia gratuita de usuario único para que el público pudiera acceder a
SCO UNIX. Sin embargo y aunque parezca una contradicción, la distribución de este programa tiene un
pequeño coste, mientras que la de Linux es totalmente gratuita. Además y aunque SCO facilita una copia
de su sistema operativo, en ella no va incluido el código fuente, lo que lógicamente ha hecho de Linux un
sistema operativo mucho más competitivo e interesante para el usuario.
UNIX resultó en una versión basada en BSD, un hecho interesante si tenemos en cuenta que el SVR4.2
de AT&T también es compatible con BSD, gracias a la colaboración entre AT&T y Sun Microsystems
para desarrollar el UNIX System V Versión 4.0.
La incursión de IBM en el universo UNIX se tradujo en el sistema operativo AIX (Advanced Interactive
Executive). Aunque AIX no es tan conocido como otras versiones de UNIX, posee un buen rendimiento y
no causa problemas, lo que le ha llevado a ocupar un lugar en el mercado de sistemas operativos.
Probablemente, las mismas reticencias que tacharon a UNIX de sistema complicado han impedido que
AIX cuente con mayor aceptación entre el público.
3.2.4 LINUX
Linux fue el proyecto original de un estudiante de informática llamado Linus Torvalds, que entonces
contaba 23 años. Linux empezó siendo un pasatiempo para Linus, que esperaba crear una versión más
sólida de UNIX para usuarios de Minix.
Minix es un programa desarrollado por el profesor de informática Andrew Tannebaum. El sistema Minix
se escribió para demostrar algunos conceptos informáticos que se encuentran en los sistemas
operativos. Torvalds incorporó estos conceptos en un sistema autónomo que imitaba a UNIX. El
programa se puso a disposición de los estudiantes de informática de todo el mundo y muy pronto contó
con muchos seguidores, incluyendo aquellos que participaban en sus grupos de debate de Usenet. Linus
Torvalds decidió entonces proporcionar una plataforma más accesible para los usuarios de Minix que
pudiera ejecutarse en cualquier IBM PC y centró su atención en las recién aparecidas computadoras
basadas en 386, debido a las propiedades de conmutación de tareas que incorporaba la interfaz en
modo protegido del 80386.
A continuación reproducimos algunas de las anotaciones de Linus cuando dio a conocer su programa
Linux.
"Después de aquello, todo fue coser y cantar: algún que otro código se me resistía, pero contaba
con dispositivos y la depuración fue sencilla. Empecé a utilizar C en esta fase y me di cuenta de
que aceleraba el desarrollo. Por aquel entonces, también empecé a tomarme en serio mis ideas,
megalómanas para crear ‘un Minix mejor que el mismísimo Minix'. Esperaba algún día poder
compilar de nuevo gcc bajo Linux..."
"Pasé dos meses con la configuración básica, que me llevó más tiempo del esperado hasta que
conseguí un controlador de disco (algo anticuado pero que resultó funcionar en mi máquina) y un
pequeño sistema de archivos. Fue entonces cuando terminé la versión 0.01 (hacia finales de
agosto de 1991): no era ninguna maravilla, no tenía controlador de disquete y apenas sí podía
hacer algo con ella. No creo que nadie compilara aquella versión. Pero ya estaba enganchado y
no quería parar hasta que no consiguiera darle un empujón final a Minix."
"¿Añora aquellos gloriosos días de Minix 1.1, cuando los hombres eran hombres y escribían sus
propios administradores de dispositivos? ¿Anhela un proyecto atractivo con el que poder
modificar un sistema operativo para adaptarlo a sus necesidades? ¿Encuentra frustrante que
todo tenga que funcionar con Minix? ¿Está harto de pasar noches en vela tratando de que
funcione un programa? Sí su respuesta a todas estas preguntas es afirmativa, entonces le
interesa este anuncio."
"Como dije hace un mes, estoy trabajando en una versión gratuita de un sistema parecido a
Minix para computadoras AT 386. He alcanzado la fase de utilización (o tal vez no, según lo que
necesite), y quiero dar a conocer sus fuentes para obtener una mayor difusión del mismo. Se
trata de la versión 0.02, que me ha permitido ejecutar satisfactoriamente bash, gcc, gnumake,
gnu-sed, compress, entre otros."
BSD: familia originada por el licenciamiento de UNIX a Berkely. BSD se reescribió para no incorporar
propiedad intelectual originaria de AT&T en la versión 4. La primera implementación de los
protocolos TCP/IP que dieron origen a Internet son la pila (CÓ XL) TCP/IP BSD.
AIX: Esta familia surge por el licenciamiento de UNIX System III a IBM.
Xenix: familia derivada de la adquisición de los derechos originales de AT&T primero por parte de
Microsoft y de esta los vendió a SCO.
GNU: En 1983, Richard Stallman anunció el Proyecto GNU, un ambicioso esfuerzo para crear un
sistema similar a Unix, que pudiese ser distribuido libremente. El software desarrollado por este
proyecto -por ejemplo, GNU Emacs y GCC - también han sido parte fundamental de otros sistemas
UNIX.
Linux: En 1991, cuando Linus Torvalds empezó a proponer el núcleo Linux y a reunir colaboradores,
las herramientas GNU eran la elección perfecta. Al combinarse ambos elementos, conformaron la
base del sistema operativo (basado en POSIX) que hoy se conoce como GNU/Linux. Las
distribuciones basadas en el núcleo, el software GNU y otros agregados entre las que se pueden
mencionar a Slackware Linux, Red Hat Linux y Debian GNU/Linux se han hecho populares tanto
entre los aficionados a la computación como en el mundo empresarial. Obsérvese que Linux tiene un
origen independiente, por lo que se considera un 'clónico' de UNIX y no un UNIX en el sentido
histórico.
Las interrelaciones entre estas familias son las siguientes, aproximadamente en orden cronológico:
Xenix también surge por licenciamiento del UNIX original de AT&T, aunque aún no era propiedad de
SCO.
AIX surge por licenciamiento de UNIX System III, pero también incorpora propiedad intelectual de
BSD.
La familia original AT&T incorpora ilegalmente propiedad intelectual de BSD en UNIX System III r3.
La familia AIX vuelve a incorporar propiedad intelectual de la familia AT&T, esta vez procedente de
UNIX System V.
Linux incorpora propiedad intelectual de BSD, gracias a que éste también se libera con una licencia
de código abierto denominada Open-source BSD.
Según SCO Group, Linux incorpora propiedad intelectual procedente de AIX, gracias a la
colaboración de IBM en la versión 2.4, más aún no está demostrado, hay un proceso judicial al
respecto: Disputas de SCO sobre Linux.
alcanzado la certificación UNIX], FreeBSD, NetBSD, OpenBSD), los cuales no buscan la certificación
UNIX por resultar cara para productos destinados al consumidor final o que se distribuyen libremente en
Internet. En estos casos, el término se suele escribir como "UN*X", "*NIX", o "*N?X".
A lo largo de la historia ha surgido una gran multitud de implementaciones comerciales de UNIX. Sin
embargo, un conjunto reducido de productos han consolidado el mercado y prevalecen gracias a un
continuo esfuerzo de desarrollo por parte de sus fabricantes. Los más importantes son:
Solaris de Sun Microsystems. Uno de los sistemas operativos Unix más difundidos en el entorno
empresarial y conocido por su gran estabilidad. Parte del código fuente de Solaris se ha liberado con
licencia de fuentes abiertas (OpenSolaris).
AIX de IBM. El UNIX "propietario" de IBM ha cumplido 20 años de vida en el 2006 y continúa en
pleno desarrollo, con una perceptible herencia del U JR6M UN en campos como la virtualización o la
RAS de los servicios, heredada de sus "hermanos mayores".
HP-UX de Hewlett-Packard. Este sistema operativo también nació ligado a las computadoras
departamentales de este fabricante. También es un sistema operativo estable que continua en
desarrollo.
Mac OS X. Curiosamente sus propios usuarios suelen desconocer que se trata de un UNIX
completo, aprobado por The Open Group. Su diferencia marcada es que posee una interfaz gráfica
propietaria llamada Aqua, y es principalmente desarrollada en Objective-C en lugar de C o C++.
Existen sistemas operativos basados en el núcleo Linux, y el conjunto de aplicaciones GNU (también
denominado GNU/Linux), entre las más utilizadas encontramos:
Red Hat Enterprise Linux. Cuyo fabricante Red Hat es conocido por su amplia gama de soluciones
y aportes al desarrollo de software libre. Apoya el proyecto Fedora del cual se beneficia y de ella se
derivan distribuciones compatibles como Oracle Enterprise Linux y CentOS, también distribuciones
como Mandriva Linux, se basó en una de sus primeras versiones.
SUSE Linux de Novell. Originalmente liberado por la compañía alemana SuSE. Es popular por sus
herramientas de administración centralizada. De manera análoga a Fedora con RedHat, Apoya el
proyecto openSUSE.
Debian GNU/Linux. Con una de las comunidades más grandes y antiguas del movimiento de
software libre, es base para distribuciones como Xandros, Mepis, Linspire y Ubuntu.
FreeBSD. Quizá el sistema operativo más popular de la familia, de propósito múltiple. Con una
implementación SMP muy elaborada, es el sistema operativo utilizado por los servidores de Yahoo.
Y base de muchos sistemas operativos entre ellos Mac OS X de Apple.
OpenBSD. Ampliamente reconocida por su seguridad proactiva y auditoría permanente del código
fuente. Es utilizada en ambientes donde la seguridad prima sobre todo, es usual encontrarlo
instalado en servidores que actúan como Firewall, VPN o Proxy.
Las siguientes implementaciones de UNIX tienen importancia desde el punto de vista histórico, no
obstante, actualmente están en desuso:
UnixWare y SCO OpenServer anteriormente de Santa Cruz Operation y ahora de SCO Group.
UX/4800 de NEC.
El sistema operativo SunOS 5.x (basado en el sistema operativo System V Release 4 [SVR4]
UNIX).
El sistema operativo UNIX está basado en ficheros. Esta perspectiva de ficheros permite al software
UNIX correr en una gran variedad de plataformas, desde supercomputadoras a ordenadores
individuales.
Kernel.
Shell.
Estructura de ficheros.
Para gestionar los servicios, el sistema operativo se sirve de procesos conocidos como demonios.
4.1.1 KERNEL
h rdw re
kernel
Ilustración 4 Kernel
Controla las funciones (transmisión de información) entre los programas del sistema (utilidades) y el
hardware del sistema.
o Área de CD E - Es una parte del disco reservada para uso del kernel cuando se está
procesando.
4.1.2 SHELLS
h rdw re
kernel
shell
Ilustración 5 kernel y shell
Una CONSS es una interfaz entre el usuario y el núcleo. Actúa como un intérprete o traductor de comandos.
La CONSS acepta los comandos que se le ordenan, interpreta lo que se escribe en el teclado y envía el
ejecutable al núcleo.
Shells OS
Bourne CONSS ($) - La CONSS por defecto para el entorno Solaris. La CONSS Bourne fue desarrollada para
el entorno AT&T UNIX.
Korn CONSS ($) - Una ampliación de la Bourne CONSS. A las características de ésta última se suman
otras como alias, history, y edición de la línea de comandos.
El directorio principal del que parte la jerarquía se denomina directorio raíz (/).
El directorio raíz es fundamental para el funcionamiento del sistema operativo y contiene ficheros críticos
del sistema (tales como el kernel, llamado /kernel/genunix).
El directorio /usr contiene comandos ejecutables, utilidades de administración del sistema y rutinas
de biblioteca.
El directorio /etc contiene ficheros de administración del sistema tales como los ficheros passwd o
hosts.
4.1.5 DEMONIOS
Los demonios son también importantes para la funcionalidad del sistema operativo. Se trata de
programas que corren en background para gestionar las funciones del sistema, por ejemplo la impresión.
4.2.1 TERMINOLOGÍA
A continuación se definen términos comunes empleados por los administradores del sistema:
Nombre de eACÓ - Cada sistema en red debe tener un nombre único, el nombre de OACÓ.
Cliente - Se trata de un OACÓ o un proceso que usa servicios de uno o más servidores en una red.
Servidor - Un OACÓ o un proceso que proporciona recursos a uno o mas clientes en una red.
Red - Una red es un grupo de computadores que, en un entorno Solaris, están conectadas a través
de Ethernet.
Dirección IP - Es el número usado por el software de red para identificar las máquinas conectadas a
la red.
Multiusuario - Permite a más de un usuario acceder a los mismos recursos del sistema.
Ejemplos de servidores
Un servidor de archivos es una máquina que comparte sus archivos y lo que tiene almacenado en
disco con otras máquinas de la red.
Un servidor NIS+ (o NIS) proporciona la base de datos NIS+ (network information service plus) (NIS)
a sus clientes.
Un servidor de impresión hace que su impresora local esté disponible para otras máquinas de la red.
hostp1 hostpY
eroceso eroceso
servódor clóente
eroceso
clóente
La red conecta máquinas físicamente para permitir la comunicación entre sistemas. El sistema de
ficheros de red (NFS) distribuido permite compartir los ficheros a través de la red. Se pueden hacer
disponibles en toda la red los directorios raíz, de forma que los usuarios puedan sentarse frente a
cualquier estación de trabajo y acceder a sus propios ficheros.
Las estaciones de trabajo con espacio en disco mínimo lo pueden usar para sus particiones de disco y
CD E y obtener de otros sistemas el resto de datos y archivos ejecutables.
MMU
Bancos de Memoria stdout
/dev/mem Unidad
stderr
/dev/kmem Manejadora
/dev/pmem de Memoria
/dev/console
stdin Línea
Comunica.
C.P.U. Unidad Central de Proceso
DM A
Acceso directo
/proc Procesador /dev/
a memoria
ttya
ESPDM A módem
Nuestra primera misión, suponiendo que tenemos instalado perfectamente el sistema operativo, será
encender la máquina, y es aquí donde vamos a perder un poco de tiempo en explicar los pasos
generales que se producen hasta que el usuario puede acceder a identificarse al sistema, como veremos
posteriormente.
Una vez que la máquina tiene alimentación, el primer componente que actúa es la BIOS / EPROM /
dispositivos-similares, que no son mas que pequeños sistemas que almacenan un programa, que
cargado en el procesador para ejecutarse, puede realizar las primeras tareas de inicio del sistema (test,
configuración, etc.) y sobre todo, al final es capaz de leer de un cierto sitio de algún dispositivo externo,
normalmente un disco, un programa mas complejo, denominado genéricamente boot-loader, que
cargado en el procesador es capaz de iniciar las tareas mas complejas de carga del sistema operativo.
Este proceso es capaz sobre todo de cargar el núcleo (kernel) del sistema operativo, que reside
también en un dispositivo externo y que va a gobernar de forma básica todo el sistema. Se encargará,
entre otras tareas, de gestionar la memoria, los dispositivos y los procesos, controlar las funciones de
transmisión de información entre los programas del sistema y el hardware del mismo, y controlar el área
de “swap” (utilización de una zona de disco como memoria del sistema, para ampliar la capacidad
disponible) y el sistema de archivos.
El proceso del núcleo continuará activando una serie de procesos en la tabla del sistema, del que el
principal es uno denominado “init”, que será el padre de todos los procesos posteriores del sistema. El
proceso “init” tiene un identificador de valor “0”, los demás procesos del sistema tendrán números
superiores al “0”. Entre los procesos que serán controlados por el proceso “init”, están los procesos de
shell que permitirán a los usuarios controlar de forma efectiva el sistema y comunicarse con él. No existe
ningún secreto, solo son procesos que activan partes del sistema y finalizan lanzado otro proceso mas
complejo que es capaz de realizar mas tareas del sistema, hasta que al final todo es controlado por un
proceso especializado, denominado “kernel” del sistema, que se basa en delegar tareas a procesos hijos
que a su vez podrán, en cascada, activar nuevos procesos en árboles mas complejos de trabajo,
entrando ya en conceptos que son parte de un estudio mas avanzado, al que llegaremos mas adelante.
Cuando se pretende acceder al sistema operativo UNIX, lo primero que debemos hacer es presentarnos
al mismo. Esto se consigue con un identificador que permita al sistema comprobar si se poseen los
derechos propios de acceso, identificador que es asignado por el administrador del sistema.
Muchos de los caracteres que se pueden digitar son directamente visualizables en pantalla, pero existen
caracteres especiales que poseen otra interpretación y significado para el sistema. Uno de los más
importantes es el carácter generado por la tecla de retorno de carro “RETURN”. Este carácter indica al
sistema el fin de línea de entrada, moviendo el cursor al principio de la siguiente línea. El carácter
RETURN debe ser enviado al sistema antes de que este interprete la secuencia de caracteres enviada
previamente. Como podemos observar, es uno de los caracteres de control (caracteres invisibles) que
producen una serie de efectos especiales en nuestro terminal. Este carácter RETURN está
implementado directamente sobre el teclado de los terminales. Otros caracteres de control deben ser
generados presionando una tecla especial denominada CTRL, CTL o CNTL y otro carácter, que
normalmente suele ser una letra. El carácter RETURN es equivalente a presionar la tecla CTRL seguida
de "m". Existen otra serie de caracteres de control, que definimos a continuación:
<CTRL> d - Indica al proceso que se ha finalizado la entrada de caracteres. No hay más caracteres
en la entrada.
<CTRL> h - Efecto de B XLCE XN (espacio atrás). Se utiliza para la corrección de errores de tecleo.
<CTRL> j - Tabulador. Avanza el cursor de la pantalla hasta el próximo tabulador definido (Ó B,CÓAE).
<DELETE> - < RUBOUT> - <CTRL> c - En muchos sistemas UNIX este carácter produce la
finalización de un proceso sin esperar a su término, salvo que el proceso tenga capturada y
controlada esta señal.
<BREAK> - Esta tecla, dependiendo de como esté definido el terminal, produce efectos similares a
la DELETE y RUBOUT, con corte físico de la conexión en algunos casos.
Tengamos en cuenta un aspecto importante y que a veces nos resulta extraño: todo lo que sigamos
tecleando en el terminal pasará a ejecutarse, es decir, mientras se está ejecutando un comando, en el
terminal pueden seguir introduciéndose comandos, que serán ejecutados en el orden introducido. Esto
puede producir la mezcla de la salida de un comando con nuestra entrada en el terminal, lo que no es
ningún inconveniente para el sistema, solo para nuestra visión. Todo lo tecleado es almacenado para su
ejecución, no debiendo esperar a la finalización de un comando para la introducción de otro. Veamos un
posible ejemplo:
$ ls
a.out fich1 fich2 fich3 ground hip.hop
halt wc prog1.c fich3 prog2.c resuelve sistema
$ 5 13 95 fich3
$
Hemos digitado un comando que veremos en otro capítulo y que lista el contenido del directorio actual.
Mientras se está produciendo la salida de la lista de ficheros se ha tecleado: wc fich3, que como vemos
se ha mezclado con la salida del comando ls, incluso las dos palabras del comando no han salido
seguidas, sino que se ha mezclado con uno de los nombres de fichero listados por el comando previo ls:
wc prog1.c fich3. Recomendamos que para usuarios no expertos se espere a la finalización de un
comando para la introducción del siguiente. De todas formas, las velocidades de proceso alcanzadas por
los ordenadores actuales minimizan este efecto hasta límites casi imperceptibles.
En las próximas secciones desarrollaremos esta sesión e incluiremos algunos otros comandos de
utilización dentro del sistema.
“root”. Trabajando en este usuario se poseen los mismos privilegios del sistema y se pueden efectuar
tareas de mantenimiento del mismo. Su nombre común de identificación es súper usuario. Este súper
usuario se encargará de mantener la integridad del sistema de ficheros, restaurarlo en caso de caída del
mismo o error de operación, mantener los usuarios que se vayan a definir, y en general efectuar tareas
de mantenimiento del sistema e instalación de aplicaciones. Existen comandos que solamente puede
efectuar el súper usuario.
Trabajando dentro de cualquier usuario que no sea MAAÓ se pueden adquirir los privilegios de este
mediante el comando su.
Como vemos, la palabra clave del usuario MAAÓ debe ser conocida por muy pocas personas puesto que
nos garantizará la integridad del sistema ante posibles operadores inexpertos o malintencionados que
pudiesen entrar en el sistema con ese privilegio. Cuando se tiene el privilegio de súper usuario, el
sistema no efectúa control alguno sobre los procesos que se le ordenan ejecutar, con lo cual la
responsabilidad del mismo debe ser grande.
El sistema operativo posee una lista definida de usuarios (aparte de los de gestión y base del sistema)
definidos por un nombre, una palabra clave de acceso y una serie de atributos internos. Para la entrada
en el sistema es necesario el conocimiento del nombre y palabra de acceso al usuario.
Suponemos que el terminal utilizado tiene la posibilidad de trabajar con caracteres alfabéticos en
minúsculas y mayúsculas. Debemos comprobar que todos los conmutadores del terminal están
correctamente instalados para trabajar bajo sistema operativo UNIX (consultando el manual del terminal
se puede obtener la configuración correcta). Entre estos, los más importantes son la velocidad de
transmisión (baudios), modo "full duplex", paridad y mayúsculas / minúsculas. Una vez conectado el
terminal, nos aparecerá en el mismo, el mensaje:
En respuesta a este mensaje, el operador debe digitar el nombre del usuario con el que se va a producir
la sesión de trabajo, y presionar la tecla RETURN. Si el usuario (que habrá definido el administrador del
sistema) posee una palabra o clave de acceso, el sistema la solicitara y el operador deberá digitarla
correctamente, no produciendo el sistema eco en pantalla para preservar el secreto de dicha palabra.
La digitación en el teclado del nombre de usuario debe ser efectuada en minúsculas, puesto que si se
hace en mayúsculas, posteriormente el sistema utilizará ese mismo tipo de letra en todas las
comunicaciones con el usuario, entendiendo que el terminal carece de la posibilidad de trabajar en
mayúsculas y minúsculas. Este tipo de funcionamiento también es configurable en las nuevas versiones
de UNIX.
Existe un comando para el cambio de la palabra de paso o acceso a un usuario. Para ello se debe entrar
(SATJR) en el usuario deseado y digitar el comando passwd:
$ passwd
Old password:
New password:
Retype new password:
Una vez digitado, el sistema solicitará la actual palabra de paso del usuario, que deberá ser digitada por
el operador y no producirá eco en pantalla. En caso de error en la misma, el sistema abortará el
comando. A continuación pedirá la nueva palabra de paso que tampoco tendrá eco en pantalla. Una vez
digitada, volverá a solicitarla, de tal forma que debemos digitar la misma palabra de paso que
anteriormente. Esto se debe a motivos de seguridad del sistema. Si coinciden, la nueva palabra de paso
será tomada como la actual para el acceso al sistema. Recuerde esta palabra de acceso puesto que si
se le olvida, deberá solicitar su cambio al administrador del sistema o persona encargada de su
mantenimiento.
Una vez que se ha recibido el EMAUEÓ del sistema, se puede comenzar a digitar comandos, que no son
más que requerimientos al sistema de que efectúe un determinado proceso. Como podemos ver en la
sesión de trabajo representada, el operador ha digitado el comando ‘date’ y la tecla RETN, que produce
una salida a pantalla de la fecha y hora del sistema
El próximo comando digitado es “who”, que es una solicitud al sistema para que muestre la lista de
usuarios que actualmente están activos en el mismo. La primera columna de la salida corresponde al
nombre de usuario que esta activo. La segunda es el nombre que el sistema asigna a la conexión
utilizada por el usuario (tty es un sinónimo de "teletype"). El resto de la salida son los datos de fecha y
hora de conexión del usuario. Podríamos haber digitado otra serie de comandos:
Si el operador digita el carácter de borrado de línea al final del comando, este será ignorado
completamente y se comenzará a interpretar lo digitado a continuación del carácter "kill”.
En caso de que el operador digite el borrado de carácter a continuación de cualquier otro carácter, este
será ignorado a la hora de interpretar el comando, con lo cual se pueden hacer las correcciones en el
comando antes de su envío mediante la tecla RETURN:
$ dd#atte##e
Sat May 17 16:45:28 EDT 1986
$
Los caracteres de borrado de línea y carácter son muy dependientes del sistema y terminal que se estén
utilizando. En muchos sistemas el borrado de carácter se ha asimilado a la tecla de "B XLCE XN", que
trabaja mucho mejor en los terminales con pantalla de vídeo.
En caso de que deseemos incluir estos caracteres especiales de borrado dentro de un texto por ejemplo,
deberán ir precedidos por el carácter "B XLCS CO" \ (carácter de escape), de tal forma que deberemos
digitar \@ o \#. Este carácter de escape \ indica al sistema que el carácter que viene a continuación debe
ser tratado de una forma especial.
Una vez que el operador ha presionado la tecla RETURN, los caracteres digitados son enviados al
proceso que lee el terminal, de tal forma que son interpretados conforme a las reglas que definimos
anteriormente.
La digitación de comandos puede ser efectuada a la vez que el proceso en ejecución produce salida a la
pantalla. Debido a esto se puede producir la mezcla en la misma de caracteres correspondientes a
entrada del operador y salida del proceso. Esta situación no tiene ningún problema, salvo el desorden de
salida de caracteres a pantalla. Todo esto es debido a la existencia de un "buffer" de almacenamiento de
los caracteres de comandos que el operador está digitando y la posibilidad de multiprocesamiento que
implementa el sistema operativo UNIX.
Existe un comando de nombre “stty”, que nos permite, por un lado visualizar los criterios de
comunicación con el terminal, y por otro la modificación de estos criterios.
$ stty
speed 9600 baud
interrupt = 'DEL' quit=’^\’ erase=’^H’ kill=’^U’
even odd -n echo -tabs ff1
$ stty ek
speed 9600 baud
interrupt = 'DEL' quit=’^\’ erase=’#’ kill=’@’
even odd -n echo -tabs ff1
Al ejecutar el comando stty nos muestra la velocidad de transmisión con el terminal, los caracteres
definidos por el sistema para la detención de un proceso, borrado de carácter y línea, salida del sistema,
paridad, estado del eco y tabuladores definidos.
La ejecución del comando stty ek (ek = erase kill) restaura los caracteres de borrado de carácter y línea
al estado normal del sistema. Si volvemos a efectuar stty nos muestra el nuevo estado del terminal.
$ stty -a
speed 9600 baud;
La primera ejecución del comando nos indica que los caracteres siguientes asumen un significado
especial:
intr -> carácter ^{ (tecla DELETE de teclado de PC) para abortar procesos o comandos.
erase -> carácter # (sostenido) para borrar un carácter.
kill -> carácter @ (arroba) para borrar la línea entera.
Los siguientes comandos stty cambian las teclas asociadas a los eventos anteriores a los siguientes
valores:
El siguiente comando stty –a muestra el resultado de las acciones anteriores, donde podemos
comprobar que los cambios han sido realizados.
Si queremos lograr la parada momentánea de un proceso, podemos teclear CTRL-S (recordar que se
debe presionar a la vez la tecla de CTRL y el carácter S). Con esto podemos conseguir la parada de la
visualización en pantalla de unos datos que por la marcha del proceso van a desaparecer de la misma.
Para continuar el proceso normalmente debemos digitar CTRL-Q.
Los parámetros del comando stty que controlan estos eventos son:
Pueden ser ajustados igual que el resto de parámetros del comando stty, y de forma similar a los
caracteres de borrado.
Los parámetros del comando stty que controlan estos eventos son:
Veamos un ejemplo de suspensión del editor "vi", trabajo en la shel, y retorno al editor:
$ vi prog1.c
hello, world Se teclea CTRL-z (tecla de suspensión)
~
~
"prog1.c" [New file]
Stopped (user)
<conta> 48 => who
conta pts006 Feb 10 16:38
<conta> 49 => date
Thu Feb 10 17:51:52 EST 2011
<conta> 50 => fg Se usa el comando fg para reanudar el proceso
hello, world
~
~
Como podemos observar en las salidas del comando stty –a, el carácter dsusp no está definido, por lo
que podemos usar el comando fg (6AMNTMAHRI) para reanudar el proceso.
En caso de que el usuario en el que hemos entrado tenga correo pendiente, el sistema lo avisará
mediante un mensaje, siendo optativo del operador la visualización o no del mismo. Se obtendrá el
correo ejecutando el comando mail.
Después de cada mensaje de correo mostrado por el comando, este espera la acción que se va a
desarrollar con el mismo. Hay dos respuestas básicas, una el borrado del correo visualizado, mediante la
digitación de la secuencia d <RETN>, y otra la visualización del siguiente mensaje pendiente, que se
obtiene digitando RETURN. Otras posibilidades del comando mail son:
En caso de que deseemos enviar correo a otros usuarios, deberemos digitar el comando seguido del
nombre de usuario al que se desea enviar. El cursor se nos posicionará al principio de la siguiente línea
y estará listo para la digitación del mensaje. El final de una línea se marca con RETN y el mensaje
continúa en la siguiente línea. Para finalizar el texto del mensaje, digitaremos RETURN y CTRL-d,
retornando a la CONSS.
El comando mail también permite el envío de correo a múltiplex usuarios, a usuarios de otras máquinas
o el envío de cartas ya preparadas. Para mayor información del comando se debe acudir a los manuales
originales de UNIX.
$ write pedro
Este comando establecerá una doble vía de comunicación entre ambos usuarios, de tal forma que todas
las líneas que se digiten en los terminales de los mismos aparecerán en el terminal del otro usuario.
Como el comando write no se establecen ningunas reglas de comunicación, los usuarios se deben regir
por algún tipo de protocolo. En el caso que vamos a mostrar a continuación, la secuencia (f) indica fin de
texto de envío (el otro usuario puede enviar mensajes) y la (ff) indica que se está listo para el fin de la
comunicación:
Terminal de pedro Terminal de pruebas
$ write pruebas $ Message from pedro tty06
$ write pedro
Message from pruebas tty02
Recuerdas la cita de hoy? (f) Recuerdas la cita de hoy (f)
A las diez@
A las once. Correcto? (f)
A las once. Correcto ? (f)
Correcto (ff) Correcto (ff)
Ctrl-d
EOF
Ctrl-d
$ $ EOF
Mediante la tecla DELETE se puede salir del comando write. Notar que los errores de digitación
corregidos por el usuario "pruebas" no aparecen en el terminal de "pedro", sino que solo se muestra la
línea corregida. En caso de que se intente la conversación con un usuario que no está conectado al
sistema (SATJR) o que estando conectado no desea entablar la conversación, el sistema avisará de ello.
Muchos de los sistemas UNIX poseen un comando especial de nombre news, para visualizar las
posibles noticias relevantes del sistema, su desarrollo y posibles mejoras e incidencias.
descripción de comandos UNIX. La Sección 2 trata de los "system calls" del sistema y la Sección 6
incluye los juegos implementados en UNIX. Las demás secciones tratan funciones que pueden ser
tratadas por programadores en lenguaje C, formatos de ficheros y mantenimiento del sistema, tarea del
administrador del mismo. A menudo el Manual original de UNIX está almacenado en el propio sistema y
puede ser leído bajo el comando man seguido por el nombre del comando cuya sintaxis y descripción se
desea:
$ man who
................... Visualización de la explicación
................... detallada del comando who, sirviendo
................... de ayuda al usuario.
...................
$ man man
................... Lo mismo del propio comando man
$
El sistema, asimismo posee un comando que facilita el aprendizaje del sistema operativo, cuyo nombre
es learn. Este comando incluye el estudio del sistema de ficheros, comandos básicos, editor ed del
sistema, preparación de cartas y documentos e incluso lenguaje C (actualmente está en desuso y
muchos sistemas ni siquiera lo implementan).
Existe otro comando muy interesante, el comando whatis, que nos muestra la descripción corta de un
comando del sistema operativo, en contraposición con la ayuda completa mostrada por el comando man.
Veamos un ejemplo:
$ whatis ls
ls (1bsd) - (BSD) list the contents of a directory
ls, lc, l, lf, lr, lx (1) - list contents of directory
$ whatis stty
stty (1) - set the options for a terminal
stty (1bsd) - (BSD) set the options for a terminal
$ whatis livecom
livecom: not found
$
Los dos primeros comandos nos muestran la descripción corta de los comandos ls y stty, y el tercer
comando muestra un mensaje de error debido a la no existencia del comando SJÍNUXAU.
El comando man dispone de una opción especial que nos permite localizar los comandos que contienen
en su descripción principal una cadena determinada. Veamos un ejemplo:
La salida del comando nos indica que el comando que contiene la descripción buscada es el comando
“ctrace” en el primer caso, y los comandos ed, red, edit y ex en el segundo caso.
Es muy importante fijarse en la salida del comando man –k, en la columna donde muestra un
identificador entre paréntesis. El manual de UNIX está divido en bloques, agrupando en cada uno de
ellos los comandos referentes al mismo. En la segunda columna aparece un identificador entre
paréntesis. Este identificador puede ser interesante para referenciar comandos con el mismo nombre,
pero sobre dos implementaciones diferentes, por ejemplo System V y BSD. Veamos un ejemplo:
$ man –k name
.............
.............
remque (3C) - remove element from a queue
rename (1) - change the name of a file
rename (1tcl) - rename or delete a command
rename (2) - change the name of a file
$
Vemos que el comando rename aparece tres veces, pero sobre bloques diferentes del manual, en el 1,
en el 1tcl y en el 2. Si queremos obtener el manual del comando rename en cada uno de los bloques
podemos utilizar una nueva sintaxis del comando man:
Las descripciones de los comandos que proporciona el comando man son muy extensas y a veces
complejas, pero representan la esencia de los comandos y procesos disponibles en el sistema. Muchas
veces es el único cauce de información completa sobre los comandos, fuera de cualquier resumen o
explicación académica.
2. Enviar un correo a un usuario llamado "nadie". Después de un tiempo consultar el correo y el fichero
dead.letter.
4. Entablar una conversación con las utilidades write y talk. Probar a proteger el terminal ante esos
mensajes.
Los constructores han desarrollado sus propias tecnologías de redes. Por esto, ISO (International
Standars Organization) ha introducido el concepto de sistema abierto, a través de normas de
interconexión que definan la interacción de los equipos. Eso ha conllevado la definición de una
arquitectura normalizada para las redes que se conoce con el nombre de ISO/OSI (Open Systems
Interconnection). En este capitulo analizaremos los conceptos y mecanismos generales que intervienen
en las redes.
M s q u ón pA M sq u ón pB
e ro t o c o lo po óv e l pó
o óv e lpó o óv e l pó
o ó v e lp1 e ro t o c o lo po óv e l p1 o ó v elp1
G o p o r t e pF ís óc o
Efectuarse en los dos sentidos pero alternativamente (enlace semiduplex o alternado 'half-duplex')
Elección de modo síncrono (señal de reloj del emisor o receptor), o asíncrono (señal de reloj no
suministrada --> existencia de una transmisión START/STOP entre bytes.
RS232C (CCITT V24) y su sucesora RS449 para realizar la conexión entre un ETTD y un ERCD
utilizando la red telefónica.
X24 para realizar una conexión utilizando una red publica de datos (por ejemplo TRANSPAC).
Una dirección de este tipo se denomina física. Esta dirección memorizada sobre la tarjeta del interfaz lo
identifica de forma única.
Dos bytes para la longitud de los datos (expresada en bytes) que constituyen el mensaje (siguiente
campo). Este campo se puede interpretar en ciertas circunstancias como un tipo de paquete.
Una zona de relleno de 0 a 64 bytes que asegura que el mensaje completo contiene al menos 64
bytes.
Topología en bus
Red difusora
Protocolo CSMA/CD
La VPN permite gestionar conexiones seguras a través de una red privada virtual que capacita a los
usuarios a conectarse de forma remota al entorno de PCs Virtuales.
En los diagramas de arquitecturas lógicas de red se muestran dos tipos: uno con un solo interfaz de
red, que gestiona una sola red; y otro con tres interfaces de red, que gestionan tres redes, una para
el ESX Server 3 y las conexiones desde Internet, otra para la red local interna y segura, así como
para ciertas máquinas virtuales, y la última para gestionar un servidor de autenticación externo a
todas las redes corporativas.
Se puede tener instalado un servidor de autenticación LDAP (Active Directory u OpenLDAP) para
realizar el control y acceso de Usuarios al entorno.
Ilustración 10 Diagrama de una arquitectura lógica de red (red única) en un entorno de PCs Virtuales
eth0
Servidor DHCP SWITCH Virtual PC Oracle
VirtualCenter
(física-virtual) 10.2.20.200 Fibra SFImpresora Debian Linux
(física-virtual) (física) (virtual) (física-virtual)
10.2.20.198 Genera direcciones 10.2.20.201 10.2.20.197 10.2.20.202
IP entre 10.2.20.21
PCs y 10.2.20.250
Virtuales
10.2.20.193
Ge stionados
LAN
FIREWALL
Con SF2007 (Interna)
10.2.20.(1-190) Interno
Ilustración 11 Diagrama de una arquitectura lógica de red (múltiples redes) en un entorno de PCs
Virtuales
Desde el punto de vista del usuario, el intérprete de comandos proporciona un medio sencillo de
comunicarse con el sistema, ofreciéndole dos posibilidades:
Entre las características más importantes del intérprete de comandos, llamado "CONSS" ("concha" o
"coraza" que aísla y protege al usuario del sistema) se pueden citar:
Modificación del entorno de ejecución ("NRÍJMARUNRÓ") del usuario (conjunto de variables y modos de
funcionamiento predefinidos).
$ date <RETURN>
Ejecutaría el comando "date", devolviéndonos como resultado la fecha y hora del sistema en un formato
como:
Indicando que se trata del jueves 15 de Mayo de 1986, a las 21 horas 15 minutos y 5 segundos, con una
diferencia de una hora (+1:00) con respecto al meridiano de Grenwhich (GMT).
Análogamente, el comando:
$ ls -l
$ cc prog1.c
Llamaría al compilador de lenguaje “C” para proceder a compilar el programa fuente "prog1.c",
devolviendo el EMAUEÓ "$" de la CONSS una vez finalizada la compilación del programa. En cambio:
$ cc prog1.c&
Produciría la compilación del programa en B XLTMAHRI (bajo tierra o en segundo plano) o en modo no
interactivo, de manera que se produciría la compilación del programa por medio de un nuevo proceso
creado en ese momento, devolviéndose el control al terminal inmediatamente, sin esperar a que finalice
la compilación.
El operador "&" indica a la CONSS que no debe esperar a la terminación del proceso llamado. Para permitir
el control del mismo por medio de comandos como "ps" ("EMAXNCC,CÓ ÓHC", muestra el estado de uno o
varios procesos) o "kill" (fuerza la terminación de un proceso), la CONSS devuelve su número de proceso o
"pid" (EMAXNCC,JINRÓJ6JNM).
$ ls -l > fichero
No produciría ninguna salida sobre la pantalla, enviando el resultado de la ejecución del comando ls -l
(listado de un directorio en formato extendido) al fichero denominado "fichero".
El carácter ">” indica un reencaminamiento de la salida estándar. Si el fichero utilizado para la salida no
existiese, éste sería creado por la CONSS, mientras que si por el contrario ya existiese, vería reemplazado
su contenido por la salida del comando, y si el fichero no fuese accesible o no se pudiese crear, se
obtendría un mensaje de error.
Análogamente, se puede reencaminar la entrada estándar por medio del carácter "<”, utilizado como:
$ wc < fichero
Ejecutando el comando "wc" (DAMI,XAHRÓNM, o contador de palabras), que cuenta el número de líneas,
palabras y caracteres presentes en su fichero de entrada estándar, en este caso "fichero", debido al
redireccionamiento de la entrada.
$ ls | sort –r
Produciría un listado del directorio clasificado por orden alfabético inverso. "ls" daría lugar a un listado
del directorio sobre la salida estándar, que se vería reencaminada por efecto del "EJEN" "|" hacia la
entrada del comando "sort", que mediante la opción "-r" produciría la clasificación por orden alfabético
inverso.
$ ls > auxiliar
$ sort -r auxiliar
Con la diferencia de que no es necesaria la utilización del fichero intermedio "auxiliar". Además, los dos
comandos conectados mediante un "EJEN" se ejecutarían simultáneamente, y no uno a continuación de
otro como sucedería en éste segundo caso.
Las "EJENC" no son bidireccionales (para ello se requeriría la utilización de dos "EJENC"), en el sentido de
que no permiten la lectura y escritura en ambos sentidos, sino sólo la escritura en un extremo y la lectura
en el otro, y realizan su sincronismo por medio de la detención de los comandos cuando estos no tienen
nada que leer o escribir. Así se detendría la ejecución del comando "sort" cuando no tuviese nada que
leer, y la de "ls" cuando no tuviese nada más que escribir.
En el sistema operativo UNIX se denominan "filtros" a los programas que actúan sobre la entrada
estándar, y la modifican de alguna manera antes de devolverla a la salida estándar. Un ejemplo típico es
el del comando "grep", que muestra a su salida aquellas líneas de la entrada que contengan una
determinada cadena. La ejecución de:
Provocaría que se listasen sobre el fichero de salida estándar, todas las líneas de un fichero denominado
"movimientos", que contuviesen en algún lugar la cadena "factura", actuando como un "filtro" de las
líneas de entrada.
Un "EJEN" puede constar de más de dos comandos, produciéndose el encaminamiento múltiple de sus
entradas y salidas consecutivamente. Por ejemplo:
Produciría como resultado un listado por pantalla con paginación (espera antes de pasar a una nueva
página), de todos los nombres de fichero que contengan en algún lugar la palabra "carta".
$ ls -l *.c
produce un listado de todos los nombres de ficheros que posean la terminación ".c" (habitualmente
programas fuente en lenguaje C). El carácter "*" consiste en un formato verificado por cualquier cadena
de caracteres, incluso el carácter nulo.
Expresado en forma de tabla:
Por ejemplo:
$ ls bloque?
Produciría un listado del directorio con todos los nombres de ficheros que comenzasen por la cadena
"bloque”, y contuviesen a continuación cualquier carácter (bloqueo, bloque9, bloques, .....).
$ ls [a-m]*
Sería verificado para todos los nombres de ficheros que comenzasen por una letra comprendida entre la
"a" y la "m", inclusive.
El carácter "*" no incluye aquellos nombres de ficheros que comiencen por un punto “.”. Si tuviésemos un
fichero con el nombre “.profile”, no sería mostrado mediante el comando:
$ ls *
$ echo \?
$ echo \\
Con el fin de permitir que las cadenas de comandos puedan alcanzar la longitud suficiente con todas sus
opciones, se ignora el carácter de salto de línea "\n" <RETURN> si previamente se digita el carácter “\”.
Para proteger un cadena de caracteres de la CONSS, y evitar que pueda ser interpretada como si
contuviese metacaracteres, se puede rodear la cadena por comillas simples "‘”, como en el caso de:
$ cat ‘bloque?‘
Produciría un listado por pantalla (comando cat) del fichero “bloque?”, en lugar de referirse a los
nombres de ficheros “bloque0”, “bloques”, etc.
Si introduce este comando, aparecerá un número en la pantalla del terminal utilizado. Éste es el número
identificador del proceso (PID) para el proceso que se sitúa en segundo plano. El PID es la forma que
tiene el sistema operativo de identificar dicho proceso.
Normalmente, cuando se ejecuta un comando, la CONSS suspende la operación hasta que el comando está
completado. Si añade el símbolo & al final de una secuencia de comando, esta secuencia se ejecutará
en paralelo con la CONSS. Al colocar el símbolo & detrás de una secuencia de comando, la CONSS comienza
a ejecutar el comando siguiente tan pronto como se activa el comando de segundo plano. A menos que
utilice la redirección de E/S con el comando en segundo plano, tanto éste como la CONSS actual esperarán
recibir entradas de su terminal y producirán salidas dirigidas a éste. A menos que su propio comando en
segundo plano se ocupe de la E/S, la sintaxis correcta para el proceso en segundo plano es la siguiente:
Por ejemplo, para copiar un conjunto de archivos cuyos nombres terminan con los caracteres .ven a un
subdirectorio llamado old y, sin esperar a que este proceso finalice, imprimir una lista ordenada de los
datos en todos los archivos con nombres que empiecen por ventas, introduzca los dos comandos
siguientes:
Sitúe los trabajos en segundo plano cuando no desee esperar a que un programa termine antes de
poner otro en marcha, quizás por la larga duración del mismo. También puede colocar trabajos en
segundo plano cuando tenga una serie de tareas en las que al menos una pueda ejecutarse
También puede utilizar los terminales virtuales que incluyen la mayoría de los Unix del mercado para
ejecutar un comando y después entrar en el sistema con otro terminal.
Puesto que el proceso en segundo plano es un hijo de la CONSS, se elimina automáticamente cuando deja
de estar conectado al sistema. Todos los procesos hijos desaparecen cuando sus padres desaparecen.
El demonio crond es un comando ejecutado en segundo plano por Unix, o, más concretamente, por init,
el programa maestro. cron ejecuta servicios de programación a todos los procesos de Unix. Puede pedir
a cron que ejecute un programa en un momento determinado, de forma periódica, en un momento
especificado del día o cuando la carga de cron lo permita.
7.6.4 EL COMANDO at
El comando at utiliza una hora o fecha como parámetro y toma cualquier número de secuencias de
comando de sus entrada estándar. Cuando el comando at detecta una marca de final de archivo, crea un
archivo de secuencias CONSS para su ejecución a la hora anteriormente especificada.
El comando at es flexible por lo que se refiere a los tipos de fechas y horas que acepta. Por ejemplo, si
introduce el comando at now +1 day, los comandos siguientes, tomados de la entrada estándar, se
ejecutarán mañana a esta misma hora. Una forma de utilizar el comando at es dentro de un archivo de
secuencias CONSS.
Un archivo de secuencias CONSS sólo es un archivo que contiene los comandos necesarios para ejecutar
un conjunto de comandos. El nombre del archivo se convierte entonces en su propia contribución al
lenguaje de comandos de Unix. Una forma de utilizar el comando at es:
at now +1 day
comando_1
comando_2
Cuando se colocan dentro de un archivo de secuencias CONSS, estas líneas le permiten ejecutar
adecuadamente uno o más comandos al día siguiente. Para ejecutar comandos distintos, sencillamente
añada más comandos tras la línea de comando at. Puede ejecutar cualquier número de comandos
desde este archivo de secuencias.
Después podrá llamar al sistema para que realice una copia de seguridad del directorio
dHCMdOAUNd S6MNIA, utilizando el comando:
batch copia
Deberá crear un archivo en el formato crontab para ejecutar comandos de forma periódica. El archivo
XMARÓ B consta de seis campos separados por espacios o tabulaciones. Los primeros cinco campos son
números enteros que especifican los minutos (0-59), horas (0-23), día del mes (1-31), mes del año (1-12)
y día de la semana (0-6, donde 0 representa el domingo). El sexto campo es una secuencia de
comandos. Cada campo numérico puede contener un intervalo de números, como 1-3 para indicar de
lunes a miércoles, o conjuntos discontinuos de números como, por ejemplo, 0, 20, 40, para indicar que
se deberá ejecutar una instrucción cada 20 minutos. Un campo puede también contener un asterisco
para indicar todos los valores legales.
El siguiente ejemplo ejecuta el comando X SNRI M cada 30 minutos, empezando a la media noche del
lunes y terminando a las 23.30 horas del miércoles:
Si nombra este archivo 6JXONMAXMAR, podrá instalarlo en el sistema cron utilizando el comando:
crontab ficherocron.
El demonio XMARI tiene uan cadencia temporal de un minuto, es decir, que el periodo más corto de
tiempo con el que puede trabajar es un minuto. El administrador del sistema puede limitar el número de
comandos que se pueden ejecutar en cualquier momento. Especificar a XMAR que ejecute un archivo Ój,
B ÓXOj,A,XMARÓ B no quiere decir que éste vaya a ejecutarse precisamente en el momento que ha
especificado.
Si intenta utilizar un nombre de archivo inexistente, Unix le contestará con algo parecido a:
Si intenta ejecutar un comando con RAOHE y no ha redirigido el error estándar, Unix automáticamente
coloca los mensajes de error en un archivo llamado nohup.out, en el directorio desde el que se ejecutó
el comando.
Puesto que los comandos ejecutados por XMARI son menos urgentes, los errores que pudieran ocurrir, y
de hecho, cualquier salida colocada en la salida estándar y no redirigida, se le enviarán por correo
electrónico mail.
En las dos CONSSC (XCO y LCO), el comando history muestra la lista de comandos anteriores guardados por
la CONSS. Los comandos están numerados. Por ejemplo, puede escribir !10 para ejecutar el comando de
orden 10 en el historial.
alias ayuda=man
Ahora podrá introducir ayuda cp o man cp para mostrar las páginas U R de Unix referidas al comando
XE.
Los alias pueden utilizarse también con comandos que tienen opciones o argumentos. Por ejemplo, si
desea relacionar los nombres de todos los archivos en el directorio actual de forma descendente y según
la fecha en que fueron modificados por última vez (de forma que los archivos más recientes se
encuentren en la parte inferior de la lista), puede utilizar el comando siguiente:
ls –art
El comando ls se usa para listar archivos; la opción –a especifica todos los archivos, la opción –r los
organiza en orden inverso descendente y la opción –t los ordena de acuerdo con la fecha en que fueron
modificados por última vez. Todo ello engloba información que difícilmente recordará. Podrá asignar el
alias horadir a este comando complejo, utilizando el comando siguiente:
Las comillas ("") son necesarias porque la CONSS espera que el alias de OAM IJM termine con un espacio o
<Intro>, Si escribe OAM IJM, obtendrá el listado de directorio que desea.
La configuración de un alias desde la línea de comandos mantiene este alias vigente sólo durante la
sesión que se esté ejecutando. Para que el alias se active cada vez que se conecte al sistema, incluya la
definición del mismo en el archivo .profile, si utiliza la Bourne shell; si se encuentra en la C shell,
inclúyala en el archivo .login.
Con ello ahorrará tiempo y evitará el riesgo de cometer errores ortográficos al introducir los comandos. Si
dos archivos comparten un prefijo común, Unix amplía el comando hasta el último carácter en común,
detiene la expansión del nombre de archivo y emite una señal acústica. Deberá proporcionar el nombre
de archivo exclusivo.
Puede escribir comandos en el terminal o bien pueden proceder de un archivo. Un archivo de secuencias
de CONSS es una serie de uno o más comandos de CONSS en un archivo. Para ejecutar los comandos deberá
escribir el nombre del archivo. Esto tiene algunas ventajas:
Determina una sola vez los pasos necesarios para alcanzar un objetivo.
Mediante la utilización de variables y palabras clave se escriben programas que la CONSS pueda
interpretar. Esta característica es muy útil porque permite crear archivos de secuencias del CONSS
generales que el mismo usuario, u otros usuarios, pueden posteriormente utilizar en una amplia variedad
de situaciones.
Suponga que después de conectarse al sistema, quiere comprobar periódicamente quién está conectado
a él, ejecutar un programa llamado X SNRI MJA que muestra sus citas para ese mismo día y el siguiente e
imprimir la fecha y hora actual. Para hacer todas estas cosas, escriba los comandos siguientes:
who
calendario
date
Si coloca estos tres comandos en un archivo llamado KHJNRNCÓ y convierte este archivo en ejecutable,
tendrá un archivo de secuencias de CONSS ejecutable como cualquier otro comando. El archivo KHJNRNCÓ
debe ser un archivo de texto. Puede utilizar el editor de texto ÍJ para situar los comandos en el archivo
KHJNRNCÓ . Para hacer el archivo ejecutable, escriba el siguiente comando:
chmod +x quienesta
El comando chmod modifica o configura los permisos para un archivo. La opción +x hace el archivo
ejecutable, es decir, que el archivo funcione como un comando estándar de Unix. Ubicar comandos en el
archivo y hacer que el archivo sea ejecutable son operaciones que se realizan una sola vez. A partir de
ese momento podrá escribir KHJNRNCÓ y pulsar <Intro> para ejecutar su archivo de secuencias de shell.
Puede utilizar el archivo de secuencias de shell igual que cualquier otro comando. Por ejemplo, para
quienesta | lp
Para colocar los resultados del comando KHJNRNCÓ en un archivo llamado JR6AÁKHJNR como referencia
futura, escriba:
En resumidas cuentas, si desea crear un archivo de secuencias de CONSS para utilizarlo cuando desee,
siga los pasos que se detallan a continuación:
Utilice un editor de texto, como ÍJ, para colocar los comandos de shell en un archivo ASCII o de
texto. En el ejemplo anterior se pusieron los comandos en un archivo llamado KHJNRNCÓ .
Créelo de forma que tenga permiso de ejecución en el archivo. Para ello utilice XOUAI,QY,
RAUBMNs MXOJÍA (por ejemplo, XOUAI,QY,KHJNRNCÓ ).
Después de realizar este proceso unas cuantas veces, comprobará lo fácil que es crear secuencias útiles
y cómo hacer uso de las capacidades de programación de la CONSS para determinar los pasos necesarios
en su ejecución.
Puede probar un archivo de secuencias de la CONSS y comprobar todos los pasos según se desarrollan,
escribiendo:
sh -x nombre_script
En esta sintaxis, RAUBMNsCXMJEÓ,es el nombre del archivo que contiene las secuencias que está
examinando. El comando sh –x muestra todos los pasos que recorre el comando y es muy útil para
depurarlo.
3. Usando redireccionamiento de entrada, enviar por correo electrónico el fichero "salidate" al propio
usuario.
4. Escribir el comando cp sin argumentos. Redireccionar la salida a un fichero con nombre "salida.cp".
5. Ejecutar un comando que tenga como salida el número de usuarios activos en esos momentos, y
otro con el número de usuarios totales del sistema.
En este capitulo se cubrirán algunos detalles sobre la estructura, creación y organización de ficheros del
sistema, directorios, permisos de acceso. 9RAIAC y manejadores de dispositivos son conceptos que serán
explicados en otros capítulos del sistema operativo UNIX. Estos mantienen una estrecha relación con la
estructura de ficheros del sistema.
Se incluirá la descripción de numerosos comandos del sistema que efectuarán tareas de mantenimiento
y manipulación de ficheros o que en definitiva mantienen una fuerte ligazón con el sistema de ficheros
UNIX.
Profundicemos algo más en la comprensión del concepto fichero. Tenemos claro el concepto de bit, una
unidad de información que puede almacenar solo dos estados (0-1, TRUE-FALSE). Si agrupamos 8 bits
para obtener un byte, conseguimos una unidad de información que puede almacenar hasta 256 estados
distintos, mediante la utilización de los 8 bits. El comité ASCII ha definido una norma en la que se
representan los caracteres alfabéticos, numéricos, especiales y de control mediante alguno de esos 256
estados o posibilidades. La codificación ASCII multinacional tiene la siguiente estructura genérica,
identificando a cada carácter en notación decimal:
0 - 31 Caracteres de Control con significado especial, entre los que podemos destacar:
0 - Nulo. 8 – Backspace. 10 - Newline. 13 – Return. 27- Escape
32 – 126 Alfabéticos (A-Z, a-z) numéricos (0-9), y especiales (! “ # $ % & ´ ( ) * + , - . / [ \ ^ _ ` { | }
~)
127 Carácter de Control DELETE
128 al 255 Caracteres adicionales (letras acentuadas agudas y graves. Diéresis y circunflejos,
semigráficos, letras Ñ, símbolos y varios).
Secuencias de bits sin significado especial, salvo para los programas que lo traten.
Secuencias de bits conformados como caracteres ASCII, es decir, secuencias de 8 bits con
significado especial.
En el primero caso, solo los programas especializados en leer e interpretar la información del fichero
serán capaces de utilizarlo. En el segundo caso, existen multitud de programas capaces de leer e
interpretar esa información; el fichero entonces tomará un significado especial. Vamos a realizar una
clasificación en árbol de posibles ficheros por su contenido, definiendo tipos que nos ayudarán a clarificar
la idea de fichero:
Ficheros Binarios
Especiales del sistema (IMJÍNMC, procesos, manejadores de memoria, SATC del sistema, etc.),
usados por los ficheros del subtipo anterior.
Programas compilados del usuario. Ficheros ejecutables obtenidos de compilar un fichero fuente
escrito en un lenguaje de programación, con el compilador correspondiente.
Ficheros ASCII:
Ficheros de configuración del sistema. Usados por los comandos del sistema y editables por el
usuario, para adaptarlos a las exigencias deseadas.
Esta clasificación aun nos puede sonar extraña, iremos desgranando estos tipos a lo largo del libro, no
siendo necesario en esta fase la comprensión total de los tipos definidos anteriormente y que tampoco
son todos, pero nos ayudará a ir conociendo el terreno de ficheros por el que nos iremos moviendo.
La mejor forma de conocer y profundizar en el sistema de ficheros UNIX es crear uno del tipo ASCII, y
efectuar sobre él una serie de procesos. Hagámoslo mediante el comando del sistema ed:
$ ed
a
ABCDEFGHIJKLMNO
0123456789
.
w texto
27
q
$ ls -l texto
-rw-r--r-- 1 prueba 27 May 12 09:54 texto
$
El fichero ÓNYÓA contiene 27 bytes, que son los caracteres tecleados por el usuario que lo ha creado, más
ciertos caracteres de control. Para visualizar el contenido del fichero utilizaremos el comando cat:
$ cat texto
ABCDEFGHIJKLMNO
0123456789
$
Vamos a visualizar el contenido interno (en bytes) del fichero “texto”. Podemos hacer una nota
importante: todos los comandos básicos de UNIX suelen ser de muy poca longitud, de 2 a 4 caracteres,
correspondiendo normalmente con las iniciales del significado del comando). Mediante el comando od
(AXÓ S,IHUEW,obtendremos una representación visible de todos los bytes que componen el fichero:
$ od -c texto
00000000 A B C D E F G H I J K L M N O \n
00000010 0 1 2 3 4 5 6 7 8 9 \n
00000020
$
Mediante la opción -c se interpretan los bytes como si fuesen "caracteres". La opción –x nos mostrará
los bytes en codificación hexadecimal (base 16):
$ od -cx texto
00000000 A B C D E F G H I J K L M N O \n
41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 0A
00000010 0 1 2 3 4 5 6 7 8 9 \n
30 31 32 33 34 35 36 37 38 39 0A
00000020
$
Los dígitos numéricos que aparecen en la parte izquierda de la salida son las posiciones que ocupan los
bytes dentro del fichero, en notación hexadecimal. Fijémonos que cada línea de salida representa el
contenido de 16 bytes del fichero.
Al final de cada una de las líneas del fichero "texto" aparece un carácter \n que representa el "final de
línea" (RNDSJRN) que el usuario ha introducido mediante la tecla RETURN. Por convención basada en el
desarrollo del Lenguaje C, este carácter se representa mediante la notación \n. Internamente se
almacena el carácter ASCII "12" en octal o el carácter ASCII "0A" en hexadecimal. El ejemplo de este
carácter especial es uno de los muchos existentes.
Es muy importante que sepamos distinguir entre el contenido interno de un fichero, o sea, los bytes
almacenados en el mismo, y la interpretación que de ellos se hace dependiendo de las situaciones o los
procesos que traten dicho contenido.
Supongamos que en un momento de nuestro trabajo con el sistema tecleamos el carácter B XLCE XN y
que dicho carácter está definido como borrado de carácter, el kernel interpreta que se pretende borrar el
carácter anteriormente tecleado, con lo cual nos desaparecerán de la entrada ambos caracteres. Si en
cambio el usuario teclea la secuencia \<backspace>, el kernel interpreta que se desea almacenar dentro
de nuestro fichero de entrada (en este caso la consola o terminal) el carácter B XLCE XN, y el byte
representado por 08 en hexadecimal será almacenado, haciendo eco del mismo a la consola (salida).
Si utilizamos el comando print sobre un fichero que contenga un carácter especial B XLCE XN, con salida
a consola, producirá el movimiento del cursor un espacio a la izquierda. Si en cambio, sobre el mismo
fichero se utiliza el comando od con la misma salida, nos aparecerá como un byte de representación 08
en hexadecimal o 10 en octal.
El sistema operativo UNIX no posee registros, ni contadores de bytes en registros, ni ningún otro byte
que no sean los almacenados por nuestro propio programa de mantenimiento del fichero. Esta es una de
las reglas básicas que se establecieron durante el desarrollo del sistema de ficheros que soportaría el
sistema operativo UNIX.
Por otro lado, vemos que al final del fichero no aparece ningún carácter especial indicativo de fin de
fichero, sino que simplemente se detiene la representación del mismo. El sistema indica que se ha
terminado el fichero simplemente porque no hay más datos en el mismo. El kernel mantiene tablas
indicativas de la longitud total del fichero, de tal forma que los procesos encontraran el fin de fichero
cuando hayan procesado la totalidad de bytes del mismo.
Lo habitual es utilizar dispositivos de almacenamiento de datos que permiten el acceso a los mismos
como una cadena de bloques de un mismo tamaño, llamados sectores, usualmente de 512 bytes de
longitud. El software del sistema de archivos es responsable de la organización de estos sectores en
archivos y directorios y mantiene un registro de qué sectores pertenecen a qué archivos y cuáles no han
sido utilizados. En la práctica, un sistema de archivos también puede ser utilizado para acceder a datos
generados dinámicamente, como los recibidos a través de una conexión de red (sin la intervención de un
dispositivo de almacenamiento).
Los sistemas de archivos tradicionales proveen métodos para crear, mover, renombrar y eliminar tanto
archivos como directorios, pero carecen de métodos para crear, por ejemplo, enlaces adicionales a un
directorio o archivo (enlace duro en Unix) o renombrar enlaces padres (".." en Unix).
El acceso seguro a sistemas de archivos básicos puede estar basado en los esquemas de ACL (Lista
de Control de Accesos). Las listas de control de acceso hace décadas que demostraron ser inseguras,
por lo que los sistemas operativos experimentales utilizan el acceso por capacidades. Los sistemas
operativos comerciales aún funcionan con listas de control de acceso.
La estructura de directorios suele ser jerárquica, ramificada o "en árbol", aunque en algún caso podría
ser plana. En algunos sistemas de archivos los nombres de archivos son estructurados con sintaxis
especiales para extensiones de archivos y números de versión. En otros, los nombres de archivos son
simplemente cadenas de texto y los metadatos de cada fichero son alojados separadamente.
En los sistemas de archivos jerárquicos, usualmente, se declara la ubicación precisa de un archivo con
una cadena de texto llamada "ruta" —o E ÓO en inglés—. La nomenclatura para rutas varía ligeramente
de sistema en sistema, pero mantienen por lo general una misma estructura. Una ruta viene dada por
una sucesión de nombres de directorios y subdirectorios, ordenados jerárquicamente de izquierda a
derecha y separados por algún carácter especial que suele ser un ('/') o un ('\') y puede terminar en el
nombre de un archivo presente en la última rama de directorios especificada.
Una ruta (E ÓO) es la forma de referenciar un fichero o directorio en un sistema de ficheros de un sistema
operativo determinado. Una ruta señala la localización exacta de un fichero o directorio mediante una
cadena de caracteres concreta. Ésta puede ser de diversas formas dependiendo del sistema operativo y
del sistema de ficheros en cuestión. En líneas generales se compondrá de los nombres de los directorios
que conforman el camino hasta nuestro fichero o directorio a lo largo del árbol de directorios, y
finalmente estará el nombre del fichero o directorio que se quiere referenciar. Estos nombres estarán
separados por un carácter delimitador que usualmente será "\" en sistemas MS-DOS/Windows
(Microsoft) o "/" en sistemas UNIX.
Dentro de los sistemas operativos UNIX existen dos notaciones importantes para referenciar a dos tipos
de directorios especiales y muy frecuentemente usados:
Este nombre de directorio hace referencia al directorio actual donde nos encontramos posicionados
dentro del sistema de ficheros.
Por ejemplo, tenemos un fichero cuya ruta completa es dOAUNdÍ CZdEMATXdXHNRÓ CÁX. Este nombre
hace referencia a un fichero de nombre XHNRÓ CÁX, situado en el directorio dOAUNdÍ CZdEMATX. Si
dentro del sistema de ficheros nos posicionamos en el directorio dOAUNdÍ CZ, podríamos referenciar
el fichero anterior mediante la ruta ÁdEMATXdXHNRÓ CÁX. En este caso, la notación “.” sería sustituida
por el directorio actual donde estamos posicionados, es decir dOAUNdÍ CZ.
Este nombre de directorio hace referencia al directorio anterior al actual donde nos encontramos
posicionados dentro del sistema de ficheros o jerarquía del árbol de directorios.
Por ejemplo, tenemos un fichero cuya ruta completa es dOAUNdÍ CZdEMATXdXHNRÓ CÁX. Este nombre
hace referencia a un fichero de nombre XHNRÓ CÁX, situado en el directorio dOAUNdÍ CZdEMATX. Si
dentro del sistema de ficheros nos posicionamos en el directorio dOAUNdÍ CZdI ÓAC, podríamos
referenciar el fichero anterior mediante la ruta ÁÁdEMATXdXHNRÓ CÁX. En este caso, la notación “..” sería
sustituida por el directorio anterior al actual donde estamos posicionados, es decir dOAUNdÍ CZ.
/home/vas1/actual/temas.dat
Donde:
ÓNU CÁI Ó es el nombre del archivo que se establece como único en la ruta del fichero.
Donde:
ÁI Ó es la extensión del archivo, este elemento, parte del nombre, es especialmente relevante en los
sistemas Windows, ya que sirve para identificar qué aplicación está asociada con el archivo en
cuestión, es decir, con qué programa se puede editar o reproducir el archivo.
Las rutas absolutas señalan la ubicación de un fichero o directorio desde el directorio raíz del sistema de
ficheros. Por ejemplo es una ruta absoluta dOAUNdB CNdXSJNRÓNCÁI Ó que señala la ubicación de
XSJNRÓNCÁI Ó desde la raíz del sistema de ficheros.
Las rutas relativas señalan la ubicación de un fichero o directorio a partir de la posición actual dentro del
sistema de ficheros. Por ejemplo, una ruta relativa B CNdÍ SÁJIY señala al fichero Í SÁJIY dentro del
directorio B CN en la ubicación actual.
En sistemas tipo UNIX, la ruta ~/ es una ruta relativa que lleva al directorio personal del usuario (OAUN);
por ejemplo, si el usuario usu1 tiene un fichero de imagen en su directorio personal, esta imagen podría
tener dos rutas de acceso, una relativa y una absoluta:
Absoluta:
/home/usu1/imagen.jpg
Relativa:
~/imagen.jpg
En este caso, la ruta relativa sólo puede ser verdaderamente valida si el sistema está ubicado en el
usuario HCH1. En este mismo caso, ~/ seria el sinónimo relativo de la ruta dOAUNdHCH1.
o UGO (Usuario, Grupo, Otros, o por sus siglas en inglés, PCNM, 0MAHE, ”ÓONMC)
o Capacidades granuladas
o Atributos extendidos (Ej.: sólo añadir al archivo pero no modificar, no modificar nunca, etc.)
El archivo de dispositivo representa al dispositivo para comunicarlo con programas que se ejecutan en la
máquina. No es un archivo propiamente dicho, sino que el usuario lo ve como un archivo. Para ello debe
existir un controlador (IMJÍNM) apropiado para el dispositivo.
Por ejemplo, el programa de edición de imágenes Gimp puede acceder al scanner a través del archivo
de dispositivo /dev/scan.
La tarjeta de red, por ejemplo Ethernet, ISDN, no se conecta a través de ficheros de dispositivo, sino a
través de TCP/IP, aunque existen ficheros de dispositivo para aplicaciones especiales como Netlink
Device, D-Channel, etc.
Ejemplo Descripción
pro.* válidos "pro.<cadena>" Ejemplo "pro.c" "pro.program" "pro.12". No son válidos "nom.l"
"program" “pro.12” "pr.c"
fic.[123] válidos únicamente "fic.1" "fic.2 "fic.3”
fic.[^123] Válidos todos los "fic.<carácter>" excepto los "fic.1" "fic.2" y "fic.3”
uno[a-d] Válidos "unoa" "unob" "unoc" y "unod"
Vamos a crear dos ficheros (siempre dentro del usuario "prueba") mediante el comando ed:
$ ed
a
Texto del documento uno
.
w texto
24
q
$ ed
a
El sistema UNIX en estudio
.
w fich.1
27
q
$
Recordemos que el contador de caracteres mostrado por el comando incluye el carácter de fin de línea
(RNDSJRN), que es la forma que tiene el sistema de representar la digitación de la tecla RETURN.
8.7.1 EL COMANDO ls
El comando ls nos muestra una lista de nombres de los ficheros que mantiene el usuario o el sistema, no
el contenido de los mismos:
$ ls
fich.1 texto
$
Coincide con los dos ficheros creados por el usuario. Los nombres están automáticamente ordenados
alfabéticamente. Como muchos de los comandos UNIX, ls posee opciones que pueden ser utilizadas
para cambiar el modo de acción del mismo. Las opciones deben ir a continuación del nombre del
comando, y normalmente van precedidas del carácter -. La opción –t produce una ordenación de los
nombres de ficheros por la hora de última modificación del mismo. Los de cambio más reciente son
colocados al principio:
$ ls -t
texto
fich.1
$
La opción -l produce una salida con información mucho más completa sobre los ficheros:
$ ls -l
total 2
-rw-r--r-- 1 prueba 27 May 17 18:21 fich.1
-rw-r--r-- 1 prueba 24 May 17 18:22 texto
$
El primer mensaje de salida ("total 2") nos indica el número total de bloques de disco utilizados para
almacenar la información de los ficheros que han sido procesados por el comando. Un bloque está
constituido por 512 o 1024 caracteres (u otros tamaños dependiendo del sistema, siendo este dato de
vital importancia y de necesario conocimiento). La cadena "-rw-r--r--" nos da información de los permisos
de acceso al fichero. En este caso el propietario del fichero ("prueba") tiene permiso de lectura y
escritura, pero el resto de usuarios solamente tienen permiso de lectura. La siguiente información que
observamos en la salida ("1") es el número de enlaces (SJRLC) del fichero. La cadena "prueba" nos indica
el nombre de usuario al que pertenece el fichero, es decir el usuario que lo creó. La siguiente cadena de
salida ("27" y "24") corresponde al número de caracteres que componen cada fichero (bytes) y que
vemos que coincide con el obtenido por el comando ed en la creación de ambos ficheros. A continuación
muestra la fecha y hora de última modificación del fichero y por último el nombre del mismo.
Las opciones del comando ls (así como las de muchos otros) pueden ser agrupadas, de tal forma que el
comando ls -lt produce una salida con información completa de los ficheros, y ordenados por fecha/hora
de última modificación. La opción -u nos da información del momento de último uso del fichero (no
cambio sino utilización o acceso al mismo). La opción -r produce la inversión del orden de salida de los
ficheros procesados por el comando.
Después de las opciones del comando ls podemos incluir uno o varios nombres de fichero, de tal forma
que la información visualizada por el comando pertenecerá a la lista de ficheros digitada.
$ ls -l texto
-rw-r--r-- 1 prueba 24 May 17 18:22 texto
$ ls -l fich.1
-rw-r--r-- 1 prueba 27 May 17 18:21 fich.1
$ ls -l tex
ls: tex not found
$
Como podemos observar, en caso de que no exista el fichero solicitado en el comando, nos muestra un
mensaje de aviso o error. Veamos a continuación una tabla de las opciones mas importantes del
comando ls. Tener en cuenta que en esta parte del capítulo aparece la noción de directorio, que será
más tarde explicada. Quede aquí su reseña a nivel de su utilización en el comando ls:
Opción Descripción
-l Lista en formato completo (largo) de información
-t Lista por orden de fecha-hora de última modificación. Primero los mas recientes
-a Lista todos los ficheros incluyendo directorios
-s Visualiza el tamaño de los ficheros en bloques. 1 Bloque = XXXX caracteres (bytes)
-d Informa sobre la situación de directorios
-r Lista en orden inverso al normal
-u Lista por orden de fecha-hora de última utilización de los ficheros. Primero el mas reciente.
$ ls -a
. .. .profile fich.1 texto
$ ls -s
total 2
1 fich.1 1 texto
$ ls -r
texto fich.1
$ ls -u
fich.1 texto
$
Vemos que en la opción -a nos aparecen tres ficheros extraños. El representado por “.” nos indica el
directorio actual en el que nos encontramos. El “..” corresponde al directorio padre del actual, es decir, el
directorio del que proviene o cuelga. Y el fichero .profile es uno de los ficheros "invisibles" del usuario, y
que contiene una serie de parámetros importantes para el control del usuario.
El comando ls no suele responder con mensajes de error, incluso en el caso de una digitación incorrecta
de las opciones. Cuando no se le pasan argumentos de nombres de ficheros, lista todos los ficheros del
directorio actual. En caso de digitar la opción -l del comando, esta imprime entre otras informaciones,
una lista de 10 caracteres, de los cuales el primero indica el tipo de fichero que se ha listado, y los
restantes 9 son los permisos de acceso al mismo, que serán explicados posteriormente. Los tipos
posibles de ficheros, indicados por el primer carácter de la cadena, son los siguientes:
Tipo Descripción
d la entrada es un directorio
b la entrada es un fichero especial de tipo bloque
c la entrada es un fichero especial de tipo carácter
- la entrada es un fichero del tipo ordinario. Fichero normal de usuario.
$ ed texto
24 Indica el número de caracteres
1,$p Listar líneas desde la 1 hasta la última
Texto del documento uno
q Salida del editor
$
Llamamos al comando ed pasándole el nombre del fichero que queremos editar ("texto") y este nos
indica el número de caracteres (bytes) que lo compone. En el capítulo dedicado al editor ed se podrán
ver las formas de hacer un listado selectivo de las líneas del fichero.
Existen numerosos casos en los que no es viable es uso de un editor para la visualización de la
información almacenada en un fichero, por ejemplo en el caso de que el tamaño del mismo sea superior
al máximo procesado por el editor o que se desee la visualización de mas de un fichero. Para estos
casos existen varias alternativas que veremos a continuación.
$ cat texto
Texto del documento uno
$ cat fich.1
El sistema UNIX en estudio
$ cat texto fich.1
Texto del documento uno
El sistema UNIX en estudio
$
El comando cat solo sirve para la visualización de ficheros que estén compuestos por caracteres ASCII o
bien caracteres que se puedan imprimir. Si por ejemplo se lista un fichero con caracteres de control, el
efecto que pueden causar en nuestro terminal puede ser bastante extraño. El comando cat puede
visualizar un mensaje de error indicando que no encuentra el fichero solicitado:
$ cat salvador
cat: can't open salvador
$
En todos los sistemas UNIX existe uno o varios comandos que permiten acomodar la salida a las
características del terminal, de tal forma que nos permita la visualización del contenido por páginas. El
nombre del comando depende del sistema y puede ser page, pg y more.
8.8.2 EL COMANDO pr
Existe otro comando, de nombre pr, que lista el contenido de uno o varios ficheros, acomodándose a las
características de paginación deseadas. Es decir, lista páginas de un numero determinado de líneas (66
líneas) con la fecha y hora de la última modificación del fichero, numera las páginas y coloca el nombre
del fichero en el principio de cada una. Entre cada uno de los ficheros a listar efectúa un salto de página,
de tal forma que cada fichero comience al principio de una página.
$ pr texto fich.1
Mediante este comando se puede producir una salida en multicolumna o en paralelo. Por ejemplo pr -3
fich.1 fich.2 fich.3 efectúa una salida en formato de tres columnas. La opción -m asigna la salida en
columnas paralelas. Para mas información sobre el comando se debe acudir al manual original de UNIX
(UNIX iMATM UUNMC,) RH S)
Debemos hacer notar que este comando no efectúa ningún tipo de arreglo en las líneas del fichero, ni
justifica márgenes. Estas tareas son ejecutadas por comandos más complejos y de mayor potencia como
son el nroff y troff cuya discusión escapa a las intenciones de este libro.
El comando pr no produce ningún tipo de mensaje de error en caso de no encontrar los ficheros a
imprimir, o que se digiten opciones incorrectas. Existe otro detalle acerca del comando, en cuanto se
comienza a imprimir el listado en el terminal, se suprimen todas las comunicaciones establecidas
mediante el comando write, de tal forma que se evita la alteración del formato del listado. Veamos una
tabla con las opciones mas comunes del comando:
Opción Descripción
-<n> La salida se imprime en formato de n columnas.
+<n> Imprime el fichero a partir de la línea n especificada, inclusive.
-h <cadena> Indica cambio de la cabecera. La <cadena> es ahora la cabecera de cada pagina.
-w<n> La anchura de cada página del listado será de n caracteres, en lugar de 72, tomado
por defecto.
-l<n> Cambia el número de líneas por página al valor n, en vez de 66 líneas tomadas por
defecto.
-t El listado se imprime sin cabecera y pie de página, es decir, no se imprimen las 5
líneas de la cabecera y pie de página, teniendo disponibles todas las líneas para el
contenido de los ficheros listados.
-s<carácter> En vez de separar las columnas por el carácter de tabulación, se separan por el
carácter especificado.
-m Imprime todos los ficheros especificados en columnas paralelas y de forma
simultanea.
8.9.1 EL COMANDO mv
Una de las tareas más normales en el trabajo con un sistema operativo es el cambio del nombre de un
fichero o renombrado del mismo. El comando que lo efectúa se denomina mv, y su sintaxis básica es:
$ mv texto archivo
$ ls
archivo
fich.1
$ cat texto
cat: can´t open texto
$ cat archivo
Texto del documento uno
$
Hemos cambiado el nombre del fichero "texto" a "archivo". El contenido del fichero permanece
inalterado. Posteriormente ejecutamos el comando ls, mostrándonos una lista de los ficheros del usuario
en la que no aparece el fichero "texto" y si lo hace el "archivo". Su intentamos listar el contenido del
fichero "texto" mediante el comando cat, este nos avisará con un mensaje de error indicativo de su no
existencia. Tener muy en cuenta que si pretendemos renombrar un fichero con un nombre de otro que ya
existe, este será borrado del sistema y pasará a contener la información del fichero que se ha
renombrado.
En el apartado dedicado a directorios UNIX volveremos sobre este comando para ver la posibilidad de
"mover" ficheros dentro de los caminos <pathnames> del árbol de directorios del sistema y del usuario.
8.9.2 EL COMANDO cp
Para efectuar copias de ficheros, es decir, proceder a una duplicación de los mismos con nombres
distintos, existe el comando cp
$ cp archivo salva
$ cat salva
Texto del documento uno
$ cp fich.1 fich.2
$ cat fich.2
El sistema UNIX en estudio
$
Se han generado dos copias, una del fichero “archivo” sobre otro de nombre “salva", y otra del fichero
"fich.1" sobre el "fich.2', y que poseerán exactamente el mismo contenido, como hemos visto mediante el
comando cat salva y cat fich.2.
$ cp arch.1 files
cp: can´t open archi.1
$ cp archivo archivo
cp: cannot copy file to itself
$ cp –s archivo nuevo
Usage: cp f1 f2 or cp f1 f2 ... fn d1
Podemos ver que el comando cp avisa en caso de no encontrar el fichero que va a ser copiado.
Igualmente, en caso de intentar copiar un fichero sobre sí mismo, nos avisa de tal situación. Por último,
el comando no posee ningún tipo de opciones, y en caso de digitar alguna nos avisa de que no es
correcta la sintaxis del comando.
8.9.3 EL COMANDO rm
Existe otro comando que permite el borrado o desaparición de ficheros del usuario y del sistema, de
nombre rm y cuya sintaxis es:
rm <lista de ficheros>
$ rm fich.2
$ rm texto
rm: texto not found
$ rm salva
$
Hay que tener mucho cuidado con los ficheros que se van a borrar puesto que el comando rm no solicita
la conformidad para tal borrado. Existe una opción del comando, de nombre -i, que solicita
interactivamente la conformidad para cada uno de los ficheros de la lista de argumentos del comando.
Esta opción es muy conveniente de usar cuando no se sepa exactamente la lista de ficheros a borrar por
utilizar caracteres "DíSIX MIC". El borrado de ficheros se efectúa en "modo silencioso", es decir, no se
visualiza ningún tipo de mensaje de aviso del borrado efectuado por el comando. Veamos una tabla de
las opciones del comando rm:
Opción Descripción
-f También serán borrados aquellos ficheros protegidos contra escritura.
-r Borra recursivamente todos los ficheros de un directorio, e incluso el propio directorio.
-i Solicita confirmación para el borrado de cada fichero involucrado.
$ rm arch.1
rm: arch.1 nonexistent
$ rm -v fic.1 fic.2
rm: unknown option -v
$
Debemos tener mucho cuidado con la opción –r, puesto que nos borrará sin pedir confirmación, todos los
ficheros del directorio especificado. En este caso es muy conveniente usar la opción –i, para la solicitud
de la confirmación de cada borrado de fichero.
$ ed
a
Con cien cañones por banda
8.11.1 EL COMANDO wc
El primer comando que vamos a desarrollar efectúa la cuenta del número de líneas, palabras y
caracteres que componen uno o más ficheros. Su nombre es wc (DAMI,XAHRÓNM):
$ wc poema
5 22 119 poema
$
Palabra se puede definir como el conjunto de caracteres que no contiene ningún blanco, tabulador o
"RNDSJRN". El fichero "poema" contiene 5 líneas, 22 palabras y 119 caracteres. En caso de que al
comando wc se le pase como argumentos una lista de ficheros (más de uno), nos listara la cuenta para
cada uno de los ficheros de la lista, así como el número total de caracteres, palabras y líneas en la
totalidad de los mismos:
$ wc poema archivo
5 22 119 poema
1 4 24 archivo
6 26 143 total
$
Opción Descripción
-l Cuenta únicamente las líneas del fichero
-w Cuenta únicamente las palabras del fichero
-c Cuenta únicamente los caracteres del fichero
$ wc -n archivo
archivo
$ wc -lv archivo
archivo
$ wc +c archivo
wc: can´t open +c
1 4 24 archivo
$
En el primer caso, al ser inválida la opción y existir el fichero, no muestra ningún tipo de información del
mismo. En el segundo caso, ignora la opción inválida y muestra la información correspondiente a la
opción válida. En el tercer caso, nos avisa da la no-existencia del fichero.
Sobre el fichero "poema" hemos localizado todas las líneas que contienen la cadena "viento" y sobre el
fichero "archivo" las que contienen "documento". El comando grep también nos localiza las líneas que
"no" contienen la cadena especificada. Esto se consigue mediante la opción –v:
El comando grep posee numerosas opciones que efectúan tareas diferentes basadas en la norma
fundamental del comando, que es la búsqueda de líneas de ficheros que contengan una determinada
cadena de caracteres definida por una expresión regular (vistas en un capítulo posterior). Se puede
efectuar búsqueda en varios ficheros, contar líneas y caracteres y numerar líneas. Veamos una tabla de
las opciones más comunes e importantes del comando:
Opción Descripción
-v Muestra todas las líneas, excepto las que contienen la cadena dada
-c Muestra todas las líneas que contienen la cadena digitada
-l Muestra los nombres de los ficheros que contienen la cadena digitada
-n Aparte de mostrar las líneas, visualiza el número de línea
-h No visualiza el nombre de los ficheros
-y Efectúa igual tratamiento a las mayúsculas que a las minúsculas
-c Permite comenzar la <cadena> por el carácter
$ sort poema
un velero bergantín
viento en popa a toda vela
Con cien cañones por banda
No cruza el mar sino vuela
Poema viento
$
La clasificación es línea a línea. El orden natural de clasificación incluye antes los blancos, después las
letras mayúsculas y por último las minúsculas, por lo que no es estrictamente una clasificación alfabética.
El comando sort posee múltiples opciones para controlar el orden de la clasificación. Posibilidad de
orden inverso, numérico, ignorando blancos repetidos, clasificando campos dentro la línea, etc. Damos a
continuación una lista de las opciones más comunes e importantes del comando:
Opción Descripción
sort -r Invierte el orden normal de clasificación
sort -n Clasifica en orden numérico
sort -nr Clasifica en orden numérico inverso
sort -f Considera igual las mayúsculas y minúsculas
sort +n Comienza a clasificar en el campo n+1 de la línea
$ tail archivo
Texto documento uno
$ tail -1 poema
Poema viento
$ tail +3 poema
No cruza el mar sino vuela
un velero bergantín
Poema viento
$
Mediante la opción -<n>, donde <n> debe ser un dato numérico, nos visualiza las "n" últimas líneas del
fichero. En este caso hemos ejecutado: tail -1 poema, que nos mostrará la última línea del fichero
"poema". La opción +<n>, donde <n> tiene el mismo significado anterior, visualiza a partir de la "n" línea
del fichero. El comando ejecutado: tail +3 poema, muestra todas las líneas del fichero "poema" a partir
de la tercera inclusive. Veamos una tabla de las opciones del comando:
OPCIONES:
Opción Descripción
l El número <n> se refiere a líneas. Esta opción es por defecto.
c El número <n> se refiere a caracteres.
b El número <n> se refiere a bloques (512 o 1024 o 2048 o xxxx bytes) de datos de disco.
$ ed
a
Con cien canones por banda
viento en popa a toda vela
no cruza el mal sino vuela
un velero bergantín
Poema viento
.
w poema.dos
119
q
$
Vemos que entre ambos ficheros no existe mucha diferencia, apenas dos palabras escritas de forma
distinta: canones por cañones, y mal por mar. El comando cmp encuentra la primera línea en la que
difieren dos ficheros y nos indica la posición primera de diferencia entre ambos:
El comando cmp nos indica que los dos ficheros son idénticos hasta el carácter 12 de la primera línea.
No nos dice las diferencias entre ambos, sino solamente la primera. Este comando es muy interesante
para casos en los que deseemos verificar la igualdad total entre dos ficheros.
El comando nos indica que la línea 1 del primer fichero (“poema”) está cambiada en la línea 1 del
segundo fichero (“poema.dos”) y igualmente con la tercera.
El comando cmp funciona con multitud de tipos de ficheros, mientras que diff solamente funciona con
ficheros de tipo texto. El comando diff se usará cuando se deseen conocer las diferencias exactas entre
dos ficheros. Evidentemente es más rápido el comando cmp pues solamente busca la primera
diferencia. Veamos una tabla de las Opciones del comando:
Opción Descripción
-f La salida de las diferencias entre los dos ficheros se efectúa en orden inverso
-h Localiza pequeñas diferencias, pero actúa de forma mucho más rápida, y es muy
conveniente en grandes ficheros. No es compatible con ed.
-b Ignora los tabuladores y blancos de final de líneas, y trata como un solo blanco los
repetitivos
-e Admite las ordenes de añadir, borrar y modificar líneas, con los mismos comandos que el
editor ed.
Mensajes de error
El comando diff avisa en caso de que alguno de los dos ficheros no exista. En caso de digitar una opción
inválida, el comando no muestra ningún mensaje de error.
awk divide la entrada en registros; por defecto cada línea se considera un registro, es decir el separador
de registros por defecto es el salto de línea (RNDSJRN).
Cada registro se divide a su vez en campos, el separador por defecto entre campos es el espacio en
blanco o el carácter tabulador.
Utilizando la formula ' /patrón / { acción } ' en la que se buscan registros que sigan el patrón en el o
los ficheros especificados en el mandato, y posteriormente, con las líneas que se han seleccionado,
se ejecuta la acción.
Con la opción -f fich_ordenes de forma que se ponen los mandatos de las acciones en el fichero
fich_ordenes, y con esto se pueden ejecutar acciones mas complicadas. Con esta opción no se
puede utilizar la selección por patrones, pero esto no es un problema ya que dentro del fichero de
comando se puede controlar la selección de patrones.
La opción -F 'separador ' se utiliza para cambiar el separador entre campos por el separador indicado,
que por defecto es el espacio en blanco.
awk es muy útil en variedad de operaciones, por ejemplo para generar impresos, buscar patrones,
validaciones de datos, filtrado de datos para comunicaciones, etc.
Ejemplos
Hay también unos caracteres especiales que nos ayudan a hacer selecciones más complejas:
* Utilizado después de un carácter sustituye a cualquier repetición de este, el carácter puede ser
incluso vacío.
^ Entre [ ] todos los caracteres menos los indicados después del signo. Sin [ ] hace referencia a la
primera posición de la línea es decir el carácter que siga estará al comienzo de la línea.
8.12.2 SELECCIÓN
Hay varios criterios para seleccionar registros con el comando awk.
Otro es el indicar dos patrones separados por una coma, de tal forma que seleccionarán aquellos
registros que estén entre el primer registro que cumple el primer patrón y el primer registro que cumple el
segundo patrón; si hay alguno de los patrones que no se cumple, se seleccionará comenzando desde el
principio o desde el final.
Similar al anterior criterio de selección, se puede utilizar la variable NR, que indica el número de registro
que se está tratando en secuencia, de manera que se puede ejecutar:
También se pueden utilizar las variables que veremos a continuación; un ejemplo de esto es la variable
NF, que indica el número de campos que tiene un registro ( por defecto línea ) y se puede utilizar de esta
forma:
8.12.3 VARIABLES
Estas son algunas de las variables que se pueden utilizar, tanto en los ficheros de acciones, como
directamente sobre el comando awk.
8.12.4 PRINT
El comando print se puede utilizar en el fichero de órdenes o directamente sobre el comando awk.
Se puede utilizar sin argumentos, entonces por defecto tomará todo el fichero de entrada.
Si solo tiene un argumento visualizará el argumento referente a cada registro de entrada. Por ejemplo:
Si tiene varios argumentos y están separados por blancos, la salida será los argumentos requeridos para
cada registro, sin separadores entre ellos. Por ejemplo:
Visualizará el primer y tercer campo concatenados, sin espacio separador, de todos los registros del
fichero fichero-ejemplo.
Cuando se disponen los argumentos entre comas, separará la salida con el separador por defecto de
salida. Por ejemplo:
awk es un lenguaje interpretativo, se pueden usar variables definidas por el usuario, y no se declaran en
el fichero, es decir, se utilizan directamente.
Las variables de caracteres son convertidas a numéricas y viceversa cuando lo demanda el contexto.
Con las variables numéricas se pueden utilizar operadores numéricos + - * / , incrementar una variable
(variable++) o decrementarla (variable--), también concatenar variables alfanuméricas de la forma
siguiente :
Cuando una línea del fichero de ordenes comienza por el signo # no es una línea ejecutable, solo
contiene comentarios.
Se permiten varias ordenes en la misma línea del fichero, tan solo hay que separarlas con punto y coma
;.
Para continuar con una orden en otra línea deberemos terminar la línea con el carácter \.
BEGIN
Se utiliza para realizar una acción antes de empezar el proceso de los registros del fichero de entrada.
Se pone la palabra BEGIN delante de la orden que queramos ejecutar antes de empezar con el proceso.
La orden BEGIN debe ir situada en primera posición del fichero de órdenes. Por ejemplo :
BEGIN { FS = ":" }
.......
Con este código al comienzo del proceso, fijamos el separador de campo a dos puntos (:) en vez del
espacio en blanco.
END
Se utiliza para realizar una acción al final del procesamiento de todos los registros del fichero de entrada.
La utilización de END es similar a la de BEGIN, tan solo que lógicamente se insertará en el fichero de
órdenes al final de él.
8.12.7 REDIRECCIONAR
Se puede redireccionar desde la salida estándar a varios ficheros. El máximo de estos ficheros es 10.
Ejemplos
Imprime el primer campo de cada línea del fichero_entrada en el fichero que tiene como nombre el
contenido de la variable variable_fichero sin afectar a su contenido previo.
Imprime los primeros campos de cada línea de fichero_entrada cada uno en un fichero que se llamara
como el segundo campo de la línea.
Manda por correo a usuario1 los primeros campos de cada línea del fichero fichero_entrada.
Comando Descripción
ls –u Clasificada por fecha - hora de último uso de los ficheros. También ls -lu y
ls –lut
Is –r Invierte el orden de salida. También ls -rt, ls -rlt, etc.
ed <fichero> Edición del fichero indicado
cp <fic1> <fic2> Copia <fic1> sobre <fic2>. Copia encima del fic2 si este ya existe
mv <fic1> <fic2> Mueve (renombrar) <fic1> a <fic2>. Copia sobre <fic2> si este ya existe
rm <ficheros> Borra ficheros indicados irrevocablemente
cat <ficheros> Lista (visualiza) el contenido de los ficheros indicados
pr <ficheros> Lista el contenido de los ficheros con páginas de 66 líneas y cabecera
pr -n <ficheros> Igual pero en formato de n columnas
pr -m <ficheros> Igual pero en múltiples columnas. Un fichero al lado del otro
wc <ficheros> Cuenta líneas, palabras y caracteres de cada fichero y en total
wc -l <ficheros> Cuenta solamente líneas
grep <cad> <ficheros> Lista líneas de los ficheros que contengan la cadena <cad>
grep -v <cad> <ficheros> Lista líneas de los ficheros que no contengan la cadena <cad>
sort <ficheros> Clasifica los ficheros por orden alfabético de líneas
tail <fichero> Lista las últimas 10 líneas del fichero
tail -n <fichero> Lista las n últimas líneas del fichero
tail +n <fichero> Lista las líneas del fichero comenzando en la línea n
cmp <fic1> <fic2> Indica la primera diferencia localizada entre los dos ficheros
diff <fic1> <fic2> Lista todas las diferencias entre los dos ficheros
8.14 DIRECTORIOS
El sistema operativo UNIX distingue a cada uno de los ficheros de sistema, además de por su nombre,
por la agrupación de los mismos dentro de entidades denominadas directorios. Es similar a la idea de
como los libros son colocados en una biblioteca dentro de librerías. La biblioteca es el sistema, las
librerías son los directorios y los libros son los ficheros.
Cada usuario del sistema (definido entre otras cosas por su nombre) tiene un directorio particular
denominado directorio del usuario o directorio corriente. El usuario puede estar trabajando en otro
directorio, pero siempre poseerá su propio directorio. A menos que se efectúe un cambio de directorio,
cualquier fichero creado por el usuario pertenecerá al directorio del mismo. Al efectuar la conexión al
sistema (SATJR) se produce la entrada en el directorio del usuario, que posteriormente veremos como se
representa.
Un directorio, además de poseer ficheros normales, puede contener otros directorios. La forma normal
de representación de esta situación es la de un árbol de ficheros y directorios. El sistema da la
posibilidad de moverse dentro de ese árbol y localizar cualquier fichero del sistema iniciando la búsqueda
en la raíz (MAAÓ) del árbol.
$ pwd
/usr/export/prueba
$
El comando nos visualiza el directorio actual de trabajo, que coincide con el directorio del usuario
"pruebas". Como podemos apreciar, el directorio del usuario es un directorio dentro del directorio NYEAMÓ,
que a su vez es un directorio dentro del directorio HCM, que a su vez y por último es un directorio del
directorio base del árbol, denominado MAAÓ (raíz) y que se representa por /. Este carácter se usa como
separador de los directorios y ficheros del árbol. También existe la limitación de 14 caracteres (32 en
sistemas más modernos) para el nombre de un directorio. En casi todos los sistemas UNIX, los usuarios
del mismo cuelgan del árbol en la forma /home.
Veamos unos ejemplos del comando ls incorporando la noción de directorios introducida en esta
sección:
$ ls /home/pruebas
fic.c
$ ls /home
antonio
director
fuentes
pruebas
$ ls /
bin
dev
etc
lib
tmp
unix
usr
$
El comando ls /usr/pruebas lista los ficheros que existen en el usuario "pruebas", es decir, dentro de su
directorio normal. El comando ls /usr lista los nombres de los directorios de usuarios definidos en el
sistema, o en general la lista de ficheros y directorios que cuelgan del árbol, desde la base /usr. Por
último, el comando ls / lista la totalidad de ficheros y directorios que cuelgan desde la raíz (MAAÓ) del
árbol. Vemos unos ejemplos con el comando cat:
$ cat /usr/pruebas/archivo
Texto del documento uno
$ cat /usr/director/prueba
prueba de textos.
fichero de prueba
$ ls /usr/director
prueba
carta
$
Hemos representado un fichero por el camino que este recorre dentro del árbol del sistema desde la raíz
del mismo (MAAÓ). Este camino se denomina en UNIX E ÓOR UN y su significado es el recorrido que se
debe hacer en el árbol del sistema para localizar el fichero, desde la base (MAAÓ) del árbol. Como vemos,
se ha listado el contenido de un fichero "prueba" residente en el usuario "director". Es una norma
universal de UNIX el poder representar un fichero por su camino o "E ÓOR UN". Asimismo es posible
listar los nombres de ficheros de otro usuario del sistema, mediante su camino (E ÓOR UN) del árbol.
Vamos a representar la estructura de árbol que reside en un sistema UNIX con varios usuarios,
representado en la figura 1
Vamos a ejecutar el comando cp, definiendo ficheros por su camino (pathname) en el árbol de directorio
del sistema
$ cp /usr/director/prueba datos
$ ed /usr/director/prueba
......
......
$
Como podemos ver, hemos efectuado la copia de un fichero del usuario "director" sobre el fichero
"datos" en el directorio donde el usuario está trabajando normalmente /usr/pruebas. Asimismo, hemos
editado el propio fichero del usuario "director". Llegado a este punto, vamos a desarrollar un tema
importante en UNIX, los permisos de acceso a ficheros del sistema.
El sistema reconoce a cada usuario por un cierto número que se le asigna a la hora de su creación. El
nombre del usuario no es mas que un identificador para el sistema y una especie de clave de acceso al
mismo. Debido a esto, varios nombres de usuarios distintos pueden tener el mismo número identificador.
Esta situación no es nada segura dentro de un sistema, y el administrador del mismo se encargaría de
controlarla en tal caso. Cada usuario, además de su número de identificación, posee un número
identificador del grupo al que pertenece. En muchos de los sistemas UNIX, el grupo de 'todos’ los
usuarios del sistema se denomina other. Toda la información referente a los parámetros de los grupos y
usuarios del sistema se encuentra en un fichero localizado en el E ÓOR UN /etc/passwd.
read r (lectura)
write w (escritura)
execute x (ejecución)
La opción -l del comando ls nos muestra los permisos de acceso que poseen los ficheros pasados como
argumentos:
$ ls -l /etc/passwd
-rw-r--r-- 1 root 2048 May 9 13:30 /etc/passwd
$ ls -lg /etc/passwd
-rw-r--r-- 1 adm 2048 May 9 13:30 /etc/passwd
$ ls -l /bin/passwd
-rwxr-xr-x 1 root 8484 Feb 24 15:10 /bin/passwd
$ ls -l /bin/who
-rwxr-xr-x 1 root 6348 Mar 24 12:00 /bin/who
$ ls -l archivo
-rw-r--r-- 1 pruebas 24 May 17 18:30 archivo
La opción -l del primer comando nos informa del nombre del propietario o usuario del fichero, que
corresponde al nombre de usuario MAAÓ. La opción -g nos muestra el nombre del grupo al que pertenece
el fichero, en este caso adm. La cadena -rw-r--r-- nos da información acerca de los permisos del fichero.
El primer carácter de la cadena "-' indica el tipo de fichero de que se trata, en este caso un fichero
ordinario, en caso de ser un directorio aparecería el carácter "d". Los siguientes tres caracteres de la
cadena indican las protecciones del fichero para el propio usuario del mismo. Las tres siguientes son las
protecciones del fichero para el grupo de usuarios al que pertenece el propio usuario creador del fichero.
Las tres últimas posiciones corresponden a la protección para el resto de los usuarios del sistema.
Veamos un cuadro de interpretación de estos temas:
Indicador Descripción
- Indica que no hay permiso para acceder al fichero
r Se permite acceso de lectura al fichero
w Se permite acceso de escritura al fichero
x Se permite la ejecución del fichero. Podría ser un programa ejecutable por el sistema
Ejemplos:
-rwxr-xr-x Fichero ordinario. Permitida la lectura y ejecución a todos los usuarios, usuario propio,
grupo y resto de los usuarios. Permitida escritura solo al usuario del fichero.
-rwxrwxr-x fichero ordinario. Permitida lectura y ejecución a todos los usuarios del sistema.
Permitida la escritura al usuario y al grupo. No permitida escritura al resto de los usuarios
Cuando nosotros enviamos a la CONSS la orden de ejecución de un comando, por ejemplo who, esta
busca en una serie de directorios del sistema, hasta encontrar dicho fichero. Uno de los directorios
buscados es /lib, donde se encuentra el fichero who. El núcleo o kernel del sistema UNIX comprueba los
permisos de acceso al fichero y obra en consecuencia. Si este comando posee permiso de ejecución
para el usuario que lo desea ejecutar, el sistema validará la ejecución. En caso contrario, si no posee
permiso de ejecución, nos avisará con un mensaje y no procederá a ejecutar el comando.
Los permisos de acceso a directorios tienen igual estructura, pero se diferencian en algún aspecto:
$ ls -ld .
drwxrwxr-x 3 pruebas 50 May 12 23:00 .
$
Como vemos, hemos incluido la opción -d dentro del comando ls. Esta opción nos visualiza la
información de un directorio (la notación . corresponde a la nomenclatura del propio directorio del
usuario). La protección r indica que el directorio tiene permiso de lectura. La protección w indica que se
pueden crear y borrar ficheros dentro del directorio. El permiso para borrar un fichero dentro de un
directorio es independiente del propio fichero. Si el usuario posee un permiso w en un directorio, puede
borrar ficheros del mismo, incluso si estos están protegidos. El comando rm solicitará confirmación para
borrar los ficheros protegidos. La protección x en un directorio indica que se posee acceso de búsqueda
de ficheros dentro del directorio. Es decir, que si un usuario posee permiso de ejecución en un directorio,
puede buscar ficheros a través del mismo. Con estas premisas se pueden asimilar las tareas que
efectúan las protecciones de acceso a directorios.
Campos Descripción
<quien>
u Usuario propietario del fichero
g Grupo de usuarios del fichero
o Resto de los usuarios del sistema
a Todos (usuario, grupo y resto). Opción por defecto
<operación>
+ Añade permiso digitado
Campos Descripción
- Quita permiso digitado
= Supone permiso absoluto para los ficheros
<permiso>
r Permiso de lectura
W Permiso de escritura
x Permiso de ejecución
$ ls -l ejemplo
-rwxrwxrwx ........
$ chmod go-wx ejemplo
$ ls -l ejemplo
-rwxr--r-- ........
$ chmod g+x ejemplo
$ ls -l ejemplo
-rwxr-xr-- .......
$ chmod a=w ejemplo
$ ls -l ejemplo
-rwxrwxr-x .......
$ chmod a-x ejemplo
$ ls -l ejemplo
-rw-rw-r-- .....
$
Existe otra forma de manejo del comando mas complicada, que dejamos al gusto del lector el consultarla
en los manuales originales de UNIX.
8.15.2 EL COMANDO cd
Vamos a desarrollar el comando cd, que permite el movimiento del usuario por los directorios propios o
los del sistema. El comando cd posiciona al usuario en el directorio indicado, bajo una cierta
nomenclatura:
cd <recorrido> cambia al directorio especificado por recorrido, que debe ser un camino (pathname)
completo
$ cd
$ pwd
/usr/pruebas
$ cd /usr
$ pwd
/usr
$ cd /usr/pruebas/programas
$ pwd
/usr/pruebas/programas
Sintaxis Descripción
cd <directorio> Cambia al directorio indicado. No hace falta poner el recorrido completo. Debe
ser un directorio dentro del actual en el que se está posicionado.
cd .. Sube un nivel en la estructura jerárquica del árbol de directorios
cd . Se mantendrá en el directorio actual.
$ cd
$ cd programas
$ pwd
/usr/pruebas/programas
$ cd ..
$ pwd
/usr/pruebas
$ cd archivo
archivo: bad directory
$ cd
$ cd .
$ pwd
/usr/pruebas
$
$ cd
$ mkdir sub
$ cd sub
$ pwd
/usr/pruebas/sub
$ mkdir fuentes textos
$ cd fuentes
$ pwd
/usr/pruebas/sub/fuentes
$ cd ..
$ pwd
/usr/pruebas/sub
$
El comando mkdir crea los directorios dentro del directorio actual de trabajo del usuario. Para crear un
directorio se debe poseer permiso de escritura en el directorio donde se encuentre el usuario, es decir en
el directorio padre del que se va a crear.
$ cd
$ cd sub
$ ls -d
fuentes textos
$ rmdir textos
$ ls -d
fuentes
$ cd ..
$ pwd
/usr/pruebas
$ rmdir sub
rmdir: sub not empty
$
En caso de que un directorio contenga algún fichero o directorio, el comando rmdir no permitirá su
borrado y nos presentará un mensaje de aviso. La eliminación de un directorio, al igual que la de un
fichero, es aceptada por el comando, si el usuario posee permiso de escritura en el mismo.
Busca a partir de los directorios especificados, los ficheros que cumplen las condiciones dadas. La lista
de directorios debe estar separada por blancos o tabuladores, y efectúa la búsqueda a partir de esos
directorios y sus subdirectorios.
Condiciones Descripción
-name <ficheros> Busca los ficheros especificados.
-type [df] d - fichero tipo directorio f - fichero totalmente lleno
-links <n> Busca ficheros con <n> enlaces.
-user <usuario> Busca los ficheros correspondientes al <usuario> especificado.
-group <grupo> Busca los ficheros correspondientes al <grupo> especificado
-size <n> Busca ficheros con tamaño de <n> bloques (xxxx bytes).
-atime <n> Busca ficheros que hace <n> días se ha efectuado un acceso a los mismos.
-mtime <n> Busca ficheros que hace <n> días se ha efectuado una modificación de los
mismos.
-print Imprime el camino de recorrido dentro del árbol de directorios del sistema.
2. Cambiar el directorio de trabajo otra vez al directorio HOME. Desde aquí, sin cambiar el directorio de
trabajo, averiguar la estructura de árbol cuya raíz está en el directorio /lib, ¿tiene subdirectorios este
directorio? Para este ejercicio utilizar la orden ls.
3. ¿Cual es la dirección relativa desde el directorio prueba1 del fichero /etc/passwd?. ¿Y la dirección
absoluta de "prueba1"?. Cambiar el directorio de trabajo a /etc y desde allí ejecutar una orden que
liste el contenido del directorio.
prueba1/dirA
prueba1/dirA/dir1
prueba1/dirA/dir21
prueba1/dirA/dir1/dirc
5. Utilizar la opción -R del comando ls para visualizarlos. Intentar borrar el directorio "dirA" sin borrar
los demás.
6. Listar los directorios, con sus contenidos, que estén por debajo de "prueba1/dirA" y que contengan
un número en la cuarta posición de su nombre, hacer esto desde el directorio "prueba1" y con una
sola orden.
7. Con el comando "cat > prueba1/texto1", introducir el texto siguiente pulsando RETURN después de
cada palabra:
Este ejercicio nos permitirá probar algunos comandos Unix para trabajar
con ficheros
8. Visualizar el contenido del fichero "texto1" con las ordenes cat y more. Probar las opciones del
comando more.
9. Hacer una copia del fichero "texto1" en el directorio "dirA" con el nombre "texto2". Cambiar de
nombre a este fichero y llamarlo "texto3". Ahora cambiarlo de dirección, colgarlo del directorio "dirc".
Al final, copiar "texto1" en "dirc" con el nombre de "texto3" utilizando la opción -i.
10. Enlazar el fichero "textoa" con el fichero "textob" en el directorio "dir21". Borrar "textoa" y
comprobar si existe el contenido de "textob". Enlazar el directorio "dir21" con un directorio por
debajo de "dirc". Comprobar que el contenido de los dos es el mismo. Probar a borrar un fichero en
uno de los dos directorios y mirar en el otro.
11. Borrar con las opciones -r é -i, el directorio "dirc". Comprobar el funcionamiento del comando paste
con los ficheros "texto1" y "textob".
12. Intentar acceder al fichero de otro usuario. Cambiar los permisos para el otro usuario pueda listar
nuestro fichero (ver si existe) pero solo esto. Ahora, cambiar los permisos para que pueda visualizar
su contenido pero que no lo pueda modificar. Finalmente, modificar los permisos para que se pueda
actualizar el fichero.
13. Buscar sobre el directorio de entrada todos los ficheros cuyo nombre este formado por la palabra
"texto" y una letra, hacer lo mismo con directorios que contengan "dir" en alguna posición.
0123456789:
32:10
0 1 2 3 4 5 6 7 8 9
1:
23a
abcdefg test
aaaa
aaa
aa
a
za
zzzzah:
paco:lámparas:10:8
juan:mesas:3:1200
santiago:tornillos:100:10
jose:baterías:1000:1
julio:libros:500:12
16. Ejecutar un comando awk para imprimir la línea del fichero que contenga el patrón "abc".
17. Determinar cuantos campos hay en cada registro del fichero "ejemplo.awk", especificando el
carácter ":" como separador de campo. (Se debe ajustar al formato siguiente: por cada línea,
imprimir el número de campos y luego la línea del fichero correspondiente). Con el mismo fichero,
determinar cuantos registros hay, especificando ":" como separador de registro. (Formato: visualizar
primero el registro y luego el número que hace).
18. Escribir un comando awk que visualice solo las líneas que contienen algún número. Y otro similar
que contenga algún carácter que no sea número. Definir otro comando que imprima las líneas
comprendidas entre "32:10" y "a", sin utilizar la variable NR ni contadores.
19. Utilizando el fichero inventario, y con ":" como separador de campo, visualizar el tercer y segundo
campo, primero con espacio en blanco entre ellos y luego sin él.
20. Utilizando un fichero de ordenes, construir un mandato awk para que después de visualizar los dos
primeros campos del fichero "inventario", muestre en otra línea, la suma de los campos tercero y
cuarto.
21. Crear un comando awk que calcule el número de palabras que hay en un fichero.
22. Hacer lo mismo que en el ejercicio 20, pero mostrando al final también la suma total de los terceros
campos, la de los cuartos y la total de los dos.
23. Igual que el ejercicio 20, añadiendo la salida al fichero "info" pero con las líneas ordenadas
alfabéticamente por el segundo campo.
Las búsquedas en el editor vi con los comandos / y ? aceptan expresiones regulares; esto hace las
búsquedas mucho más potentes y flexibles. Las expresiones regulares son aceptadas en otros editores y
en muchos comandos, si bien con algunas diferencias de sintaxis.
Una expresión regular es un patrón que describe un conjunto de cadenas de caracteres. Por ejemplo, el
patrón aba*.txt describe el conjunto de cadenas de caracteres que comienzan con la cadena aba,
contienen cualquier otro grupo de caracteres, luego un punto, y finalmente la cadena txt. El símbolo * se
interpreta como cero, uno o más caracteres cualesquiera.
Las expresiones regulares se construyen como las expresiones aritméticas, usando operadores para
combinar expresiones más pequeñas. Analizaremos esos operadores y las reglas de construcción de
expresiones regulares, atendiendo siempre al conjunto de cadenas que representa cada patrón.
9.2 METACARACTERES
La construcción de expresiones regulares depende de la asignación de significado especial a algunos
caracteres. En el patrón aba*.txt el carácter * no vale por sí mismo, como el carácter asterisco, sino que
indica un "conjunto de caracteres cualesquiera". Asimismo, el carácter ? no se interpreta como el signo
de interrogación sino que representa "un carácter cualquiera y uno solo". Estos caracteres a los que se
asigna significado especial se denominan "metacaracteres".
\^$.[]{}|()*+?
Estos caracteres, en una expresión regular, son interpretados en su significado especial y no como los
caracteres que normalmente representan. Una búsqueda que implique alguno de estos caracteres
obligará a "escaparlo" de la interpretación mediante \, como se hace para evitar la interpretación de los
metacaracteres por la shell. En una expresión regular, el carácter ? representa "un carácter cualquiera";
si escribimos \?, estamos representando el carácter ? tal cual, sin significado adicional.
Las expresiones regulares se componen de expresiones regulares elementales que se aparean con un
único carácter:
Los paréntesis rectos [] delimitan listas de caracteres individuales. Muchos metacaracteres pierden su
significado si están dentro de listas: los caracteres especiales . * [ \ valen por sí mismos dentro de [].
Para incluir un carácter ] en una lista, colocarlo al principio; para incluir un ^ colocarlo en cualquier lugar
menos al principio; para incluir un - colocarlo al final.
[:alnum:] alfanuméricos
[:alpha:] alfabéticos
[:cntrl:] de control
[:digit:] dígitos
[:graph:] gráficos
[:lower:] minúsculas
[:print:] imprimibles
[:punct:] de puntuación
[:space:] espacios
[:upper:] mayúsculas
[:xdigit:] dígitos hexadecimales
Por ejemplo, [[:alnum:]] significa [0-9A-Za-z], pero esta última expresión depende de la secuencia de
codificación ASCII local, en cambio la primera es portable, no pierde su significado bajo distintas
codificaciones locales. En los nombres de categorías, los corchetes forman parte del nombre de la
categoría, no pueden ser omitidos.
Operador Significado
c un carácter no especial concuerda consigo mismo
\c elimina significado especial de un carácter c; el \ escapa el significado especial
^ indica una ubicación al comienzo de la línea (cadena nula al principio de línea)
$ indica una ubicación al final de la línea (cadena nula al final de línea)
. (punto) un carácter individual cualquiera
[...] uno cualquiera de los caracteres ...; acepta intervalos del tipo a-z, 0-9, A-Z (lista)
[^...] un carácter distinto de ... ; acepta intervalos del tipo a-z, 0-9, A-Z
r* 0, 1 o más ocurrencias de la ER r (repetición)
r1r2 la ER r1 seguida de la ER r2 (concatenación)
En el editor vi, las expresiones regulares permiten realizar búsquedas tales como:
/^Desde
Busca líneas que empiecen con la cadena Desde
/final$
Busca líneas que termine con la cadena final
/\$25
Busca líneas que contengan $25; \ escapa el $
Operador Significado
r+ 1 o más ocurrencias de la ER r
r? 0 o una ocurrencia de la ER r, y no más
r{n} n ocurrencias de la ER r
r{n,} n o más ocurrencias de la ER r
r{,m} 0 o a lo sumo m ocurrencias de la ER r
r{n,m} n o más ocurrencias de la ER r, pero a lo sumo m
r1|r2 la ER r1 o la ER r2 (alternativa)
(r) ER anidada
"r" evita que los caracteres de la ER r sean interpretados por la shell
9.4.1 REFERENCIAS
Cuando utilizamos subexpresiones, podemos utilizar el valor encontrado correspondiente a la
subexpresión posteriormente, normalmente cuando realizamos sustituciones en cadenas de texto. Las
subexpresiones se ordenan de izquierda a derecha correspondiendo \1 a la primera subexpresión, \2 a la
segunda y así sucesivamente.
([A-Za-z]+)([0-9]+)
Entonces \1 se refiere al conjunto de letras que han verificado la expresión regular (primer paréntesis) y
\2 a una serie de dígitos.
el ^.
/g Global, hace referencia a todas las apariciones de la expresión regular. Si se omite sólo
hacemos referencia a la primera.
Las REs tienen una sintaxis independiente del contexto y representan una variedad de conjuntos de
caracteres y ordenaciones de conjuntos de caracteres. Estos conjuntos de caracteres se interpretan de
acuerdo a la localización (SAX SN) actual. Si bien muchas REs pueden ser interpretadas de manera
diferente dependiendo de la localización actual, muchas características (tales como expresiones de
clases de caracteres) se proporcionan para una invariancia contextual en configuraciones locales.
Las Expresiones Regulares Básicas (BREs ( CJX,7NTHS M,8YEMNCCJARC) son soportadas por defecto por
el comando grep. Una notación ligeramente diferente, llamada Expresiones Regulares Extendidas
(EREs 8YÓNRINI,7NTHS M,8YEMNCCJARC), están soportadas por el comando grep-E (o egrep). Lo que se va
a desarrollar a continuación se aplica tanto a BREs y EREs.
En consonancia con la totalidad de las coincidencias siendo la más larga de las mismas la más a la
izquierda, cada sub-máscara, de izquierda a derecha, debe coincidir con la cadena más larga posible.
Con este fin, una cadena nula se considera que es más larga que las que no coinciden en absoluto. Por
ejemplo, utilizando la BRE \(.*\).* contra ”abcdef”, la subexpresión (\1) es ”abcdef”, y utilizando la BRE
\(a*\)* contra ”bc”, la subexpresión (\1) es la cadena nula.
Para las BREs, los caracteres comunes, un carácter especial precedido por una barra invertida, o un
punto, corresponden con un solo carácter. Una expresión entre corchetes se corresponde con un solo
carácter o elemento a tratar.
Un carácter ordinario es un BRE que se corresponde con si mismo (es decir, cualquier carácter del juego
de caracteres soportado, a excepción de los caracteres especiales BRE que se enumeran a
continuación).
La interpretación de un carácter ordinario precedido por una barra invertida (\) es indefinida, a excepción
de los caracteres “)”, “(“, “{“, y “}”, los números del 1 al 9, y un carácter dentro de una expresión entre
corchetes.
En ciertos contextos, un carácter especial BRE tiene propiedades especiales. Las características BRE y
los contextos en los que tienen un significado especial son:
El punto (.), el corchete izquierdo ([), y la barra invertida (\) son especiales, excepto cuando se
utilizan en una expresión entre corchetes. Si una expresión contiene un corchete de apertura no
precedido por una barra invertida (y que no forma parte de una expresión entre corchetes), producirá
resultados indefinidos.
El asterisco (*) es especial, excepto cuando se utiliza en una expresión entre corchetes, como el
primer carácter de toda una BRE (después de un circunflejo, en su caso), o como el primer carácter
de una subexpresión (después de un circunflejo, en su caso).
El acento circunflejo (^) es especial cuando se usa como ancla o como el primer carácter de una
expresión con corchetes.
Si se utiliza un punto (.) fuera de una expresión con corchetes, entonces será una BRE que se
corresponde con cualquier carácter del juego de caracteres soportado, excepto NUL.
1. Una expresión entre corchetes es una lista de expresiones que coincide o no coincide. Se compone
de una o más expresiones. Estas incluyen elementos de clasificación, símbolos de clasificación,
clases de equivalencia, clases de caracteres, o un rango de expresiones. El corchete derecho (])
pierde su significado especial y representa en sí una expresión de corchetes si se produce primero
en la lista (después de un circunflejo inicial, si los hubiera).
De lo contrario, termina la expresión con corchetes a menos que aparezca como parte de un símbolo
de clasificación, clase de equivalencia, o una clase de construcción de carácter (como [.].] y [= a =]).
Los caracteres especiales punto (.), asterisco (*), corchete izquierdo ([), y la barra invertida (\)
pierden su significado especial dentro de una expresión con corchetes.
Las secuencias de caracteres [., [=, y [: son especiales dentro de una expresión con corchetes y se
utilizan para delimitar los símbolos de clasificación, las expresiones de clase de equivalencia, y los
constructores de clase de caracteres. Estas secuencias de caracteres son seguidas por una
secuencia de caracteres y por la correspondiente secuencia de terminación .], =], o :].
2. Una expresión de lista de correspondencia especifica una lista que coincida con cualquiera de las
expresiones representadas en la lista. El primer carácter de la lista no puede ser el circunflejo. Por
ejemplo, [abc] es una RE que coincide con cualquiera de los caracteres “a”', “b”', o “c”'.
3. Una expresión de lista de no correspondencia comienza con un acento circunflejo y especifica una
lista que coincide con cualquier carácter o elemento a excepción de las expresiones representadas
en la lista después del circunflejo inicial. Por ejemplo, [^ abc] es una RE que coincide con cualquier
carácter o elemento recopilado, salvo “a”', “b”', o “c”. El circunflejo tiene este significado especial sólo
cuando se produce el primero en la lista, inmediatamente después del corchete izquierdo.
6. Una clase de caracteres representa el conjunto de caracteres que pertenecen a una clase de
caracteres, tal como se define en la parte de clasificación de caracteres de la localización actual. Se
reconocen todas las clases de caracteres especificadas en la localización actual. Una expresión de
clase de caracteres puede ser expresada como un nombre de clase de caracteres encerrado entre
los delimitadores corchetes-dos puntos ([::]).
Otras clases de caracteres dependientes de la configuración regional también pueden ser reconocidas.
El punto del rango de partida y el punto del rango final es un elemento o símbolo de recopilación o
clasificación. Una expresión de clase de equivalencia que utilice como punto de partida o final una
expresión de rango, produce resultados no especificados. El punto del rango final de recopilación debe
ser igual o mayor que el punto del rango de partida o inicial, de lo contrario, la expresión se considera
como no válida. El orden utilizado es el orden en que los elementos están clasificados según se
especifica en la definición de la localización actual (SAX SN). Las asignaciones de uno-a-muchos no se
llevan a cabo. Por ejemplo, suponiendo que el carácter eszet (letra beta minúscula en griego) se coloca
en la secuencia de recopilación después de la “r” y de la “'s”, pero antes de la “t”, entonces la expresión
[r-s] se ajusta sólo a “r” y “s”, pero la expresión [s-t] coincide con “s”, letra beta minúscula en griego, o
“t”'.
No está definida la interpretación de las expresiones de rango, donde el punto del rango final es también
el punto de partida de una subsiguiente expresión de rango.
El carácter guión se trata como a sí mismo si se produce en primer lugar (después de un circunflejo
inicial, si los hubiera) o en último lugar de la lista, o como un punto de rango final en una expresión de
rango. Como ejemplos, las expresiones [ac-] y [ca-] son equivalentes y coinciden con cualquiera de los
caracteres “a”, “c” o “-“; las expresiones [\o’^’-ac] y [\o'^'ac-] son equivalentes y coinciden con cualquier
carácter excepto “a”, “c”, o “-“; [%--] coincide con cualquiera de los caracteres entre “%” y “-“ inclusive; la
expresión [--@] coincide con alguno de los caracteres entre “-“ y “@” inclusive, y la expresión [a--@] no
es válida porque la letra “a” va detrás del símbolo “-“ en la configuración regional por defecto. Para
utilizar el guión como el punto del rango de partida, o bien debe estar el primero en la expresión de
corchetes, o está especificado como un símbolo de recopilación. Por ejemplo, [][.-.]-0] coincide, bien con
el corchete derecho o con cualquier carácter o elemento de clasificación que esté entre el guión y el 0,
ambos inclusive.
2. Una subexpresión puede definirse dentro de una BRE introduciéndola entre los pares de caracteres
“\(“ y “\)”. Tal subexpresión coincide con la que resultaría sin utilizar los caracteres “\(“ y “\)”, salvo
que el anclaje en subexpresiones es un comportamiento opcional. Las subexpresiones pueden ser
arbitrariamente anidadas.
4. Cuando una BRE que coincide con un sólo carácter, con una subexpresión, o con una referencia
inversa, es seguida por el carácter especial asterisco, se ajusta con (junto con el asterisco) cero o
más apariciones consecutivas de la BRE de la que habría partido. Por ejemplo, [ab]* y [ab][ab] son
equivalentes cuando se pongan a coincidir con la cadena “ab”.
5. Cuando una BRE que coincide con un sólo carácter, con una subexpresión, o con una referencia
inversa, es seguida por una expresión de intervalo del formato \{m\}, \{m,\} o \{m,n\}, se ajusta
(junto con que la expresión de intervalo) con apariciones consecutivas repetidas de la BRE de la que
habría partido. Los valores de m y n son enteros decimales en el rango 0 MENOR O IGUAL A m
MENOR O IGUAL n MENOR O IGUAL A {RE_DUP_MAX} donde m especifica el número exacto o
mínimo de ocurrencias y n especifica el número máximo de ocurrencias. La expresión \{m\} coincide
exactamente con m ocurrencias de la BRE anterior, \{m,\} coincide al menos m ocurrencias, y
\{m,n\} coincide con cualquier número de ocurrencias entre m y n, ambos inclusive. Por ejemplo, en
la cadena “abababccccccd”, la BRE c\{3\} coincide con los caracteres del siete al nueve, la BRE
\(ab\)\{4\} no se corresponde en absoluto, y la BRE c\{1,3\}d se corresponde los caracteres del diez
al trece. Una ocurrencia de varios símbolos de duplicación adyacentes (“*” e intervalos) produce
resultados no definidos.
9.6.1.6 ANCLAJES
Una BRE puede estar limitada a cadenas coincidentes que comienzan o terminan una línea, lo que se
llama anclaje. Los caracteres especiales circunflejo y dólar se consideran anclas BRE en los siguientes
contextos:
1. Un circunflejo es un ancla cuando se usa como el primer carácter de una BRE completa. La
implementación puede tratar el circunflejo como un ancla cuando se use como el primer carácter de
una subexpresión. El circunflejo ancla la expresión (u opcionalmente, la subexpresión) al principio de
una cadena; sólo secuencias comenzando en el primer carácter de una cadena que se corresponden
con la BRE. Por ejemplo, la BRE ^ab coincide con “ab” en la cadena “abcdef”, pero no coincide en
la cadena “cdefab”. La BRE \(ab^\) puede coincidir con la cadena anterior. Una BRE portable
escapa al acento circunflejo inicial en una subexpresión para coincidir con un acento circunflejo
literal.
2. Un signo dólar es un ancla cuando se utiliza como último carácter de una BRE completa. La
implementación puede tratar un signo de dólar como ancla cuando se utiliza como último carácter de
una subexpresión. El signo dólar ancla la expresión (u opcionalmente, la subexpresión) al final de la
cadena que se está ajustando; Se puede decir que el signo dólar coincide con el "fin de cadena" tras
el último carácter.
3. Una BRE anclada, tanto por “^” como por “$”, coincide sólo con una cadena completa. Por ejemplo,
la BRE ^abcdef$ coincide con cadenas que consisten solamente de “abcdef”.
Un carácter ordinario es una ERE que coincide con si mismo. Un carácter ordinario es cualquier carácter
de juego de caracteres soportado, a excepción de los caracteres especiales ERE que se enumeran a
continuación. La interpretación de un carácter ordinario precedido por una barra invertida no está
definida.
Un carácter especial ERE tiene propiedades especiales en determinados contextos. Fuera de estos
contextos, o cuando es precedido por una barra invertida, tal carácter es una ERE que coincide con el
carácter especial en si mismo. Los caracteres especiales ERE y los contextos en los que tienen sus
significados especiales se definen a continuación:
1. El punto (.), el corchete izquierdo ([), la barra invertida (\) y el paréntesis izquierdo (() son especiales,
excepto cuando se utilizan en una expresión de corchetes. Fuera de una expresión de corchetes, un
paréntesis izquierdo inmediatamente seguido de un paréntesis derecho produce resultados no
definidos.
2. El paréntesis ()) es especial cuando se combina con un paréntesis izquierdo anterior, ambos fuera de
una expresión de corchetes.
3. El asterisco (*), el signo más (+), signo de interrogación (?), y la llave izquierda ({) son especiales,
excepto cuando se utilizan en una expresión de corchetes. Cualquiera de los siguientes usos
produce resultados no definidos:
Estos caracteres aparecen primeros en una ERE o inmediatamente después de una línea
vertical, un circunflejo, o un paréntesis izquierdo.
4. La línea vertical (|) es especial, excepto cuando se utiliza en una expresión de corchetes. Una línea
vertical que aparece primera o última en una ERE, inmediatamente después de una línea vertical o
paréntesis izquierdo, o inmediatamente antes de un paréntesis derecho produce resultados no
definidos.
5. El acento circunflejo (^) es especial cuando se usa como ancla o como el primer carácter de una
expresión con corchetes.
Un punto (.), cuando se utiliza fuera de una expresión con corchetes, es una ERE que coincide con
cualquier carácter en el conjunto de caracteres soportado, excepto NUL.
Las reglas para las expresiones ERE de corchetes son las mismas que para las expresiones RE de
corchetes.
Las reglas siguientes se utilizan para construir EREs que coincidan con varios caracteres desde ERES
que coinciden con un sólo carácter:
1. Una concatenación de EREs coincide con la concatenación de las secuencias de caracteres que
coinciden con cada componente de la ERE. Una concatenación de ERE encerrada entre paréntesis
coincide con la concatenación incluso sin la coincidencia de los paréntesis. Por ejemplo, tanto la
ERE cd como la ERE (cd) se corresponden con el carácter tercero y cuarto de la cadena
“abcdefabcdef”.
2. Cuando una ERE que coincide con un solo carácter o una ERE entre paréntesis son seguidas por el
carácter especial de signo más (+), coinciden (junto con el signo más) con una o más apariciones
consecutivas de la ERE con la que debería coincidir. Por ejemplo, la ERE b+(bc) coincide con el
cuarto al séptimo carácter de la cadena “acabbbcde”. Por otra parte, [ab]+ y [ab][ab]* son
equivalentes.
3. Cuando una ERE que coincide con un solo carácter o una ERE entre paréntesis son seguidas por el
carácter especial asterisco (*), coinciden (junto con el asterisco) con cero o más apariciones
consecutivas de la ERE con la que debería coincidir. Por ejemplo, la ERE b*c coincide con el primer
carácter de la cadena “cabbbcde”, y la ERE b*cd coincide con el tercero al séptimo carácter de la
cadena “cabbbcdebbbbbbcdbc”. Por otra parte, [ab]* y [ab][ab] son equivalentes cuando se
ajusten a la cadena “ab”.
4. Cuando una ERE que coincidan con un solo carácter o una ERE entre paréntesis son seguidas por
el carácter especial de cerrar interrogación (?), coinciden (junto con el signo de interrogación) con
cero o una ocurrencias consecutivas de la ERE con la que debería coincidir. Por ejemplo, la ERE
b?c coincide con el segundo carácter de la cadena “acabbbcde”.
5. Cuando un ERE que coincidan con un solo carácter o un ERE entre paréntesis es seguido por una
expresión intervalo del formato {m}, {m,}, o {m, n}, que coincide con (junto con la expresión de
intervalo) lo repite consecutivos las apariciones de la ERE se correspondería. Los valores de m y n
son enteros decimales en el rango de 0 MENOR O IGUAL A MENOS DE m n O MENOS IGUAL O
IGUAL A {} RE_DUP_MAX donde m especifica el número exacto ni mínimo de ocurrencias y n
especifica el número máximo de ocurrencias. La expresión {m} coincide exactamente con m
ocurrencias del ERE anterior, {m,} coincide al menos ocurrencias m, y {m, n} coincide con cualquier
número de ocurrencias entre M y N, ambos inclusive. Por ejemplo, en la cadena `` abababccccccd''el
ERE c {3} se corresponde con los caracteres del siete al nueve, y el ERE (ab) {2} se corresponde
con los caracteres del uno al seis.
6. Cuando una ERE que coincide con un sólo carácter, con una subexpresión, o con una referencia
inversa, es seguida por una expresión de intervalo del formato \{m\}, \{m,\} o \{m,n\}, se ajusta
(junto con que la expresión de intervalo) con apariciones consecutivas repetidas de la BRE de la que
habría partido. Los valores de m y n son enteros decimales en el rango 0 MENOR O IGUAL A m
MENOR O IGUAL n MENOR O IGUAL A {RE_DUP_MAX} donde m especifica el número exacto o
mínimo de ocurrencias y n especifica el número máximo de ocurrencias. La expresión \{m\} coincide
exactamente con m ocurrencias de la BRE anterior, \{m,\} coincide al menos m ocurrencias, y
\{m,n\} coincide con cualquier número de ocurrencias entre m y n, ambos inclusive. Por ejemplo, en
la cadena “abababccccccd”, la BRE c\{3\} coincide con los caracteres del siete al nueve, la BRE
\(ab\)\{4\} no se corresponde en absoluto, y la BRE c\{1,3\}d se corresponde los caracteres del diez
al trece. Una ocurrencia de varios símbolos de duplicación adyacentes (“*” e intervalos) produce
resultados no definidos.
Una ocurrencia de varios símbolos de duplicación adyacentes (+, *, ?, y los intervalos) produce
resultados no definidos.
Dos EREs separadas por el carácter especial línea vertical (|) coinciden con una cadena que se
corresponde con cualquiera. Por ejemplo, la ERE a((bc)|d) coincide con la cadena “abc” y con la cadena
“ad”. Los caracteres individuales, o expresiones coincidentes con caracteres individuales, separados por
la línea vertical y entre paréntesis, son tratados como una ERE que coincide con un solo carácter.
Una ERE puede limitarse a cadenas coincidentes que comienzan o terminan en una línea, lo que se
llama anclaje. Los caracteres especiales circunflejo y el signo del dólar con corchetes se consideran
anclajes ERE cuando se utilizan en cualquier lugar fuera de una expresión con corchetes. Esto tiene los
siguientes efectos:
Un circunflejo fuera de una expresión de corchetes ancla la (sub)expresión que comienza al principio
de la cadena. Tal (sub)expresión puede coincidir con sólo una secuencia comenzando en el primer
carácter de la cadena. Por ejemplo, las EREs ^ab y (^ab) coinciden con “ab” en la cadena “abcdef”,
pero fallan con la cadena “cdefab”, y la ERE a^b es válida, pero nunca puede coincidir ya que la “a”
evita que la expresión ^b pueda coincidir, comenzando en el primer carácter.
Un signo de dólar fuera de una expresión de corchetes ancla la (sub)expresión que termina al final
de la cadena. Tal (sub)expresión puede coincidir con sólo una secuencia finalizando en el último
carácter de la cadena. Por ejemplo, las EREs ef$ y (ef$) coinciden con “ef” en la cadena “abcdef”,
pero fallan con la cadena “cdefab”, y la ERE e$f es válida, pero nunca puede coincidir porque la “f”
impide que la expresión e$ pueda coincidir, terminando en el último carácter.
Desarrollamos un ejemplo sobre un terminal usando un fichero denominado “ejemplo” que es pasado
por al comando “egrep” con la opción que mostramos en cada caso.
En una primera aproximación sólo comprobaremos que tenemos seis dígitos separados por "/".
Máscara: [0-9]{2}\/[0-9]{2}\/[0-9]{2}
Los caracteres "/" propios del formato de fecha tienen que ir protegidos mediante la barra invertida "\"
(escape), para diferenciarlos de posibles caracteres que compongan el comando que va a utilizar la RE.
El resto de la expresión consiste en indicar que tenemos dos dígitos.
$ cat proceso
cat ejemplos
echo "--------------"
egrep "[0-9]{2}\/[0-9]{2}\/[0-9]{2}" ejemplos
$ proceso
122/12/06
121/888/105
01/01/06
1/1/06
01-02-06
1-1-06
13/12/049
12/1/0566
12/1/85
99/34/05
1/34/05
1/34/057
--------------
122/12/06
01/01/06
13/12/049
99/34/05
$
Vemos que la cadena “122/12/06” es válida, y en cambio tiene 3 dígitos antes del primer separador /.
Esto es debido a que no hemos especificado que la búsqueda comience al principio de línea, y por tanto
la subcadena “22/12/06” concuerda con la máscara. Hacemos notar que se debe utilizar el carácter
especial ^ para indicar que el análisis se efectúa desde el principio de línea, puesto que cadenas del tipo
“122/12/06” serían aceptadas por la expresión regular mostrada.
Máscara: ^[0-9]{2}\/[0-9]{2}\/[0-9]{2}
$ cat proceso
cat ejemplos
echo "--------------"
egrep "^[0-9]{2}\/[0-9]{2}\/[0-9]{2}" ejemplos
$ proceso
122/12/06
121/888/105
01/01/06
1/1/06
01-02-06
1-1-06
13/12/049
12/1/0566
12/1/85
99/34/05
1/34/05
1/34/057
--------------
01/01/06
13/12/049
99/34/05
$
Vemos que la cadena “13/12/049” es válida, y en cambio tiene 3 dígitos después del último separador /.
Esto es debido a que no hemos especificado que la búsqueda finalice al final de línea, y por tanto la
subcadena “13/12/04” concuerda con la máscara. Hacemos notar que se debe utilizar el carácter
especial $ para indicar que el análisis se efectúa hasta el final de línea, puesto que cadenas del tipo
“13/12/04” serían aceptadas por la expresión regular mostrada.
Máscara: ^[0-9]{2}\/[0-9]{2}\/[0-9]{2}$
$ cat proceso
cat ejemplos
echo "--------------"
egrep "^[0-9]{2}\/[0-9]{2}\/[0-9]{2}$" ejemplos
$ proceso
122/12/06
121/888/105
01/01/06
1/1/06
01-02-06
1-1-06
13/12/049
12/1/0566
12/1/85
99/34/05
1/34/05
1/34/057
--------------
01/01/06
99/34/05
$
Esta expresión no verificará fechas del tipo 2/3/07, ya que según la definición obligamos a tener dos
dígitos por componente. Para mejorarla exigiremos que los componentes correspondientes al día y al
mes puedan tener uno o dos dígitos:
^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2}
$ cat proceso
cat ejemplos
echo "--------------"
egrep "^[0-9]{1,2}\/[0-9]{1,22}\/[0-9]{2}$" ejemplos
$ proceso
122/12/06
121/888/105
01/01/06
1/1/06
01-02-06
1-1-06
13/12/049
12/1/0566
12/1/85
99/34/05
1/34/05
1/34/057
--------------
01/01/06
1/1/06
12/1/85
99/34/05
1/34/05
$
No obstante seguirían siendo valores de fecha aceptados del tipo “99/34/05”. Para afinar un poco más la
expresión tendríamos que exigir que el mes no pudiera ser mayor que 12 y el día no mayor que 31:
([1-9]|1[012])
Es decir, o tenemos un solo dígito que va del 1 al 9, o tenemos dos, de forma que el primero es un 1 fijo
y el segundo puede ser 0, 1 ó 2.
([1-9]|[12][0-9]|3[01])
Es decir, el día es un solo dígito del 0 al 9, o dos dígitos donde el primero es 1 ó 2 y el segundo
cualquiera entre el 0 y el 9, y por último un dígito que puede ser 3 y seguido de un 1 o un 2.
Máscara: ^([1-9]|[12][0-9]|3[01])\/([1-9]|1[012])\/[0-9]{2}
$ cat proceso
cat ejemplos
echo "--------------"
egrep "^([1-9]|[12][0-9]|3[01])\/([1-9]|1[012])\/[0-9]{2}$" ejemplos
$ proceso
122/12/06
121/888/105
01/01/06
1/1/06
01-02-06
1-1-06
13/12/049
12/1/0566
12/1/85
99/34/05
1/34/05
1/34/057
--------------
1/1/06
12/1/85
$
Por último, si quisiéramos que también fuera válida una fecha como 01/02/08, la expresión quedaría
como:
Máscara: ^(0?[1-9]|[12][0-9]|3[01])\/(0?[1-9]|1[012])\/[0-9]{2}$
$ cat proceso
cat ejemplos
echo "--------------"
egrep "^(0?[1-9]|[12][0-9]|3[01])\/(0?[1-9]|1[012])\/[0-9]{2}$" ejemplos
$ proceso
122/12/06
121/888/105
01/01/06
1/1/06
01-02-06
1-1-06
13/12/049
12/1/0566
12/1/85
99/34/05
1/34/05
1/34/057
--------------
01/01/06
1/1/06
12/1/85
$
Es decir, añadiendo "0?" estamos diciendo que el "0" puede o no estar presente.
Será una serie de caracteres alfanuméricos, un posible carácter de separación y otra serie de caracteres
alfanuméricos opcional. Con esto se verifican valores como:
aaa
aaa-bbb
aaa.bbb
aaa_bbb
aaa_bbb_ccc
Máscara: ([0-9a-zA-Z]+)([._-]([0-9a-zA-Z]+))*
Como podemos observar la cadena puede empezar por cualquier combinación de caracteres 0-9, a-z y
A-Z, y continuar con cero o más repeticiones de una cadena formada por un ., _, o – seguido por
cualquier combinación de caracteres 0-9, a-z y A-Z.
A continuación, después del literal @, el nombre del dominio que se construye de una forma similar al
nombre del usuario y al que le añadimos un dominio de nivel superior que consta de 2 a 4 caracteres.
Máscara: ([0-9a-zA-Z]+)([._-]([0-9a-zA-Z]+))*[.]([0-9a-zA-Z]){2,4}
Máscara: ^([0-9a-zA-Z]+)([._-]([0-9a-zA-Z]+))*(EN)([0-9a-zA-Z]+)([._-]([0-9a-zA-Z]+))*[.]([0-9a-zA-
Z]){2,4}$
$ cat proceso
cat mail
echo "--------------"
egrep "^([0-9a-zA-Z]+)([._-]([0-9a-zA-Z]+))*@([0-9a-zA-Z]+)([._-]([0-9a-zA-
Z]+))
*[.]([0-9a-zA-Z]){2,4}$" mail
$ proceso
luis@no.mas@net
alfredo@financix.es
tomas.net
juan@vivo.bgz
alonso.perez-lois.net
barrio.dos@bsd.es
--------------
alfredo@financix.es
juan@vivo.bgz
barrio.dos@bsd.es
$
Comando sed
/g indica edición global y afecta a todas las apariciones del texto correspondiente a la expresión regular
en el fichero. Si omitimos /g la sustitución sólo afecta a la primera aparición de cada línea. La opción /i
evita la distinción entre mayúsculas y minúsculas.
En el primer ejemplo observamos como sólo sustituye la primera "a" por la "x". En el segundo sí ha
sustituido todas las apariciones de "a" al haber añadido la opción /g.
En el último observamos el resultado esperado, sustituir una secuencia de "a" por una “x”.
En el anterior ejemplo vemos como sustituir una palabra por otra en un texto sin que afecte a las demás.
Hemos sustituido la palabra "si" por "no" sin que afecte a la palabra "asi".
Los dos ejemplos anteriores utilizan parte o todo el valor buscado en la propia sustitución. Cada
paréntesis especifica una subexpresión regular que posteriormente podremos usar en la sustitución
llamándola como \1, \2,... según el orden de los paréntesis. Entonces la parte de (.*es) corresponde con
\1 y (.*) corresponde con \2. Es decir, hemos cambiado de posición un texto. En el segundo ejemplo
vemos como el carácter "&" se utiliza en la sustitución con el valor de toda la línea.
$ ed prog1.c
? prog1.c
prog1.c
1420
main()
{
printf("hello, world\n”);
}
$ ed prog1.c
? prog1.c
a
main()
{
printf("hello, world\n”);
}
.
w
38
q
$
El signo "$" corresponde al EMAUEÓ de la CONSS, indicando que está a la espera de recibir un nuevo
comando. La línea “ed prog1.c" llama al editor "ed" para modificar el fichero "prog1.c", respondiendo
con la línea "? prog1.c" para indicar que se trata de un nuevo fichero.
La línea que contiene una "a" corresponde al comando " EENRI" (añadir) del editor, indicando que se va
a añadir texto al contenido del fichero "prog1.c". A continuación se introduce el texto hasta la aparición
de una línea con un punto “.", indicando al editor que finaliza la introducción de texto y se pasa del "modo
texto" al "modo comando", para seguir introduciendo comandos del editor.
Finalmente, se utiliza el comando "w" ("DMJÓN", escribir) para grabar en disco el contenido del fichero, y
"q" ("KHJÓ", salir) para finalizar la sesión de edición.
$ ed prog1.c
36
Indicando que "prog1.c" contiene 36 caracteres. Si tecleamos el comando del editor "1,$p", se mostrará
en pantalla el contenido de la primera (1) a la última ($) líneas del fichero.
Para modificar la tercera línea y cambiar "hello" por "hola”, procederíamos como: 3s/hello/hola/p, con lo
que el editor nos respondería con la siguiente línea:
printf("hola, world\n");
El editor "ed" se utiliza en UNIX para mantener y modificar ficheros especiales que contengan caracteres
de control (caracteres ASCII cuyo código es inferior al del carácter espacio en blanco, o ASCII 32 en
decimal), y para modificar ficheros en modo no interactivo, es decir no utilizado desde un terminal,
mediante el empleo de un fichero de comandos y órdenes del editor.
A continuación damos una descripción de los comandos y ordenes disponibles en el editor "ed:
Opción Descripción
- suprime la cuenta de caracteres de los comandos “e”, “r” y “w”.
-p cadena el "EMAUEÓ" del editor será “cadena”
-x maneja ficheros encriptados
fichero nombre del fichero a leer en el buffer del editor
A continuación damos un sumario de los comandos del editor "ed" en orden alfabético. El número de
línea por defecto se especifica como (.), a menos que sea explícita o se implique un número de línea
determinado:
Comando Descripción
(.,.)l Comando de Iistar. Lista las líneas direccionadas, y marca los caracteres no
visualizables (caracteres de control).
(.,.)m(n) Comando de mover. Mueve las líneas especificadas, a la posición después de la
línea (n).
(.,)n Comando de numeración. Lista el fichero, señalando los números de línea.
(,.)p Comando de impresión. Lista las líneas del fichero especificadas.
P Comando "EMAUEÓ". Solicita con un asterisco (*) los siguientes comandos.
q Comando "quit". Finaliza la sesión de edición, y comprueba si se han producido
cambios en el buffer desde la última ejecución del comando "w".
Q Comando "quit". Finaliza la sesión de edición, y no chequea si se han producido
cambios en el buffer desde la última ejecución del comando "w".
($)r <fichero> Comando de lectura. Coloca una copia del fichero <fichero> después de la línea
especificada.
(.,.)s/re/re1/ Comando de sustitución. Reemplaza la primera ocurrencia de "re" en las líneas,
por la cadena "re1".
(.,.)s/re/rel/g Comando de sustitución global. Realiza un cambio global de las ocurrencias de la
cadena "re", por la cadena "re1", en las líneas especificadas.
(.,.)t(n) Comando de copia. Copia las líneas especificadas después de la línea (n).
u Comando deshacer. Anula los efectos del comando mas reciente que haya
modificado el buffer.
(.,.)v/re/re1 Comando de reemplazo global. Reemplaza globalmente las líneas que no
contienen la cadena "re", por la cadena "re1".
(.,.)V/re/ Comando global interactivo que marca cada línea en la que no aparezca las
cadena "re", y acepta un comando para cada una de las líneas marcadas.
(1,$)w fichero Comando de escritura. Escribe el contenido del buffer en el fichero de nombre
<fichero>.
x Encripta el fichero.
($)= Número de línea de la línea mostrada en pantalla.
!comando shell El resto de la línea, a partir del carácter “!”, se envía al sistema operativo,
interpretándose como un comando de CONSS.
(.+1)<newline> Comando de impresión, que muestra la línea direccionada.
10.2.1 INTRODUCCIÓN
Antes de abordar en el uso del uso del editor de texto vi, es conveniente conocer la diferencia entre un
editor de texto y un procesador de texto. Un procesador de texto es un programa (paquete) informático
diseñado para la redacción de documentos que contienen texto resaltado, gráficos, figuras, ecuaciones,
tablas, etc. Como ejemplos de este tipo de procesadores se pueden citar MS WORD, Word Perfect y
LaTeX, si bien las diferencias entre ellos son considerables.
MS WORD, por ejemplo, es un procesador de texto WY SIWY G, es decir, ”DO Ó,VAH,CNN,JC,DO Ó,VAH,
TNÓ”; esto significa que lo que el usuario ve en la ventana donde está preparando el documento, es lo que
obtendrá como resultado final en el papel impreso o cualquier otro medio que sirva como destino final del
documento.
LaTeX, por su parte, es un procesador de texto basado en la compilación de un fichero fuente escrito en
texto puro que contiene códigos y secuencias propias de un lenguaje de generación de documentos.
Crear un documento con LaTeX es complicado debido a la necesidad de aprender su lenguaje y
estructuras, sin embargo su potencial y calidad es muy grande, lo que ha ocasionado que sea este el
estándar en el cual se publican una gran cantidad de revistas, libros y publicaciones científicas en
general; entre ellas, las más importantes como las de la IEEE, Addison-Wesley, etc.
Comparado con MS WORD, Word Perfect y LaTeX, vi puede parecer insignificante al ser un simple
editor de texto. Sin embargo, el potencial de vi reside en su ubicuidad y utilidad: vi es un editor que está
presente en todos los sistemas UNIX y Linux, y en ocasiones, cuando el sistema computacional no
funciona completamente, vi es el único editor disponible y se le puede utilizar para cambiar los ficheros
de configuración del sistema a fin de restaurarlo.
vi no es el único ni el más simple de los editores de texto de UNIX, sin embargo, como se dijo antes,
está disponible en todos los sistemas UNIX y el aprender a manejarlo le permitirá realizar tareas tales
como introducir, modificar o borrar texto, buscar o sustituir cadenas, y copiar, cortar y pegar bloques de
texto. Además, es configurable por el usuario.
10.2.2 GENERALIDADES
vi funciona en dos modos: modo inserción y modo instrucción. El modo inserción es el modo normal de
escritura en el cual vi actúa como una máquina de escribir donde todos los caracteres que se teclean se
introducen como parte del documento (fichero), mientras que en el modo instrucción (XAUU RI) los
caracteres o teclas presionadas se interpretan como órdenes o directivas del editor que permiten borrar,
copiar, salir, sustituir, buscar, mover el apuntador (cursor), etc.
El texto creado o editado por vi se manipula creando o modificando ficheros, respectivamente. Cuando
se desea modificar un fichero (texto) existente se llama al fichero correspondiente a fin de que el editor
cargue una copia de este en la sesión de edición. Ya sea que se esté creando o modificando un texto
existente, el editor mantiene el texto que está manipulando en un área de almacenamiento llamada
memoria intermedia (BH66NM). Así, los cambios efectuados no se registran en el fichero hasta que se
decida explícitamente guardar el texto, es decir, el contenido de la memoria intermedia. Se puede
guardar el texto cuantas veces se desee y no es necesario salir del editor para hacerlo.
Se dice que el editor vi es interactivo porque interacciona con el usuario mostrándole mensajes de
estado y error. La última línea de la ventana (pantalla) del editor se llama línea de estado y sirve para
este propósito. Por otra parte, la posición del apuntador (cursor) siempre indica su situación actual en la
memoria intermedia y algunas de las órdenes que se introducen afectan el carácter que se encuentra en
dicha posición. Naturalmente, vi tiene varias órdenes para mover el apuntador (cursor) por la memoria
intermedia (ventana o pantalla).
10.2.3 ENTRANDO EN VI
Para iniciar vi simplemente se escribe su nombre en la línea de órdenes del intérprete. Si se sabe el
nombre del archivo que se quiere crear o editar se puede lanzar este programa usando como argumento
el nombre de dicho fichero. Por ejemplo: vi <nombre del fichero>.
Cuando se inicia vi la pantalla de la terminal se borra y aparece el contenido del fichero a editar. En el
caso de que se trate de un fichero nuevo, o de que no se haya dado nombre alguno, en la primera
columna de todas las líneas visibles de la pantalla, exceptuando la primera, se presenta el carácter tilde
˜. Este carácter es el indicador de línea de memoria intermedia vacía.
Tanto <i> como <a> tienen como efecto que el editor conmute del modo instrucción al modo inserción;
para salir del modo inserción hay que presionar la tecla <Esc>. Es importante señalar que en el modo
inserción todas las teclas presionadas se consideran parte del texto a introducir, es decir, en este modo
de operación no se pueden manipular ninguna de las teclas de posicionamiento del apuntador (cursor),
avance de página, etc. La única excepción es la tecla <BackSpace>, la cual tiene como función borrar el
carácter de pantalla inmediatamente anterior a la posición del apuntador.
Una importante variación de <i> y <a> son <I> y <A>, respectivamente. Si estando en el modo
instrucción se presiona la tecla <I> el editor se posicionará al comienzo de la línea actual para permitir la
inserción de texto en ese lugar, mientras que si se presiona <A> el indicador (cursor) se desplazará al
final de la línea actual para agregar texto a continuación.
Para introducir una nueva línea de texto debajo o encima de la línea actual se presionan las teclas <o> y
<O> respectivamente. Cada una de ellas abre una nueva línea en la memoria intermedia que permitirá
agregar nuevo texto en la posición correspondiente.
Sin embargo, en un sistema que no esté adecuadamente configurado para vi, puede ocurrir que estas
teclas introduzcan caracteres extraños. Para subsanar esto, existen otras teclas diferentes a las flechas
que le permiten desplazar el apuntador por el texto, y que conviene conocer. Debido a que cuando se
desarrollo vi muchos teclados no disponían de las teclas de flecha, se usaban y se usan las teclas <h>,
<j>, <k> y <l>; <h> y <l> se usan para desplazar el apuntador un carácter hacia la izquierda y derecha,
respectivamente, mientras que <j> y <k> se usan para mover el apuntador una línea abajo y arriba,
respectivamente.
Existen otras órdenes en vi que permiten mover el apuntador en relación a las palabras de una línea.
Una palabra es para vi una secuencia de caracteres separada de otras por espacios o símbolos tales
como la coma, punto y coma, corchetes, paréntesis, llaves, etc. Estas instrucciones son:
Tanto con las tres órdenes anteriores como con las instrucciones <h>, <j>, <k> y <l> es posible
anteponer un número al carácter de tal manera que por ejemplo <3w> ocasionará que el indicador
(cursor) avance 3 palabras a la derecha.
Existen otras órdenes que permiten realizar grandes desplazamientos del apuntador sobre el texto; en
cada uno de estos casos aparece el cursor al principio de la línea destino. Por ejemplo:
<M> coloca el apuntador en la línea que se encuentra en medio de la ventana actual de texto.
Si se desea desplazarse por el fichero de ventana en ventana se pueden utilizar las teclas <Ctrl-f> para
ir una ventana adelante y <Ctrl-b> para ir una ventana atrás. Si se desea ir rápidamente a la última línea
del fichero (memoria intermedia) se puede presionar la combinación de teclas <G> y, en general, para ir
a cualquier línea de la memoria intermedia se puede introducir el número de línea antes de presionar
<G>. Por ejemplo, para ir directamente a la primera línea del fichero se presiona <1G>.
10.2.6 BÚSQUEDA DE TEXTO
vi, como casi todos los editores de texto, dispone de órdenes para buscar cadenas de texto. La
búsqueda se puede realizar hacia adelante o hacia atrás desde la posición actual del apuntador (cursor)
y se puede continuar buscando incluso cuando ya se ha llegado al inicio o al final del texto. Las órdenes
para la búsqueda de texto en vi son:
Cuando se utiliza una de estas instrucciones de búsqueda, la orden aparece escrita en la línea de
estado. Si la cadena se encuentra en la memoria intermedia el indicador se posiciona al comienzo de
dicha cadena, en caso contrario el editor muestra en la línea de estado el mensaje “i ÓÓNMR,RAÓ,6AHRI”.
<cw>y <ce> Sustituye los caracteres de la palabra actual, desde la posición del cursor hasta el final
de la palabra.
<cb> Cambia la palabra actual, desde el comienzo de la misma hasta el carácter anterior a la
posición del apuntador (cursor).
<c$> y <C> Cambia una línea desde la posición del apuntador (cursor) hasta el final de la línea.
En todos los casos, excepto con la orden de reemplazo <r>, es necesario presionar <Esc> para volver al
modo instrucción una vez completada la sustitución.
<dw> Borra los caracteres desde la posición actual del indicador hasta el principio de la siguiente
palabra.
<d$> Suprime los caracteres desde la posición actual del cursor hasta el final de la línea.
<dd> Borra la línea actual por completo independientemente de la posición del cursor.
Algunas de las órdenes de supresión anteriores se pueden utilizar con varios caracteres, palabras o
líneas. Por ejemplo:
Las órdenes explícitas para copiar texto a la memoria genérica son las siguientes:
<yw> Copia desde la posición actual del indicador hasta el delimitador final de la palabra.
<y$> y <Y> Copian desde la posición actual del cursor hasta el final de la línea.
A algunas de las órdenes anteriores se puede anteponer un número para copiar una cierta cantidad de
palabras o líneas.
:w Esta opción es útil cuando se ha iniciado la sesión de vi usando un nombre de fichero; es decir,
se inició la sesión escribiendo vi nombre de fichero. En este caso el contenido de la memoria
intermedia se almacena en un fichero que tiene el nombre del fichero de entrada.
:w <nombre de fichero> Esta opción se usa cuando se inició la sesión de vi sin proporcionar un
fichero de entrada y se hace necesario dar un nombre de fichero de almacenamiento en disco. Esta
opción también se puede usar cuando se ha iniciado vi dando un fichero de entrada pero se desea
guardar el texto en un fichero con otro nombre.
:w! <nombre de fichero existente> En algunas ocasiones, al usar la opción :w nombre de fichero
del apartado anterior puede ocurrir que ya exista un fichero con el nombre que se desea utilizar para
el fichero que se está editando, en cuyo caso el editor despliega en la línea de estado un mensaje:
Este es un mensaje preventivo para que no se sobrescriba el fichero existente, sin embargo, si
realmente es esto lo que se desea hacer, hay que usar la orden :w! nombre de fichero existente
10.2.13 SALIDA DE VI
Se puede salir del editor de texto vi de varias formas, recordando que para hacerlo hay que estar en el
modo instrucción habiendo presionado la tecla <Esc>. Las varias formas de salir de vi son:
:q Esta opción se usa cuando no se han hecho cambios en el fichero editado o bien cuando los
cambios realizados han sido almacenados en un fichero. En caso contrario el editor mostraría un
mensaje preventivo y nos impediría salir.
:q! Esta opción se usa cuando se desea abandonar el editor aun cuando se hayan hecho cambios
en la memoria intermedia y estos cambios no se hayan registrado en un fichero. En este caso se
pierden todas las modificaciones realizadas desde la última vez que se almacenó el texto en un
fichero.
showmode o smd: Cuando se activa se presenta un mensaje en la línea de estado que indica en
que modo se encuentra el editor en cada momento.
number o nu: Cuando se activa se numeran las líneas de texto del documento.
autoindent o ai: Cuando se activa las nuevas líneas de texto que se generan se alinean con la
anterior.
showmatch o sm: Activando este parámetro se resalta el paréntesis abierto que corresponde al
paréntesis cerrado que se introduce en el texto.
wrapmargin o wm: Con esta opción se puede fijar el número de caracteres desde el margen
derecho con los cuales el editor rompe la línea actual introduciendo un retorno de carro.
Una posibilidad para evitar el trabajo de configurar vi para cada sesión es mediante el uso de un fichero
de configuración. El fichero particular que sirve para configurar vi se llama .exrc y debe estar localizado
en el directorio de inicio del usuario ($HOME). El contenido de este fichero son órdenes del tipo set
como las que se introducen en la línea de estado, con la particularidad de que no deben ir precedidas de
los dos puntos :.
Mas aun, el texto enviado a la salida estándar como consecuencia de la orden se puede integrar al
documento que se está editando mediante la sintaxis :r!<orden>; el texto se insertaría en la línea que
sigue a la posición actual del apuntador (cursor). La sintaxis :r <fichero> se puede utilizar para integrar
el contenido de <fichero> en la línea siguiente a la posición actual del apuntador (cursor) en el
documento que se está editando.
vi [-t <tag>] [-r] [+<comando>] [-l] [-w<n>] [-x] [-R] <nombres de ficheros>
Opción Descripción
-t <tag> Posiciona el editor en el identificador <tag>.
-r Recupera la última versión salvada del fichero de nombre especificado.
+<comando> Ejecuta el comando de "ex" <comando>, antes de comenzar la edición.
-l Activa las opciones "showmatch" y "lisp", para la edición LISP.
-w<n> Cambia el tamaño por defecto de la ventana de pantalla a <n> líneas.
-x Edita ficheros encriptados.
-R Utiliza únicamente el modo de lectura.
<nombres de ficheros> uno o mas nombres de ficheros (admite "DJSI,X MIC")
A continuación damos una lista de los comandos del editor “vi”. Cada comando de la lista está agrupado
de acuerdo con su función de edición, y ordenados alfabéticamente.
Los comandos "ex" pueden ser ejecutados en el editor “vi”, precediendo el comando con el carácter ":”.
Todos las comandos precedidos de la palabra clave CTRL digitados mediante la tecla <CTRL> o
<CONTROL> del teclado, que debe preceder al carácter indicado del comando.
Comando Descripción
, Mueve el cursor hasta la posición del primer carácter no blanco.
; repite el último carácter simple de búsqueda utilizado por los comandos f, F, t y
T.
$ Mueve el cursor hasta el final de la línea en curso.
% Mueve el cursor a los paréntesis (), llaves {} o corchetes [] que preceden o
siguen a los paréntesis, llaves o corchetes mas cerca de la posición actual del
cursor.
( Retrocede hasta el comienzo de una sentencia. Una sentencia finaliza con <.>,
<!> o <?>, seguido por un fin de línea (newline), o dos espacios en blanco. Las
sentencias también comienzan con párrafos y secciones.
) Avanza hasta el comienzo de una sentencia.
{ Retrocede al comienzo del párrafo anterior. Un párrafo comienza con cada
"macro" dentro del texto (.IP - .LP - .PP - .QP - .bp). Un párrafo también
comienza después de cada línea en blanco, y al final de cada sección.
} avanza hasta el comienzo del siguiente párrafo
[[ Retrocede hasta la sección anterior. Una sección comienza con cada macro
(.NH – .SH), y también en líneas que comienzan con un "formfeed" (salto de
página). Las líneas que comienzan con "{" también son localizadas por este
comando.
]] Avanza hasta la siguiente sección.
Comando Descripción
. Repite el último comando.
Comando Descripción
"nomaqic".
map <t> <sec> Asocia la tecla <t> a la secuencia de órdenes <sec>. Al pulsar <t> se genera la
secuencia de órdenes.
number Las líneas son visualizadas precedidas con su número de línea. La opción por defecto
es "nonu".
paragraphs Nombres de macros para comenzar los párrafos. Por defecto: “para"=IPLPPPQPbpP LI
redraw Simula un terminal inteligente (smart). Por defecto es "nore".
sections Nombre de macros para comenzar las secciones. Por defecto: "sect"=NHSHH HU.
shiftwidth cambia la distancia de los desplazamientos de los comandos “<” y “>” Por defecto es
"sw" = 8
showmatch Muestra las relaciones de <(> y <{>, como <)> y <}>. Por defecto es "nosm".
slowopen Pospone la visualización de las modificaciones durante las inserciones de texto. Por
defecto es “slow”.
term Especifica el tipo de terminal que se está utilizando.
wrapscan Busca el final del buffer si no se encuentra ninguna cadena en una búsqueda. Por
defecto es “ws”.
umap <t> Elimina el mapeo de la tecla <t> previamente definida
una <ab> Elimina la abreviatura <ab> definida previamente
Esta es una sesión de praticas sobre el uso del editor vi. Necesittamos
Algunas líneas más para apreender los mandatos mas usuales del editor.
Ahora estamos en el modo de introducción de textoluego vamos a pasar al
modo de mandatos (de de repetidas).
a000
a111
a222
a333
a444
a555
a666
a777
a888
a999
c000
c111
c222
c333
c444
c555
c666
c777
c888
c999
4. Insertar, sin dejar espacio, después del texto "pasar al modo mandatos.", la frase "También
haremos prácticas en modo ejecución.".
8. Recorrer el texto desde el final al comienzo saltando de comienzo de palabra a comienzo de palabra.
¿Cual es el comando para situar el cursor al final de la línea?, ¿y al final de todo el texto?
9. Borrar "c444". Borrar "c777" y "c888" con un solo comando. Con mandatos de sustitución cambiar
"c666" y "c999" por la serie "d000" a "d555". ¿Como se borraría, con un solo comando, desde la
línea "c555" al final del documento, sin saber cuantas líneas son?
11. Escribir las diez primeras líneas del fichero en otro fichero llamado "10.líneas".
12. Ir a la última línea del fichero, y en la mitad de esa pantalla añadir el texto "texto añadido por
petición del ejercicio 3", en una línea nueva.
13. Escribir el fichero sin salir de la sesión vi. Cargar el fichero "10.líneas" en el buffer "c". Copiar el
contenido del buffer "c" al final del fichero.
14. Cambiar solo la primera ocurrencia en cada línea de la palabra "de" por la palabra "DE". Probar a
deshacer esta sustitución.
15. Buscar todas las palabras que tengan una "s" seguida de vocal.
16. Sin salir de la sesión vi, visualizar que usuarios activos hay en el sistema.
17. Cambiar el formato de la sesión vi, para que numere las líneas. Listar todas las opciones de cambio
del entorno de trabajo del editor vi.
18. Crear una abreviatura, por ejemplo cambiar "es" por "ESTO ES UN CAMBIO ABREV". Probar con
los siguientes casos:
¿Que ocurre con las palabras "es" que estaban ya tecleadas?
¿Que ocurre cuando no se deja espacio en blanco después de "es"?
El núcleo básico de UNIX consistía, en sus orígenes, en unas 10000 líneas de código “C” y unas 1000 de
código ensamblador. El código ensamblador puede dividirse en unas 200 líneas incluidas por motivos de
eficiencia (que podrían haber sido escritas en C) y 800 líneas para ejecutar funciones hardware que no
son posibles realizar en C. Este código representa del 5 al 10 por ciento de lo que implica la extensa
expresión "Sistema Operativa UNIX".
El núcleo es el único código de UNIX que no puede ser sustituido por un usuario a su antojo. Cómo se
implementa el núcleo representa una gran responsabilidad y un gran poder. Todas las decisiones
importantes fueron ponderadas cuidadosamente. En todas partes la simplicidad ha sido complementada
con la eficiencia. Se utilizan algoritmos complejos únicamente si su complejidad puede ser localizada.
$ kill 0
$ ps
El comando ps muestra el número de identificación (PID) de todos los procesos activos del terminal. Por
ejemplo:
$ ps
PID TTY TIME CMD
3589 tty03 00:15 sh
3591 tty03 00:31 cc prog1.c –o prog1
3593 tty03 00:32 ps
$ kill 3591
El comando ps (EMAXNCC,CÓ ÓHC o estado de procesos) se emplea para visualizar la información sobre los
procesos activos:
ps [-alx] lista-nombres
Opción Descripción
a Muestra todos los procesos asociados con un terminal.
l Formato extendido.
x Muestra todos los procesos no asociados con un terminal.
Indicador Descripción
F Flags asociados con los procesos. Valores de 01, 02, 04, 10 y 20.
S Estado de los procesos
O no existente
S procesos durmientes (sleeping)
W esperando
R ejecutando
I intermedio
Z terminado
T parado
UID ID del usuario propietario del proceso
PID El número del ID del proceso.
PPID El número del ID para los procesos padres.
CPU Utilización del proceso para CXONIHSJRT.
PRI Prioridad de los procesos. Números altos son prioridades bajas.
NICE Número usado en computación de prioridad.
ADDR Si reside en memoria, la dirección del núcleo. En otro caso, la dirección del disco.
WCHAN El suceso por el que el proceso está esperando o durmiendo. Si es un blanco, el proceso
está en ejecución.
TTY El terminal en el que se ejecutan los procesos.
TIME El tiempo transcurrido de ejecución de los procesos.
Los EJENC se usan principalmente para pasar información entre programas, con el símbolo de la CONSS (|),
en el que la salida de un programa es la entrada de otro. Esto elimina la necesidad de crear ficheros
temporales para pasar información a otros programas.
La librería estándar posee varias funciones de gestión de EJENC. Las funciones popen y pclose controlan
a ambos, un EJEN y un proceso. La función popen abre un EJEN y crea un nuevo proceso a la vez. La
función pclose cierra el EJEN y espera la terminación de los procesos correspondientes. La función EJEN,
por otro lado, da acceso a bajo nivel a un EJEN.
Donde comando es un puntero a una cadena de caracteres que contiene un comando CONSS, y tipo es un
puntero a una cadena que define si el EJEN va a ser abierto para lectura "r" o escritura "w". Esta función
normalmente devolverá el puntero al EJEN abierto y NULL si se encuentra un error. Veamos un ejemplo:
FILE *pstrm;
pstrm = popen ("cat > response", "w");
pclose(apuntador);
Donde apuntador es un puntero al fichero del EJEN a cerrar, devuelto por la función previa de popen.
Veamos un ejemplo:
FILE *pstrm;
pclose(pstrM);
pipe(fd);
Donde fd es un puntero a una matriz de dos elementos de tipo entero. Cada elemento recibe un
descriptor de fichero, el primero para lectura y el segundo para escritura. La función normalmente
devuelve 0, y -1 si se encuentra algún error. Veamos un ejemplo:
int chan[2];
if (pipe(chan) == -1)
exit(2);
Textop(Fójop=pEódóio)
t tosp(xststócospyptónsmócos)
tóreccóones
Oórtu les
olputólóz d s
La memoria FISICA esta dividida en paginas de tamaño variable según la máquina y la versión de SO
(de 512 bytes a varios Kbytes). La asociación de una dirección virtual a una física se realiza mediante
tablas de páginas. Otro aspecto interesante de este mecanismo es que para ejecutar un programa, no es
necesario haberlo cargado en su totalidad en memoria.
La zona de datos y pila (CÓ XL) tienen la posibilidad de crecer. La pila cambia según las diferentes
llamadas a las funciones (parámetros y variables automáticas). Los datos se dividen en una zona de
tamaño fijo (variables estáticas y externas conocidas desde la compilación), y una zona dinámica
(variables según la petición de reserva dinámica por parte del proceso).
eól pdónsmóc
Ilustración 13 Memoria y breakpoints
12 CONTROL DE PROCESOS
12.1 INTRODUCCIÓN
Este capítulo introduce algunos comandos de ayuda para ver y controlar los procesos corriendo en el
sistema. También introduce algunos comandos para automatizar tareas repetitivas.
12.2.1 EL COMANDO ps
Usar el comando ps para listar los procesos que están corriendo actualmente en el sistema. Muchas
veces se necesita un número de proceso PID para usar el comando kill (analizado en la sección
siguiente).
ps [ -opciones]
Opción Descripción
-e Presenta información de todos los procesos del sistema.
-f Genera una lista completa. (Remítase a las páginas del man para ver la descripción de
las cabeceras que se presentan.)
-a Imprime información sobre todos los procesos más solicitados: todos, excepto los líderes
período de sesiones y los procesos no asociados con un terminal.
-A Imprimir información sobre todos los procesos.
-c Imprimir la información en un formato que refleja las propiedades del planificador
(CXONIHSNM), tal y como se describe en priocntl(1). La opción -c afecta a la salida de las
opciones -f y -l, como se describe a continuación.
-C Imprimir el CPU-ID de grupo para cada proceso. Si un proceso está limitado a un
determinado grupo de CPU (ver cg_bind (2)), se imprime b junto con el ID del CPU-
Group.
-d Imprimir información sobre todos los procesos, excepto los líderes sesión.
-e Permite imprimir información sobre todos los procesos ya en marcha.
-f Generar un listado completo.
-g grplist Lista únicamente procesos cuyo número de identificación de grupo líder aparezca en
grplist. (Un líder del grupo es un proceso cuyo número de identificación de proceso es
idéntico al número de ID de su grupo de procesos.
- G grplist Lista datos de procesos cuyo verdadero número de identificación de grupo aparece en
grplist.
-j Imprimir identificador de sesión y el ID de grupo de procesos.
-l Generar un listado largo.
-L Imprimir el estado de procesos LWPs dentro de un proceso.
Señales
Si ejecutamos el comando kill -l, se obtiene una lista de todas las señales que puede reconocer el
comando.
Terminar un proceso
# kill 433
Los usuarios sólo pueden terminar los procesos de los que son propietarios, si bien el súper usuario
puede terminar cualquier proceso en el sistema.
Los procesos o programas ejecutables pueden recibir una gran cantidad de señales producidas por
diferentes eventos que pueden ocurrir en el sistema.
Las señales se identifican por un número entero positivo, reconocible tanto por el sistema, como por el
comando kill o los programas en lenguaje C. Además, en lenguaje C existen unos nemotécnicos para
referirse a las señales; y el comando kill reconocer otra serie de nemotécnicos para definir las señales.
Cada una de las señales tiene una acción por defecto al recibir el evento que ha producido la señal, es
decir, cuando se recibe la señal, el proceso actúa de una determinada forma. Las formas que tiene un
proceso de actuar ante un evento son:
Salir o terminar el proceso. Los de tipo XAMN (producidas por el núcleo) siempre finalizan el proceso
por defecto.
Ignorar la señal
Detener proceso
En la siguiente tabla se muestran las señales del sistema, con información (columna a columna) del
siguiente tipo:
Nombre Lenguaje C
Descripción
nice ejecuta el comando con una prioridad de planificación de la CPU más baja. El comando priocntl es
una interfaz de comandos más general para funciones de planificación.
El proceso invocado (generalmente una shell del usuario) debe estar en la clase de planificación de
tiempo compartido. El comando se ejecuta en la clase de tiempo compartido.
El usuario con privilegios adecuados pueden ejecutar comandos con prioridad más alta de la normal
mediante un incremento negativo, por ejemplo, --10.
El comando nice devuelve como valor de retorno el estado de salida del comando.
nohup ejecuta un comando ignorando el bloqueo y el cierre. Si la salida no es re-dirigida por el usuario,
tanto la salida estándar, como el error estándar, se envían a nohup.out. Si nohup.out no se puede
escribir en el directorio actual, la salida se redirige a $HOME/nohup.out.
Ejemplos
Con frecuencia es conveniente que se apliquen nohup a tuberías o listas de comandos. Esto sólo puede
hacerse mediante la colocación de las tuberías y las listas de comandos en un solo archivo, llamado
procedimiento de shell. Se puede ejecutar: nohup sh fichero, y el nohup se aplica a todo en el archivo.
12.3.1 EL COMANDO at
El comando at ejecuta un comando o script en un momento determinado. El comando sólo se ejecuta
una vez, a diferencia de las entradas en el fichero crontab, que se ejecutan una y otra vez en el día y
hora especificados. El fichero crontab se estudia más adelante.
Opción Descripción
-m Envía correo al usuario una vez que el trabajo ha terminado.
-r Borra un trabajo específico previamente programado.
tiempo La hora puede ponerse de varias formas, incluyendo h, hh y hh:mm. Se supondrá
que se trata de un reloj de 24 horas a no ser que se añada am o pm como sufijo a
tiempo.
fecha Se puede especificar una fecha opcional o bien el mes seguido del día o bien el
día de la semana.
El archivo /etc/cron.d/at.deny identifica los usuarios que no pueden usar el comando at.
Ejecutar el comando at
1.- Especificar la hora y el comando para listar el índice de las páginas del comando man.
$ at 8:45PM
at>catman –w
at><Presione Control-d aquí>
job 458102210.a at Wed Dec 10 20:45:00 1994
$ atq
Rank Execution Date Owner Job Queue Job Name
1stDec 10, 1994 20:45 rimmer 730010700.a astdin
$ at -r 458102210.a
crontab -l
#ident "@(#)root 1.14 97/03/31 SMI" /* SVr4.O 1.1.3.1 */
#
# The root crontab should be used to perform accounting data collection.
#
# The rtc command is run to adjust the real time clock if and when
# daylight savings time changes.
#
10 3 * * 0,4 /etc/cron.d/logchecker
10 3 * * 0 /usr/1ib/newsyslog
15 3 * * 0 /usr/lib/fs/nfs/nfsfind
1 2 * * * [-x /usr/sbin/rtc] && /usr/sbin/rtc -c > /dev/null 2>&1
/etc/cron.d/logchecker
Determina si el archivo de SAT de cron /var/cron/log ha excedido el tamaño máximo de fichero y, si
es así, copia los contenidos al archivo /var/cron/olog.
/usr/lib/newsyslog
Limpia el directorio /var/adm de archivos SAT generados por el demonio CVCSAT.
/etc/cron.d/cron.allow
/etc/cron.d/cron.deny
Acceso al usuario
Si existe el archivo cron.allow, sólo los usuarios listados en el archivo pueden usar el comando.
Si ese archivo no existe, crontab comprueba el archivo cron.deny para determinar si al usuario se
le debe prohibir ejecutar crontab.
Si no existe ninguno de los dos, sólo el súper usuario puede ejecutar crontab.
Por defecto, el archivo cron.deny prohíbe el uso de crontab a los siguientes usuarios del sistema:
daemon
bin
smtp
nuucp
listen
nobody
noaccess
/var/spool/cron/crontabs/nombre_usuario
Solamente el súper usuario puede leer o editar el archivo crontab de otro usuario. El archivo crontab del
súper usuario es:
/var/spool/cron/crontabs/root
10 3 * * 0 /usr/lib/newsyslog
Formato Descripción
n Concuerda si el valor del campo es n.
n,p,q Concuerda si el valor del campo es n, p, o q.
n-p Concuerda si el valor del campo está entre n y p inclusive.
* Siempre concuerda.
1.- Defina la variable EDITOR para decirle a cron qué editor usar.
$ EDITOR=vi
$ export EDITOR
$ crontab -e
20 15 * * 5 /usr/bin/banner "TIME TO GO!" > /dev/console
0 0 * * * /usr/bin/tar cvf /dev/rmt/0 /export/home/ricky
:wq
$ crontab -l
20 15 * * 5 /usr/bin/banner "TIME TO GO!" > /dev/console
0 0 * * * /usr/bin/tar cvf /dev/rmt/0 /export/home/ricky
Atención - Si por error escribe crontab sin ningún argumento, use el carácter de interrupción
(normalmente Control-c) para salir. No intente salir escribiendo el carácter EOF (generalmente Control-
d). Esto eliminaría todas las entradas en su archivo crontab.
2. Hacer este ejercicio junto con otro usuario. Usar el comando su para cambiarse al identificador de
entrada al sistema del otro usuario. Usar el comando id para ver el cambio.
3. Visualizar que procesos están asociados al terminal y al usuario. ¿Cuáles son los procesos padres
de ellos?. Abrir ahora varias CONSS hijas y ejecutar el comando "sleep 2000 &", ¿qué procesos,
ejecutándose actualmente, son del usuario?
4. Visualizar todos los procesos activos en el sistema. Dejar los procesos igual a como estaban al
principio.
5. Ejecutar el comando "sleep 2000 &". Salir del sistema, volver a entrar e intentar visualizar el proceso
sleep. Hacer que la ejecución de ese comando no finalice cuando se salga del sistema, y
comprobarlo.
6. Ejecutar de nuevo la orden "sleep 2000 &", comprobar que se está ejecutando en modo B XLTMAHRI.
Hacer que se ejecute en interactivo, y de nuevo hacer que vuelva a modo B XLTMAHRI, por fin
cancelar el proceso. Probar a ejecutar en B XLTMAHRI un comando con salida por pantalla, y
comparar su ejecución con el modo interactivo.
7. Ejecutar los comandos siguientes y observar la diferencia, "date; pwd; banner hola &" y "(date;
pwd; banner hello) &".
8. Ordenar el fichero /etc/passwd según el tercer campo. Observar el resultado. Ordenar por el mismo
campo pero con ordenación sea numérica. ¿Hay alguna diferencia? ¿Por que?
9. Listar los usuarios que su nombre comience por "s" y en alguna posición contengan una "a".
Construir una orden que muestre el número de nombres de usuario que no contengan una "s".
10. Construir un EJENSJRN para visualizar la lista ordenada de todos los ficheros y directorios por debajo
del directorio de entrada, con un formato de tres columnas sin cabeceras ni pies de página.
11. Construir un EJENSJRN para obtener un listado paginado de los propietarios que tengan algún proceso
que se esté ejecutando actualmente en el sistema, cada usuario solo debe aparecer una sola vez.
12. ¿Cuantos ficheros ordinarios existen en el directorio de entrada? Construir un EJENSJRN que lo
muestre. Utilizar el comando tee para guardar los nombres de los ficheros en otro fichero llamado
"fichnames". Modificar de nuevo la orden para que en vez de almacenarlos en el fichero, aparezcan
por pantalla sin perder el número de ellos.
La seguridad de ficheros y datos proporciona otro nivel de seguridad además de las contraseñas para
entrar en cuentas de usuario.
Este capítulo ofrece también información sobre usuarios y grupos con poderes especiales, así como
consejos que orientan a los usuarios a no abusar de dichos poderes.
Asegurarse de que todas las cuentas de usuario están protegidas por una contraseña.
El cambio regular de las contraseñas de usuario redunda en un incremento de la seguridad del sistema.
Una manera de asegurarse que los usuarios cambian regularmente su contraseña es usar la
característica de password aging (caducidad de las contraseñas).
13.3.1 UIDS
Los UIDs autentifican los procedimientos de entrada (SATJR) e identifican la propiedad de ficheros y
directorios. Estos números se encuentran en el archivo /etc/passwd.
Los UIDs entre 0 y 99 se reservan para cuentas especiales, las cuales se usan para dar acceso
exclusivo a ficheros a ciertos servicios del sistema, tales como el demonio del servicio de impresión lp.
13.3.2 GIDS
Los GIDs identifican la pertenencia de usuarios, ficheros y directorios a grupos. Un usuario puede
pertenecer a 16 grupos - 1 primario y 15 secundarios.
Los GIDs del 0 al 99 están reservados para cuentas especiales usadas por el sistema, tales como las
cuentas de usuario bin, other, y staff. Los GIDs reservados también se usan para dar acceso exclusivo
a grupos a ciertos ficheros.
13.3.3 EL COMANDO ID
Use el comando id para conocer su UID, nombre de usuario, ID del grupo y nombre de grupo.
Esta información puede ser de ayuda para resolver problemas cuando no pueda acceder a un archivo
que cree que le pertenece.
id [ options ]
$ id
uid=10450 (usua1) gid=150 (general)
$ id -a
uid=10450 (usua1) gid=150 (general) groups=150 (general), 14(sysadmin)
Use el comando id -a para identificar el nombre e ID del usuario y todos los grupos a los que el usuario
pertenece.
Esta cuenta se utiliza solamente para realizar tareas específicas de administración del sistema, entre las
que se incluyen las siguientes:
Apagar el equipo.
Monitorizar y proteger la cuenta de MAAÓ forma parte del trabajo del administrador del sistema. Este es el
aspecto más crucial en el mantenimiento de la seguridad del sistema.
La cuenta de MAAÓ sólo debe ser usada para realizar las tareas de administración del sistema; evite el
trabajo rutinario como súper usuario. Esto ayuda a proteger el sistema frente accesos no autorizados, ya
que reduce la probabilidad de que el sistema quede desatendido con la cuenta de MAAÓ abierta.
Cuando no hay miembros en el grupo sysadmin, sólo el súper usuario puede usar la utilidad admintool.
Una vez que obtenga el grado de súper usuario, el EMAUEÓ de la CONSS pasa a ser la almohadilla (#),
indicándole que tiene acceso extra al sistema. Puede seguir el rastro de quién está usando la cuenta de
MAAÓ en el archivo /var/adm/sulog, que se graba cada vez que se usa el comando su.
$ su
Password:
Para salir del grado de súper usuario, escriba exit y presione Return.
Esta opción del guión hace cambiar el entorno al que se adoptaría si el usuario entrara como tal
realmente. El comando su - provoca la ejecución del profile del sistema (/etc/profile) y luego el EMA6JSN
del usuario en cuestión ($HOME/ .profile).
En el EMAUEÓ de la CONSS, escriba su con el guión (-), el nombre del usuario que quiere adoptar, y
pulse Return.
$ su – andres
Password:
Compruebe su UID actual, nombre de usuario, GID y nombre del grupo escribiendo id.
$ id
uid=1000(andres) gid=10(referen)
$ exit
El comando chown se usa para cambiar la propiedad de ficheros y directorios, pero sólo el usuario
propietario o el súper usuario pueden usarlo.
# ls -l memo
-rw-r--r-- 1 rimmer other 0 Jul 6 18:30 memo
# chown chris memo
# ls -l memo
-rw-r--r-- 1 chris other 0 Jul 6 18:30 memo
# cd /export/home
# chown -R chris mydocs
Por ejemplo, como administrador del sistema, puede tener ficheros de inicialización de usuarios
genéricos que cede a cada nuevo usuario. Después de ponerlos en el directorio del nuevo usuario, debe
cambiarle la propiedad.
El comando chgrp sólo puede utilizarlo el súper usuario o el propietario del fichero (el propietario debe
pertenecer al nuevo grupo).
$ groups
engine tecnico
$ groups base
clases propio
Use el comando groups para ver los miembros pertenecientes al grupo. Usado con un argumento, este
comando muestra los distintos grupos a los que el usuario pertenece.
En este ejemplo, rimmer ha entrado remotamente, como muestra el nombre del sistema (nepal) que
aparece entre paréntesis. El usuario lister ha entrado localmente.
Dispositivos de entrada
El segundo campo que aparece en la salida del comando who, identifica el dispositivo mediante el cual
ha entrado el usuario, pudiendo ser:
Dispositivo Descripción
console Una consola es un dispositivo de pantalla en el que se visualiza el arranque del
sistema y los mensajes de error.
pts pts es un seudo dispositivo que representa una entrada al sistema o una sesión
de ventana sin un dispositivo físico. Así se representan las entradas remotas.
term Un dispositivo terminal de Código estándar Americano para Intercambio de
información ASCII) se representa por term. Un terminal ASCII es un dispositivo
de entrada/salida que presenta una sola línea cada vez.
El comando last muestra primero las entradas más recientes. Cada entrada incluye nombre de usuario,
dispositivo, sistema desde el que entró, hora y fecha de entrada y salida, y el tiempo total en horas y
minutos. También se muestran las horas de arranque del sistema.
$ last
rimmer pts/4 pluto Fri Dec 18 10:24 - 11:00 (00:36)
lister pts/4 pluto Tue Dec 8 09:39 - 09:49 (00:10)
rimmer pts/4 pluto Thu Dec 3 15:16 - 15:17 (00:00)
rimmer console :0 Wed Dec 2 08:47 still logged in
reboot system boot Wed Dec 2 08:44
rimmer pts/0 pluto Tue Dec 1 17:27 - 17:28 (00:00)
rimmer pts/3 pluto Tue Dec 1 16:13 - 16:39 (00:26)
rimmer pts/2 pluto Tue Dec 1 15:32 - 15:38 (00:06)
holly term/a pluto Tue Dec 1 15:12 - 08:41 (17:29)
root console Tue Dec 1 15:12 - 15:12 (00:00)
loginID:x:UID:GID:comentario:home-directory:login-shell
Campo Descripción
loginlD. También llamado username, este campo representa el nombre que usa el usuario para
entrar al sistema y debería ser único. El campo está restringido a 8 caracteres de longitud y sólo la
primera letra puede ser mayúscula.
UID. Este campo contiene el número de identificación del usuario (UID) que usa el sistema operativo
para identificar al usuario. Los números UID para usuarios generalmente van del 100 al 60000. Los
valores del 0 al 99 están reservados para cuentas del sistema. El UID 60001 está reservado para la
cuenta nobody. El UID 60002 está reservado para la cuenta noaccess. Duplicar UIDs está
permitido, pero debe evitarse en la medida de lo posible. Si dos usuarios tienen el mismo UID,
ambos tendrán acceso a los ficheros que cada uno cree. La cuenta nobody se usa para cuestiones
de seguridad de recursos NFS. Cuando un usuario está en un cliente NFS como súper usuario e
intenta acceder a recursos de fichero remotos, el UID cambia de 0 al UID de nobody (60001);
nobody obtiene los mismos permisos de acceso que los que se definen para todo el mundo.
GID. Este campo contiene el número de identificación del grupo y le sirve al sistema para identificar
el grupo primario de cada usuario. Los números GID generalmente van desde el 100 al 60000 (del 0
al 99 son los reservados).
Comentario. Campo de comentario para almacenar, normalmente, el nombre completo del usuario.
Históricamente se le conoce como gcos-field.
home-directory. Este campo contiene la ruta completa del directorio OAUN del usuario.
login-shell. En este campo se define la CONSS de entrada por defecto para el usuario, que puede ser
/bin/sh, /bin/csh, o /bin/ksh.
lister:x:901:410:Dave Lister:/export/home/lister:/bin/sh
Una x en el campo E CCDAMI de la base de datos /etc/passwd significa que existe una contraseña en el
fichero /etc/shadow Sólo el súper usuario puede acceder a /etc/shadow, donde se guarda la
información relativa a las contraseñas.
Sólo el súper usuario puede leer o modificar el fichero /etc/shadow, pero éste no debería editarse nunca
directamente, sino servirse del admintool para modificarlo.
Hágase súper usuario y edite el archivo /etc/shadow. Este archivo consta de entradas de línea en línea
en las que los dos puntos sirven para delimitar los campos. A continuación vemos un archivo parecido:
root:LXeokt/C/oXtw:6445::::::
daemon:NP:6445::::::
bin:NP:6445::::::
sys:NP:6445::::::
adm:NP:6445::::::
lp:NP:6445::::::
smtp:NP:6445::::::
uucp:NP:6445::::::
nuucp:NP:6445::::::
listen:*LK*::::::
nobody:NP:6445::::::
noaccess:NP:6445::::::
lister:ubQhZXEMv/lyI:8532::::::
loginID:clave:ult_cambio:min:max:aviso:inactivo:expiración
Campo Descripción
IoginID. También llamado username, este campo contiene el nombre de entrada del usuario.
clave (password). Este campo puede contener a su vez las siguientes entradas: una contraseña
encriptada de 13 caracteres; la secuencia *LK*, que indica que la cuenta es inaccesible; o la
secuencia NP, que indica que no tiene contraseña.
ult_cambio. Este campo indica el número de días transcurridos entre el 1 de enero de 1970 y la
fecha de la última modificación.
min. Este campo contiene el número mínimo de días que tienen que transcurrir entre cambios.
max. Contiene el máximo número de días que la contraseña es válida antes de que se le requiera al
usuario especificar una nueva.
aviso. En este campo se especifica el número de días antes de la caducidad de la contraseña que el
usuario es advertido de la misma.
inactivo. En este campo se especifica el número de días inactivos permitidos antes de bloquearse la
cuenta.
expiración. Este campo contiene la fecha en que caduca la cuenta. A partir de ese día, el usuario no
podrá utilizarla.
Mientras cada registro passwd especifica tanto el número UID como el nombre de usuario, tan sólo
especifica el GID del grupo, no el nombre del mismo. La correspondencia entre el GID y el nombre del
grupo se establece mediante la base de datos /etc/group.
nombre-grupo:clave:GID:lista-usuarios
Campo Descripción
nombre-grupo. Este campo contiene el nombre del grupo, que puede tener hasta ocho caracteres.
lista-usuarios. Se trata de la lista de usuarios, separados por comas, que tienen a ese grupo como
grupo secundario.
$ cat /etc/group
root::0:root
other::l:
bin::2:root,bin,daemon
sys::3:root,bin,sys,adm
adm::4:root,adm,daemon
uucp::5:root,uucp
mail::6:root
tty::7:root,tty,adm
lp::8:root,lp,adm
nuucp::9:root,nuucp
staff::l0:
daemon::l2:root,daemon
sysadmin::l4:
nobody::60001:
noaccess::60002:
# cd /etc/default
# ls
cron fs init login passwd su tar
Los archivos login, passwd y su están relacionados con la seguridad del sistema.
El fichero login, entre otras cosas, ayuda a restringir el acceso como súper usuario.
En el archivo su se graban todos los intentos de los usuarios de realizar un cambio de usuario.
# cat passwd
# ident "@(#)passwd.dfl 1.3 92/07/14 SMI"
MAXWEEKS=
MINWEEKS=
PASSLENGTH=6
La variable MAXWEEKS
El valor de la variable MAXWEEKS es el máximo número de semanas (semanas de 7 días) que pueden
transcurrir antes del cambio de contraseña de todos los usuarios normales. Sí se define como nulo
(como está por defecto), sólo los usuarios que tienen asignado un valor para MAX especificado en el
archivo /etc/shadow deben cambiar sus contraseñas cuando les corresponda.
La variable MINWEEKS
El valor de la variable MINWEEKS especifica el número mínimo de días que han de transcurrir entre
cambios de contraseña para los usuarios normales. Si está definido nulo, sólo tendrán que hacerlo los
usuarios que tengan un valor para MIN especificado en el archivo /etc/shadow
La variable PASSLENGTH
El propósito de la variable PASSLENGTH es especificar una longitud mínima de contraseña para todos
los usuarios normales.
La variable PASSREQ
Si la variable PASSREQ está definida como YES, (que es el valor por defecto), a los usuarios a los que
no se les asignaron contraseñas cuando se crearon sus cuentas, se les requiere que elijan una
contraseña la primera vez que entren al sistema. En caso contrario, se permiten contraseñas nulas.
La variable CONSOLE
La variable CONSOLE sirve para especificar tres condiciones para las entradas del súper usuario:
Si la variable está definida como /dev/console, entrar al sistema como súper usuario sólo se permite
desde la consola.
# rlogin sydney
Not on system console
Connection closed.
Si la variable no está definida, se permite la entrada como súper usuario desde cualquier otro punto,
a través de la red, de un módem o de un terminal conectado.
Si la variable está definida como nula (CONSOLE=), no se permite entrar como súper usuario. En
este caso, la única manera de hacerse con los privilegios del súper usuario es entrar como un
usuario normal y entonces hacerse súper usuario con el comando su.
La variable SULOG
El valor de la variable SULOG especifica el nombre del fichero donde se graban todos los intentos de
cambiar de usuario. Si no está definido, no se grabará ningún intento.
La variable CONSOLE
Por defecto, esta variable se ignora comentándola con el signo # al principio de la línea. De todas
formas, todos los intentos de cambio de usuario aparecen en la consola independientemente de si tuvo
éxito o no.
Feb 2 09:50:09 mars su: 'su root' failed for ken on /dev/pts/4
Feb 2 09:50:33 mars su: 'su bob' succeeded for ken on /dev/pts/4
Feb 2 09:50:51 mars su: 'su root' succeeded for ken on /dev/pts/4
Si el valor de la variable CONSOLE se define como /dev/console (sin el signo de comentario), todos los
intentos de hacerse súper usuario que tengan éxito se presentan en la consola con el mensaje sulog.
Los intentos sin éxito se controlarán como en el caso anterior.
Feb 2 11:20:07 mars su: 'su root' succeeded for ken on /dev/pts/4
SU 02/02 11:20 + pts/4 ken-root
Nota - Todos los ficheros del sistema son sólo de lectura. Para hacer cambios con el vi, necesita escribir
:wq! para grabar los cambios y salir.
# more /var/adm/sulog
SU 10/20 14:50 + console root-sys
SU 10/20 16:55 + pts/2 lister-root
SU 10/20 17:00 + pts/2 lister-root
SU 10/21 11:02 + pts/2 lister-root
SU 10/21 12:01 + pts/3 lister-root
SU 10/24 13:43 + pts/3 lister-root
SU 10/24 13:49 + console root-sys
SU 10/28 08:14 + pts/3 lister-root
SU 10/28 08:18 + console root-sys
SU l1/05 11:21 + pts/3 rimmer-root
SU 12/01 08:56 + pts/1 rimmer-root
Campo Descripción
SU El primer campo presenta el comando su.
10 /20 El segundo y tercer campo presentan la fecha y hora.
+o- El cuarto campo presenta un signo + ó - , según si el comando tuvo éxito o no,
respectivamente.
console El quinto campo muestra cuál es el dispositivo.
root-sys El sexto campo da el nombre del usuario y el del usuario que ha suplantado su identidad.
14 PERMISOS DE FICHEROS
14.1 INTRODUCCIÓN
Este capítulo describe los conceptos y los conocimientos necesarios para administrar las características
básicas de seguridad para proteger ficheros y directorios.
$ umask
022
El valor de umask se establece con un valor octal de tres dígitos. Cada dígito representa los permisos
que se deniegan, por defecto, cuando se crean ficheros y directorios. El primer dígito determina los
permisos por defecto para el usuario, el segundo los del grupo y el tercero los permisos para otros (el
resto de usuarios).
Para un directorio, la máscara por defecto (umask) 022, otorga todos los permisos al propietario, y le da
permiso de ejecución y lectura para el grupo y el resto.
Para un fichero, la máscara por defecto (umask) 022, otorga permisos de lectura y escritura para el
propietario y permiso de lectura para el resto. La máscara inicial 022 se establece con umask en el
fichero /etc/profile.
Una máscara más segura que 022 podría ser 027, que quita todos los permisos al resto de los usuarios.
Los administradores de sistema no pueden forzar a los usuarios a utilizar un determinado valor de
umask, pero pueden advertir a los usuarios para que refuercen la seguridad.
Modo Acción
4000 Ajustar ID de usuario en ejecución.
20#0 Ajustar ID de grupo en ejecución si # es 7, 5, 3, o 1. Activar el bloqueo obligatorio si # es 6,
4, 2, ó 0. Este bit se ignora si el archivo es un directorio, solamente se puede activar o
desactivar usando el modo simbólico.
1000 Activa el CÓJXLV,BJÓ.
0400 Permitir lectura por el propietario.
Modo Acción
0200 Permitir escritura para el propietario.
0100 Permitir ejecutar (búsqueda en el directorio) por el propietario.
0070 Permitir lectura, escritura y ejecución (de búsqueda) por grupo.
0007 Permitir lectura, escritura y ejecución (de búsqueda) por otros.
$ umask 022
$ umask 027
$ umask
027
El nuevo valor de umask se perderá cuando abandone el sistema, excepto si lo establece también en el
fichero .profile.
$ vi .profile
# e(#)local.profile 1.4 93/09/15 SMI
#
stty istrip
PATH=.:/usr/bin:/usr/ucb:/etc
export PATH
umask 027
#
# If possible, start the windows system
#
Salga del sistema y entre de nuevo para activar el cambio, o escriba el comando:
$ . ./.profile
Opciones
m [ask) : perms La máscara de ACL. La máscara indica los máximos permisos permitidos
para los usuarios (que no sean el propietario) y para los grupos. La máscara
es un camino rápido para cambiar los permisos de todos los usuarios y
grupos.
u [ser] :uid:perms Permisos para un usuario específico.
g[roup] :gid:perms Permisos para un grupo específico.
Vamos a ampliar la tabla anterior para detallar las máscaras posibles de las opciones -m y -s.
Para las opciones -m y -s, entradas_acl son una o más entradas ACL separadas por comas. Para la
opción –f, el fichero fichero_acl debe contener entradas ACL, una por línea. Las entradas por defecto
sólo se pueden especificar para los directorios.
u[ser]::operm | perm
u[ser]:uid:operm | perm
g[roup]::operm | perm
g[roup]:gid:operm | perm
c[lass]:operm | perm
o[ther]:operm | perm
d[efault]:u[ser]::operm | perm
d[efault]:u[ser]:uid:operm | perm
d[efault]:g[roup]::operm | perm
d[efault]:g[roup]:gid:operm | perm
d[efault]:c[lass]:operm | perm
d[efault]:o[ther]:operm | perm
Para la opción -d, entradas_acl son una o más entradas ACL separadas por comas sin permisos,
seleccionados de la siguiente lista.
NOTA: Las entradas para el propietario del fichero, grupo propietario y otros no se pueden eliminar.
u[ser]:uid
g[roup]:gid
d[efault]:u[ser]:
d[efault]:u[ser]:uid
d[efault]:g[roup]:
d[efault]:g[roup]:gid
d[efault]:c[lass]:
d[efault]:o[ther]:
perm
Es una cadena de permisos integrada por los caracteres “r” (lectura), “w” (escritura), y “x”
(ejecución). El carácter “-“ puede ser especificado como un marcador de posición.
operm
Es la representación octal de los permisos anteriores, con 7 representan todos los permisos, o rwx, y
0 representa ningún permiso, o ---.
UID
gid
Revisar si un fichero tiene una ACL usando el comando ls. Un signo (+) a la derecha del campo de los
modos indica que el fichero tiene una ACL.
$ ls -l ch3.doc
-rwxr-----+ 1 william sysadmin 163 Nov 11 11:12 ch3.doc
Opciones
Opción Descripción
-a Muestra el nombre del fichero, propietario, grupo, y las entradas de ACL para el
fichero específico o directorio.
-d Muestra el nombre del fichero, propietario, grupo y las entradas por defecto del
ACL para el directorio específico.
Si especifica varios nombres de ficheros en la línea de comando, las entradas del ACL hay que
separarlas por una línea en blanco.
$ getacl chl.txt
# file: chl.txt
# owner: William
# group: sysadmin
user::rw-
user:ssa20:rw- #effective:r--
group::r-- #effective:r--
mask:r--
other:---
Nota - Los permisos del usuario específico ssa20 son rw-. De cualquier forma, como la máscara por
defecto umask (022) no ha sido reiniciada todavía con la opción mask del comando setacl, los permisos
efectivos para el usuario ssa20 son todavía de lectura-escritura.
$ ls -1 total 124
-rw-r-----+1 william sysadmin 34816 Nov 12 14:15 chl.txt
$ getacl chl.txt
# file:chl.txt
# owner: William
# group: sysadmin
user::rw-
user:ssa20:rw- #effective:rw-
group::r-- #effective:r--
mask:rw-
other:---
Nota - La opción mask del comando setacl ha sido definida con los permisos efectivos rw- para el
usuario ssa20.
Programas ejecutables
Si un programa posee permiso setuid, cualquiera que posea permiso para ejecutar el programa será
tratado como si fuera el propietario del programa.
Si el programa tiene el permiso setgid, cualquiera que tenga permiso para ejecutar el programa será
tratado como si perteneciera al grupo del programa.
Los ficheros ejecutables con permisos setuid o setgid, obtienen sus UIDs o GIDs del propietario o
grupos del fichero del programa, en lugar de incorporar sus propios UIDs y GIDs desde los procesos
(normalmente una CONSS) que los han lanzado. Esto se utiliza cuando un programa debe acceder a
ficheros que normalmente solo son accesibles al propietario o grupo propietario del programa.
El fichero ejecutable define la interacción con el fichero (o ficheros) que son modificados.
Directorios
Los directorios que tienen permiso setgid propagan su GID a los ficheros que se crean por debajo de él.
Los bits setuid y setgid se muestran como la letra "s" en el campo de ejecución para el propietario y el
grupo.
$ ls -1 /bin/passwd /etc/shadow
-r-sr-sr-x 1 root sys 22208 Mar 27 06:21 /bin/passwd
-r-------- 1 root sys 529 May 26 09:57 /etc/shadow
Estos permisos permiten al usuario cambiar ciertos campos en el fichero /etc/shadow cuando usan el
comando passwd. Si la "S" aparece en mayúsculas, indica que el permiso de ejecución no está
activado.
Los permisos setuid y setgid se activan con el comando chmod. La notación numérica requiere de
cuatro números para definir los permisos setuid o setgid y se utiliza el primer dígito para ello.
4 = setuid
2 = setgid
1 = sticky bit
El bit setgid en un directorio debe ser definido o cambiado usando la notación simbólica.
Esto previene que los usuarios borren ficheros de otros usuarios en directorios públicos como /var/tmp.
El sticky bit se muestra como la letra "'t" en el campo de ejecución perteneciente a otros. (Una "T"
indicaría que el permiso de ejecución esta desactivado.)
$ ls -ld /var/tmp
drwxrwxrwt 2 sys sys 512 May 26 11:02 /var/tmp
Activación del permiso Sticky
Busca entre las descripciones cortas de las páginas del manual la presencia de la palabra clave.
Opción Descipción
-r interpreta cada nombre como una expresión regular
-w interpreta cada nombre como conteniendo caracteres comodines
Opción Descripción
a añade nuevos ficheros tras el nombre “postnombre”
b añade nuevos ficheros antes del nombre “postnombre”
c suprime el mensaje al crear el fichero de archivo
l sitúa los ficheros temporales en el directorio local
u reemplaza únicamente ficheros cuya fecha de modificación sea superior a la que
tiene el fichero en el archivo.
V (verbose) amplia la información dada por otras opciones
d Borra ficheros del archivo
m mueve ficheros hasta el final del archivo
p lista los nombre de los ficheros en el archivo
q añade (rápidamente) ficheros al final del archivo
r reemplaza ficheros en archivo
s fuerza la regeneración de la tabla de símbolos del archivo
t lista la tabla de contenido del archivo
x extrae ficheros del archivo.
postnombre nombre del fichero de posicionamiento. Usualmente empleado con a, b, i, r, y m
nombre_archivo nombre del fichero de archivo
fichero uno o mas ficheros con los que se va a trabajar en el archivo.
Opción Descripción
trabajo fichero ejecutable. Comando a ejecutar o fichero que empleará la "shell" para su
ejecución
Tiempo[APNM] especifica la hora y minuto donde A indica AM, P indica PM, N indica tarde, y M
indica medianoche
día se refiere tanto a un nombre de mes seguido por un número de día u opcionalmente
un día de la semana
+ incremento incremento de factor de tiempo "incremento”
-r numero borra trabajo (numero) a efectuar
-l numero lista trabajo (número) a efectuar
Muestra el mensaje (cadena de caracteres) en letras grandes y girado 90°; para imprimir carteles.
Opciones Descipción
-w N en un ancho de N columnas
Opción Descripción
cadena indica cadena de caracteres a buscar.
sufijo indica sufijo (terminación) a eliminar del nombre
Opción Descripción
-c opción de compilación (solamente)
-l carga de la librería matemática de precisión arbitraria
archivo uno o más nombres de ficheros
Opción Descripción
archivo1 primer nombre de fichero
archivo2 segundo nombre de fichero
-n compara solamente un número de líneas.
-s suprime diagnósticos
Opción Descripción
mes número de dos dígitos correspondiente al mes
año número de cuatro dígitos correspondiente al año
Opción Descripción
-e pone el carácter $ al final de la línea cuando se emplea con la opción -v
-n numera las líneas
-s omite mensajes de error sobre ficheros no existentes
-t pone el carácter ^I como tabulador cuando se emplea con conjuntamente con la opción -v
Opción Descripción
-u causa que la salida sea sin buffer (carácter a carácter)
-v hace que se muestren los caracteres no imprimibles
fichero uno o más nombres de ficheros
Opción Descripción
-Bcadena construye nombres de ficheros para sustituir las fases del preprocesador,
compilador, ensamblador y link-editor
-c suprime la fase de link-edición
-g genera información para el "sdb" (simbolic debugger)
-f genera objetos con aritmética de coma flotante, versión 2.x
-E ejecuta solamente cpp sobre los programas indicados.
-O(ks) optimiza el código objeto
K optimizaciones dependientes del kernel.
S optimiza el empleo del stack (pila)
-o salida nombre del módulo de salida link-editado
-P ejecuta solo el preprocesador, con salida sobre el fichero de sufijo .i
-p monitoriza la ejecución (profile)
-S produce la salida en lenguaje ensamblador sobre un fichero con sufijo .s
-t[p012al] utiliza solamente el preprocesador, compilador, ensamblador, y link:-editor
correspondientes a los nombres de ficheros construidos con la opción -B.
-v muestra el nombre de cada subproceso que se ejecuta.
-wc,arg1[,arg2...] elimina los argumentos de paso c pertenecientes al conjunto p012al
fichero uno o mas nombres de ficheros fuentes en lenguaje “C”
Opción Descripción
directorio nombre del nuevo directorio de trabajo; por defecto es el valor de la variable de "shell"
HOME
Opción Descripción
modo absoluto (absmode)
4000 pone identificador de usuario en ejecución.
2000 pone identificador de grupo en ejecución.
1000 activa sticky bit. Guarda texto en memoria después de ejecución (en versiones antiguas)
0400 permite lectura por el propietario.
0200 permite escritura por el propietario
0100 permite ejecución por el propietario.
0070 lectura, escritura y ejecución por grupo.
0007 lectura, escritura y ejecución por restantes
modo simbólico [quien] op permiso [op permiso]
quien
u usuario
g grupo
o otros
op
+ añade permiso
Opción Descripción
- quita permiso
= asignar permiso absoluto
permisos
r lectura
w escritura
x ejecución
s pone identificador de usuario o grupo en ejecución
t guarda texto del programa
fichero fichero(s) a cambiar
Opción Descripción
propietario indica el número (decimal) del usuario, o el nombre de login.
grupo indica el número (decimal) del grupo, o un nombre de grupo correspondiente al fichero
de grupos.
fichero uno o mas ficheros a cambiar el propietario o grupo especificados.
Opción Descripción
-l muestra el número y los bytes que difieren.
-s no muestra las diferencias, solamente retorna código de error.
fichero1 nombre del primer fichero
fichero2 nombre del segundo fichero
Opción Descripción
-1 suprime líneas sólo del fichero1.
-2 suprime líneas solo del fichero2.
-3 suprime líneas de ambos ficheros.
fichero1 nombre del primer fichero.
fichero2 nombre del segundo fichero.
Opción Descripción
fichero1 fichero origen
fichero2 fichero origen
destino fichero de destino, o nombre de directorio
-f no se solicitan preguntas
Extrae partes de cada línea de los archivos indicados o de la entrada estándar. Los campos y columnas
se indican con números 1, 2,... o con intervalos n-m. Intervalos incompletos: -n es 1-n, m- es m hasta el
último campo o columna.
Opción Descripción
-f campos numerados, por defecto separados por TAB
-c columnas, ubicación posicional de caracteres en la línea
-d fija el carácter delimitador de campos, TAB por defecto
-s para no imprimir líneas que no contengan el delimitador
Opción Descripción
yy dos dígitos del año
mm dos dígitos del mes
dd dos dígitos del día
hh dos dígitos de la hora del día
mm dos dígitos del minuto de la hora
ss dos dígitos del segundo del minuto.
+formato formato de salida controlable por el usuario.
n inserta un carácter de salto de línea.
c inserta un carácter de tabulación.
D fecha en formato mm/dd/yy
H hora; de 00 a 23
M minuto; de 00 a 59
S segundo; de 00 a 59
T hora en formato HH:MM:SS
j día del año; 001 a 366
w día de la semana - Domingo = 0
a día de la semana abreviado - "Sun" a "Sat"
n mes abreviado - "Jan" a "Dic"
r hora en formato AM/PM
Copia un archivo, de la entrada estándar a salida estándar por defecto, opcionalmente cambiando el
tamaño de bloques de entrada / salida y realizando diversas conversiones.
Opción Descipción
if=ARCHIVO Leer la entrada del archivo indicado.
of=ARCHIVO Dirigir la salida al archivo indicado.
ibs=BYTES Leer la entrada en bloques de BYTES bytes.
obs=BYTES Grabar la salida en bloques de BYTES bytes.
bs=BYTES Leer y grabar entrada y salida en bloques.
conv=CONVERSION[,CONVERSION]... Convertir según argumentos.
Las opciones numéricas admiten los multiplicadores b para 512, y k para 1024.
Argumento Conversión
ascii Convierte EBCDIC a ASCII.
ebcdic Convierte ASCII a EBCDIC.
ibm Convierte ASCII a EBCDIC alternativo.
block Agrupa cada línea de entrada en 'cbs' bytes, reemplaza nueva línea por espacio,
rellena con espacios.
unblock Reemplaza espacios finales de cada bloque con nueva línea.
lcase Convierte mayúsculas a minúsculas
ucase Convierte minúsculas a mayúsculas.
notrunc No truncar el archivo de salida.
Opción Descripción
-e genera un fichero de comandos del editor "ed", para hacer el fichero2 a partir del fichero1
-f produce un texto similar a la opción -e, no utilizable con el editor "ed". Es el caso opuesto
-b ignora los blancos posteriores (trailing blanks)
-h detecta diferencias en forma rápida, pero no tan efectiva
fichero1 nombre del primer fichero.
fichero2 nombre del segundo fichero.
Opción Descripción
-a proporciona una entrada por cada fichero de disco, mostrando los bloques utilizados por el
fichero.
-r suministra información acerca de los directorios que no pueden ser leídos, ficheros que no
pueden ser abiertos, etc.
-s muestra sólo las estadísticas totales.
fichero nombres de ficheros o directorio
Opción Descripción
arg información a mostrar en el terminal
Opción Descripción
- el "environment" actual es ignorado. El comando es ejecutado con el "environment"
especificado por "args"
nombre= valor inicializa la variable de "shell" <nombre> al valor especificado <valor>.
comando comando que se va a ejecutar
args argumentos que van a modificar al “environment”
Produce la salida de la shell con estado de terminación N (número); si no se indica retorna con 0.
Opción Descripción
arg uno o mas argumentos para ser evaluados como expresiones
Expresión Descripción
x1 /| x2 devuelve x1 si es distinto de nulo o 0, sino devuelve x2.
x1 /& x2 devuelve x1 si x1 o x2 (no ambos a la vez) son distintos de nulo o 0, sino devuelve 0.
x1 /< x2 compara si x1 es menor que x2, devolviendo 1 si es cierto, y 0 si es falso.
x1 /<= x2 compara si x1 es menar o igual que x2, devolviendo 1 si es cierto, y 0 si es falso.
x1 = x2 compara si x1 y x2 son iguales. Devuelve 1 si es cierto, y 0 si es falso.
x1 != x2 compara si x1 es distinto de x2. Devuelve 1 si es cierto, y 0 si es falso
x1 /> x2 compara si x1 es mayor que x2, devolviendo 1 si es cierto, y 0 si es falso.
x1 <= x2 compara si x1 es menor o igual que x2, devolviendo 1 si es cierto, y 0 si es falso.
x1 + x2 suma x1 a x2.
x1 - x2 resta x2 a x1.
x1 * x2 multiplica x1 por x2
x1 / x2 divide x1 por x2
x1 % x2 devuelve el valor de x1 resto módulo x2
Opción Descripción
-f ffile "ffile" contiene los nombres de ficheros a examinar.
-m mfile Utiliza "mfile" como fichero "mágico" o alternativo.
-c chequea el fichero "mágico" para errores de formato, y suprime el tecleo de ficheros
ficheros uno o mas ficheros a examinar
Opción Descripción
pathname-list uno o mas nombres de directorios
expresión busca por la máscara especificada, donde n es un entero, +n es mayor que n, y -n
es menor que n.
Expresión Descripción
-atime n cierto si el fichero ha sido accedido en los últimos n días.
-ctime n cierto si el fichero ha sido cambiado en los último n días
-exec comando cierto si el código de retorno del comando "comando" es 0
(expresión) cierto si la expresión entre paréntesis “()" es cierta
-group gname cierto si el fichero pertenece al grupo gname
-links n cierto si el fichero posee n enlaces (links).
-mtime n cierto si el fichero ha sido modificado en n días.
-name filename cierto si el nombre de fichero coincide con “filename".
-ok comando igual que el comando exec, pero se ejecuta solo tras recibir conformidad por parte
del usuario.
-newer filename cierto si el fichero "filename" fue modificado antes que el fichero encontrado
-perm onum cierto si coinciden los permisos del fichero, con los especificados en "onum" (octal)
-print muestra el nombre completo del fichero encontrado
-size n [c] cierto si el fichero ocupa n bloques. "c" especifica que el tamaño está en caracteres.
-type x cierto si el fichero tiene el tipo x, donde x puede ser una b para un fichero especial
organizado en modo bloques, c para un fichero especial organizado en modo
carácter, d para un directorio y f para un fichero normal.
-user nombre cierto si el fichero pertenece al usuario "nombre"
-depth siempre cierto. Actúa en las entradas de directorios, antes de hacerlo en el directorio
Opción Descripción
-v muestra todas las líneas, excepto aquellas que coinciden con las máscara
-x muestra solo las líneas que coinciden en su totalidad con la máscara (fgrep)
-c muestra un contador de las líneas iguales
-i ignora el tipo de letra (mayúscula – minúscula) en las búsquedas
-l lista nombres de ficheros con líneas iguales
Opción Descripción
-n precede cada línea con su número de línea dentro del fichero
-b precede cada línea con el número de bloque en el que ha sido encontrada
-s suprime mensajes de error para ficheros no existentes, o imposibles de leer (grep)
-e expresión permite expresiones comenzando con - (egrep, fgrep)
-f fichero toma la expresión regular (egrep), o lista de strings (fgrep) del fichero "fichero"
limexpr busca la máscara especificada. Debe ser una expresión regular limitada, en el estilo de
las del comando ed.
regexpr busca por la expresión regular especificada
strings busca la cadena "strings" especificada
ficheros ficheros donde se va a efectuar la búsqueda
Opción Descripción
-contador muestra el número "contador" de líneas
fichero uno o mas nombres de ficheros
Sin argumentos, da el nombre de la máquina; con NOMBRE, fija el nombre de la máquina (su).
Opción Descripción
-h ayuda
-f --fqdn nombre de máquina completo, con dominio DNS
-d --domain nombre de dominio DNS
-i --ip-address dirección (número IP)
-a --alias nombres de alias
-v modo verbose
Muestra información sobre un usuario. Muestra nombre, UID, grupo, GID y grupos suplementarios. Si el
id real y el efectivo no corresponden muestra ambos. Las opciones limitan el despliegue.
Opción Descipción
-g sólo el grupo primario
-G grupos suplementarios
-n nombre en lugar de número; requiere -u, -g, o -G
-r real en lugar de efectivo; requiere -u, -g o -G
-u sólo el número de usuario (UID)
Opción Descripción
-sig señal a enviar al proceso
1 orte de línea de comunicación (SIGHUP)
2 nterrupción (SIGINT)
3 alir (SIGQUIT)
4 nstrucción ilegal (SIGILL)
5 race trap (SIGTRAP)
6 nstrucción IOT (SIGIOT)
7 nstrucción EMT (SIGEMT)
8 rror en operación en coma flotante (SIGFPE)
9 inalizar (SIGKILL)
10 error de bus (SIGBUS)
11 violación de segmentación de memoria (SIGSEGV)
12 error en llamada al núcleo (system call) (SIGSYS)
13 escribir en un "pipe" sin ningún proceso en lectura (SIGPIP)
14 alarma por temporización (SIGALARM)
15 terminación software (SIGTERM)
16 no asignado
process-id uno o más números de identificación de procesos.
Comando de paginado y búsqueda similar a more, con más opciones y subcomandos. Permite el
movimiento hacia adelante y atrás, pero no lee todo el archivo al principio, por lo que es más rápido. Sus
comandos están tomados de more y vi.
Opción Descripción
--help -? muestra ayuda sobre comandos internos
Si el último argumento es un directorio, ln crea en ese directorio enlaces a todos los archivos origen con
el mismo nombre; si sólo se indica un nombre de archivo, crea un enlace hacia ese archivo en el
directorio actual; si se indican dos archivos, crea un enlace con el primer nombre (archivo real) hacia el
segundo (enlace). Por defecto, crea enlaces O MI y no elimina archivos existentes.
Opción Descripción
-f forzoso, elimina archivos destino existentes
-i interactivo, pide confirmación para eliminar archivos
-s simbólico, crea enlaces simbólicos en lugar de O MI
Opción Descripción
nombre de usuario cambia un usuario ya conectado al sistema, al usuario especificado "nombre
de usuario"
env-var argumentos para expandir o modificar el entorno de ejecución (environment)
Opción Descripción
-c efectúa copia de los ficheros a imprimir, inmediatamente antes de la solicitud de
impresión
-d dest envía impresión a impresora "dest"
-m envía correo "mail" después de la impresión de los ficheros
-n número número de copias. Por defecto es 1.
-o opción especifica opciones de "class" de impresora, o impresora dependiente
-s suprime los mensajes de "lp"
-t titulo imprime el título "título" en la primera página de la salida (página de "banner")
-w visualiza un mensaje en el terminal, después de la impresión de los ficheros
ficheros uno o mas ficheros para ser impresos
Opción Descripción
-a lista todas las entradas
-b visualiza los caracteres no-gráficos, en notación octal
-c usa la fecha-hora de modificación del fichero para clasificación (-t), o visualización (-l)
-C fuerza la salida en multi-columna
-d solo lista el nombre si el argumento es un directorio
-f fuerza cada argumento a ser interpretado como un directorio. Desactiva las opciones "-l", "-
t", "-s", y “-r”. Activa la opción "-a"
-F marca los directorios con una barra (/), los ficheros ejecutables con un asterisco (*), los
pipes con un igual (=), y los links simbólicos (enlaces) con una arroba (@).
-g no incluye el propietario del fichero en la opción -l
-i visualiza el número de "i-nodo" en la primera columna de cada fichero
-l muestra los ficheros en formato "largo" (toda la información)
-m salida en formato de "stream"
-n visualiza el "número de usuario" en la opción "-l"
-o no incluye el grupo al que pertenece el fichero, en la opción "-l"
-p marca los directorios con una barra (/)
-q fuerza la impresión de los caracteres no gráficos de los nombres del fichero como “?”
-r clasifica en orden inverso
-R recursivo. Lista subdirectorios
-s da el tamaño de los ficheros en bloques
-t ordena por la fecha de modificación de los ficheros
-u clasifica por la fecha de último acceso al fichero
-x salida en multi-columna, con entradas clasificadas a través de la página
ficheros uno o más nombres de ficheros o directorios
dir equivale al ls –C.
Vdir equivale al la -l
Opción Descripción
usuarios usuario(s) a quienes se envía el mensaje
-f ficheros envía mensaje al fichero "file", en lugar de enviarlo al fichero de "mail" por defecto
-e no imprime mensajes: devuelve 0 si el usuario tiene mensajes, ó 1 si no los tiene
-p visualiza el fichero de mensajes de "mail"
-q produce la terminación de "mail" tras una interrupción
-r orden de salida: primero en entrar - primero en salir (FIFO)
-t pone en el buzón los nombres de todas las personas a las cuales se envió en mensaje
Comandos interactivos
Comando Descripción
d borra el mensaje y continua con el siguiente
EOT (control-D) cierra el fichero de mensajes y termina
m[usuarios] envía el mensaje a uno o más usuarios
newline continua con el siguiente mensaje
p imprime el mensaje de nuevo
q cierra el fichero de mensajes y termina
s[file] salva el mensaje en el fichero “file”
x sale sin cambiar el fichero de mensajes
w[file] salva el mensaje en el fichero nombrado, sin cabecera
!comando escape a la "shell" para ejecución del "comando"
* imprime un resumen de los comandos disponibles
- vuelve al mensaje anterior
Controla acceso de escritura a la terminal propia por otros usuarios, típicamente con programas tales
como talk y write. Sin parámetros, muestra el estado: is y si está habilitada la escritura, o is n si no está
habilitada la escritura.
Opción Descripción
y permite a otros usuarios escribir mensajes en la terminal
n no permite a otros usuarios escribir mensajes en la terminal
Opción Descripción
nombre_dir uno o mas nombres de directorios
Opción Descripción
-c borra cada línea de pantalla antes de rescribirla
-d solicita, con el mensaje "Hit space to continue", la continuación de la paginación
-f no trunca las líneas de longitud excesiva
-s reduce múltiples líneas en blanco a una sola
-l no trata los “^L” (form feed) de forma especial
-u no permite el subrayado en el terminal
-n especifica el numero de las líneas a visualizar
+linenum empieza por el número de línea "linenum" indicado
+/máscara empieza dos líneas antes de la que contiene la máscara "máscara"
Nombre uno o mas ficheros a visualizar
Comandos interactivos
Comando Descripción
[i]<espacio> muestra “i” líneas adicionales u otra pantalla si no se especifica argumento
^D <CTRL-D> muestra 11 líneas mas
= visualiza el número de la línea actual
V activa el editor “vi” en la línea en curso
H ayuda
’ vuelve al punto en el que se inicio la ultima búsqueda
i/expr busca la ocurrencia "i-ésima" de la expresión (expr)
If salta “i” pantallas, y visualiza una pantalla completa
Is salta “i” líneas, y visualiza una pantalla completa
Iz especifica una nueva ventana de pantalla de tamaño "i"
Q salida del comando
!cmd invoca "shell" para la ejecución de un comando
i:n salta al "i" próximo fichero de la lista especificada.
i:f salta al "i" previo fichero de la lista especificada
:f visualiza el nombre y el numero de línea del fichero en curso
. repite el comando anterior
Opción Descripción
-número número de prioridad. La mayor prioridad es 0, y la menor 19
Comando comando a ejecutar con la prioridad mas baja
Argumentos argumentos para el comando especificado
Opción Descripción
-b interpreta los bytes en octal
-c interpreta les bytes en ASCII
-d interpreta palabras en decimal sin signo
-v interpreta palabras en octal
-s interpreta palabras de 16 bits en decimal con signo
-x interpreta palabras en hexadecimal
Opción Descripción
fichero fichero a volcar o visualizar
+ especifica si se omite el nombre de fichero anterior “fichero”
offset especifica el desplazamiento (offset) inicial
. interpreta el desplazamiento en decimal
b interpreta el desplazamiento en bloques de 512 bytes
Opción Descripción
-a imprime en multi-columnas a lo ancho de la página
-d Salida a doble-espacio
-eck Expande los tabuladores de entrada, a sus espacios en blanco. "c" designa el carácter de
tabulación de entrada.
.f lista con saltos de línea
-h hd usa "hd" como cabecera de página, en lugar del nombre del fichero
-ick reemplaza los espacios en blanco de salida, por tabuladores. “c” designa el carácter de
tabulación de salida
-ln usa “n” como longitud de pagina, por defecto es 66
-m imprime todos los ficheros en columnas separadas
-n salida a “n” columnas
+n comienza a listar en la página “n”
-nck utiliza una anchura de “k” dígitos para numeración de líneas (por defecto k es 5)
-ok desplaza cada línea en k caracteres
-p efectúa una pausa antes de imprimir cada página
-r no imprime errores de apertura de ficheros, o de imposibilidad de lectura
-sc separa las columnas con el carácter “c”
-t no imprime las 5 líneas de cabecera o pie de pagina.
-wn ancho de página de n caracteres, por defecto es 72
fichero uno o más nombres de ficheros
Opción Descripción
-b imprime con página inicial de cabecera (banner)
-cp nnn especifica el número de copias (nnn) a imprimir, por defecto es 1
-fm xxxxx designa la cola de impresión correspondiente al tipo de formulario (xxxxx), para control de
la misma
-In nn especifica el numero de líneas por pulgada (nn), por defecto es 6
-pr nn especifica el número de prioridad (nn) para la impresión
-pt lpnn reencamina la salida a la impresora especificada (lpnn). Por defecto se encamina a la
"lp00"
Ficheros uno o mas nombres de ficheros a imprimir
Muestra el valor de todas las variables de entorno; si se indica un nombre de variable, muestra el valor
de esa variable.
Opción Descripción
-a lista información sobre todos los procesos asociados con el terminal
-d lista la información de todos los procesos, excepto los procesos del grupo de
usuarios
-e lista información de todos los procesos
-f genera un listado completo
-g glist lista solo los procesos del grupo especificado en "glist'
-l genera un listado en formato largo
-n lista de nombres usa "lista de nombres" como una alternativa. "/unix" es el valor por defecto
-p plist lista solo los procesos especificados
-s swapdev usa "swapdev" en lugar de /dev/swap
-t tlist lista solo los procesos asociados con los terminales especificados en tlist.
-u ulist lista solo los procesos asociados con los usuarios especificados en ulist.
Opción Descripción
-f fuerza el borrado
-i Solicitud interactiva antes del borrado
-r Borra un directorio y todos los ficheros del mismo
fichero uno o mas nombres de ficheros o directorios
Opción Descripción
-c cadena usa “cadena” como un comando
-e produce la salida si hay un mal estado (código de retorno), si la ejecución es en modo no-
interactivo
-i entra modo interactivo
-k pone palabras clave en un entorno de comando
-n lee pero no ejecuta comandos
-r restringe el entorno (environment)
-s lee desde la entrada estándar
-t sale después de ejecutar un comando
Opción Descripción
-u trata las variables no activadas como un error
-v imprime las líneas de entrada cuando son leídas
-x imprime el comando cuando lo va a ejecutar
arg uno o varios argumentos
Carácter Descripción
| ejecuta "pipelines"
; ejecuta secuencialmente los comandos
& ejecuta sin esperar a terminar el comando
&& ejecuta el comando si el comando anterior retornó 0
|| ejecuta el comando si el comando anterior retornó distinto de 0
`...` cita todos los caracteres que están limitados entre las comillas simples
\ cita todos los caracteres que están detrás de la barra invertida
“...” comandos y parámetros a sustituir
#text considera todo el texto introducido hasta el final de la línea como comentario
Carácter Descripción
* cualquier cadena de caracteres
? cualquier carácter simple
[..] cualquiera de los caracteres encerrados
(lista)
{lista}
Parámetro Descripción
$# número de parámetros
$- flag suministrado por invocación, o activado
$? valor retornado del último comando ejecutado
$$ número de proceso de la shell
$! número del último comando (background)
$HOME especifica el directorio "home"
$IFS especifica los separadores internos de campos
$MAIL especifica el fichero de "mail"
$PATH especifica los directorios de búsqueda de ficheros
$CDPATH especifica el directorio de retorno del comando “cd” por defecto
$PS1 especifica el prompt primario, $ por defecto
$PS2 especifica el prompt secundario, > por defecto
$TERM especifica el tipo de terminal
nombre=valor especifica valores de parámetros
${parámetro} utiliza "parámetro" activado
${parámetro:-palabra} utiliza "parámetro" si está activado, en otro caso lo activa a "palabra"
${parámetro:=palabra} utiliza "parámetro" si no está activado, en otro caso lo activa a "palabra"
Parámetro Descripción
${parámetro:?palabra} utiliza "parámetro" si está activado y no es nulo, sino imprime “palabra” y
después sale.
${parámetro:+palabra} utiliza "palabra" si el “parámetro” está activado. En otro caso no hace
nada
Entrada / Salida
Opción Descripción
<palabra usa fichero "palabra" como entrada estándar
<<palabra [-] usa fichero "palabra" como entrada estándar, seguido de una línea idéntica a "palabra"
o fin de fichero
>palabra utiliza el fichero "palabra" como salida estándar
>>palabra utiliza el fichero "palabra" como salida estándar. Lo añade al final del fichero, si este ya
existe
>&dígito duplica la entrada estándar para el "dígito" del descriptor de fichero
<f- cierra la entrada estándar
Comando Descripción
.file lee y ejecuta comandos del fichero "file", y retorna
break[n] sale de un "for" o "while" en "n" niveles
cd [arg] cambia el directorio actual a "arg"; directorio "home" por defecto
continue [n] resume "n"-iteración de un "for" o "while"
eval [arg...] lee y ejecuta argumentos
exec [arg...] ejecuta argumentos en lugar de la shell
exit [n] sale con el status "n"
export [nombre..] exporta el nombre "nombre"
login [arg...] cambia de usuario
newgrp [arg...] cambia de grupo
read name... lectura de la entrada estándar
readonly [nombre] marca el nombre "nombre" como de solo lectura
set [-ekntuvx [arg...]] -l
-el produce la salida si hay un mal estado (código de retorno) si la ejecución
es en modo no-interactivo
-k pone palabras clave en un entorno de comando
-n lee pero no ejecuta comandos
-t sale después de ejecutar un comando
-u trata las variables no activadas como un error
-v imprime las líneas de entrada cuando son leídas
-x imprime el comando cuando lo va a ejecutar
-- no cambia ninguna de las opciones
arg uno o más argumentos
shift renombra argumentos posicionales
test evalúa expresiones condicionales
times imprime tiempo de procesos acumulados
trap [arg] [n] ejecuta "arg" si la señal "n" es recibida
ulimit [-fp] [n] -l
-f impone como tamaño límite "n" bloques, en los ficheros escritos por los
procesos hijos
-p cambia el tamaño del pipe a "n"
umask [nnn] pone la máscara de creación del fichero al valor octal "nnn"
wait [n] espera por el proceso de número [n] de identificación especificado, e
imprime el status de la terminación
file lee y ejecuta comandos desde el fichero "file"
Opción Descripción
-x imprime números en hexadecimal
-o imprime números en octal
-V imprime la información de la versión del objeto
objeto uno o varios nombres de ficheros objetos
Opción Descripción
time suspende por el tiempo “time” especificado en segundos
Opción Descripción
-b ignora blancos repetitivos
-c chequea que los ficheros de entrada estén clasificados de acuerdo a las reglas
-d clasifica en orden de diccionario
-f igual tratamiento de mayúsculas que minúsculas
-i ignora caracteres fuera de código ASCII desde el 40 hasta el 176
-m mezcla ficheros (merge)
-n clasifica en orden aritmético
-r clasifica en orden inverso
-u saca una copia de las líneas iguales
-ykmem inicia el tamaño de memoria de clasificación
-zrecsz longitud del registro mayor de entrada.
+pos1[-pos2] la clave de clasificación comienza en la pos1 y finaliza en la pos2
-o nombre usa “nombre” como fichero de salida
ficheros uno o varios nombres de ficheros
Opción Descripción
- cambia los parámetros de usuario, como si se estuviese entrando en uno nuevo
nombre nombre de usuario
argumentos argumentos para la shell
Opción Descripción
+contador número de unidades desde el comienzo del fichero
b cuenta unidades por bloques
c cuenta unidades por caracteres
l cuenta unidades por líneas
f entra en un bucle sin fin, para atender la lectura y posterior copia de registros, desde el
fichero de entrada
fichero nombre del fichero
Conversar con otro usuario. Si está en la misma máquina, alcanza con el nombre de login del usuario; si
está en otra máquina, es preciso usar la forma usuario@maquina. Si el usuario tiene varias sesiones a
la vez, puede indicarse la terminal, usualmente en la forma ttyXX.
Opción Descripción
clave controla la acción del comando
-b usa el próximo argumento como factor de bloque
c crea una nueva copia
f usa el próximo argumento como nombre del "archivo". Por defecto es el definido en
/etc/default/tar”
l visualiza mensajes de error si existe algún link incorrecto
m no recupera la fecha-hora de modificación de los ficheros "files"
o asigna el usuario y grupo de usuarios del usuario que ejecuta el tar a los ficheros extraídos
r escribe los ficheros “ficheros” al final de la cinta de archivo
#s selecciona "drive" y densidad
t lista los nombres de los ficheros "ficheros”
u añade las ficheros "ficheros” a la cinta, si no están en esta, o han sido modificados
v lista los nombres de los ficheros "ficheros", precedidos por una letra que indica su función
w espera confirmación de cada fichero a copiar o recuperar
x extrae los ficheros "ficheros" de la cinta (archivo)
ficheros uno o mas ficheros a ser volcados o recuperados
Opción Descripción
-a añade
-i ignora interrupciones
ficheros nombre de fichero(s)
Opción Descripción
-b fichero verdadero si el fichero existe, y es un fichero especial de tipo "bloque"
-c fichero verdadero si el fichero existe, y es un fichero especial de tipo “carácter”
-d fichero verdadero si el fichero existe, y es un directorio
-f fichero verdadero si el fichero existe, y es un fichero normal
-g fichero verdadero si el fichero existe, y su bit de grupo ID está activado
-k fichero verdadero si el fichero existe, y su bit de “sticky” está activado
-ns1 verdadero si la longitud de la cadena “s1” no es 0
n1 -eq n2 verdadero si los enteros n1 y n2 son iguales
-p fichero verdadero si el fichero existe, y es de tipo "pipe”
-r fichero verdadero si el fichero existe, y se puede leer
-s fichero verdadero si el fichero existe y su tamaño es mayor que 0
s1 verdadero si la cadena s1 no es nula
s1=s2 verdadero si las cadenas s1 y s2 son iguales
s1!=s2 verdadero si las cadenas s1 y s2 no son iguales
-t fildes verdadero si el número descriptor del fichero está asociado con el terminal. Por defecto
es 1
-u fichero verdadero si el fichero existe, y su bit de usuario ID está activado
-w fichero verdadero si el fichero existe, y se puede escribir
-x fichero verdadero si el fichero existe, y es ejecutable
-z s1 verdadero si la longitud de la cadena "s1" es 0
Opción Descripción
comando comando a ser ejecutado, y controlado su tiempo de ejecución
Cambia fecha, hora de acceso y/o modificación de los archivos indicados; les pone la fecha y hora
actuales. Si los archivos no existen los crea vacíos.
Opción Descripción
-a cambia sólo fecha de acceso
-c no crea el archivo si no existe
-m cambiar sólo fecha de modificación
-r arch_ref fija la fecha según fecha del archivo arch_ref
-t MMDDhhmm[[CC]YY][.ss] fija la fecha indicando mes MM, día DD, hora hh y minuto mm; puede
agregarse también centuria CC y año YY y segundos ss.
Opción Descripción
-c complementa caracteres en "cadena1"
-d borra todos los caracteres en "cadena1"
-s traslada todos los caracteres repetidos a uno solo
cadena1 cadena a buscar o primera cadena de caracteres
cadena2 cadena por la que sustituir la cadena1, o segunda cadena de caracteres
tr
tr [OPCION]... CONJ1 [CONJ2]
Opción Descripción
-d elimina los caracteres de CONJ1.
-s comprime caracteres repetidos en CONJ1 en una sola ocurrencia.
-ds primero borra según CONJ1 y después comprime según CONJ2.
El formato de CONJ1 y CONJ2 se parece al de las expresiones regulares, pero son sólo listas de
caracteres. La mayoría de los caracteres se representan a sí mismos, pero existen las siguientes
abreviaturas:
\a Control-G,
\b Control-H,
\f Control-L,
\' Control-J,
\r Control-M,
\t Control-I,
\v Control-K,
\OOO caracter representado por dígitos octales
\\ barra inversa.
M-N intervalo de caracteres desde el M al N (M anterior al N)
0-9 equivale a 0123456789
La traducción se realiza cambiando el primer carácter de CONJ1 por el primer carácter de CONJ2, el 2o.
de CON1 por el 2o. de CONJ2, etc. Los caracteres no indicados en CONJ1 pasan sin cambio.
tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
tr a-z A-Z
tr '[:lower:]' '[:upper:]'
tr -d '\000'
tr -s '\n'
Opción Descripción
-l visualiza el número de línea síncrona, al cual el terminal está conectado
-s suprime la impresión del nombre del terminal; retorna código de salida
Opción Descripción
ooo cambia la máscara del modo de creación de un fichero a su valor octal “ooo”
-S muestra la máscara, sin fijarla (por defecto, sin parámetros)
Opción Descripción
-a toda la información
-m máquina, tipo de hardware
-n nombre de máquina en la red
-p tipo de procesador
-r edición (release) del sistema operativo
-s nombre del sistema operativo
-v versión del sistema operativo
Muestra una única línea para una entrada ordenada, eliminando líneas repetidas sucesivas.
Opcionalmente, puede mostrar solo líneas que aparecen una vez, o sólo líneas que aparecen varias
veces. La entrada debe estar ya ordenada; si no lo está, puede usars sort -u para lograr un efecto
similar.
Opción Descipción
-f N saltar N campos antes de verificar la unicidad.
-s N saltar N caracteres antes de verificar la unicidad.
-c indicar junto a cada línea el número de veces que aparece.
-i ignorar mayúsculas y minúsculas al comparar.
-d mostrar sólo líneas repetidas.
-u mostrar sólo líneas únicas.
Los campos son cadenas de caracteres separadas por uno o más blancos (espacios o tabuladores). Si
se indica saltar campos y caracteres, los campos se saltan primero.
Opción Descripción
-c cuenta sólo caracteres
-l cuenta sólo líneas
-w cuenta sólo palabras
fichero uno o mas nombres de ficheros
Indica la ruta completa de programa, si éste está accesible a través de la variable PATH..
Opción Descripción
-u lista información acerca de los usuarios que estén en el sistema
-T lista si alguien puede o no escribir a ese terminal; + si puede, - en caso contrario
-l lista las líneas del sistema que estén esperando para que alguien entre con "login"
-p lista los procesos activos actualmente, previamente producidos por el "init" del sistema
-d imprime los procesos terminados, no producidos por el "init" del sistema
-b muestra fecha y hora del último botado del sistema
-r indica el nivel de ejecución actual del proceso "init"
-t indica el último cambio de reloj del sistema, por "root”
-s lista solo el nombre, línea, y campos de fecha y hora. Es opción por defecto
fichero examina el fichero especificado en lugar del /etc/utmp
am i lista el nombre del usuario actual de trabajo
Muestra identificador del usuario efectivo actual. Si se ha usado su para adoptar otro usuario, whoami
muestra el nombre asociado con el usuario adoptado.
Opción Descripción
usuario nombre de usuario
nombre_tty nombre del terminal (si el nombre de usuario está en mas de un terminal)
Conocer un vocabulario y una gramática no equivale a saber un idioma. Conocer un idioma implica
además el hábito de combinar sus elementos de forma semiautomática para producir frases que
expresen lo que uno quiere decir. Conocer las palabras, las sentencias y la sintaxis del lenguaje C no
equivalen a saber programar, pero son condición necesaria para estar en condiciones de empezar a
hacerlo, o de entender cómo funcionan programas ya hechos. El proporcionar la base necesaria para
aprender a programar en lenguaje C es el objetivo de este capítulo.
C++ puede ser considerado como una extensión de C. En principio, casi cualquier programa escrito en
ANSI C puede ser compilado con un compilador de C++. El mismo programa, en un fichero con
extensión *.c puede ser convertido en un programa en C++ cambiando la extensión a *.cpp. C++ permite
muchas más posibilidades que C, pero casi cualquier programa en C, con algunas restricciones, es
aceptado por un compilador de C++.
El que la CPU pudiera acceder por separado a cada uno de los bytes de la memoria resultaría
antieconómico. Normalmente se accede a una unidad de memoria superior llamada palabra (DAMI),
constituida por varios bytes. En los sistemas antiguos la palabra tenía 1 y 2 bytes (8 o 16 bits); a partir
del procesador 386 la palabra tiene 4 bytes (32 bits). Algunos procesadores más avanzados tienen
palabras de 8 bytes.
Hay que señalar que la memoria de un ordenador se utiliza siempre para almacenar diversos tipos de
información. Quizás la distinción más importante que ha de hacerse es entre datos y programas. A su
vez, los programas pueden corresponder a aplicaciones (programas de usuario, destinados a una tarea
concreta), o al propio sistema operativo del ordenador, que tiene como misión el arrancar, coordinar y
cerrar las aplicaciones, así como mantener activos y accesibles todos los recursos del ordenador.
16.1.1.1 IDENTIFICADORES
Como se ha dicho, la memoria de un computador consta de un conjunto enorme de palabras, en el que
se almacenan datos y programas. Las necesidades de memoria de cada tipo de dato no son
homogéneas (por ejemplo, un carácter alfanumérico ocupa un byte, mientras que un número real con 16
cifras ocupa 8 bytes), y tampoco lo son las de los programas. Además, el uso de la memoria cambia a lo
largo del tiempo dentro incluso de una misma sesión de trabajo, ya que el sistema reserva o libera
memoria a medida que la va necesitando.
Cada posición de memoria puede identificarse mediante un número o una dirección, y éste es el modo
más básico de referirse a una determinada información. No es, sin embargo, un sistema cómodo o
práctico, por la nula relación nemotécnica que una dirección de memoria suele tener con el dato
contenido, y porque –como se ha dicho antes– la dirección física de un dato cambia de ejecución a
ejecución, o incluso en el transcurso de una misma ejecución del programa. Lo mismo ocurre con partes
concretas de un programa determinado.
Dadas las citadas dificultades para referirse a un dato por medio de su dirección en memoria, se ha
hecho habitual el uso de identificadores. Un identificador es un nombre simbólico que se refiere a un dato
determinado. Es muy fácil elegir identificadores cuyo nombre guarde estrecha relación con el sentido
físico, matemático o real del dato que representan. Así por ejemplo, es lógico utilizar un identificador
llamado salario_bruto para representar el coste anual de un empleado. El usuario no tiene nunca que
preocuparse de direcciones físicas de memoria: el sistema se preocupa por él por medio de una tabla, en
la que se relaciona cada identificador con el tipo de dato que representa y la posición de memoria en la
que está almacenado.
El lenguaje C, como todos los demás lenguajes de programación, tiene sus propias reglas para elegir los
identificadores. Los usuarios pueden elegir con gran libertad los nombres de sus variables, teniendo
siempre cuidado de respetar las reglas del lenguaje y de no utilizar un conjunto de palabras reservadas
(LNVDAMIC), que son utilizadas por el propio lenguaje. Más adelante se explicarán las reglas para elegir
nombres y cuáles son las palabras reservadas del lenguaje C. Baste decir por ahora que todos los
identificadores que se utilicen han de ser declarados por el usuario, es decir, hay que indicar
explícitamente qué nombres se van a utilizar en el programa para datos y funciones, y qué tipo de dato
va a representar cada uno de ellos. Más adelante se volverá sobre estos conceptos.
Análogamente a los datos que maneja, las instrucciones que un procesador digital es capaz de entender
están constituidas por conjuntos de unos y ceros. A esto se llama lenguaje de máquina o binario, y es
muy difícil de manejar. Por ello, desde casi los primeros años de los ordenadores, se comenzaron a
desarrollar los llamados lenguajes de alto nivel (tales como Fortran, Cobol, Basic, etc.), que están mucho
más cerca del lenguaje natural. Estos lenguajes están basados en el uso de identificadores, tanto para
los datos como para las componentes elementales del programa, que en algunos lenguajes se llaman
rutinas o procedimientos, y que en lenguaje C se denominan funciones. Además, cada lenguaje dispone
de una sintaxis o conjunto de reglas con las que se indica de modo inequívoco las operaciones que se
quiere realizar.
Los lenguajes de alto nivel son más o menos comprensibles para el usuario, pero no para el procesador.
Para que éste pueda ejecutarlos es necesario traducirlos a su propio lenguaje de máquina. Esta es una
tarea que realiza un programa especial llamado compilador, que traduce el programa a lenguaje
máquina. Esta tarea se suele descomponer en dos etapas, que se pueden realizar juntas o por
separado. El programa de alto nivel se suele almacenar en uno o más ficheros llamados ficheros fuente,
que en casi todos los sistemas operativos se caracterizan por una terminación –también llamada
extensión– especial. Así, todos los ficheros fuente de C deben terminar por (.c); ejemplos de nombres de
estos ficheros son calculos.c, derivada.c, etc. La primera tarea del compilador es realizar una
traducción directa del programa a un lenguaje más próximo al del computador (llamado ensamblador),
produciendo un fichero objeto con el mismo nombre que el fichero original, pero con la extensión (.obj o
.o). En una segunda etapa se realiza el proceso de montaje (SJRL TN) del programa, consistente en
producir un programa ejecutable en lenguaje de máquina, en el que están ya incorporados todos los
otros módulos que aporta el sistema sin intervención explícita del programador (funciones de librería,
recursos del sistema operativo, etc.).
Una de las ventajas más importantes de los lenguajes de alto nivel es la portabilidad de los ficheros
fuente resultantes. Quiere esto decir que un programa desarrollado en un PC podrá ser ejecutado en un
Macintosh o en una máquina UNIX, con mínimas modificaciones y una simple compilación. El lenguaje
C, originalmente desarrollado por D. Ritchie en los laboratorios Bell de la AT&T, fue posteriormente
estandarizado por un comité del ANSI (AUNMJX R,N ÓJAR S,5Ó RI MI,9RCÓJÓHÓN) con objeto de garantizar su
portabilidad entre distintos computadores, dando lugar al ANSI C, que es la variante que actualmente se
utiliza casi universalmente.
Las aplicaciones informáticas que habitualmente se utilizan, incluso a nivel de informática personal,
suelen contener decenas y aún cientos de miles de líneas de código fuente. A medida que los programas
se van desarrollando y aumentan de tamaño, se convertirían rápidamente en sistemas poco manejables
si no fuera por la modularización, que es el proceso consistente en dividir un programa muy grande en
una serie de módulos mucho más pequeños y manejables.
La división de un programa en unidades más pequeñas o funciones presenta –entre otras– las ventajas
siguientes:
1. Modularización. Cada función tiene una misión muy concreta, de modo que nunca tiene un número
de líneas excesivo y siempre se mantiene dentro de un tamaño manejable.
Además, una misma función (por ejemplo, un producto de matrices, una resolución de un sistema de
ecuaciones lineales,...) puede ser llamada muchas veces en un mismo programa, e incluso puede
ser reutilizada por otros programas. Cada función puede ser desarrollada y comprobada por
separado.
2. Ahorro de memoria y tiempo de desarrollo. En la medida en que una misma función es utilizada
muchas veces, el número total de líneas de código del programa disminuye, y también lo hace la
probabilidad de introducir errores en el programa.
Las funciones de lenguaje C están implementadas con un particular cuidado y riqueza, constituyendo
uno de los aspectos más potentes del lenguaje. Es muy importante entender bien su funcionamiento y
sus posibilidades.
Una función está asociada con un identificador o nombre, que se utiliza para referirse a ella desde el
resto del programa. En toda función utilizada en lenguaje C hay que distinguir entre su lenguaje de
definición, su declaración y su llamada. Para explicar estos conceptos hay que introducir los conceptos
de valor de retorno y de argumentos.
Quizás lo mejor sea empezar por el concepto más próximo al usuario, que es el concepto de llamada.
Las funciones en lenguaje C se llaman incluyendo su nombre, seguido de los argumentos, en una
sentencia del programa principal o de otra función de rango superior. Los argumentos son datos que se
envían a la función incluyéndolos entre paréntesis a continuación del nombre, separados por comas. Por
ejemplo, supóngase una función llamada power que calcula x elevado a y. Una forma de llamar a esta
función es escribir la siguiente sentencia (las sentencias de C terminan con punto y coma):
power(x,y);
En este ejemplo power es el nombre de la función, y x e y son los argumentos, que en este caso
constituyen los datos necesarios para calcular el resultado deseado. ¿Qué pasa con el resultado?
¿Dónde aparece? Pues en el ejemplo anterior el resultado es el valor de retorno de la función, que está
disponible pero no se utiliza. En efecto, el resultado de la llamada a power está disponible, pues aparece
sustituyendo al nombre de la función en el mismo lugar donde se ha hecho la llamada; en el ejemplo
anterior, el resultado aparece, pero no se hace nada con él. A este mecanismo de sustitución de la
llamada por el resultado es a lo que se llama valor de retorno. Otra forma de llamar a esta función
utilizando el resultado podría ser la siguiente:
En este caso el primer argumento (x+3) es elevado al segundo argumento (y), el resultado de la potencia
–el valor de retorno– es multiplicado por escala, y este nuevo resultado se almacena en la posición de
memoria asociada con el identificador distancia. Este ejemplo resulta típico de lo que es una instrucción
o sentencia que incluye una llamada a una función en el lenguaje C.
Para poder llamar a una función es necesario que en algún otro lado, en el mismo o en algún otro fichero
fuente, aparezca la definición de dicha función, que en el ejemplo anterior es la función power. La
definición de una función es ni más ni menos que el conjunto de sentencias o instrucciones necesarias
para que la función pueda realizar su tarea cuando sea llamada. En otras palabras, la definición es el
código correspondiente a la función. Además del código, la definición de la función incluye la definición
del tipo del valor de retorno y de cada uno de los argumentos. A continuación se presenta un ejemplo –
incompleto– de cómo podría ser la definición de la función power utilizada en el ejemplo anterior.
La primera línea de la definición es particularmente importante. La primera palabra double indica el tipo
del valor de retorno. Esto quiere decir que el resultado de la función será un número de punto flotante
con unas 16 cifras de precisión (así es el tipo double, como se verá más adelante). Después viene el
nombre de la función seguido de –entre paréntesis– la definición de los argumentos y de sus tipos
respectivos. En este caso hay dos argumentos, base y exponente, que son ambos de tipo double. A
continuación se abren las llaves que contienen el código de la función. La primera sentencia declara la
variable resultado, que es también de tipo double. Después vendrían las sentencias necesarias para
calcular resultado como base elevado a exponente. Finalmente, con la sentencia return se devuelve
resultado al programa o función que ha llamado a power.
Conviene notar que las variables base y exponente han sido declaradas en la cabecera –primera línea–
de la definición, y por tanto ya no hace falta declararlas después, como se ha hecho con resultado.
Cuando la función es llamada, las variables base y exponente reciben sendas copias de los valores del
primer y segundo argumento que siguen al nombre de la función en la llamada.
Una función debe ser también declarada antes de ser llamada. Además de la llamada y la definición,
está también la declaración de la función. Ya se verá más adelante dónde se puede realizar esta
declaración. La declaración de una función se puede realizar por medio de la primera línea de la
definición, de la que pueden suprimirse los nombres de los argumentos, pero no sus tipos; al final debe
incluirse el punto y coma (;). Por ejemplo, la función power se puede declarar en otra función que la va a
llamar incluyendo la línea siguiente:
La declaración de una función permite que el compilador chequee el número y tipo de los argumentos,
así como el tipo del valor de retorno. La declaración de la función se conoce también con el nombre de
prototipo de la función.
Todo programa C, desde el más pequeño hasta el más complejo, tiene un programa principal que es con
el que se comienza la ejecución del mismo. Este programa principal es también una función, pero una
función que está por encima de todas las demás. Esta función se llama main() y tiene la forma siguiente
(la palabra void es opcional en este caso):
void main(void)
{
sentencia_1
sentencia_2
...
}
Las llaves {...} constituyen el modo utilizado por el lenguaje C para agrupar varias sentencias de modo
que se comporten como una sentencia única (sentencia compuesta o bloque). Todo el cuerpo de la
función debe ir comprendido entre las llaves de apertura y cierre.
16.1.4 TOKENS
Existen seis clases de componentes sintácticos o ÓALNRC en el vocabulario del lenguaje C:
Palabras clave
Identificadores
Constantes
Cadenas de caracteres
Operadores
Separadores
Los separadores –uno o varios espacios en blanco, tabuladores, caracteres de nueva línea
(denominados "espacios en blanco" en conjunto), y también los comentarios escritos por el
programador– se emplean para separar los demás ÓALNRC; por lo demás son ignorados por el
compilador. El compilador descompone el texto fuente o programa en cada uno de sus ÓALNRC, y a partir
de esta descomposición genera el código objeto correspondiente.
A una porción de código encerrada entre llaves {...} se le llama sentencia compuesta o bloque. El
compilador ignora también los sangrados al comienzo de las líneas.
En lenguaje C, como en cualquier otro lenguaje, existen una serie de palabras clave (LNVDAMIC) que el
usuario no puede utilizar como identificadores (nombres de variables y/o de funciones). Estas palabras
sirven para indicar al computador que realice una tarea muy determinada (desde evaluar una
comparación, hasta definir el tipo de una variable) y tienen un especial significado para el compilador. El
lenguaje C es un lenguaje muy conciso, con muchas menos palabras clave que otros lenguajes. A
continuación se presenta la lista de las 32 palabras clave del ANSI C, para las que más adelante se dará
detalle de su significado (algunos compiladores añaden otras palabras clave, propias de cada uno de
ellos. Es importante evitarlas como identificadores):
16.1.4.2 IDENTIFICADORES
Ya se ha explicado lo que es un identificador: un nombre con el que se hace referencia a una función o al
contenido de una zona de la memoria (variable). Cada lenguaje tiene sus propias reglas respecto a las
posibilidades de elección de nombres para las funciones y variables. En ANSI C estas reglas son las
siguientes:
3. Un identificador no puede contener espacios en blanco, ni otros caracteres distintos de los citados,
como por ejemplo (*,;.:-+).
4. El primer carácter de un identificador debe ser siempre una letra o un (_), es decir, no puede ser un
dígito.
5. Se hace distinción entre letras mayúsculas y minúsculas. Así, Masa es considerado como un
identificador distinto de masa y de MASA.
En general es muy aconsejable elegir los nombres de las funciones y las variables de forma que
permitan conocer a simple vista qué tipo de variable o función representan, utilizando para ello tantos
caracteres como sean necesarios. Esto simplifica enormemente la tarea de programación y –sobre todo–
de corrección y mantenimiento de los programas. Es cierto que los nombres largos son más laboriosos
de teclear, pero en general resulta rentable tomarse esa pequeña molestia.
16.1.4.3 CONSTANTES
Las variables pueden cambiar de valor a lo largo de la ejecución de un programa, o bien en ejecuciones
distintas de un mismo programa. Además de variables, un programa utiliza también constantes, es decir,
valores que siempre son los mismos. Un ejemplo típico es el número pi, que vale 3.141592654. Este
valor, con más o menos cifras significativas, puede aparecer muchas veces en las sentencias de un
programa. En lenguaje C existen distintos tipos de constantes:
1. Constantes numéricas. Son valores numéricos, enteros o de punto flotante. Se permiten también
constantes octales (números enteros en base 8) y hexadecimales (base 16).
2. Constantes carácter. Cualquier carácter individual encerrado entre apóstrofos (tal como 'a', 'Y', ')',
'+', etc.) es considerado por el lenguaje C como una constante carácter, o en realidad como un
número entero pequeño (entre 0 y 255, o entre -128 y 127, según los sistemas).
Existe un código, llamado código ASCII, que establece una equivalencia entre cada carácter y un
valor numérico correspondiente.
Más adelante se verán con más detalle estos distintos tipos de constantes, así como las constantes de
tipo enumeración.
16.1.4.4 OPERADORES
Los operadores son signos especiales –a veces, conjuntos de dos caracteres– que indican determinadas
operaciones a realizar con las variables y/o constantes sobre las que actúan en el programa. El lenguaje
C es particularmente rico en distintos tipos de operadores: aritméticos (+, -, *, /, %), de asignación (=, +=,
-=, *=, /=), relacionales (==, <, >, <=, >=, !=), lógicos (&&, ||, !) y otros. Por ejemplo, en la sentencia:
Aparece un operador de asignación (=) y dos operadores aritméticos (+ y *). También los operadores
serán vistos con mucho más detalle en apartados posteriores.
16.1.4.5 SEPARADORES
Como ya se ha comentado, los separadores están constituidos por uno o varios espacios en blanco,
tabuladores, y caracteres de nueva línea. Su papel es ayudar al compilador a descomponer el programa
fuente en cada uno de sus ÓALNRC. Es conveniente introducir espacios en blanco incluso cuando no son
estrictamente necesarios, con objeto de mejorar la legibilidad de los programas.
16.1.4.6 COMENTARIOS
El lenguaje C permite que el programador introduzca comentarios en los ficheros fuente que contienen el
código de su programa. La misión de los comentarios es servir de explicación o aclaración sobre cómo
está hecho el programa, de forma que pueda ser entendido por una persona diferente (o por el propio
programador algún tiempo después). Los comentarios son también particularmente útiles (y peligrosos...)
cuando el programa forma parte de un examen que el profesor debe corregir. El compilador ignora por
completo los comentarios.
Los caracteres (d*) se emplean para iniciar un comentario introducido entre el código del programa; el
comentario termina con los caracteres (*d). No se puede introducir un comentario dentro de otro. Todo
texto introducido entre los símbolos de comienzo (d*) y final (*d) de comentario son siempre ignorados por
el compilador. Por ejemplo:
Los comentarios pueden actuar también como separadores de otros ÓALNRC propios del lenguaje C. Una
fuente frecuente de errores –no especialmente difíciles de detectar– al programar en lenguaje C, es el
olvidarse de cerrar un comentario que se ha abierto previamente.
El lenguaje ANSI C permite también otro tipo de comentarios, tomado del C++. Todo lo que va en
cualquier línea del código detrás de la doble barra (//) y hasta el final de la línea, se considera como un
comentario y es ignorado por el compilador. Para comentarios cortos, esta forma es más cómoda que la
anterior, pues no hay que preocuparse de cerrar el comentario (el fin de línea actúa como cierre). Como
contrapartida, si un comentario ocupa varias líneas hay que repetir la doble barra en cada una de las
líneas. Con este segundo procedimiento de introducir comentarios, el último ejemplo podría ponerse en
la forma:
16.1.5.1 COMPILADOR
El compilador es el elemento más característico del lenguaje C. Como ya se ha dicho anteriormente, su
misión consiste en traducir a lenguaje de máquina el programa C contenido en uno o más ficheros
fuente. El compilador es capaz de detectar ciertos errores durante el proceso de compilación, enviando
al usuario el correspondiente mensaje de error.
16.1.5.2 PREPROCESADOR
El preprocesador realiza muchas otras funciones que se irán viendo a medida que se vaya explicando el
lenguaje. Lo importante es recordar que actúa siempre por delante del compilador (de ahí su nombre),
facilitando su tarea y la del programador.
16.1.6 FICHEROS
El código de cualquier programa escrito en lenguaje C se almacena en uno o más ficheros, en el disco
del ordenador. La magnitud del programa y su estructura interna determina o aconseja sobre el número
de ficheros a utilizar. Como se verá más adelante, la división de un programa en varios ficheros es una
forma de controlar su manejo y su modularidad. Cuando los programas son pequeños, un solo fichero
suele bastar. Para programas más grandes, y cuando se quiere mantener más independencia entre los
distintos subprogramas, es conveniente repartir el código entre varios ficheros.
Recuérdese además que cada vez que se introduce un cambio en el programa hay que volver a
compilarlo. La compilación se realiza a nivel de fichero, por lo que sólo los ficheros modificados deben
ser compilados de nuevo. Si el programa está repartido entre varios ficheros pequeños esta operación se
realiza mucho más rápidamente.
Recuérdese también que todos los ficheros que contienen código fuente en lenguaje C deben terminar
con la extensión (.c), como por ejemplo: producto.c, solucion.c, etc.
Es importante considerar que las funciones de entrada y salida de datos son verdaderas funciones, con
todas sus características: nombre, valor de retorno y argumentos.
De ordinario se comienza escribiendo el programa en el fichero fuente correspondiente (extensión ÁX) por
medio de un editor de texto. Existen también entornos de programación más sofisticados que se pueden
utilizar desde entornos gráficos, como por ejemplo Visual C++ de Microsoft, o C++ de Borland. Estos
programas ofrecen muchas más posibilidades que las de un simple compilador de ANSI C. En cualquier
caso, lo que hay que hacer siempre es consultar el manual correspondiente al compilador que se vaya a
utilizar. Estos sistemas disponen de editores propios con ayudas suplementarias para la programación,
como por ejemplo criterios de color para distinguir las palabras clave del lenguaje C.
La palabra char hace referencia a que se trata de un carácter (una letra mayúscula o minúscula, un
dígito, un carácter especial, ...). La palabra int indica que se trata de un número entero, mientras que
float se refiere a un número real (también llamado de punto o coma flotante). Los números enteros
pueden ser positivos o negativos (signed), o bien esencialmente no negativos (unsigned); los
caracteres tienen un tratamiento muy similar a los enteros y admiten estos mismos cualificadores. En los
datos enteros, las palabras short y long hacen referencia al número de cifras o rango de dichos
números. En los datos reales las palabras double y long apuntan en esta misma dirección, aunque con
un significado ligeramente diferente, como más adelante se verá.
Esta nomenclatura puede simplificarse: las palabras signed e int son las opciones por defecto para los
números enteros y pueden omitirse, resultando la siguiente tabla, que indica la nomenclatura más
habitual para los tipos fundamentales del C.
A continuación se va a explicar cómo puede ser y cómo se almacena en lenguaje C un dato de cada tipo
fundamental.
Recuérdese que en lenguaje C es necesario declarar todas las variables que se vayan a utilizar. Una
variable no declarada produce un mensaje de error en la compilación. Cuando una variable es declarada
se le reserva memoria de acuerdo con el tipo incluido en la declaración.
Es posible inicializar –dar un valor inicial– las variables en el momento de la declaración; ya se verá que
en ciertas ocasiones el compilador da un valor inicial por defecto, mientras que en otros casos no se
realiza esta inicialización y la memoria asociada con la variable correspondiente contiene basura
(combinaciones sin sentido de unos y ceros, resultado de operaciones anteriores con esa zona de la
memoria, para otros fines).
char nombre;
char nombre1, nombre2, nombre3;
Se puede declarar más de una variable de un tipo determinado en una sola sentencia. Se puede también
inicializar la variable en la declaración. Por ejemplo, para definir la variable carácter letra y asignarle el
valor a, se puede escribir:
A partir de ese momento queda definida la variable letra con el valor correspondiente a la letra a.
Recuérdese que el valor ’a’ utilizado para inicializar la variable letra es una constante carácter. En
realidad, letra se guarda en un solo byte como un número entero, el correspondiente a la letra a en el
código ASCII, que se muestra en la tabla siguiente para los caracteres estándar (existe un código ASCII
extendido que utiliza los 256 valores y que contiene caracteres especiales y caracteres específicos de
los alfabetos de diversos países, como por ejemplo las vocales acentuadas y la letra ñ para el
castellano).
0 1 2 3 4 5 6 7 8 9
0 nul soh stx etx Eot enq ack bel bs ht
1 nl vt np cr So si dle dc1 dc2 dc3
2 dc4 nak syn etb Can em sub esc fs gs
3 rs us sp ! “ # $ % & ‘
4 ( ) * + , - . / 0 1
5 2 3 4 5 6 7 8 9 : ;
6 < = > ? @ A B C D E
7 F G H I J K L M N O
8 P Q R S T U V W X Y
9 Z [ \ ] ^ _ ` a b c
10 d e f g h i j k l m
11 n o p q r s t u v w
12 x y z { | } ~ del
La tabla anterior se utiliza de la siguiente forma. La primera cifra (las dos primeras cifras, en el caso de
los números mayores o iguales que 100) del número ASCII correspondiente a un carácter determinado
figura en la primera columna de la Tabla, y la última cifra en la primera fila de la Tabla. Sabiendo la fila y
la columna en la que está un determinado carácter puede componerse el número correspondiente. Por
ejemplo, la letra A está en la fila 6 y la columna 5. Su número ASCII es por tanto el 65. El carácter % está
en la fila 3 y la columna 7, por lo que su representación ASCII será el 37. Obsérvese que el código ASCII
asocia números consecutivos con las letras mayúsculas y minúsculas ordenadas alfabéticamente. Esto
simplifica notablemente ciertas operaciones de ordenación alfabética de nombres.
En la Tabla 2.3 aparecen muchos caracteres no imprimibles (todos aquellos que se expresan con 2 ó 3
letras). Por ejemplo, el ht es el tabulador horizontal, el nl es el carácter nueva línea, etc.
Volviendo al ejemplo de la variable letra, su contenido puede ser variado cuando se desee por medio de
una sentencia que le asigne otro valor, por ejemplo:
letra = ’z’;
También puede utilizarse una variable char para dar valor a otra variable de tipo char:
Como una variable tipo char es un número entero pequeño (entre 0 y 255), se puede utilizar el contenido
de una variable char de la misma forma que se utiliza un entero, por lo que están permitidas operaciones
como:
letra = letra + 1;
letra_minuscula = letra_mayuscula + (’a’ - ’A’);
En el primer ejemplo, si el contenido de letra era una a, al incrementarse en una unidad pasa a contener
una b. El segundo ejemplo es interesante: puesto que la diferencia numérica entre las letras minúsculas
y mayúsculas es siempre la misma (según el código ASCII), la segunda sentencia pasa una letra
mayúscula a la correspondiente letra minúscula sumándole dicha diferencia numérica.
Recuérdese para concluir que las variables tipo char son y se almacenan como números enteros
pequeños. Ya se verá más adelante que se pueden escribir como caracteres o como números según que
formato de conversión se utilice en la llamada a la función de escritura.
Con 16 bits se pueden almacenar 2^16 = 65536 números enteros diferentes: de 0 al 65535 para
variables sin signo, y de -32768 al 32767 para variables con signo (que pueden ser positivas y
negativas), que es la opción por defecto. Este es el rango de las variables tipo int.
En este caso la variable numero podrá estar entre 0 y 65535, mientras que nota deberá estar
comprendida entre -32768 al 32767. Cuando a una variable int se le asigna en tiempo de ejecución un
valor que queda fuera del rango permitido (situación de AÍNM6SAD o valor excesivo), se produce un error
en el resultado de consecuencias tanto más imprevisibles cuanto que de ordinario el programa no avisa
al usuario de dicha circunstancia.
Cuando el ahorro de memoria es muy importante puede asegurarse que el computador utiliza 2 bytes
para cada entero declarándolo en una de las formas siguientes:
short numero;
short int numero;
Como se ha dicho antes, ANSI C no obliga a que una variable int ocupe 2 bytes, pero declarándola
como short o short int sí que necesitará sólo 2 bytes.
long numero_grande;
El rango de un entero long puede variar según el computador o el compilador que se utilice, pero de
ordinario se utilizan 4 bytes (32 bits) para almacenarlos, por lo que se pueden representar 2^32 =
4294967296 números enteros diferentes. Si se utilizan números con signo, podrán representarse
números entre -2147483648 y 2147483647. También se pueden declarar enteros long que sean siempre
positivos con la palabra unsigned:
En algunos computadores una variable int ocupa 2 bytes (coincidiendo con short) y en otros 4 bytes
(coincidiendo con long). Lo que garantiza el ANSI C es que el rango de int no es nunca menor que el de
short ni mayor que el de long.
Tanto la mantisa como el exponente pueden ser positivos y negativos. Los computadores trabajan en
base 2. Por eso un número de tipo float se almacena en 4 bytes (32 bits), utilizando 24 bits para la
mantisa (1 para el signo y 23 para el valor) y 8 bits para el exponente (1 para el signo y 7 para el valor).
Es interesante ver qué clase de números de punto flotante pueden representarse de esta forma. En este
caso hay que distinguir el rango de la precisión. La precisión hace referencia al número de cifras con las
que se representa la mantisa: con 23 bits el número más grande que se puede representar es:
2^23 = 8388608
Lo cual quiere decir que se pueden representar todos los números decimales de 6 cifras y la mayor parte
–aunque no todos– de los de 7 cifras (por ejemplo, el número 9213456 no se puede representar con 23
bits). Por eso se dice que las variables tipo float tienen entre 6 y 7 cifras decimales equivalentes de
precisión.
Respecto al exponente de dos por el que hay que multiplicar la mantisa en base 2, con 7 bits el número
más grande que se puede representar es 127. El rango vendrá definido por la potencia:
lo cual indica el número más grande representable de esta forma. El número más pequeño en
valor absoluto será del orden de
float numero_real;
Las variables tipo float pueden ser inicializadas en el momento de la declaración, de forma análoga a las
variables tipo int.
2^52 = 4503599627370496
Lo cual representa entre 15 y 16 cifras decimales equivalentes. Con respecto al rango, con un exponente
de 10 bits el número más grande que se puede representar será del orden de 2 elevado a 2 elevado a 10
(que es 1024):
double real_grande;
Por último, existe la posibilidad de declarar una variable como long double, aunque el ANSI C no
garantiza un rango y una precisión mayores que las de double. Eso depende del compilador y del tipo
de computador. Estas variables se declaran en la forma:
El modo de almacenamiento (CÓAM TN,XS CC) es otra característica de las variables de lenguaje C que
determina cuándo se crea una variable, cuándo deja de existir y desde dónde se puede acceder a ella,
es decir, desde dónde es visible.
1. auto (automático). Es la opción por defecto para las variables que se declaran dentro de un bloque
{...}, incluido el bloque que contiene el código de las funciones. En lenguaje C la declaración debe
estar siempre al comienzo del bloque. En C++ la declaración puede estar en cualquier lugar y hay
autores que aconsejan ponerla justo antes del primer uso de la variable. No es necesario poner la
palabra auto. Cada variable auto es creada al comenzar a ejecutarse el bloque y deja de existir
cuando el bloque se termina de ejecutar. Cada vez que se ejecuta el bloque, las variables auto se
crean y se destruyen de nuevo. Las variables auto son variables locales, es decir, sólo son visibles
en el bloque en el que están definidas y en otros bloques anidados en él, aunque pueden ser
ocultadas por una nueva declaración de una nueva variable con el mismo nombre en un bloque
anidado. No son inicializadas por defecto, y –antes de que el programa les asigne un valor– pueden
contener basura (conjuntos aleatorios de unos y ceros, consecuencia de un uso anterior de esa zona
de la memoria).
{
int i=1, j=2; // se declaran e inicializan i y j
...
{
float a=7., j=3.; // se declara una nueva variable j
...
j=j+a; // aqui j es float
... // la variable int j es invisible
... // la variable i=1 es visible
}
... // fuera del bloque, a ya no existe
... // la variable j=2 existe y es entera
}
2. extern. Son variables globales, que se definen fuera de cualquier bloque o función, por ejemplo
antes de definir la función main(). Estas variables existen durante toda la ejecución del programa.
Las variables extern son visibles por todas las funciones que están entre la definición y el fin del
fichero. Para verlas desde otras funciones definidas anteriormente o desde otros ficheros, deben ser
declaradas en ellos como variables extern. Por defecto, son inicializadas a cero.
Una variable extern es definida o creada (una variable se crea en el momento en el que se le
reserva memoria y se le asigna un valor) una sola vez, pero puede ser declarada (es decir,
reconocida para poder ser utilizada) varias veces, con objeto de hacerla accesible desde diversas
funciones o ficheros. También estas variables pueden ocultarse mediante la declaración de otra
variable con el mismo nombre en el interior de un bloque. La variables extern permiten transmitir
valores entre distintas funciones, pero ésta es una práctica considerada como peligrosa. A
continuación se presenta un ejemplo de uso de variables extern:
3. static. Cuando ciertas variables son declaradas como static dentro de un bloque, estas variables
conservan su valor entre distintas ejecuciones de ese bloque. Dicho de otra forma, las variables
static se declaran dentro de un bloque como las auto, pero permanecen en memoria durante toda la
ejecución del programa como las extern.
Cuando se llama varias veces sucesivas a una función (o se ejecuta varias veces un bloque) que
tiene declaradas variables static, los valores de dichas variables se conservan entre dichas
llamadas. La inicialización sólo se realiza la primera vez. Por defecto, son inicializadas a cero.
Las variables definidas como static extern son visibles sólo para las funciones y bloques
comprendidos desde su definición hasta el fin del fichero. No son visibles desde otras funciones ni
aunque se declaren como extern. Ésta es una forma de restringir la visibilidad de las variables.
Por defecto, y por lo que respecta a su visibilidad, las funciones tienen modo extern. Una función
puede también ser definida como static, y entonces sólo es visible para las funciones que están
definidas después de dicha función y en el mismo fichero. Con estos modos se puede controlar la
visibilidad de una función, es decir, desde qué otras funciones puede ser llamada.
4. register. Este modo es una recomendación para el compilador, con objeto de que –si es posible–
ciertas variables sean almacenadas en los registros de la CPU y los cálculos con ellas sean más
rápidos. No existen los modos auto y register para las funciones.
Así pues, cuando dos tipos diferentes de constantes y/o variables aparecen en una misma expresión
relacionadas por un operador, el compilador convierte los dos operandos al mismo tipo de acuerdo con
los rangos, que de mayor a menor se ordenan del siguiente modo:
long double > double > float > unsigned long > long > unsigned int > int > char
Otra clase de conversión implícita tiene lugar cuando el resultado de una expresión es asignado a una
variable, pues dicho resultado se convierte al tipo de la variable (en este caso, ésta puede ser de menor
rango que la expresión, por lo que esta conversión puede perder información y ser peligrosa). Por
ejemplo, si i y j son variables enteras y x es double:
x = i * j – j + 1;
En lenguaje C existe también la posibilidad de realizar conversiones explícitas de tipo (llamadas X CÓJRT,
en la literatura inglesa). El X CÓJRT es pues una conversión de tipo, forzada por el programador. Para ello
basta preceder la constante, variable o expresión que se desea convertir por el tipo al que se desea
convertir, encerrado entre paréntesis. En el siguiente ejemplo:
La variable U C es convertida a tipo JRÓ, y la constante 1.7 (que es de tipo IAHBSN) también. El X CÓJRT
se aplica con frecuencia a los valores de retorno de las funciones.
16.3 CONSTANTES
Se entiende por constantes aquel tipo de información numérica o alfanumérica que no puede cambiar
más que con una nueva compilación del programa. Como ya se ha dicho anteriormente, en el código de
un programa en lenguaje C pueden aparecer diversos tipos de constantes que se van a explicar a
continuación.
En lenguaje C se pueden definir también constantes enteras octales, esto es, expresadas en base 8 con
dígitos del 0 al 7. Se considera que una constante está expresada en base 8 si el primer dígito por la
izquierda es un cero (0). Análogamente, una secuencia de dígitos (del 0 al 9) y de letras (A, B, C, D, E,
F) precedida por 0x o por 0X, se interpreta como una constante entera hexadecimal, esto es, una
constante numérica expresada en base 16. Por ejemplo:
Es probable que no haya necesidad de utilizar constantes octales y hexadecimales, pero conviene
conocer su existencia y saber interpretarlas por si hiciera falta. La ventaja de los números expresados en
base 8 y base 16 proviene de su estrecha relación con la base 2 ( 8 y 16 son potencias de 2), que es la
forma en la que el ordenador almacena la información.
Estas constantes se pueden expresar de varias formas. La más sencilla es un conjunto de dígitos del 0 al
9, incluyendo un punto decimal. Para constantes muy grandes o muy pequeñas puede utilizarse la
notación científica; en este caso la constante tiene una parte entera, un punto decimal, una parte
fraccionaria, una e o E, y un exponente entero (afectando a la base 10), con un signo opcional. Se puede
omitir la parte entera o la fraccionaria, pero no ambas a la vez. Las constantes de punto flotante son
siempre positivas. Puede anteponerse un signo (-), pero no forma parte de la constante, sino que con
ésta constituye una expresión, como se verá más adelante. A continuación se presentan algunos
ejemplos válidos:
Hay que señalar que el valor ASCII de los números del 0 al 9 no coincide con el propio valor numérico.
Por ejemplo, el valor ASCII de la constante carácter '7' es 55.
Ciertos caracteres no representables gráficamente, el apóstrofo (') y la barra invertida (\) y otros
caracteres, se representan mediante la siguiente tabla de secuencias de escape, con ayuda de la barra
invertida (\). Una secuencia de escape está constituida por la barra invertida (\) seguida de otro carácter.
La finalidad de la secuencia de escape es cambiar el significado habitual del carácter que sigue a la
barra invertida.
Los caracteres ASCII pueden ser también representados mediante el número octal correspondiente,
encerrado entre apóstrofos y precedido por la barra invertida. Por ejemplo, '\07' y '\7' representan el
número 7 del código ASCII (sin embargo, '\007' es la representación octal del carácter '7'), que es el
sonido de alerta. El ANSI C también admite secuencias de escape hexadecimales, por ejemplo '\x1a'.
"Informática I"
"'A'"
" cadena con espacios en blanco "
"Esto es una \"cadena de caracteres\".\n"
En realidad, las constantes enumeración son los posibles valores de ciertas variables definidas como de
ese tipo concreto. Considérese como ejemplo la siguiente declaración:
Esta declaración crea un nuevo tipo de variable –el tipo de variable dia– que sólo puede tomar uno de
los 7 valores encerrados entre las llaves. Estos valores son en realidad constantes tipo int: lunes es un
0, martes es un 1, miércoles es un 2, etc. Ahora, es posible definir variables, llamadas dia1 y dia2, que
sean de tipo dia, en la forma (obsérvese que en C deben aparecer las palabras enum dia; en C++ basta
que aparezca la palabra dia)
dia1 = martes;
O aparecer en diversos tipos de expresiones y de sentencias que se explicarán más adelante. Los
valores enteros que se asocian con cada constante tipo enumeración pueden ser controlados por el
programador. Por ejemplo, la declaración,
Se puede también hacer la definición del tipo enum y la declaración de las variables en una única
sentencia, en la forma
Donde carta1, carta2 y carta3 son variables que sólo pueden tomar los valores oros, copas, espadas y
bastos (equivalentes respectivamente a 0, 1, 2 y 3).
El lenguaje C no define lo que ocurre si en otra parte del programa o en tiempo de ejecución se intenta
modificar una variable declarada como const. De ordinario se obtendrá un mensaje de error en la
compilación si una variable const figura a la izquierda de un operador de asignación.
C++ es mucho más restrictivo en este sentido, y no permite de ninguna manera modificar las variables
declaradas como const.
El calificador const se suele utilizar cuando, por motivos de eficiencia, se pasan argumentos por
referencia a funciones y no se desea que dichos argumentos sean modificados por éstas.
16.4.1 OPERADORES
Un operador es un carácter o grupo de caracteres que actúa sobre una, dos o más variables para
realizar una determinada operación con un determinado resultado. Ejemplos típicos de operadores son la
suma (+), la diferencia (-), el producto (*), etc. Los operadores pueden ser unarios, binarios y ternarios,
según actúen sobre uno, dos o tres operandos, respectivamente. En lenguaje C existen muchos
operadores de diversos tipos (éste es uno de los puntos fuertes del lenguaje), que se verán a
continuación.
Los operadores aritméticos son los más sencillos de entender y de utilizar. Todos ellos son operadores
binarios. En lenguaje C se utilizan los cinco operadores siguientes:
– Suma +
– Resta -
– Multiplicación *
– División /
– Resto %
Todos estos operadores se pueden aplicar a constantes, variables y expresiones. El resultado es el que
se obtiene de aplicar la operación correspondiente entre los dos operandos.
El único operador que requiere una explicación adicional es el operador resto %. En realidad su nombre
completo es resto de la división entera. Este operador se aplica solamente a constantes, variables o
expresiones de tipo int. Aclarado esto, su significado es evidente: 23%4 es 3, puesto que el resto de
dividir 23 por 4 es 3. Si a%b es cero, a es múltiplo de b.
Como se verá más adelante, una expresión es un conjunto de variables y constantes –y también de otras
expresiones más sencillas– relacionadas mediante distintos operadores. Un ejemplo de expresión en la
que intervienen operadores aritméticos es el siguiente polinomio de grado 2 en la variable x:
Las expresiones pueden contener paréntesis (...) que agrupan a algunos de sus términos. Puede haber
paréntesis contenidos dentro de otros paréntesis. El significado de los paréntesis coincide con el habitual
en las expresiones matemáticas, con algunas características importantes que se verán más adelante. En
ocasiones, la introducción de espacios en blanco mejora la legibilidad de las expresiones.
El operador de asignación más utilizado es el operador de igualdad (=), que no debe ser confundido con
la igualdad matemática. Su forma general es:
nombre_de_variable = expresion;
variable = variable + 1;
Desde el punto de vista matemático este ejemplo no tiene sentido (¡Equivale a 0 = 1!), pero sí lo tiene
considerando que en realidad el operador de asignación (=) representa una sustitución; en efecto, se
toma el valor de variable contenido en la memoria, se le suma una unidad y el valor resultante vuelve a
depositarse en memoria en la zona correspondiente al identificador variable, sustituyendo al valor que
había anteriormente. El resultado ha sido incrementar el valor de variable en una unidad.
Así pues, una variable puede aparecer a la izquierda y a la derecha del operador (=). Sin embargo, a la
izquierda del operador de asignación (=) no puede haber nunca una expresión: tiene que ser
necesariamente el nombre de una variable. Es incorrecto, por tanto, escribir algo así como:
a + b = c; // incorrecto
También podría ir una dirección de memoria -o una expresión cuyo resultado fuera una dirección de
memoria-, precedida del operador indirección (*). Esto es lo que En lenguaje C se llama left-value o
l-value (algo que puede estar a la izquierda del operador (=)). Más adelante, al hablar de punteros,
quedará más claro este tema.
Existen otros cuatro operadores de asignación (+=, -=, *= y /=) formados por los 4 operadores aritméticos
seguidos por el carácter de igualdad. Estos operadores simplifican algunas operaciones recurrentes
sobre una misma variable. Su forma general es:
i = 2;
j = 2;
m = i++; // despues de ejecutarse esta sentencia m=2 e i=3
n = ++j; // despues de ejecutarse esta sentencia n=3 y j=3
Estos operadores son muy utilizados. Es importante entender muy bien por qué los resultados m y n del
ejemplo anterior son diferentes.
En el lenguaje natural, existen varias palabras o formas de indicar si se cumple o no una determinada
condición. En inglés estas formas son (yes, no), (on, off), (true, false). En Informática se ha hecho
bastante general el utilizar la última de las formas citadas: (true, false). Si una condición se cumple, el
resultado es true; en caso contrario, el resultado es false
.
En lenguaje C un 0 representa la condición de false, y cualquier número distinto de 0 equivale a la
condición true. Cuando el resultado de una expresión es true y hay que asignar un valor concreto
distinto de cero, por defecto se toma un valor unidad. Los operadores relacionales de C son los
siguientes:
– Igual que ==
– Menor que <
– Mayor que >
Todos los operadores relacionales son operadores binarios (tienen dos operandos), y su forma general
es la siguiente:
expresion1 op expresion2
Donde op es uno de los operadores (==, <, >, <=, >=, !=). El funcionamiento de estos operadores es el
siguiente: se evalúan expresion1 y expresion2, y se comparan los valores resultantes. Si la condición
representada por el operador relacional se cumple, el resultado es 1; si la condición no se cumple, el
resultado es 0.
Los operadores lógicos son operadores binarios que permiten combinar los resultados de los operadores
relacionales, comprobando que se cumplen simultáneamente varias condiciones, que se cumple una u
otra, etc. El lenguaje C tiene dos operadores lógicos: el operador Y (&&) y el operador O (||). En inglés
son los operadores and y or. Su forma general es la siguiente:
expresion1 || expresion2
expresion1 && expresion2
El operador && devuelve un 1 si tanto expresion1 como expresion2 son verdaderas (o distintas de 0), y
0 en caso contrario, es decir si una de las dos expresiones o las dos son falsas (iguales a 0); por otra
parte, el operador || devuelve 1 si al menos una de las expresiones es cierta. Es importante tener en
cuenta que los compiladores de C tratan de optimizar la ejecución de estas expresiones, lo cual puede
tener a veces efectos no deseados. Por ejemplo: para que el resultado del operador && sea verdadero,
ambas expresiones tienen que ser verdaderas; si se evalúa expresion1 y es falsa, ya no hace falta
evaluar expresion2, y de hecho no se evalúa. Algo parecido pasa con el operador ||: si expresion1 es
verdadera, ya no hace falta evaluar expresion2.
Los operadores && y || se pueden combinar entre sí –quizás agrupados entre paréntesis–, dando a
veces un código de más difícil interpretación. Por ejemplo:
Además de los operadores vistos hasta ahora, el lenguaje C dispone de otros operadores. En esta
sección se describen algunos operadores unarios adicionales.
El efecto de este operador en una expresión es cambiar el signo de la variable o expresión que le
sigue. Recuérdese que en lenguaje C no hay constantes numéricas negativas. La forma general de
este operador es:
- expresion
Este es un nuevo operador unario introducido en el ANSI C, y que tiene como finalidad la de servir
de complemento al operador (–) visto anteriormente. Se puede anteponer a una variable o expresión
como operador unario, pero en realidad no hace nada.
Operador sizeof().
Este es el operador de C con el nombre más largo. Puede parecer una función, pero en realidad es
un operador. La finalidad del operador sizeof() es devolver el tamaño, en bytes, del tipo de variable
introducida entre los paréntesis. Recuérdese que este tamaño depende del compilador y del tipo de
computador que se está utilizando, por lo que es necesario disponer de este operador para producir
código portable. Por ejemplo:
Este operador devuelve un cero (false) si se aplica a un valor distinto de cero (true), y devuelve un 1
(true) si se aplica a un valor cero (false). Su forma general es:
!expresion
En este caso, expresion_1 se evalúa primero, y luego se evalúa expresion_2. El resultado global es
el valor de la segunda expresión, es decir de expresion_2. Este es el operador de menos
precedencia de todos los operadores de C. Como se explicará más adelante, su uso más frecuente
es para introducir expresiones múltiples en la sentencia for.
*expresion;
&variable;
El operador dirección & devuelve la dirección de memoria de la variable que le sigue. Por ejemplo:
variable_1 = &variable_2;
No se puede modificar la dirección de una variable, por lo que no están permitidas operaciones en
las que el operador & figura a la izquierda del operador (=), al estilo de:
&variable_1 = nueva_direccion;
El operador indirección * es el operador complementario del &. Aplicado a una expresión que
represente una dirección de memoria (puntero) permite hallar el contenido o valor almacenado en
esa dirección. Por ejemplo:
variable_3 = *variable_1;
Como ya se ha indicado, las variables puntero y los operadores dirección (&) e indirección (*) serán
explicados con mucho más detalle en un capítulo posterior.
16.4.2 EXPRESIONES
Ya han aparecido algunos ejemplos de expresiones del lenguaje C en las secciones precedentes. Una
expresión es una combinación de variables y/o constantes, y operadores. La expresión es equivalente al
resultado que proporciona al aplicar sus operadores a sus operandos. Por ejemplo, 1+5 es una
expresión formada por dos operandos (1 y 5) y un operador (el +); esta expresión es equivalente al valor
6, lo cual quiere decir que allí donde esta expresión aparece en el programa, en el momento de la
ejecución es evaluada y sustituida por su resultado. Una expresión puede estar formada por otras
expresiones más sencillas, y puede contener paréntesis de varios niveles agrupando distintos términos.
En lenguaje C existen distintos tipos de expresiones.
Están formadas por variables y/o constantes, y distintos operadores aritméticos e incrementales (+, -, *, /,
%, ++, --). Como se ha dicho, también se pueden emplear paréntesis de tantos niveles como se desee, y
su interpretación sigue las normas aritméticas convencionales. Por ejemplo, la solución de la ecuación
de segundo grado se escribe en lenguaje C en la forma:
x=(-b+sqrt((b*b)-(4*a*c)))/(2*a);
Donde, estrictamente hablando, sólo lo que está a la derecha del operador de asignación (=) es una
expresión aritmética. El conjunto de la variable que está a la izquierda del signo (=), el operador de
asignación, la expresión aritmética y el carácter (;) constituyen una sentencia. En la expresión anterior
aparece la llamada a la función de librería sqrt(), que tiene como valor de retorno la raíz cuadrada de su
único argumento. En las expresiones se pueden introducir espacios en blanco entre operandos y
operadores; por ejemplo, la expresión anterior se puede escribir también de la forma:
Donde de nuevo la expresión lógica es lo que está entre el operador de asignación (=) y el (;). La
variable a valdrá 1 si b es mayor que c y c mayor que d, ó si c es igual a e ó e es igual a b.
Recuérdese que el resultado de una expresión lógica es siempre un valor numérico (un 1 ó un 0); esto
permite que cualquier expresión lógica pueda aparecer como sub-expresión en una expresión aritmética.
Recíprocamente, cualquier valor numérico puede ser considerado como un valor lógico: true si es
distinto de 0 y false si es igual a 0. Esto permite introducir cualquier expresión aritmética como sub-
expresión de una expresión lógica. Por ejemplo:
(a - b*2.0) && (c != d)
A su vez, el operador de asignación (=), además de introducir un nuevo valor en la variable que figura a
su izquierda, deja también este valor disponible para ser utilizado en una expresión más general. Por
ejemplo, supóngase el siguiente código que inicializa a 1 las tres variables a, b y c:
a = b = c = 1;
Qque equivale a:
a = (b = (c = 1));
En realidad, lo que se ha hecho ha sido lo siguiente. En primer lugar se ha asignado un valor unidad a c;
el resultado de esta asignación es también un valor unidad, que está disponible para ser asignado a b; a
su vez el resultado de esta segunda asignación vuelve a quedar disponible y se puede asignar a la
variable a.
3 + 4 * 2
Si se realiza primero la suma (3+4) y después el producto (7*2), el resultado es 14; si se realiza primero
el producto (4*2) y luego la suma (3+8), el resultado es 11. Con objeto de que el resultado de cada
expresión quede claro e inequívoco, es necesario definir las reglas que definen el orden con el que se
ejecutan las expresiones de C. Existe dos tipos de reglas para determinar este orden de evaluación: las
reglas de precedencia y de asociatividad. Además, el orden de evaluación puede modificarse por medio
de paréntesis, pues siempre se realizan primero las operaciones encerradas en los paréntesis más
interiores. Los distintos operadores de C se ordenan según su distinta precedencia o prioridad; para
operadores de la misma precedencia o prioridad, en algunos el orden de ejecución es de izquierda a
derecha, y otros de derecha a izquierda (se dice que se asocian de izquierda a derecha, o de derecha a
izquierda). A este orden se le llama asociatividad.
Precedencia Asociatividad
() [] -> . izda a dcha
++ -- ! sizeof (tipo) +(unario) -(unario) *(indir.) &(dirección) dcha a izda
*/% izda a dcha
+- izda a dcha
< <= > >= izda a dcha
== != izda a dcha
&& izda a dcha
|| izda a dcha
?: dcha a izda
= += -= *= /= dcha a izda
, (operador coma) izda a dcha
En la Tabla anterior se indica que el operador (*) tiene precedencia sobre el operador (+). Esto quiere
decir que, en ausencia de paréntesis, el resultado de la expresión 3+4*2 es 11 y no 14. Los operadores
binarios (+) y (-) tienen igual precedencia, y asociatividad de izquierda a derecha. Eso quiere decir que
en la expresión:
a-b+d*5.0+u/2.0 // (((a-b)+(d*5.0))+(u/2.0))
El orden de evaluación es el indicado por los paréntesis en la parte derecha de la línea (Las últimas
operaciones en ejecutarse son las de los paréntesis más exteriores).
16.4.4 SENTENCIAS
Las expresiones de lenguaje C son unidades o componentes elementales de unas entidades de rango
superior que son las sentencias. Las sentencias son unidades completas, ejecutables en sí mismas. Ya
se verá que muchos tipos de sentencias incorporan expresiones aritméticas, lógicas o generales como
componentes de dichas sentencias.
float real;
espacio = espacio_inicial + velocidad * tiempo;
Muchas veces es necesario poner varias sentencias en un lugar del programa donde debería haber una
sola. Esto se realiza por medio de sentencias compuestas. Una sentencia compuesta es un conjunto de
declaraciones y de sentencias agrupadas dentro de llaves {...}. También se conocen con el nombre de
bloques. Una sentencia compuesta puede incluir otras sentencias, simples y compuestas. Un ejemplo de
sentencia compuesta es el siguiente:
{
int i = 1, j = 3, k;
double masa;
masa = 3.0;
k = y + j;
}
Las sentencias compuestas se utilizarán con mucha frecuencia en las sentencias que permiten modificar
el flujo de control del programa.
Las más utilizadas se agrupan en dos familias: las bifurcaciones, que permiten elegir entre dos o más
opciones según ciertas condiciones, y los bucles, que permiten ejecutar repetidamente un conjunto de
instrucciones tantas veces como se desee, cambiando o actualizando ciertos valores.
16.5.1 BIFURCACIONES
16.5.1.1 OPERADOR CONDICIONAL
El operador condicional es un operador con tres operandos (ternario) que tiene la siguiente forma
general:
16.5.1.2 SENTENCIA IF
Esta sentencia de control permite ejecutar o no una sentencia simple o compuesta según se cumpla o no
una determinada condición. Esta sentencia tiene la siguiente forma general:
if (expresion)
sentencia;
Esta sentencia permite realizar una bifurcación, ejecutando una parte u otra del programa según se
cumpla o no una cierta condición. La forma general es la siguiente:
if (expresion)
sentencia_1;
else
sentencia_2;
Esta sentencia permite realizar una ramificación múltiple, ejecutando una entre varias partes del
programa según se cumpla una entre n condiciones. La forma general es la siguiente:
if (expresion_1)
sentencia_1;
else if (expresion_2)
sentencia_2;
else if (expresion_3)
sentencia_3;
else if (...)
...
[else
sentencia_n;]
y en ese caso puede eliminarse junto con la palabra else). Todas las sentencias pueden ser simples o
compuestas.
switch (expresion) {
case expresion_cte_1:
sentencia_1;
case expresion_cte_2:
sentencia_2;
...
case expresion_cte_n:
sentencia_n;
[default:
sentencia;]
}
switch (expresion) {
case expresion_cte_1:
sentencia_1;
break;
case expresion_cte_2: case expresion_cte_3:
sentencia_2;
break;
default:
sentencia_3;
}
if (a >= b)
if (b != 0.0)
c = a/b;
En ocasiones pueden aparecer dificultades de interpretación con sentencias if...else anidadas, como en
el caso siguiente:
if (a >= b)
if (b != 0.0)
c = a/b;
else
c = 0.0;
En principio se podría plantear la duda de a cuál de los dos if corresponde la parte else del programa.
Los espacios en blanco –las indentaciones de las líneas– parecen indicar que la sentencia que sigue a
else corresponde al segundo de los if, y así es en realidad, pues la regla es que el else pertenece al if
más cercano. Sin embargo, no se olvide que el compilador de C no considera los espacios en blanco
(aunque sea muy conveniente introducirlos para hacer más claro y legible el programa), y que si se
quisiera que el else perteneciera al primero de los if no bastaría cambiar los espacios en blanco, sino
que habría que utilizar llaves, en la forma:
if (a >= b) {
if (b != 0.0)
c = a/b;
} else
c = 0.0;
Recuérdese que todas las sentencias if e if...else, equivalen a una única sentencia por la posición que
ocupan en el programa.
16.5.2 BUCLES
Además de bifurcaciones, en el lenguaje C existen también varias sentencias que permiten repetir una
serie de veces la ejecución de unas líneas de código. Esta repetición se realiza, bien un número
determinado de veces, bien hasta que se cumpla una determinada condición de tipo lógico o aritmético.
De modo genérico, a estas sentencias se les denomina bucles. Las tres construcciones del lenguaje C
para realizar bucles son while, for y do...while.
while (expresion_de_control)
sentencia;
Obsérvese que en este caso el control para decidir si se sale o no del bucle está antes de sentencia, por
lo que es posible que sentencia no se llegue a ejecutar ni una sola vez.
Explicación: Posiblemente la forma más sencilla de explicar la sentencia for sea utilizando la
construcción while que sería equivalente. Dicha construcción es la siguiente:
inicializacion;
while (expresion_de_control) {
sentencia;
actualizacion;
}
Donde sentencia puede ser una única sentencia terminada con (;), otra sentencia de control ocupando
varias líneas (if, while, for,...), o una sentencia compuesta o un bloque encerrado entre llaves {...}. Antes
de iniciarse el bucle se ejecuta inicializacion, que es una o más sentencias que asignan valores iniciales
a ciertas variables o contadores. A continuación se evalúa expresion_de_control y si es false se
prosigue en la sentencia siguiente a la construcción for; si es true se ejecutan sentencia y
actualizacion, y se vuelve a evaluar expresion_de_control. El proceso prosigue hasta que
expresion_de_control sea false. La parte de actualizacion sirve para actualizar variables o
incrementar contadores. Un ejemplo típico puede ser el producto escalar de dos vectores a y b de
dimensión n:
Primeramente se inicializa la variable pe a cero y la variable i a 1; el ciclo se repetirá mientras que i sea
menor o igual que n, y al final de cada ciclo el valor de i se incrementará en una unidad. En total, el bucle
se repetirá n veces. La ventaja de la construcción for sobre la construcción while equivalente está en
que en la cabecera de la construcción for se tiene toda la información sobre como se inicializan,
controlan y actualizan las variables del bucle. Obsérvese que la inicialización consta de dos sentencias
separadas por el operador (,).
do
sentencia;
while(expresion_de_control);
Donde sentencia puede ser una única sentencia o un bloque, y en la que debe observarse que hay que
poner (;) a continuación del paréntesis que encierra a expresion_de_control, entre otros motivos para
que esa línea se distinga de una sentencia while ordinaria.
La sentencia continue hace que el programa comience el siguiente ciclo del bucle donde se halla,
aunque no haya llegado al final de las sentencia compuesta o bloque.
La sentencia goto etiqueta hace saltar al programa a la sentencia donde se haya escrito la etiqueta
correspondiente. Por ejemplo:
sentencias ...
...
if (condicion)
goto otro_lugar; // salto al lugar indicado por la etiqueta
sentencia_1;
sentencia_2;
...
otro_lugar: // esta es la sentencia a la que se salta
sentencia_3;
...
Obsérvese que la etiqueta termina con el carácter (:). La sentencia goto no es una sentencia muy
prestigiada en el mundo de los programadores de C, pues disminuye la claridad y legibilidad del código.
Fue introducida en el lenguaje por motivos de compatibilidad con antiguos hábitos de programación, y
siempre puede ser sustituida por otras construcciones más claras y estructuradas.
Hola, mundo.
Comentarios:
Esta es la mínima expresión de un programa escrito en lenguaje C. Consta de un bloque principal y una
instrucción.
Programa Nro. 2.
“NCXMJEXJóR:,
Escribir un programa C que utilice los diversos tipos de variable que contempla la función printf. Probarlo
para enteros, Char, long, float y double. Probar además los distintos formatos de salida.
Programa Nro. 3.
“NCXMJEXJóR:,
Realizar un programa que genere el factorial de un Número. Se recuerda que el factorial de 'n' es n * (n-
1) * (n-2) * ....* 1.
Comentarios:
Una vez realizaba la primera versión, aumentar la potencia del programa utilizando funciones recursivas.
Programa Nro. 4.
“NCXMJEXJóR:,
Realizar un programa que imprima la Tabla de grados Fahrenheit de ‘0’ a ‘300’, en intervalos de 20
grados, y sus correspondientes equivalencias en grados Celsius, utilizando la formula C = (5/9)(F-32).
Programa Nro. 5.
“NCXMJEXJóR:,
Escribir un programa que calcule las potencias de ‘2’ y ‘-3’ con exponentes de ‘1’ a ‘10’, y las visualice
por pantalla.
Comentarios:
La función de cálculo de potencias deberá ser contemplada solo para números enteros, tanto de base
como de exponente.
Programa Nro. 6.
“NCXMJEXJóR:,
Escribir un programa que recoja los caracteres digitados en el teclado y los imprima en pantalla. Para
ello utilizar las funciones ‘getchar’ y ‘putchar’.
Comentarios:
Para poder utilizar estas funciones se tiene que incluir el fichero 'stdio.h' con las definiciones
correspondientes.
Una vez depurada esta fase, que cuente las líneas que se han impreso, y las totalice al final de la
ejecución.
Programa Nro. 7.
“NCXMJEXJóR:,
Escribir un programa que saque por pantalla los argumentos con los que se ha llamado al mismo.
Comentarios:
Hay que declarar los parámetros de 'main' 'argc' y 'argv'.
Nótese que el primer argumento siempre es el nombre del programa que se está ejecutando.
Programa Nro. 8.
“NCXMJEXJóR:,
Realizar un programa que cuente las líneas, palabras y caracteres tecleados, usando la definición de que
una palabra es cualquier secuencia de caracteres que no contiene espacio en blanco, tabulación o final
de línea.
Programa Nro. 9.
“NCXMJEXJóR:,
Mediante en algoritmo de ordenación por el método de la burbuja, ordenar un array de Números enteros.
Comentario:
Recordar que el método de la burbuja consiste en comparar cada elemento del array con los siguientes a
él, e intercambiar las posiciones en caso de una mala ordenación.
Realizar un programa que calcula la longitud de un una cadena de caracteres. Este programa hará lo
mismo que la función estándar 'strlen'.
Comentarios:
Las cadenas de caracteres terminan con un carácter nulo '\0'. Realizar varias versiones del programa
utilizando indexación de cadenas ó punteros.
Comentarios:
Hacerlo de dos maneras, comparando con 'if' y 'else', o con la forma abreviado.
Hacer un programa que se encargue de dar la vuelta a una cadena de caracteres, o sea, si la cadena es
"ABCD", debe devolver la cadena "DCBA".
Hacer un programa que pasándole dos nombres de ficheros, copie el primero sobre el segundo, cuente
el Número de líneas y el Nro. de caracteres, y los muestre al final de la ejecución.
Comentarios:
Se deben definir los argumentos del 'main'. También sería interesante comparar dos versiones, una con
las funciones de bajo nivel, y otra con las funciones de alto nivel (streams).
Escribir un programa que grave registros en un fichero secuencial utilizando ras funciones de bajo nivel y
estructuras de datos.
Comentarios:
Cuando se utilizan las funciones de bajo nivel en acceso a ficheros, la información se graba en formato
compactado (binario)
Escribir un programa que liste el contenido del fichero grabado en el programa Nro. 14.
Escribir un programa que traduzca las mayúsculas a minúsculas del contenido de un fichero, y lo deje en
un nuevo fichero de salida
Realizar un programa que lea un conjunto de líneas de texto e imprima la de mayor longitud.
Comentario:
La lógica o pseudocódigo del programa es simple
Produciría una llamada a la CONSS para que leyese y ejecutase los comandos contenidos en
"fic_comandos", diciéndose entonces que "fic_comandos” es un “fichero de comandos”.
Se pueden utilizar argumentos en la llamada al fichero de comandos, por medio de los "parámetros
posicionales ” $1, $2, ...., $n. Por ejemplo, si el fichero “compila” contiene el texto:
cc -o $1 $1.c
Entonces
$ sh compila prog1
Es equivalente a:
cc -o prog1 prog1.c
Donde vemos que el parámetro posicional $1 ha sido reemplazado por “prog1”. Este ejemplo serviría
para compilar un programa fuente en lenguaje “C” llamado “prog1.c”, dejando el programa compilado en
“prog1”, en lugar de "a.out", como denomina por defecto el compilador de “C” a su salida.
También puede convertirse un fichero de comandos en "ejecutable”, con solo cambiar sus protecciones
de ejecución. Así:
Produce el efecto de cambiar la protección de ejecución del fichero “compila” para el usuario y grupo,
convirtiéndolo en ejecutable, de manera que:
$ compila prog1
Es equivalente a:
$ sh compila prog1
La CONSS proporciona dos variables reservadas para su empleo con parámetros posicionales, como son el
número de argumentos de llamada, contenido en la variable "$#", y el nombre del fichero en ejecución,
contenido en la variable “$0”. También existe una variable reservada "$*”, equivalente a todos los
parámetros posicionales con excepción del primero "$0”.
i=100
x1_max=f200j
s1 = f1
Que asignaría a las variables "i", "x1_max" y “s1”, los valores “100”, “f200j” y “f1” receptivamente.
nulo=
Para acceder al valor de una variable se antepone el carácter “$” a su nombre. Por ejemplo:
echo i
echo $i
d=/usr/juan/programas/fuentes/c
mv *.c $d
mv /tmp/*.c $d
Llevaría los ficheros fuentes en lenguaje “C” contenidos en el directorio actual de trabajo, y en el
directorio /tmp, al directorio “/usr/juan/programas/fuentes/c".
echo ${var}
echo $var
Pero que se utiliza cuando el nombre de la variable viene seguido por una letra o dígito, como es el caso
de:
tmp=/tmp/pruebas
ps -a > ${tmp}1
Produciría el reencaminamiento de la salida del comando “ps” al fichero “/tmp/pruebas1”, mientras que:
ps –a > $tmp1
Las siguientes variables son inicializadas por la CONSS al proceder a la ejecución de cada comando:
$? Consiste en el código de retorno (CÓ ÓHC) del último comando ejecutado, devuelto como una
cadena de caracteres decimales. Normalmente se recibe el valor cero (0) tras la ejecución de un
comando satisfactoriamente, y un valor distinto de cero (0) para indicar la existencia de algún
problema en su ejecución.
$$ Consiste en el número identificador de proceso de esta shell, en decimal. Se utiliza con frecuencia
para generar nombres de ficheros temporales, con la garantía de que sean únicos. Por ejemplo: ps
-a > /tmp/pruebas$$ ..... rm /tmplpruebas$$
$! Es el número identificador de proceso del último comando ejecutado en modo "B XLTMAHRI" (no
interactivo).
Algunas variables poseen un significado especial para la CONSS, pasándose al "NRÍJMARUNRÓ" o entorno de
ejecución del usuario, de modo que son accesibles desde otros programas:
$MAIL Cuando se maneja interactivamente, la shell busca ésta variable antes de devolver su EMAUEÓ
"$". Si el fichero especificado en la variable ha sido modificado desde la última consulta, la shell
imprimirá el mensaje "You have mail", antes de pasar a solicitar el siguiente comando. Normalmente
MAIL se inicializa en el fichero ".profile", existente en el directorio de trabajo del usuario. Por
ejemplo: MAIL=/usr/spool/mail/juan inicializaría MAIL al valor de un nombre de fichero en el
que almacenar el correo manejado por el comando "mail".
$HOME Almacena el directorio del usuario que ha realizado el proceso de SATJR. Es el argumento por
defecto para el comando "cd" (cambio de directorio). Así la utilización de "cd" sin argumentos es
equivalente al empleo de: cd $HOME La variable HOME también suele inicializarse en el fichero de
comandos ".profile".
$PATH Consiste en una lista de directorios en los cuales deben de buscarse los comandos a
ejecutar. Cada vez que se procede a la ejecución de un comando, la CONSS busca este comando en
los directorios (y en el orden) especificados por PATH, o por defecto en "/bin" y "/usr/bin". PATH
suele inicializarse en el fichero ".profile", consistiendo en una serie de nombres separados por el
carácter “:”. PATH=/usr/juan/bin:/usr/ucb:/bin:/usr/bin:/opt/informix/bin
$ man sh
$ man 2 exec
A continuación se muestra una versión del comando “man” realizado íntegramente en el lenguaje de
comandos de la CONSS:
N=n; s=1
for i
do
case $i in
[1-9]*)
s=$1
;;
-t)
N=t
;;
-n)
N=n
;;
-*)
echo “Opción desconocida \$i\”
;;
*)
if test –f man$s/$i.$s
then
$[N]roff man0/${N}aa man$s/$i.$s
else : busca a través de todas las secciones
found=no
for j in 1 2 3 4 5 6 7 8 9
do
if test -f man$j/$i.$j
then
man $j $i
found=yes
fi
done
case $found in
no)
echo “No existe página: $i”
;;
esac
fi
;;
esac
done
El programa utilizaría los impresores "troff" o "nroff”, tomando este último por defecto, al inicializar N=n.
Si entre los argumentos aparece un número en el rango de 1 a 9, este número se toma como la sección.
Tras comprobar la existencia del comando y la sección especificados, procede a su impresión,
devolviendo un mensaje de error en caso contrario.
echo $d
O bien:
echo ${d}
No hará nada, al ser “d” una cadena de caracteres nula. Sin embargo, es posible especificar un valor por
defecto, en la forma:
echo ${d-.}
Que hace que se imprima el valor de la variable “d” si esta variable ha sido inicializada, o un punto “.” en
caso contrario. Análogamente:
echo ${d-$1}
Mostrará el valor de la variable "d" si ha sido inicializada, o el valor del parámetro posicional $1 en caso
contrario.
echo ${d?mensaje}
Mostrará el valor de la variable "d", o sino el texto “mensaje” finalizando la ejecución del programa. Si no
se ha especificado "mensaje”, entonces se emplearía un mensaje de error estándar. Un programa CONSS
que requiera algunos parámetros podría entonces inicializarse como:
Donde el carácter dos puntos ":" es un comando que no hace nada una vez que sus argumentos han
sido evaluados. Si cualquiera de las variables "usuario”, "acct" o "bin" no han sido inicializadas,
entonces se abandonará la ejecución del programa.
d=`pwd`
d=/usr/juan/programas
La totalidad de la cadena de caracteres comprendida entre acentos graves (“`”) se considera como un
comando a ejecutar, y se reemplaza el texto entre “`” por la salida de ese comando.
La sustitución de comandos tiene lugar en todos aquéllos casos donde se realiza la sustitución de
parámetros, permitiendo el empleo de comandos de procesamiento de cadenas de caracteres, incluidos
en instrucciones de la CONSS. Por ejemplo, consideremos el comando "basename" que elimina un sufijo
(una terminación) determinada de una cadena de caracteres. Así:
basename main.c .c
Produciría como resultado la cadena "main", al eliminar la terminación “.”. Esto podría aparecer como
una parte de una CONSS destinada a compilar programas C, en la que se incluiría una parte como:
case $A in
“....”
*.c) B=´basename $A .c´
“....”
esac
Inicializando B como la parte correspondiente al nombre $A, con la terminación “.c” suprimida.
Tener cuidado al utilizar las comillas (“), apóstrofes (‘) y acentos graves (`). La Tabla siguiente explica lo
que supone cada uno de estos símbolos
Símbolo Significado
“ Las comillas desactivan la creación de nombres de archivos y suprimen la expansión del
parámetro. Sin embargo, la sustitución de comandos y variables de CONSS sigue activada.
‘ El apóstrofe desactiva toda la función de análisis; todo lo que se encuentre dentro de los
apóstrofes se traspasa como un solo parámetro.
` El acento grave, o comilla inversa, implica sustitución de comandos. Todo lo que está
incluido entre acentos graves se ejecuta como si el comando hubiera sido ejecutado en su
propia línea. Cualquier salida situada en la salida estándar sustituye entonces el comando.
La línea de comandos vuelve a analizarse en busca de parámetros.
Today’s date and time are Mon May 18 14:35:09 EST 1994
Para conseguir que el comando echo se comporte correctamente, la posición ‘s en Today’s del
comando anterior va precedida de una barra inversa (\), también llamada carácter de escape. (Today\'s).
Virtualmente, cada carácter no alfanumérico de su teclado tiene algún significado especial para la CONSS.
Para utilizar cualquiera de los caracteres especiales en una secuencia y evitar que la shell interprete el
carácter, deberá “escapar” el carácter, es decir, deberá hacerlo preceder del carácter de escape. Si
deseara pasar el propio carácter de barra inversa, escriba \\. Para pasar un signo de dólar como un
comando, escriba \$.
El tipo más sencillo de expresión regular es la cadena. Una cadena es un conjunto de caracteres, como
and. La sintaxis para un comando grep es la siguiente:
Por ejemplo, para buscar la palabra parte en un archivo denominado michel, habría que introducir el
comando siguiente:
Si ésta fuera la única línea del archivo de texto que contuviera la palabra parte, grep devuelve todas y
cada una de las líneas de un archivo de texto donde aparezca la cadena buscada.
Las expresiones regulares utilizan caracteres especiales. Los caracteres especiales más utilizados en las
expresiones regulares son el punto (.), el asterisco (*), los paréntesis cuadrados ([ ]), la barra lateral (/),
el acento circunflejo (^) y el signo dólar ($), La Tabla siguiente presenta todos estos caracteres
especiales junto a la función que cumplen en las expresiones regulares.
Carácter Descripción
. Busca todas las coincidencias con un solo carácter, salvo que este carácter único sea un
retorno de línea. Por ejemplo, b.d coincidirá con bad y bod.
* Busca cero o más coincidencias de la expresión regular anterior. Así, el patrón 4*
coincidirá con 4, 41, 422, etc.
Carácter Descripción
[] Se utiliza para agrupar un conjunto de distintos elementos y buscar sus coincidencias.
Recuerde que UNIX distingue entre mayúsculas y minúsculas. Por ejemplo, si desea
buscar todas las coincidencias del nombre Michel, puede utilizar [Mm]ichel para buscar
tanto michel como Michel, pero no MICHEL. Si desea buscar el carácter ], puede utilizar [
]], o bien usar la barra lateral como carácter de escape para que el paréntesis derecho se
considere como un carácter de texto, como /]. Un guión dentro de los paréntesis cuadrados
sirve para indicar un intervalo. Por lo que [a-j] es lo mismo que [abcdefghij].
/ Se utiliza para salir de las distintas funciones que tienen asignados todos los caracteres
especiales y para que sean considerados como caracteres de texto susceptibles de ser
buscados. Así son, con * se buscan todos los elementos coincidentes, con /* sólo se
buscará el que contenga el carácter *. Lógicamente, para buscar un carácter de barra
lateral dentro de una cadena, habría que escribir //.
^ Si ^ se encuentra en el principio de la cadena, sólo se buscarán aquellas cadenas que
empiecen por la cadena buscada. Por ejemplo, si tiene un archivo de texto con números de
teléfonos ordenados por código de área, la expresión regular ^704 buscará todos los
números de teléfono que empiecen por el código de área 704, pero no aquellos que
contengan los tres números como 407.
$ Si $ se encuentra al final de una expresión regular, sólo se buscarán aquellas cadenas
cuya máscara se encuentre al final de la cadena.
Puede especificar el número de caracteres coincidentes que desea buscar utilizando las llaves { }. Por
ejemplo, el comando:
g\{3,4}
Aunque probablemente una forma más efectiva de hacer lo anterior sea buscar directamente el número
de teléfono. Supongamos que su amigo vive en un área de código telefónico 408. El comando:
Buscará todos los números de teléfono que empiecen por 408. Observe que las cadenas 408, [0-9] \ {3}
y [0-9] \ {4\} están separadas por un punto (.). El punto permite buscar cualquier carácter único, lo que
hace que se encuentren los números de teléfono 408-555-1212 o 408.555.1212.
Cuando la CONSS analice la línea de comandos, tratará el punto y coma como un carácter de final de línea.
Si a continuación escribe más comandos, la CONSS ejecutará cada comando secuencialmente como si
hubiera escrito cada uno de ellos en su propia línea:
Por ejemplo, puede escribir clear;ls para borrar su pantalla y mostrar un listado del directorio.
También puede utilizarse cualquier forma de redirección. La salida de un grupo de comandos puede
situarse en una tubería (EJEN) como en el ejemplo siguiente:
En este caso, la salida de XAU RIA–1 se incluye en la tubería; seguidamente la salida de XAU RIA–2 se
incluye en la misma tubería; y XAU RIA–Z observa sólo un cauce de datos.
Los comandos ejecutados en un grupo de comandos se ejecutan en la CONSS actual. Esto significa que es
posible que modifiquen el entorno o cambien directorios.
17.7.2 SUBSHELLS
Cuando ejecuta una serie de comandos como un grupo de comandos, éstos se ejecutan en la CONSS
actual. Si uno de los comandos modifica el entorno o cambia el directorio, los cambios se aplican cuando
el grupo de comandos termina de ejecutarse. Para evitar este problema, ejecutar un grupo de comandos
en una subshell.
Una CHBCONSS es una copia de la CONSS actual pero, puesto que los procesos hijo no pueden modificar el
entorno de proceso padre, los comandos ejecutados en una CHBCONSS no tienen efecto alguno sobre el
entorno cuando el grupo de comandos finaliza. Para ejecutar un grupo de comandos en una CHBCONSS,
sustituir las llaves por paréntesis. El ejemplo de grupo de comandos utilizado en el apartado anterior se
convierte en lo siguiente:
Sólo XAU RIA–Z se ejecuta en la CONSS actual, pero la salida de la CHBCONSS se conduce a la entrada
estándar de XAU RIA–ZÁ
Sustitución de comandos, por ejemplo ´pwd´. Solo tiene lugar una evaluación, de manera que si, por
ejemplo, el valor de la variable X es la cadena $y, entonces:
echo $X
Interpretación de espacios en blanco. De acuerdo con las sustituciones anteriores, los caracteres
resultantes se parten en palabras distintas de blancos. Para esta finalidad se consideran "blancos"
los caracteres de la cadena $IFS, variable da la CONSS (lo mismo que HOME y PATH, definidas
anteriormente). Por defecto, la cadena de caracteres $IFS contiene un espacio en blanco, un
tabulador y un salto de línea.
La cadena nula no se considera como una palabra, a menos que vaya entre comillas simples (´´).
Así:
echo ´´
Tomaría un nulo como primer argumento del comando echo, mientras que:
echo $nulo
Ejecutará echo sin argumentos, si la variable nulo no ha sido inicializada o si su contenido es una
cadena nula.
Generación de nombres de ficheros. Se explora cada palabra buscando los caracteres "*", "?” y
“[....]”, y se genera una lista alfabética de nombres de ficheros para reemplazar la palabra. Cada
nombre de fichero es un argumento por separado.
Esta lista de sustituciones que acaba de describirse tiene lugar para cada uno de los argumentos
integrantes de un bucle “for”.
La ejecución de un comando puede producir un error por cualquiera de las siguientes razones:
Fallos en la redirección de la entrada o salida. Por ejemplo un fichero no existe, no puede crearse, o
no se puede abrir.
El comando termina su ejecución normalmente pero sin embargo devuelve un valor distinto de cero a
su finalización.
El indicador "-e" de la CONSS causa su terminación en caso de que se detecte algún error durante la
ejecución.
Las señales indicadas con un "*" producen un volcado de memoria si no son invalidadas. Las señales
software que poseen algún interés para nosotros son las número 1, 2, 3, 14 y 15.
Los programas en CONSS normalmente terminan su ejecución cuando reciben una señal de interrupción
desde el terminal. Se utiliza el comando "trap" cuando se desea ejecutar alguna acción antes de finalizar
la ejecución, como borrar algún fichero temporal, cerrar ficheros, etc... Por ejemplo:
Inicializa un “trap” (rutina de tratamiento de errores) para la señal número 2 (interrupción), de manera
que cuando se reciba la señal se ejecutarán los comandos:
rm /tmp/ps$$; exit
"exit" es otro comando de la CONSS que finaliza la ejecución de un programa. Es obligatorio incluirlo en
este caso porque sino, después de ejecutar el "trap", la CONSS proseguiría la ejecución a partir de la línea
en la que se produjo la interrupción.
Pueden ser ignoradas, en cuyo caso las señales nunca llegaran a enviarse al proceso.
Pueden ser detectadas, de modo que el proceso decida que acción tomar cuando reciba una señal.
Se puede dejar que causen la terminación del proceso sin por ello llevar a cabo ninguna acción
posterior.
El siguiente ejemplo muestra el programa "busca", que es un ejemplo de un "trap" sin sentencia "exit".
"busca" explora cada directorio incluido en el directorio de trabajo, solicita y ejecuta los comandos
introducidos desde el terminal, hasta que se alcance un final de fichero o se reciba una interrupción. Las
interrupciones se ignoran mientras se están ejecutando los comandes indicados, pero causan la
terminación del programa cuando "busca" está esperando una entrada de datos por pantalla:
d=`pwd`
for i in *
do
if test –d $d/$i
then
cd $d/$i
while echo “$i:“
trap exit 2
read x
do trap : 2; eval $x; done
fi
done
"read x" es un comando de la CONSS que acepta una línea a partir de la entrada estándar, y deja el
resultado en la variable “x”. Devuelve un valor distinto tanto si se alcanza un final de fichero, como si se
produce una interrupción.
trap ´´ 1 2 3 15
exec $*
El “trap” invalida las señales 1, 2, 3 y 15, que seguirán siendo ignoradas por los comandos que se
ejecuten posteriormente, al reemplazar "exec" la CONSS por cada uno de los comandos que figuren en “$*”.
Para finalizar esta sección dedicada al intérprete de comandos o CONSS, realizaremos un pequeño
resumen acerca de la redirección de la entrada y salida, que ya hemos tratado con anterioridad:
Redirección Descripción
> f1 La salida estándar (descriptor de fichero 1) se envía al fichero "f1", creándose si no
existiese anteriormente.
>> f1 La salida estándar se envía al fichero "f1". Si ya existía el fichero, entonces se añade
al contenido anterior, y en caso contrario se crea el fichero.
< f1 Se toma la entrada estándar (descriptor de fichero 0) a partir del fichero “f1”.
<< f1 Se toma la entrada estándar a partir de líneas de entrada de la CONSS, hasta que se
encuentre una línea que contenga la cadena "f1".
>&<num> El descriptor de fichero "num" se duplica por medio de la función primitiva dup,
utilizándose el resultado como fichero de salida estándar.
<&<num> La entrada estándar se duplica a partir del descriptor de fichero <num>.
El comando:
El comando echo permite tranquilizar a los usuarios después de haber introducido datos en un comando,
en especial si el comando no proporciona salida alguna durante un periodo de tiempo.
El comando echo es también de utilidad cuando desee rastrear un archivo de secuencias de CONSS. Si
utiliza el comando echo como puntos clave, sabrá en todo momento lo que está ocurriendo en un
proceso CONSS. A continuación se muestra el archivo KHJNRNCÓ con varios comandos echo añadidos:
$ quienesta
Veamos quién está en el sistema
root tty01 Jan 17 10:22
pedro tty03 Jan 17 10:13
elena tty07 Jan 17 10:17
¿Alguna cita?
12/20 Reunión de Ventas at 1.45
12/21 comida posterior
Mon Dec 20 09:02 EST 1993
Todo realizado
$
El símbolo de la almohadilla (#) indica el principio del comentario incluido en la CONSS. Cada carácter
incluido desde donde está ubicada la almohadilla hasta el final de la línea forma parte del comentario. A
continuación, le presentamos un ejemplo de archivo de secuencias de CONSS comentado:
#Nombre: quienesta
#Escrito: 3-12/99, Juan Pérez
#Objetivo: Visualizar quien está conectado, citas, fecha
echo “Veamos quién está en el sistema“
#Comprobar quien está conectado
who
echo “¿Alguna cita?“
#Comprobar citas
calendar
#Mostrar fecha
date
echo “Todo hecho“
Vuelva a ejecutar el archivo de secuencias de CONSS y aparecerá de nuevo los mensajes anteriores. Los
comentarios no modifican en absoluto la ejecución de la CONSS.
La forma más directa de otorgar un valor a una variable es escribiendo una expresión como, por ejemplo:
miemail=juanl@criton.com
Esta expresión asigna a la variable UJNU JS,el valor jH RS@XMJÓARÁXAU. No incluya espacios a los lados
del signo igual (=). El método de asignación directa para otorgar un valor a una variable tiene el siguiente
formato:
nombre_variable=valor_variable
Si Í SAMsÍ MJ BSN contiene espacios en blanco, ponga el valor entre comillas. Por ejemplo, para asignar
una dirección de oficina de 1d,7AC j,21Á,iJCA,4Á1 a la variable UJIJMNX, se utiliza el comando siguiente:
La CONSS recupera el valor de la variable siempre que vea un signo de dólar ($) seguido del nombre de la
variable. Podrá verlo cuando se ejecuten las dos instrucciones siguientes:
Suponga que copia archivos con frecuencia a un directorio llamado dB CNdEHBSJXAdNUEMNC dXAUEM C.
Para copiar un archivo llamado B CJXA a este directorio, escriba lo siguiente:
cp basico /base/publico/empresa/compras
Para simplificar este directorio, puede asignar el nombre largo de directorio a la variable IJMXAUEM ,
utilizando la expresión siguiente:
dircompra=/base/publico/empresa/compras
cp basico $dircompra
La shell sustituye $IJMXAUEM por el valor de la variable IJMXAUEM y después procesa comando copiar.
# Nombre: copiabase
El comando read detiene el comando y espera la entrada procedente del teclado. El comando continúa
cuando se pulsa la tecla <Intro>. El comando finaliza si se introduce <Ctrl.-d> (representado algunas
veces como ^D) mientras el comando read está esperando entradas.
# Nombre: mosvars
# Objetivo: mostrar el uso de variables de la línea de comandos
echo $0
echo $2 $4!
echo $3
mosvars
hola luis!
Ves?
En esta salida, la primera línea es el nombre del comando (variable $0), la segunda línea está constituida
por el segundo y cuarto argumento (variables $2 y $4). La última línea es el tercer argumento (variable
$3).
A continuación, le presentamos un ejemplo más serio. Este archivo de secuencias de CONSS borra un
archivo pero antes lo copia al directorio dÓUE para que pueda recuperarse si fuera necesario.
#Nombre: segrm
#Objetivo: copiar el archivo a directorio /tmp ,luego eliminarlo
# desde el directorio actual
# primero copia $1 to /tmp
cp $1 /tmp
#ahora elimina el archivo
rm $1
Si escribe CNTMU, BX,IN6 y pulsa <Intro> sólo se eliminará el archivo BX del directorio actual puesto que
el archivo de secuencias CNTMU borra sólo la variable $1. Puede, sin embargo, representar todos los
parámetros de la línea de comandos con $*. Convierta CNTMU en un archivo más general sustituyendo
cada caso $1 por $*. Si escribe entonces CNTMU,YVz,B C,IHC se eliminarán los tres archivos (YVzj,B C,V,
IHC) del directorio actual.
cwd=`pwd`
Observe que EDI, el comando de impresión del directorio de trabajo, está puesto entre acentos graves
en lugar de apóstrofes.
El siguiente archivo de secuencias shell modifica el nombre de un archivo añadiendo el mes, día y año
actual al nombre del archivo:
# Nombre: marca
# Objetivo: asignar nuevo nombre de archivo: añadir fecha de hoy
# al nombre del archivo
# asignar td a la fecha actual en forma de mmddyy
td=`date +%m%d%y`
# asignar un nuevo nombre de archivo
mv $1 $1.$td
En este ejemplo la variable ÓI se asigna a la fecha actual. En la última línea esta información se añade a
la variable $1. Si hoy fuera el 2 de enero de 1999 y utilizase este comando en un archivo llamado
UJ6JXONMA, se le asignaría al archivo el siguiente nombre (se le desplaza) a UJ6JXONMAÁ010299.
Puede utilizar el apóstrofe para hacer que la CONSS ignore caracteres especiales. Ponga entre apóstrofes
la secuencia de caracteres como en el ejemplo siguiente:
Con ello se consigue que el comando TMNE muestre las líneas del archivo NUESN IAC que empiecen por
AS6MNIA,2óENz. El acento circunflejo (^) indica a TMNE que busque desde el principio de la línea. Si AS6MNIA,
2óENz no se hubiera escrito entre apóstrofes, se hubiese interpretado literalmente (o como un símbolo de
conexión en algunos sistemas). Además, la CONSS ignora el espacio entre AS6MNIA,2óENz cuando no se
pone entre apóstrofes.
También puede utilizar comillas para hacer que la CONSS ignore la mayor parte de caracteres especiales,
con la excepción del signo del dólar y el acento grave. En el ejemplo siguiente, los asteriscos, espacios y
el signo mayor se tratan como caracteres ordinarios debido a que la secuencia está puesta entre
comillas:
En este ejemplo, sin embargo, $LOGNAME se evalúa correctamente, pero no hay valor para $5:
Utilice la barra inversa (\) para hacer que la CONSS ignore un solo carácter. Por ejemplo, introduzca el
comando siguiente para hacer que la CONSS ignore el signo del dólar delante del 5:
Los apartados siguientes utilizan ejemplos que no son demasiado complicados pero que muestran las
características esenciales de la programación con algún tipo de control.
case $var in
v1)
comandos;;
v2)
comandos;;
......
esac
La CONSS comprueba secuencialmente si el valor de "var" coincide con alguno de los “v1”, “v2”, ....,
referenciados, ejecutando los comandos especificados en su zona, antes de los dos “;” punto y coma
finales, finalizando la ejecución del "case" y pasando a ejecutar las sentencias posterior al “esac”. Como
el “*” es un valor que verifica siempre la CONSS, si lo incluimos como ultimo valor de búsqueda de la
variable “var” en el “case”, obtendremos como un IN6 HSÓ (defecto) en el caso de que no pase por
ninguno de los valores previamente definidos en el “case”. Veamos un ejemplo:
case $# in
1)
cat >> $1;;
2)
cat >> $2 < $1;;
*)
echo “empleo: suma desde [hasta]”;;
esac
$ suma f1
$# valdría 1, copiando la entrada estándar al final del fichero f1 por medio del comando cat.
Analogamente:
$ suma f1 f2
Añade el contenido del fichero f1 al final del fichero f2. Por el contrario, si el número de argumentos de
llamada fuese distinto de 1 o de 2, entonces se alcanzaría el valor por defecto "*", pasando a imprimirse
un mensaje de error.
También pueden emplearse valores alternativos en cada una de los "v1", “v2",..., por medio del empleo
de una barra vertical “|”. Así:
case $x in
-S|-s) .....
-N|-n) ....
esac
sería equivalente a:
case $x in
-[Ss]) .....
-[Nn]).....
esac
# Nombre: ShrtMenu
# Objetivo: Permite al usuario imprimir un archivo, eliminar
# Un archivo, o salir de un programa
# Visualización del menú
echo “Por favor seleccione P, D, o Q para”
echo “ [P]rint Imprime un archivo”
echo “ [D]elete Borra un archivo”
echo “ [Q]uit Sale de un programa”
# Obtiene respuesta del usuario
read respuesta
# Utilice case para que la respuesta coincida con la acción
case $respuesta in
P|p)
echo “¿Nombre del archivo a imprimir?
read filename
lp $filename
;;
D|d)
echo “¿Nombre del archivo a eliminar?”
read filename
rm –i $filename
;;
*)
echo “Salir ahora”;;
esac
case word in
pattern)
statement(s)
;;
pattern)
statement(s)
;;
…
esac
El parámetro DAMI se compara con cada uno de los parámetros E ÓÓNMR, empezando por el patrón en
cabeza del listado. Las instrucciones que se ejecutan si DAMI coincide con el patrón, se terminan por dos
signos de punto y coma (;;). El final de la instrucción case viene marcada por la palabra esac (de hecho
es la palabra “case” pero deletreada al revés).
En el listado anterior, la barra vertical (|) se utilizó para proporcionar una elección a una concordancia.
Por ejemplo, P|p significa que tanto la P mayúscula como la p minúscula se consideraban una
concordancia.
El patrón * se utiliza para representar el resto de patrones no explícitamente descritos. El usuario saldrá
del menú si pulsa cualquier tecla que no sea <P>, <p>, <D> o <d>.
El Listado siguiente utiliza una instrucción case que realiza una selección según el número de
parámetros que la shell representa como $#.
# Nombre: reciente
# Objetivo: listar los archivos más recientes en un directorio
# Si el usuario escribe reciente <Return> se mostrarán los
# nombres de los 10 archivos modificados más recientes
# Si el usuario escribe reciente n <Return> entonces se
# mostrarán los nombres de los n archivos modificados más
# recientes. De lo contrario, se informa al usuario de un uso
# incorrecto
#
# case basado en número de parámetros
case $# in
0)
ls –lt | head
;;
# ls –lt lista nombre de archivos en función del tiempo de
# modificación del fichero. Head muestra las 10 primeras líneas
# de un archivo
1)
case $1 in
[0-9]
ls –lt | head -$1
;;
*)
echo “Uso: número de archivos recientes“
;;
esac
;;
*)
echo “Uso: número de archivos recientes“
;;
esac
Si $? Tiene un valor igual a 0, esto significa que el comando anterior ha tenido éxito; en caso contrario, el
comando no se ha ejecutado con éxito.
A continuación, se muestra un ejemplo en el que se utiliza el estado de salida del comando DOA,|,TMNE,$1
en la instrucción X CN:
# Nombre: just.check
# Objetivo: Determinar si alguien está conectado al sistema
# Uso: just.check nombre_login
#
case ‘who | grep $1 > /dev/null‘ in
0)
echo “$1 está conectado“
;;
*)
echo “$1 No está aquí. Inténtelo más tarde.“
;;
esac
echo “Pase un buen día!”
if condición
then
comando
else
comando
fi
La condición lógica incluida en el if suele consistir en una instrucción "test", al igual que el caso de
"while". Las alternativas "then" y "else" se refieren a las acciones a ejecutar en el caso de que la
condición lógica comprobada en el "if" sea cierta o falsa, respectivamente.
La secuencia:
if comando1
then
comando2
fi
comando1 || comando2
Ejecutaría "comando2" solamente si "comando1” devuelve un valor falso. En cada uno de los casos el
valor devuelto por la expresión corresponde al del último comando simple ejecutado.
La estructura if...then...else...fi es una estructura de decisión que le permite seleccionar entre dos
posibilidades de acción, según el resultado de un comando. La porción NSCN de la estructura es optativa.
Uno o más comandos van en lugar de los puntos (...). Los comandos que siguen a ÓONR y preceden a
NSCN (si lo hubiera) se ejecutarán siempre que el estado de salida del último comando después de J6 sea
cero (es decir, que el comando se haya ejecutado con éxito). En caso contrario, se ejecutarán los
comandos que siguen a NSCN.
En otras palabras, se ejecutan uno o más comandos. Si el último comando ha tenido éxito, se ejecutarán
los comandos de la porción ÓONR de la instrucción y después los comandos a continuación de 6J (el final
de la estructura). Si los últimos comandos no tienen éxito, se ejecutarán los comandos situados tras NSCN.
Observe este ejemplo que se comporta como el escrito anteriormente con la instrucción case:
# Nombre: just.check
# Objetivo: Determinar si alguien está conectado al sistema
# Uso: just.check nombre_login
#
if who | grep $1 > /dev/null
then
echo “$1 está conectado“
else
echo “$1 No está aquí. Inténtelo más tarde.“
fi
echo “Pase un buen día!”
El comando "test", aunque no forma parte de la CONSS, se utiliza para su uso exclusivo. Consiste en la
evaluación de una determinada condición, devolviendo un valor cierto o falso, según que se cumpla o no
la condición. Por ejemplo:
test -f f1
Devuelve el valor 0 si el fichero “f1” existe, y un valor distinto de cero en caso contrario. Entre las
comprobaciones mas habituales se pueden citar:
Opción Descripción
test s cierto si la cadena s no es nula.
test -f fichero cierto si "fichero" existe.
test -r fichero cierto si "fichero" se puede leer.
test -w fichero cierto si "fichero" se puede escribir.
test -d fichero cierto si "fichero" es un directorio.
Muchos de los archivos de secuencias de CONSS utilizados en este capítulo esperan que el usuario se
comporte correctamente. Las secuencias no tienen forma de comprobar si el usuario tiene permiso para
copiar o mover archivos o si el usuario estaba tratando con un archivo ordinario en lugar de con un
directorio. El comando test trata con estas cuestiones (y con otras más). Por ejemplo, ÓNCÓ,–6, BX tendrá
éxito si BX existe y es un archivo regular.
Puede invertir el significado de una prueba utilizando un signo de exclamación delante de la opción. Por
ejemplo, para probar que no tiene permiso de lectura para el archivo BX, utilice ÓNCÓ,!4M, BX. La Tabla
siguiente lista varias opciones para el comando test.
Opción Significado
-f Con éxito si el archivo existe y es un archivo ordinario.
-d Con éxito si el archivo es un directorio.
-r Con éxito si el archivo existe y es legible.
-s Con éxito si el archivo existe y no está vacío.
-w Con éxito si el archivo existe y puede escribirse en él.
-x Con éxito si el archivo existe y es ejecutable.
# Nombre: copia_seg
# Objetivo: Copiar archivo1 a archivo2
# Comprobar si existe permiso de lectura en archivo1
# Si el archivo2 existe entonces
# si el archivo2 es un archivo en el que se
# puede escribir entonces avisar a usuario, y
# obtener permiso para continuar
# else exit
# else
# copy file
#
# Buscar número correcto de argumentos
case $# in
2)
if test !-r $1 # no puede leer el primer archivo;;
then
exit(1) # salida sin estado de cero
fi
if test –f $2 # existe el segundo archivo
then
if test –w $2 # puede escribirse en él?
then
echo “$2 ¿Existe una copia de esto? (Y/N)“
read resp #obtener permiso del usuario
case $resp in
Y|y)
cp $1 $2 #seguir adelante
;;
*)
exit(1) #Adiós!
;;
esac
else
exit(1) # Segundo archivo existe pero no
# puede escribirse
fi
else # Segundo archivo no existe, seguir adelante y
# copiar!
cp $1 $2
fi
;;
*)
echo “Uso: copia_seg fuente destino“
exit (1)
;;
esac
También puede utilizar el comando test para probar números. Utilice ÓNCÓ,$OAM ,–TÓ,12 para determinar si
un valor en la variable OAM es mayor que 12. La Tabla siguiente muestra algunas opciones que podrá
utilizar con test cuando está comparando números.
Tabla: Opciones para la utilización del comando test durante la comparación de números
Opción Significado
-eq Igual.
-ne Desigual.
-ge Mayor o igual que.
-gt Mayor que.
-le Menor o igual que.
-lt Menor.
El listado siguiente muestra estas opciones utilizadas para mostrar un saludo de acuerdo con la hora del
día.
# Nombre: saludo
# Objetivo: Mostrar Buenos días si la hora es menor que 12
# Buenas tardes si la hora es menor que 17
# Buenas noches si la hora es mayor que 16
# Obtener la hora
hora=‘date +%H‘
# Comprobar la hora del día
if test $hora –lt 12
then
echo “Buenos días, $LOGNAME“
else
if test $hora –lt 17
then
echo “Buenas tardes, $LOGNAME“
else
echo ”Buenas noches, $LOGNAME“
fi
fi
“.......”
juan 4712912
tomas 4167811
fernando 4527833
alfredo 4450122
“.....”
for i in $*
# podríamos poner solo: for i
do
grep $i /usr/agenda/telefonos
done
La línea de comando:
$ tel juan
Mostraría en pantalla aquéllas líneas que contuviesen la cadera de caracteres "jH R" en el fichero
"dHCMd TNRI dÓNSN6ARAC".
Imprimiría las líneas que contuviesen el nombre “jH R”, y a continuación las que contuviesen el nombre
"6NMR RIA".
Donde lista-de-comandos se refiere a uno a mas comandos simples separados por un salto de línea o
por un punto y coma ";”. “do" y "done" son dos separadores para delimitar el cuerpo del bucle, "var" es
una variable de la CONSS, y "v1", “v2", ..., son algunos de sus posibles valores.
Cada vez que se encuentra un valor de "var" comprendido entre los “v1”, “v2”, ....., se ejecutará el
conjunto de instrucciones comprendidas en el cuerpo del bucle “for”.
En el caso de que "v1", "v2", .... se omitan, entonces se ejecutar el bucle para cada uno de los
parámetros posicionales, como si se tratase de la variable “$*”.
Las estructuras iterativas de control le permiten escribir archivos de secuencias de CONSS que contienen
bucles. Los dos tipos básicos de bucles son los bucles for y while.
Con los bucles for podrá especificar un conjunto de archivos o valores para que se utilicen con algunos
comandos. Por ejemplo, para copiar todos los archivos cuyos nombres terminen por los caracteres ÁÓYÓ al
directorio ÓNYÓ,IJM, utilice el siguiente bucle for:
for i in *.txt
do
cp $i textdir/$i
done
La CONSS interpreta la expresión 6AM,J,JR,*ÁÓYÓ y permite a la variable J que tome el nombre de cualquier
archivo en el directorio actual que termine por ÁÓYÓ. A continuación podrá utilizar la variable $J con
cualquier expresión comprendida entre las palabras clave do y done.
La secuencia que se relaciona en el Listado siguiente imprime un conjunto de archivos, cada uno de
ellos con su propia página titular. También envía correo al usuario sobre el estado de las solicitudes de
impresión. El carácter $* representa todos los parámetros dados al comando shell.
# Nombre: printil
# Objetivo: Imprimir uno o más archivos,
# cada uno con su página de titular
# Avisar al usuario que archivos se enviaron a la
# impresora y cuáles no.
# Hacer esto con todos los parámetros del comando
for i in $*
do
if lp –t $i –d lasers $i > /dev/null
then
echo $i >> impreso
else
echo $i >> no_impreso
fi
done
#fin del bucle
if test –s impreso
then
echo “Estos archivos fueron enviados a impresora“ > mes
cat impreso >> mes
mail $LOGNAME < mes
rm mes impreso
fi
if test –s no_impreso
then
echo “Estos archivos no fueron enviados a impresora” > mes
cat no_impreso >> mes
mail $LOGNAME < mes
rm mes no_impreso
fi
while condición
do
comando
done
Donde la condición comprobada por el while suele incluir la ejecución de un comando "test". Cada vez
que se comprueba la condición y esta es cierta, se ejecuta el comando(s) incluido(s) en el cuerpo del
bucle. Por ejemplo:
while test $1
do
“......“
shift
done
Es equivalente a la construcción:
for i
do
“......“
done
“shift” es un nuevo comando de la CONSS que desplaza los parámetros posicionales $2, $3, ....,
convirtiéndolos a $1, $2, ...., perdiendo el parámetro $1 anterior.
El bucle "until" es semejante al "while", con la diferencia de que se invierte la condición de permanencia
en el bucle: se ejecuta el bucle mientras la condición sea falsa y finaliza la ejecución cuando sea cierta.
El bucle while examina el estado de salida de un comando como la expresión if. La secuencia del listado
siguiente avisa a un usuario de la recepción de correo. La secuencia entiende que el usuario ha recibido
correo si el buzón de correo cambia. La secuencia utiliza el comando diff para comparar dos archivos y
después informa sobre las diferencias. El estado de salida es cero si los archivos son iguales (El
comando ha tenido éxito).
# Nombre: checkmail
# Objetivo: Avisar al usuario si el buzón de correo ha
# cambiado
# Sugerencia: Ejecutar esto en segundo plano
# obtener un tamaño del buzón para compararlo
cp $MAIL omail # Obtener el conjunto por primera vez
# mediante MAIL que es una es una variable
# especial referida al buzón del usuario
# mientras que omail y $MAIL son lo mismo, mantener en bucle
while diff omail $MAIL > /dev/null
do
cp $MAIL omail
sleep 30 #dormir, pausa de 30 segundos
done
#Tiene que haber un cambio en los archivos
echo “Correo Nuevo!!!!” | write $LOGNAME
Como habrá podido comprobar, algunos comandos y conceptos que utilizan las expresiones
if...then...else pueden transferirse a bucles while. La diferencia es que con los bucles while se está
tratando con un proceso iterativo y repetitivo.
Siempre que emita un comando, se iniciará una nueva CONSS, que heredará muchas de las características,
o gran parte del entorno, del la CONSS ya existente. En cuanto a la nueva CONSS, deben tenerse en cuenta
estas dos consideraciones:
La nueva CONSS se ejecuta en su directorio actual. El comando pwd devuelve el mismo valor dentro de
una CONSS que se proporciona antes del arranque de la CONSS.
La nueva CONSS recibe muchas de sus variables de la CONSS ya existente. Existen medios para asegurar
que las variables establecidas en la CONSS ya existente se exportan a la nueva CONSS.
today=Jueves
echo $today
Suponga que el comando echo muestra Jueves. Entonces decide escribir y ejecutar el siguiente archivo
de secuencias de shell llamado KHNIJ :
# Nombre: quedia
$ chmod +x quedia
$ today=Jueves
$ quedia
Hoy es .
Hoy es Viernes.
$ echo $today
Jueves
El valor de la variable ÓAI V en la CONSS de entrada al sistema es ÑHNÍNC. Cuando ejecute el archivo de
secuencias de CONSS KHNIJ , verá que la variable ÓAI V no está definida inicialmente (como muestra la
visualización eAV,NCÁ). En este momento la variable ÓAI V tiene asignado el valor VJNMRNC en la shell.
Cuando el comando KHNIJ termine, volverá a la shell de entrada al sistema y ÓAI V recuperará su valor
original.
Utilice el comando export para dar a la variable ÓAI V el mismo valor que tiene en la CONSS de entrada al
sistema, cuando se ponga en marcha el archivo de comandos KHNIJ . Este comando exporta o traslada
las variables desde una CONSS a CONSSC hijas.
Ahora cualquier CONSS que se ponga en marcha desde la shell del sistema heredará el valor de la variable
ÓAI V
$ today=Jueves
$ export today
$ quedia
Hoy es Jueves.
Hoy es Viernes.
$ echo today
Jueves.
Observe que el valor que se asigna a la variable ÓAI V,en la CONSS iniciada por el comando KHNIJ no
aparece de nuevo a la CONSS de entrada al sistema. La exportación o herencia de valores de variables
transcurre sólo en una dirección: desde una CONSS en ejecución hacia abajo a la nueva CONSS, nunca de
vuelta hacia arriba. Esto explica que, al cambiar su directorio actual dentro de una CONSS, siempre regrese
al lugar desde donde partió cuando finalice la CONSS.
Puede exportar cualquier variable para una CONSS hacia abajo a otra CONSS utilizando la sintaxis siguiente:
export nombre_variable
En esta sintaxis, RAUBMNsÍ MJ BSN es el nombre de la variable que desea exportar. Por ejemplo, para
cambiar su tipo de terminal desde su configuración actual a ÍÓ220, introduzca los comandos que se
muestran a continuación para hacer que el nuevo valor de 387),se encuentre disponible para todas las
CONSSC o programas posteriores:
TERM=vt220
export TERM
export PATH
cd $MACPROGC
echo "----- INICIO DE BUSQUEDA EN 'progc' --------" > $TEMP/$2
find `cat $HOME/install/MODULOS_PROGC` -name "*.c" -print -exec grep $3 "$1"
{} \; >> $TEMP/$2
cd $HOME
echo "----- INICIO DE BUSQUEDA EN 'lib' --------" >> $TEMP/$2
find lib -name "*.c" -print -exec grep $3 "$1" {} \; >> $TEMP/$2
cd $HOME
echo "----- INICIO DE BUSQUEDA EN 'aces' --------" >> $TEMP/$2
find aces -name "*.ace" -print -exec grep $3 "$1" {} \; >> $TEMP/$2
i=`expr $i + 1`
done
if [ $j = 1 ]
then
echo -n "Comienzo de la inserción en Librería de FINANCIX: "
tput rev; echo "'libconta.a'"; tput sgr0
ar rv $MACLIB/libconta.a $obj
rm -f $obj
else
echo -n "No se actua sobre la Librería: "
tput rev; echo "'libconta.a'"; tput sgr0
fi
echo "============================================================="
tput sgr0
echo "===================================================="
exit
fi
cd $MACBIN
cp /dev/null ERR_COMPIL
tput rev
echo "Borrado de Ficheros Ejecutables del Directorio: '"$MACBIN"'"
tput sgr0; tput bold
echo "======================================================================"
tput sgr0
borr_EXEC
cd $MACPROGC
borr_EXEC
for j in `cat $HOME/install/MODULOS_PROGC`
do
cd $MACPROGC/$j
borr_EXEC
for i in `ls *.c | cut -f1 -d.`
do
echo "Compilando Programa: '"$j"/"$i"'"
compit_C $i
if test ! -f $MACBIN/$i
then
echo "Error Compilación Programa: $j/$i" >>$MACBIN/ERR_COMPIL
fi
done
done
date
cd $MACBIN
chown root msg_usus
clear
echo "----------------->"
echo "Teclee Clave de Superusuario para Operación de Instalación"
echo "----------------->"
su - root -c "chmod u+s $MACBIN/msg_usus"
ln borradores borra_inic
ln borradores borra_fin
echo "INSTALANDO MENU PERSONAL DE LA INSTALACION"
echo "=========================================="
i=0
j=`cat $HOME/install/NOMBRE`
case $j in
"instal1" )
echo "Detectada Instalación: instal1"
cp $MACPANT/instal1.men $MACPANT/menu_conta.men
i=1;
;;
"sucursal" )
echo "Detectada Instalación: sucursal"
cp $MACPANT/sucursal.men $MACPANT/menu_conta.men
i=1;
;;
"base" )
echo "Detectada Instalación: base"
cp $MACPANT/base.men $MACPANT/menu_conta.men
i=1;
;;
esac
if [ $i = 0 ]
then
echo "ERROR --> No es un Nombre de Instalacion Registrado"
if test ! -f $TEMP".c"
then
tput blink; tput bold
echo "NO EXISTE EL FICHERO FUENTE DEL PROGRAMA \"C\". Revise"
tput sgr0; tput rev
echo "================================================================"
tput sgr0
exit
fi
SALE="N"
while [ $SALE = "N" ]
do
echo "================================================================"
echo -n "Opción de Porting de Compilación: "
tput rev; echo $PORT; tput sgr0
echo -n "Opciones en Flags de Compilación: "
tput bold; echo $MACFLAGS; tput sgr0
echo -n "Compilando Programa: "; tput rev
echo $TEMP".c"
tput sgr0; tput rev
echo "================================================================"
tput sgr0
cc -o $TEMP $TEMP".c" $PORT $MACFLAGS
if test ! -f $TEMP
then
tput bold
echo "Error Compilando programa : "$TEMP".c"
echo "No se ha generado el Ejecutable. Revise."
tput sgr0; tput rev
echo "=========================================================="
tput sgr0
echo "Solo <N> o <n> Salen del Proceso. Cualquier otra
Tecla+RETORNO entra en Edición"
tput bold
echo -n "Desea Entrar en Edición del Programa Fuente <S/N>: "
read TER
tput sgr0
case $TER in
"N" | "n" )
echo "===================================================="
exit
;;
esac
VI $TEMP.c
else
tput bold
echo "Compilación Correcta. Compilado programa : "$TEMP".c"
tput sgr0; tput rev
echo "=========================================================="
tput sgr0; echo -n "Tamaño del Ejecutable: ";
size $TEMP
echo "=========================================================="
SALE="S"
fi
done
echo -n "Pasando a "$MACBIN" el Ejecutable: "
tput rev; echo $TEMP; tput sgr0
mv $TEMP $MACBIN
tput rev
echo "======================================================================"
tput sgr0
case $TEMP in
"borradores" )
ln $MACBIN/$TEMP $MACBIN/borra_inic
ln $MACBIN/$TEMP $MACBIN/borra_fin
echo "Ejecutable Linkado"
echo "================================================================"
;;
esac
tput bel
uncompress BASE
if test ! -d RECU_nuevo$1
then
mkdir RECU_nuevo$1
mv BASE LISTA DIREC DIREC2 RECU_nuevo$1
cd RECU_nuevo$1
else
mv BASE LISTA DIREC DIREC2 RECU_nuevo$1
cd RECU_nuevo$1
fi
tar xvf BASE
rm BASE
cd ..
mkdir RECU_antigu$1
for j in `cat $HOME/RECU_nuevo$1/DIREC`
do
mkdir RECU_antigu$1/$j
done
for j in `cat $HOME/RECU_nuevo$1/LISTA`
do
cp $HOME/$j RECU_antigu$1/$j
done
2. Crear una CONSS hija escribiendo sh. Mirar el contenido de "XXX". ¿Qué ha ocurrido? Matar la CONSS
hija con las teclas CTRL-D. Mirar ahora el contenido de la variable "XXX".
3. ¿Qué comando se puede escribir en la CONSS padre para que la CONSS hija vea el contenido de la
variable "XXX"? ¿Cómo se pueden ver todas las variables que heredará la CONSS hija?
4. Crear otra CONSS hija. Mirar el contenido de la variable "XXX". Ahora asignar la variable "XXX" al
nuestro apellido. ¿Es "XXX" ahora una variable local o del entorno? Listar las variables del entorno.
¿Cómo está "XXX" asignada?
5. Borrar la variable "XXX" de la CONSS hija. ¿Existe "XXX" localmente o dentro del entorno?.
6. Matar la CONSS hija, volviendo a la CONSS de SATJR. ¿Existe "XXX" todavía? ¿Qué valor tiene?
7. Cambiar la CONSS de entrada por defecto para que sea csh y probar si es correcto su funcionamiento.
8. Asignar a una variable llamada "usuarios", los nombres de los grupos y los usuarios de cada uno;
probar también a visualizar el contenido de la variable.
9. Script que muestra la fecha, la ruta OAUN del usuario, y hace un listado de los ficheros y directorios
del directorio actual.
date
echo $HOME
ls
nombre=Alonso
hola1='Hola $nombre'
hola2="Hola $nombre"
hola3=`Hola $nombre`
comando=`ls`
echo $nombre
echo $hola1
echo $hola2
echo $hola3
echo $comando
echo "Guion: $0"
echo "Parámetro1: $1"
echo "Todos los parámetros: $*"
echo "Numero de parámetros: $#"
echo $*
shift 1
echo $1 $2 $3
shift 2
echo $1 $2
i=20
j=40
if test $i -le $j
then
echo VERDADERO
else
echo FALSO
fi
12. Script que muestra el uso de parámetros pasados al script (a la hora de ejecutarlo)
echo $0
echo $*
echo Parámetro 1: $1
echo Parámetro 2: $2
echo Parámetro 3: $3
echo Parámetro 4: $4
echo Parámetro 5: $5
echo Parámetro 6: $6
echo Parámetro 7: $7
echo Parámetro 7: $7
echo Parámetro 8: $8
echo Todos los parámetros pasados son: $*
shift 3
echo Tras eliminar los 3 parámetros quedan: $*
nombre="Alberto"
apellidos="Fernandez Alonso"
nameyape="$nombre $apellidos"
echo $nameyape
v1=`expr 4 + 4`
v2=`expr 4 - 4`
v3=`expr 4 \* 4`
v4=`expr 4 / 4`
v5="El resultado es: "
v5="El resultado es: "
echo "Valor de v1 --> $v5 $v1"
echo "Valor de v2 --> $v5 $v2"
echo "Valor de v3 --> $v5 $v3"
echo "Valor de v4 --> $v5 $v4"
15. Script al que se le pasa 3 parámetros (directorios) y testea si son 3 en caso de serlo, mira el
contenido que hay dentro de ellos con el comando ls
clear
if test $# -eq 3
then
echo "Ha pasado 3 parámetros"
echo "======================"
echo " "
echo " "
echo "Visualizando contenido de $1"
echo " "
ls $1
echo " "
echo "Visualizando contenido de $2"
echo " "
ls $2
echo " "
echo "Visualizando contenido de $3"
echo " "
l s $3
echo " "
echo " "
echo "Fin del proceso. ;)"
else
echo "No ha pasado los 3 parámetros"
fi
n=0
while test $n -le 10
do
result=`expr $n \* $1`
echo $1*$n = [$result]
n=`expr $n + 1`
done
x=0
until test $x -eq 10
do
x=`expr $x + 1`
echo $x
done
result=0
total=0
for result in $(ls -l|grep ^-|cut -c 39-42)
do
total=`expr $total + $result`
echo $result $total
done
echo total = $total
x=$1
cont=`expr $x - 1`
while test $cont -ge 1
do
x=`expr $x \* $cont`
cont=`expr $cont - 1`
done
echo El número factorial es: [$x]
21. Script que traslade todos los ficheros que empiezan por una letra minúscula al subdirectorio
minusculas y los que empiezan por mayúsculas al subdirectorio mayusculas
if test ! -d minusculas
then mkdir minusculas
cp `ls -l [a-z]* | grep ^- |cut -c 56-90` minusculas
fi
if test ! -d mayusculas
then mkdir mayusculas
cp `ls -l [A-Z]* | grep ^- |cut -c 56-90` mayusculas
fi
22. Script que lea texto (del terminal) y lo pase al fichero temp hasta que se introduzca un punto o el
7NÓHMR.
clear
txt="x"
echo "Grabando desde (stdin) al fichero log: temp"
echo "Para finalizar teclee un punto"
echo "==========================" >> temp
echo "Comienzo del fichero [log]." > temp
23. Script que pase a mayúsculas el contenido de todos los ficheros pasados como parámetros
x=0
for x in $*
do
cat $x | tr "[a-z]" "[A-Z]" > $x
done
18.2 DESCRIPCIÓN
El intérprete de comandos sh es un lenguaje de programación de comandos que ejecuta órdenes leídas
desde un terminal o un archivo.
jsh es una interfaz a la shell, que proporciona toda la funcionalidad de sh y permite el control de
trabajos.
/usr/lib/rsh es una versión restringida del intérprete de comandos estándar sh que se utiliza para
restringir accesos a entornos de ejecución, cuyas capacidades son más controladas que las del estándar
de la shell.
sh, jsh, y rsh procesan el código suplementario del conjunto de caracteres en los argumentos de
comandos, en los valores de las variables y los separadores de campo, en las cadenas de petición, en
los comentarios y las tuberías, y en los scripts de acuerdo a la configuración regional especificada en la
variable de entorno LC_CTYPE. Lasbúsquedas de patrones se realizan en los caracteres, no en los
bytes, como se describe en la sección de Generación de Nombre de A.
18.3 DEFINICIONES
Un blanco es un tabulador o un espacio. Un nombre es una secuencia de letras, dígitos o subrayados,
comenzando con una letra o un subrayado. Un parámetro es un nombre, un dígito, o cualquiera de los
siguientes caracteres: *, @, #, ?, -, $ y !.
18.4 COMANDOS
Un comando simple es una secuencia de palabras sin blancos separados por espacios en blanco. La
primera palabra especifica el nombre del comando a ejecutar. Excepto como se especifica a
continuación, las palabras restantes se pasan como argumentos para el comando invocado. El nombre
del comando se pasa como argumento 0. El valor de un comando simple es su estado de salida si se
termina normalmente, o (octal) 200+estado si se termina de forma anormal.
Una tubería es una secuencia de uno o más comandos separados por |. (El símbolo de intercalación (^)
es un sinónimo obsoleto para la barra vertical y no debe ser utilizado en una tubería. Los scripts que
utilizan ^ para las tuberías son incompatibles con la shell de Korn.) La salida estándar de cada comando,
menos la del último, está conectada por una tubería a la entrada estándar del comando siguiente. Cada
comando se ejecuta como un proceso independiente; la shell espera a que el último comando termine. El
estado de salida de una tubería es el estado de salida del último comando de la tubería.
Una lista es una secuencia de una o más tuberías separadas por ;, &, && o ||, y, a veces terminado por ;
o &. De estos cuatro símbolos, ; y & tienen la misma prioridad, que es inferior a la de && y ||. Los
símbolos && y || también tienen la misma prioridad. Un punto y coma (;) produce la ejecución secuencial
de la tubería anterior o precedente (es decir, la shell espera a que la tubería termine antes de ejecutar
cualquier comando siguiente al punto y coma); un signo (&) produce una ejecución asíncrona de la
tubería anterior (es decir, la shell no espera a que la tubería finalice). El símbolo && (||) hace que la
siguiente lista sea ejecutada sólo si la anterior tubería devuelve un estado de salida cero (no cero). Para
delimitar los comandos puede aparecer en una lista un número arbitrario de saltos de línea, en lugar del
punto y coma.
A menos que se indique lo contrario, el valor devuelto por un comando es el del último comando simple
ejecutado en el comando.
Cada vez que el comando for es ejecutado, el R UN se establece en la siguiente palabra tomada de la
lista DAMI. Si se omite la parte DAMI,…, el comando for ejecuta IA,SJCÓ una vez para cada parámetro de
posición que se establezca. La ejecución termina cuando no hay más palabras DAMI en la lista.
Un comando case ejecuta la lista SJCÓ asociada con el primer patrón E ÓÓNMR que coincida con la palabra
DAMI. La forma de los patrones es la misma que se utiliza para la generación de nombres de archivos,
excepto que la barra (CS CO), un punto inicial, o un punto inmediatamente después de una barra no
necesitan se ajustados de forma explícita.
if list then list [ elif list then list] ... [ else list] fi
Se ejecuta la lista SJCÓ siguiente al primer if, y si retorna un estado de salida cero, la lista SJCÓ siguiente al
primer then se ejecuta. De lo contrario, la lista SJCÓ siguiente a elif se ejecuta y, sí su valor de retorno es
cero, la lista SJCÓ siguiente al próximo then se ejecuta. Si esta falla, la lista SJCÓ siguiente al else se ejecuta.
Si no hay más listas else o then para ejecutar, entonces el comando if devuelve un estado de salida
cero.
Un comando while ejecuta repetidamente la lista SJCÓ del while y, sí el estado de salida del último
comando de la lista es cero, ejecuta la lista SJCÓ del do; de lo contrario el bucle termina. Si no se ejecutan
comandos en la lista SJCÓ del do, entonces el comando while retorna un estado de salida cero. until
puede se utilizado en lugar del while para negar el test de terminación del bucle.
(list)
{ list;}
La lista SJCÓ se ejecuta en la shell actual (es decir, la shell padre). El { debe ser seguido por un espacio.
name () { list;}
Define una función que se referencia por su nombre R UN. El cuerpo de la función es la lista SJCÓ de
comandos entre { y }. La lista SJCÓ puede aparecer en la misma línea que el {. Si se hace, el { y la lista
deben estar separados por un espacio. La } no puede estar en la misma línea que la lista SJCÓ, sino que
debe estar en una nueva línea. La ejecución de las funciones se describen más adelante. Los { y } no
son necesarios si el cuerpo de la función es un comando simple tal y como se ha definido.
Las siguientes palabras sólo son reconocidas como la primera palabra de un comando y cuando no
están entrecomilladas:
18.5 COMENTARIOS
Una palabra que empiece con el carácter # causa que esa palabra y todos los caracteres siguientes
hasta una nueva línea sean ignorados.
NOTA: La excepción a esto es cuando #! se utiliza como primera línea de un script de shell.
Antes de que la cadena se lea, no se hace ninguna interpretación en la cadena, salvo para quitar las
barras invertidas (\) usadas para escapar otros caracteres. Las barras invertidas se puede utilizar para
escapar de una comilla invertida (`) u otra barra invertida (\) y se retiran antes de que la cadena de
comandos se lea. Escapar la comilla invertida (o acento grave) permite la sustitución de comandos
anidados. Si la sustitución de comandos se encuentra dentro de un par de comillas dobles (" … `…. `
…"), una barra invertida usada para escapar de una doble comilla (\") será eliminada; de lo contrario, se
dejará intacta.
Si se utiliza una barra invertida para escapar un carácter de nueva línea (\newline), tanto la barra
invertida como el salto de línea se eliminan. Además, las barras invertidas usadas para escapar signos
de dólar (\$) se retiran. Dado que no la sustitución de parámetros se realiza en la cadena de comandos
antes de que se lea, la inserción de una barra invertida para escapar de un signo dólar no tiene ningún
efecto. Las barras invertidas que preceden a otros caracteres como \, `, ", nueva línea, y $, se dejan
intactos cuando la cadena de comandos se lea.
El ajuste de patrones o máscaras no se realiza sobre el valor. No puede haber una función y una variable
con el mismo nombre.
${parámetro}
El valor del parámetro, en su caso, es sustituido. Las llaves sólo son necesarias cuando el parámetro es
seguido de una letra, dígito o subrayado que no debe interpretarse como parte de su nombre. Si el
parámetro es * o @, se sustituye por todos los parámetros de posición, empezando por $1 (separados
por espacios). El parámetro $0 se establece a partir del argumento cero cuando la shell se invoca.
${parámetro:-palabra}
Si el parámetro está establecido y no es nulo, se sustituye por su valor, de lo contrario, se sustituye por
la palabra.
${parámetro:=palabra}
Si el parámetro no está definido o es nulo, se establece a palabra, en caso contrario, el valor del
parámetro es sustituido. Los parámetros posicionales no se pueden asignar de esta manera.
${parámetro:?palabra}
${parámetro:+palabra}
En las definiciones anteriores, la palabra no se evalúa a no ser que se vaya a utilizar como cadena de
sustitución, de forma que, en el siguiente ejemplo, pwd se ejecuta sólo si (d) no se ha definido o es nulo:
echo ${d:-`pwd`}
Si se omite los dos puntos (:) en las expresiones anteriores, la shell sólo controla si el parámetro se ha
establecido o no.
*
Se expande a los parámetros posicionales, empezando por el 1.
@
Se expande a los parámetros posicionales, empezando por el 1, excepto cuando se expande dentro
de comillas dobles, en cuyo caso cada parámetro posicional se expande como un campo
independiente.
#
El número de parámetros de posición en decimal.
-
Banderas (6S TC) suministradas a la shell en la invocación o por el comando set.
?
El valor decimal devuelto por el último comando ejecutado de forma sincrónica.
$
El número de proceso de esta shell. $ reporta el ID del proceso de la shell padre en todas las
construcciones de la shell, incluyendo tuberías, y sub-shells entre paréntesis.
!
El número de proceso del último comando shell invocado en B XLTMAHRI.
Los siguientes parámetros son utilizados por la shell. Los parámetros de esta sección también se
conocen como variables de entorno.
HOME
El argumento por defecto (directorio principal o de entrada de usuario) para el comando cd, ajustado
al directorio de entrada (SATJR) del usuario, por el comando login desde el archivo de contraseñas
(/etc/passwd).
PATH
La ruta de búsqueda de comandos. El usuario no puede cambiar PATH si se ejecuta bajo
/usr/lib/rsh.
CDPATH
La ruta de búsqueda para el comando cd.
MAIL
Si este parámetro se establece al nombre de un archivo de correo y el parámetro MAILPATH no está
definido, la shell informa al usuario de la llegada del correo en el archivo especificado.
MAILCHECK
Este parámetro especifica la frecuencia (en segundos) que la shell utiliza para la verificación de la
llegada de correo en los archivos especificados por los parámetros MAILPATH o MAIL. El valor por
defecto es 600 segundos (10 minutos). Si se establece en 0, la shell lo verifica antes de cada EMAUEÓ
del sistema.
MAILPATH
Es una lista de nombres de archivo separada por dos puntos (:). Si este parámetro se establece, la
shell informa al usuario de la llegada de correo en cualquiera de los archivos especificados. Cada
nombre puede estar seguido por % y un mensaje que se mostrará cuando cambia la fecha de
modificación. El mensaje por defecto es “VAH,O ÍN,U JS”.
PS1
La cadena del EMAUEÓ primario, por defecto $.
PS2
La cadena del EMAUEÓ secundario del sistema, por defecto >.
IFS
Los separadores internos de campos, por defecto el espacio, el tabulador, y el salto de línea. El valor
predeterminado es dependiente del sitio. Los caracteres originales de blancos (espacio, tabulación y
nueva línea) se consideran siempre separadores de campo internos.
LANG
Si este parámetro se establece, la shell lo utilizará para determinar la localización actual (SAX SN).
SHACCT
Si este parámetro se establece al nombre de un archivo modificable por el usuario, la shell escribe
un registro contable en el archivo para cada procedimiento de shell ejecutado.
SHELL
Cuando la shell se invoca, se analiza el entorno para este nombre. Si se encuentra y rsh es la parte
del nombre del archivo de su valor, la shell se convierte en una shell restringida.
TIMEOUT
Un valor distinto de cero para TIMEOUT hace que la shell salga después de $TIMEOUT segundos
de inactividad.
NOTA: Esta variable sólo se puede establecer sobre una base de todo el sistema en /etc/default/sh,
y no se puede establecer en el perfil de un usuario individual.
La shell da valores por defecto para PATH, PS1, PS2, MAILCHECK, e IFS. MAIL y HOME son
establecidos por login.
<word
>word
Usar la palabra como archivo de salida estándar (descriptor de fichero 1). Si el archivo no existe, se
crea, de lo contrario, se trunca a longitud cero.
>>word
Usar la palabra como archivo de salida estándar. Si el archivo existe, la salida se añade al mismo (en
primer lugar busca hasta el final de archivo), de lo contrario, se crea el archivo.
<<[-]word
1. Los tabuladores iniciales son saltados o despojados de la palabra antes de que la entrada de la
shell sea leída (pero después de que la sustitución de parámetros y comandos se haya llevado a
cabo en la palabra)
2. Los tabuladores iniciales son saltados o despojados desde la entrada de la shell, cuando esta es
leída y antes de que cada línea se compare con la palabra.
3. La entrada de la shell se lee hasta la primera línea que, literalmente, coincide con la palabra
resultante, o hasta el fin de archivo.
<&digit
Utiliza el archivo asociado con el descriptor de archivo dígit como la entrada estándar. Del mismo
modo para la salida estándar se utiliza >digit.
<&-
La entrada estándar está cerrada. Del mismo modo para la salida estándar se utiliza >&-.
Si cualquiera de las construcciones anteriores es precedida por un dígito, el descriptor de fichero que se
asociará con el archivo es el especificado por el dígito (en lugar del predeterminado 0 o 1). Por ejemplo:
... 2>&1 asocia el descriptor de fichero 2 con el archivo que actualmente está asociado con el descriptor
de archivo 1.
El orden en que se especifican las redirecciones es muy significativo. La shell evalúa las redirecciones
de izquierda a derecha. Por ejemplo: ... 1>xxx 2>&1 primero asocia el descriptor de fichero 1 con el
archivo xxx. Luego asocia el descriptor de fichero 2 con el archivo asociado con el descriptor de fichero 1
(es decir, xxx). Si el orden de las redirecciones se invirtieran, el descriptor de fichero 2 se asociaría con
el terminal (asumiendo que el descriptor de archivo 1 existe) y el descriptor de archivo 1 se asociaría con
el fichero xxx.
Si un comando es seguido por &, la entrada estándar por defecto para el comando es el archivo vacío
/dev/null. De lo contrario, el entorno para la ejecución de un comando contiene los descriptores de
archivo de la shell invocada modificados por las especificaciones de entrada / salida.
*
Concuerda con cualquier cadena, incluyendo los códigos suplementarios del conjunto de caracteres
y la cadena nula.
?
Coincide con cualquier carácter único, incluyendo los códigos suplementarios del conjunto de
caracteres.
[...]
Coincide con cualquier carácter de la cadena entre corchetes, o de cualquier carácter con un código
de valor dentro del rango designado con un signo menos (-), incluyendo los códigos suplementarios
del conjunto de caracteres. Cuando los caracteres en el rango son de conjuntos de códigos
diferentes, uno de los caracteres especificados el intervalo será correspondido. Si el primer carácter
después de la apertura de corchete [ es !, cualquier carácter que no está entre los encerrados es
correspondido y, concretamente, los códigos suplementarios del conjunto de caracteres.
NOTA: Todos los caracteres entrecomillados deben corresponderse de manera explícita en un nombre
de archivo.
18.11 ENTRECOMILLADO
Los siguientes caracteres tienen un significado especial para la shell y causan la terminación de una
palabra a menos que se entrecomille:
Un carácter puede estar entrecomillado (es decir, construido para permanecer por sí mismo)
precediéndolo con una barra invertida (\) o insertándolo entre un par de comillas simples o dobles ('' o
""). Durante el procesamiento, la shell puede entrecomillar ciertos caracteres para prevenir que
adquieran un significado especial. La barra invertida usada para entrecomillar un solo carácter es
removida antes de que el comando se ejecute. El par \newline se quita de la palabra antes de la
sustitución de comandos y parámetros.
Todos los caracteres encerrados entre un par de comillas simples (''), excepto una comilla simple, se
entrecomillan por la shell. La barra invertida no tiene un significado especial dentro de un par de comillas
simples. Una comilla simple puede ser entrecomillada dentro de un par de comillas dobles (por ejemplo,
"'"), pero una comilla simple no puede ser entrecomillada dentro de un par de comillas simples.
Dentro de un par de comillas dobles ("") se produce la sustitución de parámetros y comandos, y la shell
entrecomilla los resultados para evitar las interpretaciones de blancos y la generación de nombres de
ficheros. Si $* está dentro de un par de comillas dobles, los parámetros de posición son sustituidos y se
entrecomillan, separados por espacios entrecomillados ("$1 $2 ..."); sin embargo, si $@ está dentro de
un par de comillas dobles, los parámetros de posición son sustituidos y se entrecomillan, separados por
espacios no entrecomillados ("$1" "$2" ...). La \ entrecomilla los caracteres \, ', ", y $. El par \newline se
elimina antes de la sustitución de parámetros y comandos. Si una barra invertida precede a otros
caracteres que no sean \,`, ", $, y RNDSJRN, entonces la propia barra invertida es entrecomillada por la
shell.
El entorno para cualquier comando simple puede ser ampliado por un prefijo con una o más
asignaciones a parámetros. Por lo tanto:
TERM=450 cmd
Son equivalentes en cuanto a que a la ejecución de XUI le preocupa si XUI no es un comando especial.
Si XUI es un comando especial, entonces:
TERM=450 cmd
echo a=b c
set -k
echo a=b c
18.15 SEÑALES
Cuando un comando se ejecuta en segundo plano (cmd &) bajo sh, puede recibir la señal de
interrupción (SIGINT) y de finalizar (SIGQUIT), pero las ignora por defecto. (Un proceso en segundo
plano puede reemplazar este comportamiento predeterminado a través de trap o signal. Cuando un
comando se ejecuta en segundo plano bajo jsh, sin embargo, no recibe las señales de interrupción o
terminación. De lo contrario las señales tienen los valores heredados por la shell desde su padre, con la
excepción de tres señales: 11 (SIGSEV), 14 (SIGALARM), y 18 (SIGCHILD).
18.16 EJECUCIÓN
Cada vez que se ejecuta un comando, se llevan a cabo la sustitución de comandos, la sustitución de
parámetros, la interpretación de blancos, la redirección de entrada y salida, y la generación de nombres
de archivos antes mencionados. Si el nombre del comando coincide con el nombre de una función
definida, la función se ejecuta en el proceso shell (tenga en cuenta como difiere esto de la ejecución de
los procedimientos de shell). Si el nombre del comando no coincide con el nombre de una función
definida, pero coincide con uno de los comandos especiales que se enumeran a continuación, se ejecuta
en el proceso shell. Los parámetros posicionales $1, $2, .... se establecen en los argumentos de la
función. Si el nombre del comando no coincide con un comando especial, ni el nombre de una función
definida, se crea un nuevo proceso y se intenta ejecutar el comando a través de exec.
El parámetro shell PATH define la ruta de búsqueda para el directorio que contiene el comando. Los
nombres alternativos de directorios están separados por dos puntos (:). La ruta predeterminada es
/usr/bin. El directorio actual se especifica mediante un nombre de ruta nula, que pueden aparecer
inmediatamente después del signo igual, entre dos : delimitadores en cualquier lugar de la lista de rutas,
o al final de la lista de rutas. Si el nombre contiene un comando /, la ruta de búsqueda no se utiliza; tales
comandos no se ejecutarán por la shell restringida. De lo contrario, en cada directorio de la ruta se busca
el archivo ejecutable. Si el archivo tiene permiso de ejecución, pero no es un archivo a.out, se supone
que es un archivo que contiene comandos de la shell. Se genera una sub-shell para leerlo. Un comando
entre paréntesis también se ejecuta en una sub-shell.
Para los archivos de script de shell, para que los modos CNÓ,HCNM,9“,AR,NYNXHÓJAR' y/o CNÓ,TMAHE,9“,AR,
NYNXHÓJAR sean efectivos, la primera línea del archivo debe ser #! /sbin/sh
La ubicación en la ruta de búsqueda donde se encontró un comando es recordada por la shell (para
ayudar a evitar ejecuciones innecesarias más adelante). Si el comando se encuentra en un directorio
relativo, su ubicación debe ser re-determinada siempre que cambie el directorio actual. La shell se olvida
de recordar todos los lugares cada vez que la variable PATH se cambia o se ejecuta el comando
hash -r.
:
. file
Leer y ejecutar comandos desde un archivo 6JSN y retornar. La ruta de búsqueda especificada por
PATH se utiliza para encontrar el directorio que contiene el fichero.
break [n]
Salir del bloque de un bucle while, en su caso. Si se especifica n, rompe los n niveles.
continue [n]
cd [arg]
Cambiar el directorio actual a arg. El parámetro de shell HOME es el argumento por defecto. El
parámetro shell CDPATH define la ruta de búsqueda para el directorio que contiene arg. Los
nombres alternativos de directorios están separados por dos puntos (:). La ruta predeterminada
es <RHSS> (especificando el directorio actual).
NOTA: El directorio actual se especifica mediante un nombre de ruta nula, que puede aparecer
inmediatamente después del signo igual, o entre los dos puntos delimitadores en cualquier otro
lugar de la lista de rutas.
Los argumentos son leídos como entrada para la shell y el (los) comando(s) resultante(s) se
ejecuta(n).
exec[arg ... ]
El comando especificado por los argumentos es ejecutado en lugar de la shell sin crear un nuevo
proceso. Los argumentos de entrada / salida pueden aparecer y, si no se dan otros argumentos,
causa que se modifique la entrada / salida de shell.
exit [n]
Causa las salida de la shell con el estado de salida especificado por n. Si n se omite, el estado
de salida es el de la última orden ejecutada (un final de fichero también hará que la shell s
termine)
export [name... ]
Los nombres dados se marcan para la exportación automática al entorno de los comandos
ejecutados posteriormente. Si no se pasan argumentos, se listan los nombres de las variables
que se han marcado para exportación durante la ejecución de la shell actual. Los nombres de
variables exportadas desde una shell padre se muestran sólo si han sido exportados de nuevo
durante la ejecución de la shell actual. Los nombres de funciones no se exportan.
getopts
Utiliza los scripts de shell para soportar los estándares de sintaxis de comandos, y analiza los
parámetros de posición y los controles para conocer las opciones legales. Ver getopts (1) para
su uso y descripción.
Para cada nombre, la ubicación en la ruta de búsqueda del comando especificado por su
nombre, se determina y se recuerda por la shell. La opción -r hace que la shell se olvide de todos
los caminos recordados. Si no se pasan argumentos, se presenta información sobre los “OJÓC” y
“XACÓ” de los comandos recordados. eJÓC es el número de veces que un comando se ha invocado
por el proceso de shell. 1ACÓ es una medida del trabajo necesario para localizar un comando en
la ruta de búsqueda. Si un comando se encuentra en un directorio relativo a la ruta de búsqueda,
después de cambiar a ese directorio, la ubicación almacenada de ese comando se vuelve a
calcular. Los comandos para los que se hace esto, se señalan con un asterisco (*) junto a la
información de accesos. 1ACÓ se incrementará cuando el cálculo se realice.
newgrp [arg]
Equivalente a exec newgrp arg. Ver newgrp (1M) para su uso y descripción.
Para cada set_name, priv establece o muestra los privilegios contenidos en el conjunto de
privilegios. set_name puede ser, bien “max” para el conjunto de privilegios máximos, o “work”
para el conjunto de trabajo. priv_name es el nombre de un privilegio. Si se suministra
priv_name, priv examina la lista y apaga aquellos privilegios que vienen precedidos por un
signo menos, y enciende aquellos que están precedidas por un signo más en cada uno de los
conjuntos listados. Si no se suministra priv_name, el comando priv imprime la lista actual de
privilegios para cada uno de los conjuntos solicitados. Los valores de priv_name son:
allprivs
audit.
auditwr
compat
core
Necesarios para volcar una imagen XAMN de un proceso que tiene privilegios setuid o setgid.
Este privilegio no requiere volcar la imagen principal de un proceso que no cumpla las
condiciones anteriores.
dacread
Invalida las restricciones del Control de Acceso Discrecional (DAC “JCXMNÓJAR MV,AXXNCC,1ARÓMAS),
pero sólo para operaciones que no alteren los objetos (es decir, permisos de lectura y ejecución).
dacwrite
Anula las restricciones del Control de Acceso Discrecional (DAC “JCXMNÓJAR MV,AXXNCC,1ARÓMAS),
pero sólo para operaciones que alteran los objetos (es decir, permisos de escritura).
dev
Actualmente no se utiliza.
driver
filesys
Necesario para operaciones privilegiadas en un sistema de archivos que tienen una sensibilidad
relativamente baja, incluyendo la creación de vínculos a los directorios, establecer el directorio
raíz de efectivo, y la construcción de archivos especiales.
fsysrange
loadmod
Necesario para realizar operaciones selectivas asociadas a los módulos cargables (lA I BSN).
macread
Actualmente no se utiliza.
macwrite
Actualmente no se utiliza.
macupgrade
Actualmente no se utiliza.
mount
multidir
Actualmente no se utiliza.
owner
Necesario para cambiar los atributos de un archivo (es decir, información contenida en el JRAIA
del archivo) que no es propiedad del identificador de usuario efectivo del proceso invocador.
plock
setflevel
Actualmente no se utiliza.
setplevel
Actualmente no se utiliza.
setspriv
Privilegios administrativos necesarios para configurar los privilegios heredables y fijos en los
archivos. Este privilegio anula las restricciones de acceso y propiedad.
setuid
setupriv
Privilegio necesario para un proceso sin privilegios, para determinar los privilegios heredables y
fijos en un archivo. Este privilegio no anula las restricciones de acceso o propiedad.
sysops
Necesario para realizar varias operaciones generales del sistema que sólo tienen implicaciones
de seguridad de menor importancia.
tshar
rtime
El control de acceso se lleva a cabo cada vez que un objeto (como un proceso) intenta acceder a
un objeto (como un archivo o directorio). El permiso para acceder a un objeto se concede o se
deniega sobre la base de modo de bits y Access Control Lists (ACL); ACL y el modo de bits se
conocen colectivamente como Control de Acceso Discrecional (DAC “JCXMNÓJAR MV,AXXNCC,
1ARÓMAS).
Estos controles se realizan en todos los componentes de la ruta de acceso, incluido el propio
objeto. Si alguno de los controles fallan, los privilegios del proceso de llamada se examinan para
determinar si el proceso de llamada tiene el privilegio adecuado para la modalidad requerida
(dacread para acceso de lectura y ejecución / búsqueda, dacwrite para acceso de escritura).
Este ejemplo agrega los privilegios de propietario y de auditoría y elimina privilegios dacread del
entorno de trabajo:
pwd
Imprimir el directorio de trabajo actual. Ver el comando pwd (1) para su uso y descripción.
Se lee una línea de la entrada estándar y, utilizando el separador de campos internos (IFS) para
delimitar los límites de las palabras; la primera palabra se asigna al primer nombre, la segunda
palabra al segundo nombre, etc., con palabras sobrantes asignadas al último nombre. Si no se
especifica -r, las líneas se pueden continuar utilizando \newline y otros caracteres que no sean de
nueva línea pueden ser entrecomillados precediéndolos con una barra invertida. Estas barras
invertidas se retiran antes de que las palabras se asignen a los nombres, y no se hace una
interpretación del carácter que sigue a la barra invertida. Si se especifica -r, las barras invertidas son
tratadas como caracteres normales, por lo que no se quitan de la entrada, ni afectan el carácter
siguiente. El código de retorno es 0, a menos que se encuentre el final de fichero.
Los nombres dados son marcados de sólo lectura y los valores de estos nombres no podrán ser
modificados por las subsiguientes asignaciones. Si no se pasan argumentos, se imprime una lista de
todos los nombres de sólo lectura.
return [n]
Causa la salida de una función con el valor de retorno especificado por n. Si se omite n, el estado de
retorno es el de la última orden ejecutada.
-a
Marca variables que se modifican o crean para exportación.
-e
Salir inmediatamente si un comando sale con un estado de salida distinto de cero.
-f
Deshabilitar la generación de nombres de archivo.
-h
Localizar y recordar los comandos de función como las funciones que están definidas (los
comandos de función normalmente se localizan cuando se ejecuta la función).
-k
Todos los argumentos clave son colocados en el entorno por un comando, no sólo aquellos que
preceden al nombre del comando.
-n
Lee los comandos pero no los ejecuta.
-t
Salir después de leer y ejecutar un comando.
-u
Tratar las variables no establecidas como un error al se sustituidas.
-v
Imprimir las líneas de entrada de la shell cuando se leen.
-x
Muestra los comandos y sus argumentos cuando se ejecutan.
--
No cambia ninguno de los 6S TC; útil en el establecimiento de $1 a -.
Usando + en lugar de -, causa que los 6S TC se desactiven. Estos 6S TC también se pueden utilizar
sobre la invocación de la shell. El conjunto actual de 6S TC se pueden encontrar en $-. El resto de
argumentos son los parámetros de posición y se asignan, en orden, a $1, $2, .... Si no hay
argumentos, se muestran los valores de todos los nombres.
shift [n]
Los parámetros de posición desde $n+1 ... son renombrados $1 ... . Si n no aparece, se supone que
es 1.
test
times
Muestra los tiempos acumulados de sistema y usuario para los procesos que se ejecutan desde la
shell.
El comando arg debe ser leído y ejecutado cuando la shell recibe una señal numérica o simbólica.
NOTA: arg se escanea una vez, cuando se establece el trap, y una vez que el trap tiene efecto.
Los comandos del trap se ejecutan en orden de número de la señal, o de los correspondientes nombres
simbólicos. Cualquier intento de establecer un trap en una señal que ha sido ignorada en la entrada en
el shell actual, es ineficaz. Se produce un error cuando se intenta atrapar cualquiera de las siguientes
tres señales:
Si arg está ausente, todo el trap se restablece a sus valores originales. Si arg es la cadena nula, se
pasa por alto esta señal por la shell y los comandos que invoca. Si n es 0, el comando arg es ejecutado
al salir de la shell. El comando trap sin argumentos imprime una lista de los comandos asociados a cada
número de la señal.
Para cada nombre, indica cómo se interpretaría si se usa como un nombre de comando.
ulimit lista o establece límites de recursos duros o blandos. Estos límites se describen en getrlimit
(2). Si el límite no está presente, ulimit lista los límites especificados. Cualquier número de límites
pueden ser listados al mismo tiempo. La opción -a imprime todos los límites. Si el límite está
presente, ulimit establece el límite especificado a limit. La cadena unlimited' asume el mayor límite
válido. Los límites pueden ser establecidos sólo para un recurso a la vez. Cualquier usuario puede
establecer un límite blando a cualquier valor por debajo del límite duro. Cualquier usuario puede
bajar un límite duro. Sólo un usuario con privilegios puede plantear un límite duro. La opción -h
especifica un límite duro. La opción -s especifica un límite blando. Si no se especifica opción, ulimit
establecerá ambos límites y mostrará el límite blando. Las opciones siguientes especifican el recurso
cuyos límites se van a mostrar o establecer. Si no se especifica la opción, se muestra o establece el
límite de tamaño de archivo.
-c
Tamaño máximo de fichero de imagen (XAMN) (en bloques de 512 bytes)
-d
Tamaño máximo de segmento de datos o pila (en kbytes)
-f
Ttamaño máximo de archivo (en bloques de 512 bytes)
-n
Máximo descriptor de archivo más 1
-s
Tamaño máximo de segmento de pila (en kbytes)
-t
Tiempo de CPU máximo (en segundos)
-v
Tamaño máximo de memoria virtual (en kbytes)
umask [ -S ] [mask]
Para cada nombre, eliminar la variable o valor de la función correspondiente. Las variables PATH, PS1,
PS2, MAILCHECK, e IFS no se pueden borrar.
Espere por los procesos en B XLTMAHRI cuyo identificador de proceso tenga el valor de pid, y retorna
el estado de terminación del pid final. Si se omite pid, todos los procesos en background activos
para la shell actual estarán en espera, y el código de retorno será cero. Ver wait (1) para más
detalles.
18.18 INVOCACIÓN
Si la shell se invoca a través de exec (2) y el primer carácter del argumento cero es -, los comandos se
leen de principio desde /etc/profile y desde $HOME/.profile, si tales archivos existen. A partir de
entonces, los comandos se leen como se describe a continuación, que es también el caso cuando la
shell se invoca como /usr/bin/sh. Los siguientes 6S TC son interpretados por el intérprete de comandos
solamente en la invocación. Tenga en cuenta que a menos que la opción -c o -s se especifique, el primer
argumento se supone que es el nombre de un archivo que contiene los comandos, y el resto de
argumentos se pasan como parámetros de posición al archivo de comandos:
-c cadena
-i
-p
Si la opción -p está presente, la shell no establece los ID de usuario y grupo efectivo a los ID del
usuario y grupo real. Si la opción -p no está presente, la shell establece el identificador de
usuario efectivo al ID de usuario real si el identificador de usuario efectivo es inferior a 100, y la
shell establece el identificador de grupo efectivo al ID de grupo real si el identificador de grupo
efectivo es menor de 100 y no es igual a 1.
-r
-s
Con el control de trabajos habilitado, cada comando o tubería que el usuario digita en el terminal se
llama trabajo (jAB). Todos los trabajos existen en uno de los siguientes estados:
Detenido (CÓAEENI)
Un trabajo en primer plano tiene accesos de lectura y escritura al terminal que lo controla.
Un trabajo en segundo plano tiene denegado el acceso de lectura y tiene condicionado el acceso de
escritura al terminal que lo controla (véase stty (1));
A cada trabajo que inicia la shell se le asigna un número entero positivo, llamado número de trabajo (jAB,
RHUBNM) que es investigado por la shell, y se utiliza como un identificador para un trabajo específico.
Además, la shell realiza un seguimiento del trabajo actual y del trabajo anterior. El trabajo actual es el
trabajo más reciente que se ha iniciado o reiniciado. El trabajo anterior es el primer trabajo no actual (el
anterior).
%jobid
%o+
-
?<cadena>
n
pref
Donde pref es un prefijo único del nombre del comando (por ejemplo, si el comando ls-l foo se
ejecuta en segundo plano, podría ser referido como %ls); pref no puede contener espacios en
blanco a menos que estén entrecomillados.
Cuando el control de trabajos está habilitado, los siguientes comandos se agregan al entorno del usuario
para manipular los trabajos:
bg [%jobid ...]
fg [%jobid ...]
Informa de todos los trabajos parados o en ejecución en segundo plano. Si se omite %jobid, se
informa de todos los trabajos que están detenidos o en ejecución en segundo plano. Las siguientes
opciones modifican o mejoran la salida de los trabajos:
-l
Informa del ID de grupo del proceso y del directorio de trabajo de trabajos.
-p
Informa sólo con el ID de grupo del proceso de los trabajos.
-x
Reemplaza cualquier jobid encontrado en el comando o en los argumentos, con el ID de grupos del
proceso correspondiente, y luego ejecuta el comando pasándole los argumentos.
Es una versión integrada de kill para proporcionar la funcionalidad del comando kill (1) para
procesos identificados con un jobid. Ver kill (1) para otras funcionalidades.
suspend
rsh es la parte de nombre de fichero de la última entrada en el archivo /etc/passwd (véase passwd
(4))
La variable de entorno SHELL existe y rsh es la parte del nombre del archivo de su valor
Cuando un comando a ejecutar detecta que es un procedimiento de shell, /usr/lib/rsh invoca a sh para
ejecutarlo. Por lo tanto, es posible proporcionar a los usuarios finales, procedimientos shell que tengan
acceso a toda la potencia de la shell estándar, mientras que se establece un menú limitado de
comandos; este esquema supone que el usuario final no tiene permisos de escritura y ejecución en el
mismo directorio.
El efecto neto de estas reglas es que el escritor del perfil .profile (Ver profile (4)) tiene el control
completo sobre las acciones del usuario mediante la realización de acciones de ajustes con garantías, y
dejando al usuario en un directorio adecuado (probablemente no en el directorio de inicio de sesión).
El administrador del sistema normalmente establece una guía de comandos (por ejemplo, /usr/rbin) que
puede ser invocado de forma segura por una shell restringida. Algunos sistemas también ofrecen un
editor restringido, red.
18.21 ARCHIVOS
/etc/profile
$HOME/.profile
/tmp/sh*
/dev/null
/usr/lib/locale/locale/LC_MESSAGES/uxcore.abi
Fichero de mensajes específicos del lenguaje (ver LANG en environ (5)).
Este es el único mensaje posible. Si se hace otro intento de salida, y todavía hay trabajos parados, se
enviará una señal SIGHUP desde el núcleo y la shell sale.
18.24 REFERENCIAS
cd(1), dup(2), echo(1), environ(5), exec(2), fork(2), getopts(1),
getrlimit(2), intro(1), intro(2), ksh88(1), ksh(1), login(1),
newgrp(1M), pipe(2), profile(4), pwd(1), setlocale(3C), signal(5),
stty(1), test(1), ulimit(2), umask(1), wait(1)
18.25 NOTAS
Las palabras que se usan para nombres de archivo en la redirección de entrada / salida no se interpretan
para generar nombres de archivos (véase la sección Generación de nombres de archivos). Por ejemplo:
Debido a que los comandos de tuberías se ejecutan como procesos separados, las variables definidas
en una tubería no tienen ningún efecto en la shell principal.
Si recibe el mensaje de error UX:sh:ERROR:cannot fork, too many processes, pruebe a utilizar el
comando wait para limpiar los procesos de fondo. Si esto no resuelve el problema, la tabla de procesos
del sistema está, probablemente, completa, o se tienen demasiados procesos activos en primer plano.
(Hay un límite en el número de identificadores de proceso asociados con un nombre de usuario, y el
número que el sistema puede mantener).
Los estados POSIX.2 asignados son ejecutados desde el comienzo del texto del comando hasta el final.
Por lo tanto, el orden de evaluación para la asignación de variables se cambia para utilizar las reglas de
expansión de izquierda a derecha.
set variable=cadena
unset variable
El comando set muestra los valores de sus variables locales por pantalla.
% set history=6
% echo $history
6
% unset history
% echo $history
history: Undefined variable
% set
cp cp –I
home /export/home/user2
noclobber
path (. /usr/bin /usr/ucb)
shell /bin/csh
user user2
unsetenv VARIABLE
% unsetenv PRINTER
% setenv
LANG=C
HZ=100
PATH=.:/usr/bin:/usr/ucb
LOGNAME=user2
MAIL=/var/mail/user2
HOME=/export/home/user2
USER=user2
LPDEST=staffp
PWD=/export/home/user2
19.1.3 path
La C CONSS puede usar un formato distinto al de la Bourne y Korn CONSS para definir la variable path
El siguiente ejemplo cambia la variable PATH para que busque en dHCMdBJR, el directorio actual, el
directorio raíz, y dHCMdAENRDJRdBJR.
%echo $PATH
/usr/bin . /usr/openwin/bin
%set path=(/usr/bin . $HOME /usr/openwin/bin)
%echo $ PATH
/usr/bin . /export/home/user2 /usr/openwin/bin
De cualquier forma, la C shell permite usar el mismo formato de varibale PATH definida bajo la Bourne
shell, con el carácter : separando los directorios dentro de la variable.
set history=n
Defina history a un número para presentar en pantalla ese número de comandos previos.
% set history=5
% history
23 set history=5
24 history
En el ejemplo superior, sólo se presentan dos líneas después de introducir el comando history. Cuando
se define la variable history, se crea la lista histórica de comandos.
Cualquier comando introducido previamente a la ejecución el comando set history, no formarán parte de
la lista histórica. Cualquier comando introducido después de definir la variable history se añade a la lista
histórica y se presenta cada vez que escribe el comando history.
% pwd
% cd /tmp
% history
23 set history=5
24 history
25 pwd
26 cd /tmp
27 history
^cadena_vieja^cadena_nueva
Cada cadena puede tener la longitud que quiera el usuario. El acento circunflejo (^) le dice a history que
localice la cadena antigua en el comando previo y lo sustituya por lo que dice la cadena nueva y
entonces se ejecuta el comando modificado.
% lp -d baser1 fich1
UX:lp: Error: Destination "baser1" is unknown to the LP print service
% ^b^l
lp -d laser1 fich1
request id is laser1-42( file(s) )
La C CONSS ofrece posibilidades adicionales para editar comandos introducidos previamente. La tabla
siguiente describe las opciones disponibles en la C CONSS.
Opción Función
!! Ejecuta el comando anterior
!* Repite los argumentos del comando anterior
!$ Repite el último argumento del último comando
!number Ejecuta el comando number de la lista histórica
!n:p Muestra el comando n de la lista histórica sin ejecutarlo
La Bourne CONSS no ofrece estas opciones para editar los comandos anteriores. La Korn CONSS tiene otros
comandos específicos para la edición de líneas.
% history
31 set history=40
32 cd /export/home/user2/practice
33 pwd
34 lpstat
35 set noclobber
36 mkdir /export/home/user2/practice/weekly
37 cd /export/home/user2/dir3
38 ls planetd
39 ls planets
40 history
% !32
cd /export/home/user2/practice
Puede combinar history y la edición de comandos para recuperar y cambiar un comando anterior. Use
:p si quiere ver el comando sin ejecutarlo.
%!37
cd /export/home/user2/dir3
%!38:p
ls planetd
% ^d^s
ls planets
mars moon pluto
% cd ..
% ls dir2 dir4
dir2:
beans recipes
dir4: flowersroses
% history
31 set history=40
32 cd /export/home/user2/practice
33 pwd
34 lpstat
35 set noclobber
36 mkdir /export/home/user2/reports/weekly
37 cd /export/home/user2/dir3
38 ls planetd
39 ls planets
40 cd /export/home/user2/practice
41 cd /export/home/user2/dir3
42 ls planetd
43 ls planets
44 cd ..
45 ls dir2 dir4 46 history
% !45:p
ls dir2 dir4
Use !! para ejecutar el comando más reciente, exactamente como se ejecutó previamente. Si ejecutó
lpstat y lo quiere hacer de nuevo, escriba !! en el EMAUEÓ del CONSS.
% lpstat –o
no entries
% !!
lpstat -o
sparky-3 root 15 Jun 9 14:55 filtered
printerl-5 root 573 Jun 9 13:14 on printer 1
printl-6 root 545 Jun 9 08:10 filtered
% cd
% mkdir a b c
% ls !*
ls a b c
a:
b:
c:
% rm –ir !$
rm -ir c
rm: examine files in dir c (y/n)? Y
rm: remove c: (y/n)? y
% ls -l > /tmp/list.file
% more !$
more /tmp/list.file
total 90
-rw-r--r-- 1 user2 other 72 Jun 21 15:07 dante
-rw-r--r-- 1 user2 other 72 Jun 21 15:07 dante_1
drw-r--r-- 5 user2 other 512 Sep 28 16:39 dirl
drw-r--r-- 2 user2 other 512 Sep 29 09:45 letters
drw-r--r-- 4 user2 other 512 Sep 29 10:01 practice
set prompt=valor
% set prompt="Mi petición: -> "
Mi petición -> set prompt="Hola `hostname`-> "
Hola, sistema1-> set prompt="%”
%
Cuando cambia su EMAUEÓ, el cambio permanecerá hasta que lo vuelva a cambiar o hasta que salga de
la sesión.
Para hacer su cambio permanente, añada el comando set prompt en el archivo .cshrc de la C CONSS.
19.5 ALIAS
En la Korn CONSS y en la C CONSS se pueden definir alias para comandos, mientras que en la Bourne CONSS
no es posible.
% alias c clear
% alias gohome 'cd;ls'
unalias nombre_alias
% unalias c
% c
c : Command not found
Los alias sólo son válidos para la sesión en la que se han creado. Añada los alias en el archivo .cshrc de
la C CONSS para activarlos siempre que se haga SATJR en el sistema.
Creada por un grupo de trabajo de laboratorios Bell, encabezado por Steve Bourne.
C shell
Creada por integrantes de la Universidad de California en Berkeley, en especial Bill Joy, la C del
nombre es por California.
Korn shell
Tiene las mejores funciones de la Bourne shell y de la C shell en una única shell. Ofrece histórico de
los comandos, edición de comandos, finalización de nombres de ficheros y alias.
19.6.2 ALIAS
Comando Alias
Si se utiliza el comando SJ C sin argumentos, informa de los alias activos en ese instante, si se hace solo
con un argumento, muestra la equivalencia que este tuviera en esos instantes.
Este método proporciona escritura muy sencilla debido a la abreviatura de largas líneas de comandos y a
la sustitución automática de largos E ÓOR UNC.
Se escribe el comando y solo una parte del nombre del fichero, se pulsa dos veces la tecla escape ESC,
si la shell responde con unos pitidos entonces significa que es incapaz de completar el nombre del
fichero en base a lo que se ha digitado.
Si no se producen los pitidos entonces hay opciones de finalización, ahora se puede pulsar escape y
luego tecla = , mostrará entonces las diferentes opciones de finalización, cada vez que se añadan
caracteres para escoger una opción, el sistema completará el nombre del fichero.
EJEMPLO
Se puede utilizar otro editor, para ello solo se ha de cambiar el valor de la variable del entorno EDITOR
al nombre del editor que se desee, por defecto contiene la cadena 'vi'.
Comando fc
fc [ -l | -e ] [ -numero | -cadena ]
Con la opción -l muestra una lista de los últimos comandos ejecutados con una numeración.
Windo
TCC Windows Rub
Bourne POSIX bash ksh ws COMMAND.CO OS/2 BeanSh Python
csh tcsh Scsh pdksh zsh ash (formerly PowerSh 4DOS rc y VMS DCL
shell shell (v4.0) (ksh93t+) cmd.ex M cmd.exe ell shell
4NT) ell shell
e
Native
CIM/WBE No No No No No No No No No No No No Yes No No No No ? ? ? No
M support
Blocking
of
No No No No No No No No No No No No Yes No No No No No No No No
unsigned
scripts
available
as
statically
Yes on
linked,
Yes Windo
independe Yes N/A Yes Yes Yes Yes Yes Yes Yes Yes Yes No No Yes No ? Yes No No
(bsh.jar) ws via
nt single
py2exe
file
executabl
e
Windo
Bour POSI ksh TCC
bash pdks Windows ws COMMAND.C OS/2 Ruby VMS
ne X csh tcsh Scsh (ksh93t zsh ash (formerly 4DOS rc BeanShell Python shell
(v4.0) h cmd.exe PowerS OM cmd.exe shell DCL
shell shell +) 4NT)
hell
Yes Yes (provided
Yes (via Yes Yes Yes Yes by the
Completi
No No (extend the (extend No (extend Yes (extenda Yes Yes (partial) Yes (partial) (extend No Yes Yes Yes Yes rlcompleter Yes No
on
able) ESC able) able) ble) able) module or
key) IPython)
Yes
(pass a
Director block
Yes (all
y stack Yes (provided to
No No Yes Yes Yes No No No Yes Yes Yes Yes location No Yes ? ? ? No
(pushd/p by IPython) Dir.chdi
types)
opd) r()
method
)
Director
y
History No No No No No No No No No No No Yes Yes No Yes No No No No No No
Window
(popup)
Implicit
Director
y
Change -
Yes Yes Yes
If Yes
No No (optiona (optio (optiona No No No No No Yes No No Yes No No No No No No
comman (optional)
l) nal) l)
d is dir
name
changes
to it
Windo
Bour POSI ksh TCC
bash pdks Windows ws COMMAND.C OS/2 Ruby VMS
ne X csh tcsh Scsh (ksh93t zsh ash (formerly 4DOS rc BeanShell Python shell
(v4.0) h cmd.exe PowerS OM cmd.exe shell DCL
shell shell +) 4NT)
hell
Comman [17]
No Yes Yes Yes Yes No Yes Yes Yes Yes Yes (F7) Yes Yes No Yes Yes Yes Yes Yes Yes Yes
d history
Yes
History (with
Yes ] [ Yes (provided
completi No No Yes Yes Yes No Yes ? Yes Yes Yes (F8) Yes No Yes ? Yes ? UtilityB No
(F8) by IPython)
on elt
gem)
Spell
experim
checkin No No No No No No No Yes No No No No No No No No No No No No
ental
g
bash-
Default
<ÍNMCJA PS irb(mai
user <OACÓR <E ÓO,AM,IMJÍN, term%
[2 $ $ R, % > > $ $ $ <E ÓO>> [<E ÓO>] <E ÓO>> <E ÓO>> [<E ÓO>] bsh % >>> n):001: $
prompt UN>% R UN>> ,;
1] RHUBNM 0>
>$
Yes
(functi Yes
Yes
Yes Yes Yes Yes Yes Yes on: (variable:
Custom Yes Yes (variabl Yes Yes Yes Yes Yes Yes Yes (SET
(varia (varia (varia (varia (variable: (varia prompt bsh.promp
comman (variabl (variabl e: (environment (environment (functio (environment (environment (environment Yes (variable: PROMPT
ble: ble: ble: No ble: $PS1, ble: , or t, or Yes
d e: e: $PS1, variable: %PR variable: %PR n: variable: %PR variable: %PR variable: %PR sys.ps1) comman
$PS1 $PS1 $pro $PS1 and $PS1 variabl method:
prompt $PS1) $prompt and OMPT%) OMPT) prompt) OMPT%) OMPT) OMPT%) d)
) ) mpt ) more) ) e: getBshPro
more)
$prom mpt())
pt)
Yes
(macro
and Yes
Yes ("macros", Yes (using SET
Aliases No Yes Yes Yes Yes proced Yes Yes Yes Yes Yes Yes Yes No (functi ? Yes (functions) Yes Yes
via doskey) or registry)
ure ons)
definiti
ons)
Binary
prefix No No No No No Yes No No No No No ? Yes No ? No No ? ? ? Yes
notation
Handl
Job
No Yes Yes Yes Yes Yes Yes Yes Yes Yes No No Yes No No No ed by ? Yes Yes Yes
control
rio
Yes
Yes
Startup [22] Yes ($PYTHONST Yes
Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes (4start) Yes No Yes (4start) No Yes (login.co
scripts (.bshrc) ARTUP or (.irbrc)
m)
ipythonrc)
19.7.3 SINTAXIS
TEE Wóndowsp
Bournep elGrX b sh Wóndows ElMMAot.El lG/Y Be nGhel uubyp OMGp
csh tcsh Gcsh kshp(ksh93t+) pdksh zsh sh (formerlyp eowerGhe 4tlG rc eythonpshell
shell shell (v4.L) cmd.exe M cmd.exe l shell tEa
4oT) ll
Yes Yes
Ye
Quotóni Yes Yes Yes Yes Yes No Yes Yes Yes Yes Yes (Backtick: Yes No (Backtick: ? ? Yes Yes Yes
s
`) `)
Yes
Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes (quotes or
Yes Yes Yes Yes (Ctrl- Ye Yes (Backslash:
xsc póni (Backslas (Backslas (Backslas (Backslas (Backslas (Backslas (Backslas (Backslas (Backslas (Backtick: No Yes (Backslas (Backslas string
(Backslash: \) (Caret: ^) (Caret: ^) X: ?) s \)
h: \) h: \) h: \) h: \) h: \) h: \) h: \) h: \) h: \) `) h: \) h: \) assignmen
t)
Yes (rem Yes (rem Yes (rem Yes (rem
Yes (; and Yes (#);
and and and and
#| ... |# for and <# ... Yes (rem and Ye
Eommen unofficial unofficiall unofficiall unofficial
No Yes (#) Yes (#) Yes (#) Yes (#) multi-line Yes (#) Yes (#) Yes (#) Yes (#) #> for unofficially the s Yes (//) Yes (#) Yes (#) Yes (!)
ts ly the y the y the ly the
comments multi-line invalid label ::) (#)
invalid invalid invalid invalid
) comments
label ::) label ::) label ::) label ::)
Yes
(including
C99-style
Gcóentófócp
No No No No No Yes base16 No Yes No No Yes[23] Yes No No No No Yes Yes Yes No
not tóon
notation %a/
%A and
typeset -X)
Equivalent Yes
Herep feature Lines
Ye
documen Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes No Yes Yes No No No No Yes without $
s ("""string"
ts in COM
"" syntax)
file
20.2 SINOPSIS
csh [-bcefinstvVxX] [argument ...]
20.3 DESCRIPCIÓN
csh, la shell C, es un intérprete de comandos con una reminiscencia de la sintaxis del lenguaje C. Ofrece
una serie de funciones prácticas para su uso interactivo que no están disponibles con el estándar de la
Bourne shell, como la culminación de nombres de fichero, los alias de comandos, la sustitución de
histórico, el control de trabajos, y una serie de comandos integrados. Al igual que el estándar de la shell,
la shell C proporciona sustitución de variables, comandos, y nombres de ficheros.
Cuando una SATJR shell termina, se llevan a cabo los comandos del fichero .logout en el directorio
principal; se aplican las mismas comprobaciones de permisos que para el fichero .cshrc.
-b
Fuerza una ruptura desde el procesamiento de opciones. Los subsiguientes argumentos de la línea
de comandos no se interpretan como opciones de la shell C. Esto permite el paso de opciones a un
script sin confusión. La shell no ejecuta un script set-user-ID a menos que esta opción esté
presente.
-c
Lee comandos desde el primer argumento de nombre de fichero (que debe estar presente). Los
restantes argumentos se colocan en argv, la lista de variables de argumentos.
-e
Salir si un comando termina de forma anormal o se obtiene un estado de salida distinto de cero.
-f
Inicio rápido. No leer ni el fichero .cshrc, ni el fichero .login (si es una SATJR shell) en el inicio.
-i
Interactivo forzoso. Preguntar por la entrada de línea de comandos, incluso si la entrada estándar no
parece ser un terminal (dispositivo de caracteres especiales).
-n
Analizar (interpretar), pero no se ejecutan comandos. Esta opción se puede utilizar para comprobar
las secuencias de comandos shell C para verificar errores de sintaxis.
-s
Toma los comandos de la entrada estándar.
-t
Leer y ejecutar una sola línea de comandos. Se puede utilizar una \ (barra invertida) para escapar
cada nueva línea, y realizar la continuación de la línea de comandos en las líneas de entrada
posteriores.
-v
Detallado (ÍNMBACN). Establece la variable predefinid verbose; la entrada del comando es visualizada
después de la sustitución del histórico (pero antes de otras sustituciones) y antes de la ejecución.
-V
Ajustar verbose antes de la lectura .cshrc.
-x
Echo. Establece la variable echo; se visualizan los comandos después de todas las sustituciones y
justo antes de la ejecución.
-X
Establecer echo antes de la lectura .cshrc.
Excepto con las opciones -c, -i, -s o -t, el primer argumento no de opción se toma como el nombre de un
comando o una secuencia de comandos. Se pasa como argumento cero, y los argumentos siguientes se
agregan a la lista de argumentos para que el comando o el script.
20.4.3 FICHEROS
~/.cshrc
Leído al inicio de la ejecución por cada shell.
~/.login
Leído por la SATJR shell después de .cshrc, al iniciar la sesión.
~/.logout
Leído por la SATJR shell al finalizar la sesión.
~/.history
Guarda el histórico para su uso en la siguiente sesión.
/usr/bin/sh
Shell estándar, para los scripts de shell que no empiezan con un #.
/tmp/sh*
Ficheros temporal para <<.
/etc/passwd
Fuente para los directorios de inicio de usuario para `~name`.
/usr/lib/locale/locale/LC_MESSAGES/uxue
Fichero de mensajes específicos del lenguaje (Ver LANG en environ (5))
20.5 USO
Si un nombre de fichero parcial es seguido por el carácter EOF (normalmente escrito como <Ctrl>-d), la
shell lista todos los nombres de ficheros que coinciden. A continuación, solicita una vez más la línea de
entrada, suministrando la línea de comandos incompleta escrita en la medida que sea posible.
Cuando la última (parcial) palabra comienza con una tilde (~), la shell intenta terminar con un nombre de
usuario, en lugar de un nombre fichero en el directorio de trabajo.
La campana del terminal señala errores o múltiples coincidencias, lo que puede ser inhibido mediante la
configuración de la variable nobeep. Se pueden excluir ficheros con sufijos determinados, listando los
sufijos en la variable fignore. Sin embargo, si la única conclusión posible incluye un sufijo de la lista, no
se ignora. fignore no afecta a la lista de nombres de ficheros por el carácter EOF.
Además, una cadena encerrada entre pares de comillas simples ('), comillas dobles ("), o acento grave
(B XLKHAÓNC) (`), forma una palabra parcial; los metacaracteres en tal cadena, incluidos los caracteres de
espacio o tabulador, no forman palabras por separado. Dentro de pares de caracteres de comilla
invertida (`) o comillas dobles ("), una nueva línea precedida por una \ (barra invertida) es un carácter
verdadero de nueva línea. Las funciones adicionales de cada tipo de función se describen en otra
sección.
Cuando la entrada de la shell no es un terminal, el carácter # introduce un comentario que sigue hasta el
final de la línea de entrada. Su significado especial se suprime cuando va precedido por una \ o
encerrado entre comillas coincidentes.
Las tuberías pueden estar separadas por punto y coma (;), en cuyo caso se ejecutan en forma
secuencial. Las tuberías que están separadas por && o || forman secuencias condicionales en las que la
ejecución de las tuberías de la derecha depende del éxito o el fracaso, respectivamente, de la tubería de
la izquierda.
Una tubería o una secuencia puede ser encerrada dentro de paréntesis () para formar un comando
simple que puede ser una componente en una tubería o en una secuencia.
Una secuencia de tuberías se puede ejecutar de forma asíncrona, o en segundo plano, añadiendo un
carácter &, en lugar de esperar a que la secuencia finalice antes de emitir un nuevo EMAUEÓ. La shell
muestra el número de trabajo y los identificadores de proceso asociados, y presenta el EMAUEÓ de
inmediato.
Las líneas de entrada que contienen sustituciones de histórico hacen eco en el terminal después de
haber sido expandidas, pero antes de que otras sustituciones se produzcan o se ejecute el comando.
!
Iniciar una sustitución del histórico, excepto cuando es seguida por un carácter de espacio,
tabulador, nueva línea, = o (.
!!
Se refiere al comando anterior. Por sí misma, esta sustitución repite el comando anterior.
!n
Se refiere a la línea de comando n.
!-n
Se refiere a la línea de comandos actual menos n.
!str
Se refiere al comando más reciente que comience por la cadena str.
!?str[?]
Se refiere al comando más reciente que contiene la cadena str.
!{. . . }
Aislar una referencia del histórico desde los caracteres adyacentes (si es necesario).
#
La línea de comando completa escrita hasta ahora.
0
La primera palabra de entrada (comando).
n
El argumento enésimo.
^
El primer argumento, es decir, 1.
$
El último argumento.
%
La palabra coincidente con la búsqueda ? más reciente.
x-y
Una serie (rango) de palabras, - y abreviadamente 0-y.
*
Todos los argumentos, o un valor nulo si solamente hay una palabra en el evento.
x*
Abreviatura de x-$.
x-
Al igual que x* pero omitiendo la palabra $.
20.5.6.1 MODIFICADORES
Después del designador de palabra opcional, se puede agregar una secuencia de uno o más de los
siguientes modificadores, cada uno precedido por un carácter :.
h
Eliminar un componente final de camino de fichero, dejando la cabecera.
r
Eliminar un sufijo final de la forma .xxx, dejando el nombre base.
e
Elimina todo, salvo el sufijo.
s/l/r[/]
Sustituye r por l.
t
Eliminar todos los componentes iniciales de la ruta de fichero, dejando la cola.
&
Repite la sustitución anterior.
g
Aplicar el cambio a la primera aparición de una coincidencia en cada palabra, anteponiendo un
modificador anterior (por ejemplo, g&).
p
Imprime el nuevo comando, pero no lo ejecuta.
q
Entrecomilla las palabras sustituidas, escapando de más sustituciones.
x
Igual que q, pero rompe las palabras en cada espacio en blanco, tabulador o salto de línea.
A menos que sea precedida de una g, la modificación sólo se aplica a la primera cadena que coincide
con l; se produce un error si no hay cadena que coincida.
El lado izquierdo de las sustituciones no son expresiones regulares, sino cadenas de caracteres.
Cualquier carácter puede ser usado como delimitador en lugar de la /. Una barra invertida entrecomilla el
carácter delimitador. El carácter &, en el lado derecho, se sustituirá por el texto dese el lado izquierdo. El
& puede ser entrecomillado con una barra invertida. Una l nula utiliza la cadena anterior bien desde una l
o desde una búsqueda contextual en la cadena s desde !?s. Se puede omitir el delimitador más a la
derecha si una nueva línea va inmediatamente después de r; el carácter ? más a la derecha en un
contexto de análisis, puede ser omitido similarmente.
Sin una especificación de evento, una referencia al histórico se refiere tanto a la orden anterior, como a
una referencia historia previa en la línea de comando (si existe).
!:s^l^r[^]
20.5.8 ALIAS
La shell C mantiene una lista de alias que se pueden crear, visualizar y modificar utilizando los
comandos alias y unalias. La shell chequea la primera palabra de cada comando para ver si coincide
con el nombre de un alias existente. Si ocurre, el comando se vuelve a procesar con la definición del
alias sustituyendo su nombre. El mecanismo de sustitución del histórico se pone a disposición, como si
esa orden fuera la línea de entrada anterior. Esto permite a las sustituciones de histórico, escapadas con
una barra invertida en la definición, ser reemplazadas con argumentos actuales de la línea de comandos
cuando se utiliza el alias. Si no se solicita la sustitución de histórico, los argumentos no cambian.
Los alias se pueden anidar. Es decir, una definición de alias puede contener el nombre de otro alias. Los
alias anidados se expanden antes de que se apliquen las sustituciones de histórico. Esto es útil en las
tuberías como:
A excepción de la primera palabra, el nombre del alias no puede aparecer en su definición, ni en ningún
alias referido por su definición. Estos bucles se detectan, y causan un mensaje de error.
20.5.9 REDIRECCIÓN I / O
Los metacaracteres siguientes indican que la palabra siguiente es el nombre de un fichero en el que la
entrada estándar del comando, la salida estándar, o el error estándar se redirigen; esta palabra es
expandida como variable, comando, y nombre de fichero de forma independiente del resto del comando.
<
Redirigir la entrada estándar.
<<word
Lee la entrada estándar, hasta una línea que es idéntica a la palabra, y coloca las líneas resultantes
en un fichero temporal. A menos que la palabra esté escapada o entrecomillada, se realizan las
sustituciones de variables y comandos en estas líneas. A continuación, invoca la tubería con el
fichero temporal como su entrada estándar. word no está sometida a la sustitución de variables,
nombres de fichero, o comandos, y cada línea se compara antes de que las sustituciones se lleven a
cabo por la shell.
>
>!
>>!
Redirigir la salida estándar a un fichero. Si el fichero no existe, se crea. Si existe, se sobrescribe, y
su contenido anterior se pierde. Cuando se establece, la variable noclobber previene la destrucción
de los ficheros existentes. También impide la redirección al terminal y a /dev/null, a menos que se
use uno de los formatos !. La forma & redirige tanto la salida estándar y como el error estándar
(salida de diagnóstico) al fichero.
>>
>>&
>>!
>>&!
Añade a la salida estándar. Al igual que >, pero coloca la salida al final del fichero en lugar de
sobrescribirlo. Si se establece noclobber, causa un error si el fichero no existe, a menos que uno se
utilice uno de los formatos !. El formato & añade ambos, tanto el error estándar como la salida
estándar al fichero.
Para hacer referencia al valor de una variable, preceder su nombre con un carácter $. Ciertas referencias
(descritas más adelante) se pueden utilizar para seleccionar palabras específicas desde el valor, o para
mostrar otro tipo de información sobre la variable. Las llaves se pueden utilizar para aislar la referencia
desde otros caracteres en una palabra de entrada de línea.
La sustitución de variables se lleva a cabo después de que se analiza la línea de entrada, se resuelven
los alias, y se aplica las redirecciones de E/S. Las excepciones a esto son las referencias a variables en
las redirecciones de E/S (sustituido en el momento de efectuar el cambio de dirección), y las cadenas
entre comilla inclinada (acento grave) (véase sustitución de comandos).
La sustitución de variables puede ser suprimida precediendo el $ con una \, excepto dentro de las
comillas dobles en las que siempre se produce. La sustitución de variables se suprime dentro de las
comillas sencillas. Un $ es escapado si está seguido por un carácter de espacio, tabulador o salto de
línea.
Las variables se pueden crear, mostrar, o destruir utilizando los comandos set y unset. Algunas
variables se mantienen o se usan por la shell. Por ejemplo, la variable argv contiene una imagen de la
lista de argumentos de la shell. De las variables utilizadas por la shell, un cierto número se utiliza como
CDJÓXO, a la shell no le importa su valor, sólo si se establecen o no.
Los valores numéricos pueden ser operados como los números (como con el @ integrado). Con
operaciones numéricas, un valor vacío se considera igual a cero; se ignoran las palabras segunda y
posteriores de los valores con varias palabras. Por ejemplo, cuando la variable verbose se establece en
cualquier valor (incluyendo un valor vacío), la entrada del comando se repite (eco) en el terminal.
La sustitución de comandos y nombres de fichero se aplica posteriormente a las palabras que resultan
de la sustitución de variables, excepto cuando se suprime con comillas dobles, cuando se establece
noglob (suprimiendo la sustitución de nombres de fichero), o cuando la referencia se cita con el
modificador :q. Dentro de las comillas dobles, una referencia se amplía para formar una (o una parte)
cadena entre comillas, los valores de varias palabras se expanden a una cadena con caracteres de
espacio incrustado. Cuando se aplica el modificador :q a la referencia, se expande a una lista de
palabras separadas por espacios, cada una de las cuales está entrecomillada para evitar posteriores
sustituciones de comando o nombre de fichero.
Excepto como se indica a continuación, es un error referirse a una variable que no está establecida.
$var
${var}
Estas se sustituirán por las palabras del valor de var, cada una separada por un espacio. Si var es
una variable de entorno, se devuelve su valor, pero los modificadores y las otras formas que figuran
a continuación no están disponibles.
$var[indice]
$var[indice]}
Estas seleccionan sólo las palabras indicadas en el valor de var. La sustitución de variables se aplica
al índice, que puede consistir en (o dar lugar a) un número simple, dos números separados por un -,
o un asterisco. Las palabras están indexadas desde el índice 1; un * selecciona todas las palabras.
Si se omite el primer número de un rango (como $argv[-2]), el valor por defecto es 1. Si se omite el
último número de un rango (como $argv[1-]), el valor por defecto es $# var (el número de palabras).
No se considera un error que un rango esté vacío si se omite el segundo argumento (o dentro del
rango.
$# var
${#var}
Estas dan el número de palabras en la variable.
$0
Esta sustituye el nombre del fichero desde el que se lee la entrada de comandos. Se produce un
error si el nombre no es conocido.
$n
${n}
Equivalente a $argv[n].
$*
Equivalente a $argv[*].
Los modificadores :e, :h, :q, :r, :t y :x pueden ser aplicados, así como :gh, :gt y :gr. Si se utilizan llaves
{}, entonces los modificadores deben aparecer dentro de las llaves. La implementación actual sólo
permite un modificador de ese tipo para la expansión.
$? var
${?var}
Sustituye por la cadena 1 si var está definida, o 0 si no está establecida.
$?0
Sustituye por la cadena 1 si se conoce el nombre del fichero de entrada, o 0 si no se sabe.
$$
Sustituye por el número de proceso de la shell (padre).
$<
Sustituye una línea desde la entrada estándar, con ninguna interpretación adicional posterior. Se
puede utilizar para leer desde el teclado en un script de shell C.
*
Coincidir con cualesquiera (cero o más) caracteres.
?
Cualquier carácter individual.
[...]
Coincide con cualquier carácter único en la lista adjunta o rango. Una lista es una cadena de
caracteres. Un rango son dos caracteres separados por un signo menos (-), e incluye todos los
caracteres en el rango según el orden de clasificación ASCII.
~[user]
El directorio personal, según lo indicado por el valor de la variable home, o el del usuario user,
según lo indicado por la entrada de usuario en el fichero passwd.
Sólo los patrones *, ? y [...] implican la coincidencia de patrones; se produce un error si no hay una
coincidencia con el patrón de nombre de fichero que los contiene. El . (carácter de punto), cuando es el
primer carácter de una componente de nombre de fichero o ruta de acceso, debe ser coincidente de
forma explícita. La / (CS CO), también debe ser coincidente de forma explícita.
El nulo o los valores perdidos se consideraron como 0. El resultado de todas las expresiones son
cadenas, que pueden representar números decimales.
(...)
Agrupación
~
Complemento a uno
!
Negación lógica
*
/
%
Multiplicación, división, resto (son asociativos por la derecha, lo que puede conducir a resultados
inesperados). Las combinaciones de grupos van explícitamente con paréntesis.
+
-
Suma, resta (también asociativo a la derecha)
<<
>>
Desplazamiento bit a bit a la izquierda, desplazamiento bit a bit a la derecha
<
>
<=
>=
Menor que, mayor que, menor o igual que, mayor o igual que.
==
!=
=~
!~
Igual a, no igual a, coincidencia de sustitución de patrón de nombre de fichero (descrito a
continuación), no coincidencia de sustitución de patrón de nombre de fichero.
&
AND bit a bit
^
XOR bit a bit (AM exclusivo)
|
OR bit a bit
&&
AND lógico
||
OR lógico
Los operadores: ==, !=, =~, y !~ comparan sus argumentos en forma de cadenas; otros operadores
utilizar números. Cada uno de los operadores =~ y !~ comprueban si una cadena a la izquierda coincide
con un patrón de sustitución de nombre de fichero a la derecha. Esto reduce la necesidad de sentencias
switch cuando el patrón de coincidencia entre las cadenas es lo único que se requiere.
-r fichero
Devuelve verdadero, o 1, si el usuario tiene acceso de lectura. De lo contrario, devuelve false, o 0.
-w fichero
Verdadero si el usuario tiene acceso de escritura.
-x fichero
Verdadero si el usuario tiene permiso de ejecución (o permiso de búsqueda en un directorio).
-e fichero
Verdadero si el fichero existe.
-o fichero
Verdadero si el usuario es propietario del fichero.
-z fichero
Verdadero si el fichero es de longitud cero (vacío).
-f fichero
Verdadero si el fichero es un fichero sin formato (plano).
-d fichero
Verdadero si el fichero es un directorio.
{comando}
Si el comando se ejecuta correctamente, la expresión se evalúa como verdadera. De lo contrario, se
evalúa como falso 0. (Tenga en cuenta que, por el contrario, el comando se vuelve típicamente 0
cuando se ejecuta correctamente, o algún otro valor si se encuentra con un problema. Si se quiere
llegar a la situación directamente, utilizar el valor de la variable de estado en lugar de esta
expresión).
Cada ocurrencia integrada de un foreach, switch, while, if…then y else, debe aparecer como la
primera palabra en su propia línea de entrada.
rehash) para eliminar los directorios que no tienen ficheros de aplicación. Esta técnica de codificación
(hashing) se puede desactivar con las opciones -c o -t, o con el comando integrado unhash.
Como caso especial, si no hay una / en el nombre del script, y hay un alias para la palabra de la shell, se
antepone la expansión del alias de shell (sin modificación), en la línea de comandos. El sistema intenta
ejecutar la primera palabra de este alias especial (de aparición tardía), que debería ser una ruta
completa. El resto del texto de la definición del alias, junto con el texto de la línea de entrada, se tratan
como argumentos.
Cuando se encuentra una ruta con los permisos adecuados de ejecución, la shell crea (6AML) un proceso
nuevo y lo pasa, junto con sus argumentos, al kernel (mediante la llamada al sistema execve). El kernel
intenta luego superponer el nuevo proceso con el programa deseado. Si el fichero es un binario
ejecutable (en formato a.out) el kernel actúa con éxito, y comienza a ejecutar el nuevo proceso. Si el
fichero es un fichero de texto, y la primera línea comienza con #!, la siguiente palabra se toma como la
ruta de una shell (o comando) para interpretar el script. Las subsiguientes palabras en la primera línea se
toman como opciones para la shell. El kernel invoca (AÍNMS VC) la shell indicada, utilizando el nombre del
script como argumento.
Si ninguna de las condiciones anteriores se cumple, el kernel no puede superponer el fichero (la llamada
execve falla), entonces la shell C intenta ejecutar el fichero lanzando una nueva shell, de la siguiente
manera:
[1] 1234
Para ver la lista actual de trabajos, utilice los comandos de trabajos incorporados. El trabajo más reciente
que se h aparado (o puesto en segundo plano si ninguno está parado) se conoce como el trabajo actual,
y está indicado con un +. El trabajo anterior se indica con un -; cuando el trabajo actual se termina o se
mueve al primer plano, este trabajo toma su lugar (se convierte en el nuevo trabajo actual).
Para manipular los trabajos, referirse a los comandos integrado bg, fg, kill, stop y %.
Una referencia a un trabajo comienza con un %. Por sí mismo, el signo de porcentaje se refiere al trabajo
actual.
%
%+
%%
El trabajo actual.
%-
El trabajo anterior.
%j
Se refiere al trabajo j como en: kill -9 % j. j puede ser un número de trabajo, o una cadena que
especifica de manera única la línea de comandos mediante la cual se inició; por ejemplo fg %vi
podría traer un trabajo parado vi al primer plano.
%? cadena
Especifique el trabajo para el que la línea de comandos contiene únicamente la cadena.
Un trabajo en ejecución en segundo plano se detiene cuando se intenta leer desde el terminal. Las
tareas en segundo plano normalmente pueden producir una salida, pero esta puede ser suprimida
mediante el comando stty tostop.
:
Comando nulo. Este comando se interpreta, pero no realiza ninguna acción.
bg [% job]...
Ejecutar en B XLTMAHRI el trabajo actual o los trabajos especificados.
break
Reanudar la ejecución después del final del bucle foreach o while más cercano en el que está
encerrado. El resto de comandos en la línea actual se ejecutan. Esto permite que se rompa en
multiniveles escribiendo una lista de comandos break, todos en una línea.
breaksw
Rompe desde un switch, reanudando después de endsw.
case label:
Una etiqueta en una sentencia switch.
cd [dir]
chdir [dir]
Cambian el directorio de trabajo de la shell al directorio dir. Si se da ningún argumento, se cambia al
directorio home del usuario. Si el directorio es una ruta relativa que no se encuentra en el directorio
actual, busca en todos los directorios listados en la variable cdpath. Si el directorio es el nombre de
una variable de shell cuyo valor comienza con un /, cambia al directorio nombrado por ese valor.
continue
Continuar la ejecución del while o foreach más cercanos en el que está encerrado.
default:
Las etiquetas por defecto en el caso de una sentencia switch. El default debe venir después de
todas las etiquetas case. Cualquier comando restante en la línea de comandos se ejecuta primero.
dirs [-l]
Imprimir la pila de directorios, los más recientes a la izquierda; el primer directorio que se muestra es
el directorio actual. Con el argumento -l, producen una salida sin abreviar; el uso de la notación ~ se
suprime.
exec comando
Ejecutar el comando en lugar de la shell actual, la cual termina.
exit [(expr)]
Salida de la shell, ya sea con el valor de la variable de estado, o con el valor especificado por la
expresión expr.
fg %[job]
Llevar el trabajo actual o especificado al primer plano.
glob wordlist
Realiza expansión de nombres de fichero sobre la lista de palabras. Igual que echo, pero no s
reconocen los escapes \. Las palabras están delimitadas por caracteres NULL en la salida.
goto label
La etiqueta especificada es un nombre de fichero y comando ampliado para sostener una etiqueta.
La shell rebobina su entrada tanto como sea posible y busca una línea con la forma label:,
posiblemente precedida por un espacio o una tabulación. La ejecución continúa después de la línea
indicada. Es un error saltar a una etiqueta que se produzca entre un comando integrado while o for,
y su extremo correspondiente.
hashstat
Muestra una línea de estadísticas que indican la eficacia de la tabla interna hash que se utiliza para
la localización de los comandos (y evitar execs). Se intenta un exec para cada componente de la
ruta en la que la función hash indica un éxito posible, y en cada componente que no empiece con un
/.
o -r
Invertir el orden de impresión al más reciente primero antes que los más antiguos.
o -h
Mostrar la lista del histórico sin números precedentes. Esto se utiliza para generar ficheros
adecuados para fuentes con la opción -h para el fuente.
if (expr) comando
Si la expresión especificada se evalúa como verdadera, se ejecuta el comando simple con los
argumentos. La sustitución de variables en el comando ocurre al principio, al mismo tiempo que se
hace para el resto del comando. El comando debe ser un comando simple, no de tubería, una lista
de comandos, o una lista de comandos entre paréntesis.
Nota: La redirección de E/S se produce incluso si expr es falsa, cuando el comando no se ejecuta
(esto es un BHT).
jobs [-l]
Lista de los trabajos activos bajo el control de trabajos.
o -l
Lista los identificadores de proceso, además de la información normal.
o -l
Lista los nombres de señales que se pueden enviar.
o -h
Utiliza límites duros (O MI) en lugar de los límites actuales. Los límites duros imponen un
tope a los valores de los límites actuales. Sólo los usuarios privilegiados podrán elevar los
límites duros.
o cputime
Máximo de segundos de CPU por proceso.
o filesize
Tamaño del fichero más grande permitido.
o datasize
Máximo tamaño de datos (incluidos los de pila) para el proceso.
o stacksize
Máximo tamaño de la pila para el proceso.
o coredumpsize
El tamaño máximo de un volcado de memoria (fichero).
o descriptors
Número máximo de descriptores de fichero por proceso.
o memoryuse
El tamaño máximo de memoria virtual asignada para el proceso.
o max-use
Es un número, con un factor de escala, de la siguiente manera:
o nh
Horas para tiempo de CPU (XEHÓJUN).
o nk
n kilobytes. Este es el valor predeterminado para todos salvo para cputime.
o nm
n megabytes o minutos (para cputime).
o mm: ss
Minutos y segundos (para cputime).
login [username -p ]
Poner fin a una shell de SATJR e invocar login (1). El fichero .logout no se procesa. Si se omite el
nombre de usuario, el proceso de SATJR solicita el nombre de un usuario.
o -p
Preservar el entorno actual (variables).
logout
Poner fin a una shell de SATJR.
nice [+ n | -n ] [command]
Incrementar en n el valor de prioridad del proceso para la shell o para un comando. Cuanto mayor
sea el valor n, menor es la prioridad de un proceso, y más lenta será su ejecución. Cuando se dé, el
comando es ejecutado en una subshell, y las restricciones impuestas a los comandos simples se
aplican. Si el comando se omite, nice incrementa el valor para la shell actual. Si no se especifica el
incremento, nice establece el valor de prioridad en 4. El rango de valores de prioridad del proceso es
de -20 a 20.
Los valores de n fuera de este rango establecen el valor más bajo, o al límite superior,
respectivamente.
o +n
Incrementar el valor de prioridad del proceso en n.
o -n
Decrementar en n. Este argumento puede ser utilizado sólo por el usuario con privilegios.
nohup [comando]
Ejecutar el comando con la señal HUP ignorada. Sin argumentos, ignora HUP durante el resto de la
secuencia de comandos. Cuando se indica un comando, este se ejecuta en una subshell, y las
restricciones impuestas a los comandos simples se aplican. Todos los procesos desasociados con &
son inmunes a la señal HUP, como si se hubiesen lanzado con nohup.
notify[ job] . . .
Notificar al usuario, de forma asíncrona, el estado de los cambios del trabajo actual o de los
especificados.
onintr [-label]
Controlar la acción de la shell ante las interrupciones. Sin argumentos, onintr restaura la acción
predeterminada de la shell antes las interrupciones. (La shell termina el script de shell y regresa al
nivel de entrada de comandos por el terminal). Con el argumento -, la shell ignora todas las
interrupciones. Con un argumento de etiqueta, la shell ejecuta un goto label cuando se recibe la
interrupción o bien cuando un proceso hijo termina, por ser interrumpido.
popd [+ n]
Salta la pila de directorios, y cambia (cd) al nuevo directorio en la pila. Los elementos de la pila de
directorios se numeran desde 0, a partir de la parte superior.
o +n
Descarta la entrada n de la pila.
pushd [n + dir]
Introduce un directorio en la pila de directorios. Sin argumentos, intercambia los dos elementos de la
cima.
o +n
Rota la entrada enésima (n) a la parte superior de la pila, y cambia el directorio (cd) a la
misma.
dir
Arroja el directorio de trabajo actual a la pila, y el cambia a ese directorio.
rehash
Vuelve a calcular la tabla interna O CO de los contenido de los directorios enumerados en la variable
path, para contabilizar los nuevos comandos agregados.
o word
Una sola palabra (o cadena entre comillas).
o (wordlist)
Una lista de palabras separadas por espacios y encerradas entre paréntesis. Los valores son
comandos y nombres de fichero expandidos antes de ser asignados. La forma set var[n] =
word reemplaza a la palabra n-ésima en un valor de varias palabras, con la palabra word.
setenv[VAR[word]]
Sin argumentos, setenv muestra todas las variables de entorno. Con el argumento VAR, set
establece la variable de entorno VAR para tener un valor vacío (nulo). Por convención, a las
variables de entorno se les suele dar nombres en mayúsculas. Con ambos argumentos, VAR y
word, setenv establece la variable de entorno al valor de la palabra word, que debe ser una sola
palabra o una cadena entre comillas. Las variables de entorno más utilizadas son USER, TERM y
PATH, y son automáticamente importadas y exportadas como variables user, term y path de la C
shell; no hay necesidad de usar setenv para estas variables. Además, la shell establece la variable
de entorno PWD desde la variable cwd de la C shell cada vez que esta última cambia.
shift [variable]
Los componentes de argv, o variable, si se suministran, se desplazan hacia la izquierda,
desechando el primer componente. Es un error para la variable que no esté establecida, o que
tengan un valor nulo.
o -h
Coloca los comandos desde el fichero name, en la lista del histórico sin ejecutarlos.
stop [% job] . . .
Interrumpir el trabajo en B XLTMAHRI actual o especificado.
suspend
Para la shell como si se hubiera enviado una señal de parada con ^Z. Esto se utiliza a menudo para
detener las shells iniciadas por su.
switch (string) case label: ... breaksw ... default: ... breaksw endsw
Cada etiqueta label está emparejada sucesivamente, contra la cadena string especificada, que es el
primer comando y nombre de fichero expandido. Los metacaracteres de fichero *, ? y [...] se pueden
utilizar en las etiquetas de case, las cuales son variables expandidas. Si ninguna de las etiquetas
coincide antes de que se encuentre la etiqueta default, la ejecución se inicia después de la etiqueta
default. Cada declaración case y default debe aparecer al principio de una línea. El comando
breaksw continúa la ejecución después del endsw. De lo contrario el control cae a través de las
sentencias case y default posteriores como en lenguaje C. Si no hay coincidencia con alguna
etiqueta label o no está definido el default, la ejecución continúa después del endsw.
time [comando]
Sin argumento, imprime un resumen del tiempo utilizado por la shell C y sus hijos. Con un comando
opcional, ejecuta el comando e imprime un resumen del tiempo que utiliza.
umask [valor]
Mostrar la máscara de creación del fichero. Con un valor establece la máscara de creación de
ficheros. valor se da en octal, y se hace un XOR con los permisos 666 para ficheros y 777 para
directorios, de cara a obtener los permisos nuevos para los ficheros. Los valores comunes son 002,
dando acceso completo al grupo y acceso de lectura (y de búsqueda de directorio) para los demás, o
022, dando lectura (y búsqueda de directorios), pero no permiso de escritura al grupo y otros.
unalias patrón
Desecha los alias que coinciden con el patrón (sustitución de nombre de fichero). Todos los alias son
eliminados por unalias *.
unhash
Deshabilitar la tabla hash interna.
o -h
Retire los correspondientes límites duros. Sólo los usuarios privilegiados pueden hacerlo.
unset patrón
Eliminar las variables cuyos nombres coincidan con el patrón (sustitución de nombre de fichero).
Todas las variables se eliminan mediante unset *, lo que puede producir desagradables efectos
secundarios.
unsetenv variable
Eliminar variables del entorno. No se realiza la concordancia de patrones como con unset.
wait
Espera a que los trabajos en segundo plano terminen (o por una interrupción) antes de nuevas
peticiones.
% [job] [&]
Llevar el trabajo actual o el indicado al primer plano. Con el signo UENMC RI (&), se continúa
ejecutando el trabajo en B XLTMAHRI.
@ [var=expr]
@ [var [n] =expr]
Sin argumentos, muestra los valores de todas las variables de la shell. Con argumentos, la variable
var, o la palabra n en el valor de var, se ajusta al valor evaluado por expr. (Si se suministra [n],
tanto var como su componente enésima deben existir.) Si la expresión contiene los caracteres >, <,
& o |, entonces por lo menos esta parte de expr debe ser colocada entre paréntesis. Los operadores
*=, +=, etc., están disponibles como en lenguaje C. El espacio que separa el nombre del operador de
asignación es opcional. Los espacios son, sin embargo, obligatorios en la separación de los
componentes de expr, que de otro modo sería una sola palabra. Los operadores especiales de post-
fijo ++ y -- incrementan o decrementan respectivamente.
argv
Lista de argumentos. Contiene la lista de argumentos suministrados en la invocación actual de la
shell. Esta variable determina el valor de los parámetros posicionales $1, $2, y así sucesivamente.
cdpath
Contiene una lista de directorios donde busca, utilizada por los comandos cd, chdir, y popd, si cada
argumento directorio aceptado no es un subdirectorio del directorio actual.
cwd
La ruta completa del directorio actual.
echo
Produce eco de comandos (después de las sustituciones), justo antes de la ejecución.
fignore
Una lista de sufijos de nombres de fichero a ignorar cuando se utiliza el completado de nombres.
Normalmente, la palabra simple .o.
filec
Habilitar la culminación de nombre de fichero, en cuyo caso el carácter <Ctrl> d y el carácter ESC
tienen un significado especial cuando se escriben en el final de una línea de entrada desde el
terminal:
o EOT
Imprime una lista de todos los nombres de los ficheros que comienzan con la cadena
anterior.
o ESC
Reemplaza la cadena anterior con la extensión mayor que no sea ambigua.
hardpaths
Si se establece, las rutas de acceso en la pila de directorios son resueltas para no contener
componentes simbólicos de enlace.
histchars
Una cadena de dos caracteres. El primer carácter sustituye al ! como el carácter de sustitución del
histórico. El segundo sustituye el símbolo de intercalación (^) para sustituciones rápidas.
history
El número de líneas guardadas en la lista de histórico. Un número muy grande puede consumir toda
la memoria de la shell C. Si no se establece, la shell C sólo guarda el comando más reciente.
home
El directorio de residencia del usuario. La expansión de nombre de fichero ~ se refiere al valor de
esta variable.
ignoreeof
Si se establece, la shell ignora EOF desde los terminales. Esto protege contra una muerte accidental
de una shell C, mediante el tecleo de <Ctrl>-d.
mail
Una lista de ficheros donde la shell C chequeo el correo. Si la primera palabra del valor es un
número, especifica un intervalo de comprobación de correo en segundos (por defecto 5 minutos).
nobeep
Suprime la campana durante la realización de comandos, cuando se solicita a la shell C que extienda
un nombre de fichero ambiguo.
noclobber
Restringir la redirección de la salida para que los ficheros existentes no sean destruidos por
accidente. Las redirecciones > sólo puede hacerse sobre nuevos ficheros. Las redirecciones >> sólo
puede hacerse a los ficheros existentes.
noglob
Inhibición de la sustitución de nombre de fichero. Esto es muy útil en los scripts de shell, una vez que
se han obtenido los nombres de fichero (si existen), y no se desea una expansión posterior.
nonomatch
Devuelve el patrón de sustitución de nombre de fichero, en lugar de un error, si el patrón no se
corresponde. Los patrones con formato incorrecto todavía dar lugar a errores.
notify
Si se establece, la shell notifica inmediatamente cuando los trabajos se han completado, en lugar de
esperar hasta justo antes de obtener el EMAUEÓ de solicitud.
path
La lista de directorios en los que se buscan comandos. path se inicializa desde la variable de
entorno PATH, que se actualiza desde la shell C cada vez que cambia path. Una palabra nula
especifica el directorio actual. El valor por defecto suele ser: (. /usr/ucb /usr/bin). Si path se elimina
con unset, sólo se ejecutará sobre caminos completos o absolutos. Una shell C interactiva
normalmente gestiona (O CO) el contenido de los directorios listados después de leer el fichero
.cshrc, y cada vez que se restablece path. Si se añaden nuevos comandos, utilizar el comando
rehash para actualizar la tabla.
prompt
La cadena con la que una shell C interactiva solicita mensajes. Las shells no interactivas dejan la
variable prompt sin establecer. Los alias y otros comandos en el .cshrc, que sólo son útiles de forma
interactiva, se puede colocar después de la siguiente prueba:
if ($?prompt == 0) exit
Para reducir el tiempo de inicio para las shells no interactivas. Un ! en la cadena de prompt se
sustituye por el número de evento actual. El prompt por defecto es hostname% para los usuarios
normales, o hostname# para el usuario con privilegios.
savehist
El número de líneas de la lista del histórico que se guardan en fichero ~/.history cuando el usuario
cierra la sesión. Valores grandes de savehist frenan a la shell C durante el inicio.
shell
El fichero en el que la shell C reside. Esto se utiliza en las shells que se bifurcan para interpretar los
ficheros que tienen el bit de ejecución establecido, pero que no son ejecutables directos del sistema.
status
El estado devuelto por el comando más reciente. Si una orden se cierra de forma anormal, se agrega
el octal 0200 al status. Los comandos integrados que fallan, retornan un estado de salida de 1, los
restantes comandos integrados establecen status a 0.
time
Control automático del tiempo de los comandos. Puede ser suministrado con uno o dos valores. El
primero es el umbral de registro en segundos de la CPU. El segundo es una cadena de etiquetas y
textos que indican los recursos sobre los que informa. Una etiqueta es un signo de porcentaje (%),
seguido de una letra mayúscula (las etiquetas no reconocidas se imprimen como texto):
o %D
Cantidad media utilizada de espacio de datos no compartidos en Kilobytes.
o %E
Tiempo transcurrido (reloj de pared) para el comando.
o %F
Errores de página.
o %I
Número de operaciones de bloques de entrada.
o %K
Cantidad media utilizada de espacio de pila no compartida en Kilobytes.
o %M
La memoria máxima real utilizada durante la ejecución del proceso.
o %O
Número de operaciones de bloques de salida.
o %P
Tiempo de CPU total - U (usuario) más S (sistema) - como porcentaje del tiempo E
(transcurrido).
o %S
Número de segundos de tiempo de CPU consumido por el núcleo en nombre del proceso del
usuario.
o %U
Número de segundos de tiempo de CPU dedicado al proceso del usuario.
o %W
Número de intercambios (CD EC).
o %X
Cantidad media utilizada de memoria compartida en Kilobytes. El resumen por defecto,
muestra salidas desde las etiquetas %U, %S, %E, %P, %X, %D, %I, %O, %F y %W, en ese
orden.
verbose
Mostrar cada comando después de que se lleve a cabo la sustitución de histórico.
20.13 DIAGNÓSTICOS
Se han dejado trabajos parados.
Se ha intentado salir de la shell C, con trabajos parados bajo el control de trabajos. Un intento para salir
inmediatamente seguido. tendrá éxito, y dará por concluidos los trabajos.
20.14 REFERENCIAS
a.out(4), access(2), ascii(5), environ(5), exec(2), fork(2), login(1),
pipe(2), sh(1), termio(7)
20.15 AVISOS
Las palabras no pueden tener más de 1024 caracteres. El sistema limita las listas de argumentos a
1.048.576 caracteres. Sin embargo, el número máximo de argumentos en un comando, para el que se
aplica la expansión de nombre de fichero, es de 1706. Las sustituciones de comandos en la lista de
argumentos no pueden ampliarse a más caracteres de los permitidos. Para detectar un bucle, la shell
restringe el número de sustituciones de alias en una sola línea a 20.
Cuando se reinicia un comando desde una parada, la shell muestra el directorio en el que se inició, si es
diferente del directorio actual, lo que puede inducir a error (no es un error) cuando el trabajo pudo haber
cambiado los directorios internamente.
Las funciones incorporadas en la shell no son parables / reiniciables. Las secuencias de comandos de la
forma a, b, c no se manejan correctamente cuando se intentan parar. Si suspende b, la shell no ejecuta
c. Esto se nota especialmente si los resultados de la expansión proceden de un alias. Esto puede ser
evitado mediante la colocación de la secuencia entre paréntesis, para forzar la ejecución en una
subshell.
El control sobre la salida del terminal, después de que los procesos se inicien, es primitivo. Usar un
sistema de ventanas 5HR,GJRIAD si se necesita un mejor control de salida.
Los procedimientos multilínea de la shell se incorporan como lo están en la shell estándar (Bourne).
Las estructuras de control debe ser analizadas en lugar de ser reconocidas como comandos integrados.
Esto permitiría a los comandos de control ser colocados en cualquier lugar, y ser combinados con |,
usados con & y ;.
Debe ser posible utilizar el modificador : en la salida de las sustituciones de comandos. Hay dos
problemas con el uso del modificador : en sustitución de variables: no todos los modificadores están
disponibles, y sólo está permitido un modificador por sustitución.
El indicador g (global) en sustitución del histórico sólo se aplica a la primera coincidencia en cada
palabra, en lugar de todas las coincidencias en todas las palabras. Los editores de texto estándar
realizan lo anterior consistentemente cuando se le da el indicador g en un comando de sustitución.
Las convenciones de entrecomillado son confusas. Reemplazar el carácter de escape para forzar la
sustitución de variables dentro de comillas dobles es contradictorio e inconsistente con la shell de
Bourne.
Los enlaces simbólicos pueden engañar a la shell. Estableciendo la variable hardpaths se alivia este
problema.
Establecer path debería eliminar nombres de ruta duplicados de la lista de rutas. Estos casos ocurren a
menudo debido a que un script de shell o un fichero .cshrc hace algo como:
La única manera de dirigir la salida estándar y error estándar por separado es mediante la invocación de
una subsehll, de la siguiente manera:
Aunque es lo suficientemente robusto para su uso general, las aventuras en la periferia esotérica de la
shell C pueden revelar caprichos inesperados.
La solicitud durante un if-then-else-endif interactivo puede ser confusa, aunque la secuencia se realiza
correctamente.
21 ADMINISTRACIÓN DE PROCESOS
21.1 RAZONES PARA LA ADMINISTRACION DE PROCESOS
EN MULTIUSUARIO
En un ambiente multiusuario, como es el caso de UNIX, es útil tener conocimiento acerca de los
procesos y la manera de controlarlos, para casos como:
Cancelar procesos que operan incorrectamente (por ejemplo, programas que entran en ciclos
infinitos o caen en recursividad infinita).
Evitar el deterioro del tiempo de respuesta y de las condiciones de los demás usuarios.
Por medio de la observación del comportamiento de los procesos, saber cuándo puede ser necesario
un afinamiento, y qué parámetros es necesario modificar para hacerlo.
ps [opciones]
Ejemplos:
ps produce un listado restringido a los procesos que el usuario tiene corriendo en su sesión de trabajo
actual.
La primera columna contiene el número identificador de proceso (PID, Process ID), que es un
número que identifica al proceso de forma única en el sistema.
La segunda columna (TTY) contiene el identificador del terminal en el que se está ejecutando el
proceso.
La columna TIME contiene el tiempo de uso de la CPU por parte del proceso, en minutos y
segundos.
La columna COMD contiene el nombre del proceso (en la mayoría de los casos, el nombre del
programa que se invocó).
ps -ef produce un listado de todos los procesos que estén en ejecución en el sistema.
La columna UID contiene el nombre del usuario que ordenó la ejecución del proceso.
Todo proceso posee un proceso padre (es decir, es invocado por otro proceso) a excepción del
proceso init y otros procesos especiales del sistema. En la columna PPID aparece la identificación
del padre del proceso (Parent Process ID).
La columna C contiene uno de los números que se emplea en el cálculo de la prioridad del proceso
(más acerca de este tema en el siguiente ejemplo).
Las columnas TIME y COMD se explicaron en el ejemplo anterior. Nótese, sin embargo, que la
columna COMD contiene en este caso todos los parámetros con los cuales se invocó el comando
(en el caso anterior sólo aparece el nombre del comando).
F S UID PID PPID CLS PRI NI C ADDR SZ WCHAN TTY HORA COMD
3 S 0 0 0 SYS 79 20 0 ece30fc0 0 ffff4638 ? 0:10 sysproc
42 S 0 1 0 TS 70 20 0 ece2fa80 100 c04c3194 ? 0:01 init
42 S 0 1562 1132 TS 80 20 0 de1c1aa0 302 cee8155c ? 0:01 in.telne
2 S 0 834 1 TS 80 20 0 e5dab500 82 c04b2248 ? 0:00 idmknodd
2 S 0 962 1 TS 70 20 0 df165a60 381 c04c3194 pts/0 0:00 pppd
42 S 0 883 1 TS 88 20 0 e5da9520 165 ecc06900 ? 0:00 mousemgr
2 S 0 860 1 TS 80 20 0 e5da9fc0 299 eabb687c ? 0:00 sco_pmd
42 S 0 1073 1 TS 80 20 0 df161aa0 153 de04b860 ? 0:00 cat
2 R 0 898 1 TS 59 20 0 e5da6000 204 ? 0:03 dlpid
42 O 0 1576 1564 TS 59 20 0 ece30520 65 pts/6 0:00 ps
2 S 0 975 1 TS 80 20 0 e5da8a80 347 de6a90ac ? 0:00 rpcbind
2 S 0 968 1 TS 80 20 0 e5da7fe0 380 df2c2a0c ? 0:00 in.snmpd
2 S 0 973 1 TS 80 20 0 df166500 347 df2c223c ? 0:00 hostmibd
2 S 60001 1048 1037 TS 83 20 0 df161000 1180 e5ce4e34 ? 0:00 httpd
2 S 0 936 1 TS 80 20 0 df164fc0 279 df184d2c ? 0:00 in.route
2 S 0 981 1 TS 80 20 0 e5daaa60 304 deac93cc ? 0:00 rpc.spra
2 S 0 943 1 TS 80 20 0 df163a80 431 df184b9c ? 0:00 syslogd
2 S 0 978 1 TS 80 20 0 df162fe0 304 de7e5ebc ? 0:00 rpc.rwal
2 S 0 1037 1 TS 80 20
0 e5da6aa0 1176 deac2b9c ? 0:00 httpd
2 S 0 1021 1 TS 80 20
0 df162540 473 de04ed2c ? 0:01 sendmail
2 S 60001 1042 1037 TS 80 20
0 de1c3a80 1180 de04ab40 ? 0:00 httpd
2 S 0 1049 1 TS 80 20
0 de1c4520 645 dc56eebc ? 0:00 sshd
2 S 60001 1058 1037 TS 83 20
0 de1c4fc0 1180 e6429b34 ? 0:00 httpd
2 S 60001 1059 1037 TS 83 20
0 de1c5a60 1180 e1ac3734 ? 0:00 httpd
2 S 0 1065 1 TS 80 20
0 de1c6500 1758 dc56d0ac ? 0:00 dtlogin
42 S 0 1564 1562 TS 70 20
0 d2b8f500 31 d2b8f8ac pts/6 0:00 sh
42 S 0 1129 1126 TS 80 20
0 de1c2540 293 da6a83cc ? 0:00 ttymon
2 S 0 1119 1 TS 80 20
0 df164520 343 de04e23c ? 0:00 statd
42 S 0 1126 1 TS 85 20
0 daad3500 180 da6a5b40 ? 0:00 sac
2 S 0 1114 1 TS 80 20
0 daad2a60 302 dc6133cc ? 0:00 pcnfsd
6 S 0 1103 1 TS 80 20
0 daad1fc0 0 da591414 ? 0:00 biod
2 S 0 1118 1 TS 80 20
0 daad1520 324 deac923c ? 0:00 mountd
6 S 0 1105 1 TS 80 20
0 daad0a80 0 de048610 ? 0:00 nfsd
42 S 0 1132 1126 TS 80 20
0 daacffe0 278 da22f3cc ? 0:00 inetd
c2 S 0 1246 1230 TS 80 20
0 d9646520 310 d2b03a0c ? 0:00 lpNet
6 S 0 1111 1 TS 80 20
0 daaceaa0 0 de048430 ? 0:00 nfsd
6 S 0 1112 1 TS 80 20
0 daace000 0 de048c90 ? 0:00 nfsd
2 S 0 1113 1 TS 80 20
0 da626500 422 da5b8a0c ? 0:00 lockd
42 S 102 1287 1283 TS 70 20
0 da625a60 170 da625e0c ? 0:00 remot
42 S 0 1127 1 TS 80 20
0 da624fc0 287 de04e3cc console 0:00 ttymon
2 S 0 1120 1 TS 80 20
0 da624520 298 dc6136ec ? 0:00 bootpara
c2 S 0 1135 1126 TS 80 20
0 da623a80 285 d9b4c3cc ? 0:00 listen
c2 S 0 1138 1126 TS 80 20
0 da622fe0 457 d9b4c23c ? 0:00 listen
2 S 0 1176 1 TS 80 20
0 da621aa0 181 d9525410 ? 0:00 cron
42 S 0 1140 1065 TS 80 0
0 da621000 5290 d9b61b9c vt01 0:01 Xsco
2 S 0 1145 1065 TS 85 20
0 d9647a60 1763 d9523470 ? 0:00 dtlogin
42 S 0 1407 1145 TS 80 20
0 e5da7540 1839 d12cad2c ? 0:01 dtgreet
82 S 0 1230 1 TS 80 20
0 d9645a80 328 d2b036ec ? 0:00 lpsched
2 S 0 1183 1 TS 80 20
0 d9644fe0 298 d9525230 ? 0:00 cs
2 S 0 1170 1 TS 80 20
0 d9644540 248 d9344b9c ? 0:00 keymaste
42 S 102 1293 1287 TS 80 20
0 daacf540 257 d9523040 ? 0:00 hpnpf
2 Z 102 1294 1293 0 0:00 <defunct>
2 S 0 1283 1230 TS 70 20 0 d2b8ea60 328 d2b8ee0c ? 0:00 lpsched
o T (Traced): El proceso está detenido porque está bajo el control de su padre, que actúa
como un debugger.
Las columnas UID, PID y PPID fueron discutidas en el ejemplo anterior. La única diferencia es que el
UID se presenta de modo numérico (el nombre completo estorbaría en un listado tan compacto).
Las columnas C, PRI y NI se emplean para el cálculo de la prioridad de ejecución del proceso,
mediante la fórmula NUEVA PRIORIDAD=PRI+NI+C/2. Debe notarse que mientras más alto sea el
valor de la prioridad, más lento corre el proceso.
La columna WCHAN indica la dirección del evento por el cual un proceso está dormido o en espera
de memoria.
Para terminar, el comando ps -u <usuario> despliega los procesos para un usuario en particular, y ps -t
<terminal> despliega los procesos que se están ejecutando en un terminal en particular.
Puede consultar el manual en línea de ps para obtener opciones específicas al sistema o a la versión del
sistema operativo.
Como se puede ver, la salida contiene el nombre del usuario, el terminal en el que está conectado, la
fecha y la hora de SATJR. Si se está accediendo al equipo a través de una red, también se indica el
nombre del computador desde el cual se está conectado.
Si se desea que la salida tenga encabezado como en el ejemplo, se usa la opción -H al invocar el
comando (who -H).
Este listado incluye, además de la información de los usuarios conectados, el registro de eventos como
el arranque del sistema (CVCÓNU,BAAÓ), los cambios de estado (MHRSNÍNS, MX2 y MXZ) y el arranque de
demonios y servicios importantes (sac, zsmon y tcp).
La columna IDLE puede contener un punto (.) en caso de que el terminal asociado a la conexión no
esté inactivo; el tiempo en horas y minutos de inactividad; o la palabra old en caso de que el terminal
haya estado inactivo más de 24 horas.
Como se ve, es una versión de who -a, pero únicamente incluye información sobre los usuarios
conectados.
Primero se presentan la fecha, hora actual y nombre del sistema. Luego, para cada usuario conectado se
muestran el terminal y hora de SATJR. Debajo de cada usuario aparece la lista de todos los procesos que
está ejecutando.
La primera línea despliega la hora actual, el tiempo que el sistema ha estado funcionando desde el
último arranque, y el número promedio de trabajos en la cola de listos para ejecutar, en los últimos 1, 5 y
15 minutos.
Luego, para cada usuario se muestra el terminal donde realizó el SATJR (tty) y a qué hora (login@), el
tiempo (idle) que el terminal ha estado desocupado (si esta columna aparece en blanco, el terminal está
activo en ese momento), el tiempo de procesador en minutos y segundos que han consumido todos los
procesos del usuario (JCPU), el tiempo de procesador en minutos y segundos consumido por el proceso
que el usuario está ejecutando actualmente (PCPU), y el nombre del proceso que está ejecutando
actualmente (what).
SIGHUP (e RTHE): Está identificada con el número 1. Cuando se apaga un terminal sin salirse
correctamente o se interrumpe la comunicación, el manejador de terminales envía esta señal a todos
los procesos que están corriendo en la sesión, para que terminen correctamente.
SIGQUIT (QHJÓ): Se identifica con el número 3. Esta señal es enviada cuando se presiona Ctrl-\ en el
teclado. Esto produce un vaciado de núcleo (XAMN) y la terminación del programa.
SIGKILL (FJSS): Su código es el 9. Esta señal se envía a un proceso como último recurso para
cancelarlo, ya que no puede ser ignorada.
SIGTERM (3NMUJR ÓN): Se identifica con el número 15. Esta señal se usa para indicar a un proceso
que termine. A diferencia de la anterior (que provoca la terminación abrupta del proceso), deja que el
proceso termine correctamente.
Normalmente estas señales se envían de modo automático. Sin embargo, a veces es necesario
enviarlas manualmente. El caso más común de envío manual de una señal a un proceso es cuando se
requiere cancelarlo por haberse salido de control previsto.
El comando kill se emplea para mandar una señal a un proceso. Su sintaxis es la siguiente:
La señal se puede especificar de dos maneras: Con el nombre de la señal omitiéndole el SIG, o
mediante el identificador numérico.
Ejemplo 1: Supóngase que el usuario 6JR RXJY está bloqueado (su terminal no responde). Un who -Hu
arroja el siguiente resultado:
Se puede ver que el identificador de la CONSS principal de 6JR RXJY es el 7240. Con cancelar esa CONSS basta
para desbloquear el terminal. Se usaría entonces cualquiera de los dos comandos que aparecen a
continuación:
kill -9 7240
kill -KILL 7240
Ejemplo 2: El demonio inetd actúa como despachador de servicios en los servidores UNIX conectados a
redes TCP/IP. Si se cambia el archivo de configuración de este demonio, debe informársele de los
cambios realizados. Para hacerlo, debe enviársele la señal de e RTHE. Suponiendo que el identificador
de proceso del inetd fuera el 128, se usaría uno de los dos comandos siguientes para la notificación:
kill -1 128
kill -HUP 128
Por lo tanto, el administrador de un sistema de este tipo debe estar monitoreando continuamente el
comportamiento del sistema, para tomar medidas correctivas cuando sea necesario. Las causas más
comunes del deterioro del rendimiento de un sistema son:
Escasez de memoria principal. Esto obliga al sistema operativo a hacer uso extensivo del CD E, en
detrimento del rendimiento.
Cambiando el procesador
Existe otro problema que no tiene solución de hardware por el momento, debido a las limitaciones de la
tecnología actual: El tiempo de acceso a disco.
Antes de hacer afinamiento por hardware, sin embargo, debe tratarse de hacer afinamiento por software,
es decir, cambiar parámetros de las estructuras del sistema operativo para hacer que éste se comporte
de manera más eficiente. A continuación se estudiarán algunos comandos que son de utilidad en las
labores de afinamiento y monitoreo de recursos. Un buen afinamiento por software puede evitar en
muchos casos la compra de hardware costoso.
sar [opciones] t n
Donde:
Ejemplo 1: sar -u permite obtener un reporte de la actividad del procesador. El siguiente listado se
produjo con el comando sar -u 2 5 :
10:42:32 0 0 0 98 2
10:42:34 0 4 0 87 9
10:42:36 0 2 0 94 4
10:42:38 0 0 0 98 1
10:42:40 0 3 0 95 1
Average 0 2 0 94 4
Las columnas indican, en su respectivo orden, el porcentaje de uso de la CPU por procesos de usuario,
sistema, procesos inactivos esperando I/O en modo bloque, y por último el porcentaje de inactividad del
sistema.
Si el porcentaje de inactividad cae por debajo del 30% con el uso normal del sistema (sin procesos fuera
de control), el procesador se está convirtiendo en un cuello de botella para el rendimiento del sistema.
El reporte se interpreta de la siguiente manera: Las dos primeras columnas indican el número de
transferencias del área de CD E a memoria por segundo, y la cantidad de bloques por segundo que se
transfirieron.
Las dos siguientes se interpretan análogamente a las dos anteriores, pero se aplican a las transferencias
de la memoria al área de CD E.
Idealmente, las cifras indicativas de CD E deben ser cero. Si en estas columnas se observan números
altos, quiere decir que el sistema está recurriendo demasiado al CD E, y esto va en detrimento del
rendimiento.
El comando sar permite obtener otros 13 reportes más. Para mayor información, puede consultar el
capítulo referente al Comandos de Control de Procesos, o consultar el manual en línea.
vmstat [opciones] t n
Las columnas r, b y w indican cuántos procesos hay en la cola de listos para ejcutar, cuántos están
bloqueados en espera de recursos (I/O, por ejemplo), y cuántos están en el área de CD E,
respectivamente.
La columna swap indica cuánto espacio libre hay disponible en el área de CD E; la columna free
muestra la cantidad de memoria principal disponible.
Valores muy bajos de la columna free pueden indicar escasez de memoria principal. Esto no es
crítico siempre y cuando la columna w (la tercera) permanezca en 0, ya que un valor mayor que 0
indica que hay procesos en el área de CD E, lo cual implica degradación del rendimiento.
Las columnas mf, pi, po, fr, de y sr muestran la cantidad de fallos de página y la actividad de
paginación en el sistema operativo. El afinamiento del sistema de paginación es un tema complejo,
debido a lo cual no se profundiza más en este aspecto.
Las columnas bajo el encabezamiento disk (en este caso, f0, s1 y s3) indican la cantidad de
accesos a disco por parte de los procesos.
Las columnas in, sy y cs muestran la cantidad de veces que el procesador ha sido interrumpido por
los periféricos, el número de CVCÓNU,X SSC atendidos y la cantidad de veces que el procesador ha
cambiado de proceso (CDJÓXO del procesador), respectivamente.
Por último, las columnas us, sy e id indican el porcentaje de tiempo que la CPU está atendiendo
procesos de usuario, procesos del sistema, o está inactiva, respectivamente.
Las tres últimas columnas son también de importancia capital. Si la columna id (la última) está por
debajo de 30 continuamente, indica que el procesador se está quedando corto para atender la
demanda de procesos.
El proceso no debe tener salida a pantalla, de lo contrario interferirá con el trabajo que se esté
realizando en el terminal. Si tiene salida a pantalla debe emplearse una redirección.
Para ejecutar un proceso en B XLTMAHRI se emplea el modificador & en la llamada al proceso, por
ejemplo:
Nótese que el sistema responde con un número (29030, en este caso), que corresponde al identificador
del proceso. Cuando termina el proceso, la CONSS informa de su terminación cuando el terminal esté
disponible:
Debe notarse que no todas las shells poseen esta capacidad de notificación. Las más nuevas, como
ksh, csh y tcsh sí la tienen.
Otro aspecto que se debe tener en cuenta es que los procesos en B XLTMAHRI se cancelan cuando el
usuario termina su sesión (recuérdese que el sistema manda en ese momento la señal SIGHUP a todos
los procesos del usuario). Para evitar esto, y de esta manera ejecutar los procesos en B XLTMAHRI aún
sin estar conectado al sistema, se usa el comando nohup, como en el siguiente ejemplo:
Cuando se enciende el computador o se hace un cambio de nivel (por medio de los comandos init ó
shutdown), se ejecuta una serie de procesos especiales que son definibles por el usuario. Las llamadas
a estos procesos (que se hacen generalmente mediante CXMJEÓC) se almacenan en una estructura
especial de directorios del sistema, así:
/etc
rc0.d rc1.d rc2.d
Comandos que se ejecutan al Comandos que se ejecutan al Comandos que se ejecutan al
pasar al estado 0 pasar al estado 1 pasar al estado 2
Mediante cambios en los CXMJEÓC que hay en estos directorios, el administrador del sistema puede
cambiar el comportamiento del sistema en los procesos de encendido, apagado y cambio de nivel.
Se puede especificar un incremento entre 0 y 19. Debe recordarse que mientras más grande es el valor
de la prioridad, más lentamente se ejecuta el proceso.
El súper usuario puede especificar valores negativos para el incremento, para forzar a un proceso a
ejecutarse más rápido.
Esta pantalla se actualiza cada 5 segundos, y organiza los procesos según su uso de la CPU (no
alcanza a mostrarlos todos, por limitación del espacio en la pantalla).
Identificar los pasos en el proceso de arranque es una tarea del administrador del sistema. Debe ser
capaz de resolver los problemas que se planteen en un arranque erróneo.
Este capítulo describe los pasos que necesita dar un administrador para modificar o añadir un servicio
adicional en el fichero de control del arranque. Este capítulo también examina los pasos de configuración
del kernel que forman parte del sistema de arranque. Entender el proceso de configuración del kernel es
importante para un administrador que deba añadir un nuevo servicio o dispositivo al sistema.
Un nivel de ejecución es un estado operativo del sistema. Está definido por un determinado conjunto de
servicios o procesos.
Solaris 2.x proporciona diferentes niveles de ejecución que determinan varios modos de funcionamiento
del sistema:
Nivel de Función
Ejecución
0 Nivel de PROM monitor
1 Estado de administración (Modo monousuario con algunos sistemas de ficheros
montados y con el acceso de usuarios deshabilitado)
2 Multiusuario (sin recursos compartidos)
3 Multiusuario (con recursos compartidos)
4 No usado actualmente
5 Parada (y apagado en arquitecturas Sun-4m y Sun-4u)
6 Rearrancar al nivel 3 por defecto
S, s Modo monousuario con algunos sistemas de ficheros montados y con el acceso de
usuarios deshabilitado
Monousuario
Modo monousuario significa que la consola virtual es asignada a la consola del sistema. Se suele referir
habitualmente como nivel de mantenimiento o súper usuario. Debe conocer la clave de MAAÓ para acceder
al modo monousuario. En este modo pocos procesos están activos y ningún usuario puede acceder al
sistema.
Multiusuario
Nivel multiusuario significa que todos los demonios están corriendo. Por defecto, el sistema es llevado al
nivel 3 (o estado multiusuario completo) después de que el sistema haya arrancado satisfactoriamente.
El arranque PROM lee el programa de arranque primario llamado BAAÓBSL (localizado en los sectores
1-15) que contiene el lector del sistema de ficheros ufs.
e u l M ph c e pu n p u to pt e s t pd e
d ó i n ó s tóc o
F se pd e p r r n q u e pe u l M
e u l M pc r i pe lpp r o i r m
( b o o t b lk )
B o o t b lk pc r i pe lpp r o i r m pd e
r r n q u e p(u f sb o o t )
F s e pd e pp r o i r m
dep rr nque x lpp r o i r m pd e p r r n q u e
(u f s b o o t)pc r i pe lp k e r n e l
F s e pd e pón óc ó lóz c óó n x lp k e rn e lp s e p ón óc ó ló z p y p r r n c
d e lp k e r n e l e lpp r o c e s o pón ót
Después de cargar el programa /platform/'uname - i' /ufsboot, el arranque PROM carga el LNMRNS
específico para la plataforma (/platform/'arch -k' /kernel/unix) y el LNMRNS genérico (/kernel/genunix).
El LNMRNS comienza cargando módulos usando el programa /platform/'uname -i' /ufsboot para leer los
ficheros tan pronto como se inicializa.
Cuando el LNMRNS ha leído los módulos necesarios para montar la partición de MAAÓ, descarga el programa
/platform/'uname -i'/ufsboot de la memoria y continúa inicializando el sistema usando sus propios
recursos.
La fase /sbin/init
El LNMRNS crea un proceso de usuario y arranca el programa /sbin/init. Este programa arranca procesos
usando la información del fichero /etc/inittab.
Crea los procesos que llevan al sistema al nivel de ejecución por defecto.
Controla la transición entre estados de ejecución según el contenido del fichero /etc/inittab.
El proceso init invoca un script rc, o scripts, que ejecutan otra serie de scripts. Estos scripts (/sbin/rc*)
revisan los sistema de ficheros y los montan, arranca varios procesos y realiza el control de las tareas.
s3R3.w ótR/sbón/rc3p>p/dev/consolepY>&1p<p/dev/console
initdefault Identifica el nivel de ejecución por defecto. Es el 3 por defecto en los sistemas Sun.
powerfail Arranca el proceso cuando init recibe una señal de fallo de alimentación.
sysinit Arranca el proceso antes de intentar acceder a la consola y espera a que concluya antes de
continuar.
wait Arranca el proceso y espera a que acabe antes de continuar con la siguiente entrada del rc.
ap::sysinit:/sbin/autopush -f /etc/iu.ap
fs::sysinit:/sbin/rcS >/dev/console 2>&1 </dev/console
is:3:initdefault:
p3:s1234:powerfail:/usr/sbin/shutdown -y -i5 -g0 >/dev/console 2>&1
s0:0:wait:/sbin/rc0 >/dev/console 2>&1 </dev/console
sl:1:wait:/usr/sbin/shutdown -y -iS -g0 >/dev/console 2>&1
s2:23:wait:/sbin/rc2 >/dev/console 2>&1 </dev/console
s3:3:wait:/sbin/rc3 >/dev/console 2>&1 </dev/console
s5:5:wait:/sbin/rc5 >/dev/console 2>&1 </dev/console
s6:6:wait:/sbin/rc6 >/dev/console 2>&1 </dev/console
fw:0:wait:/sbin/uadmin 2 0 >/dev/console 2>&1 </dev/console
of:5:wait:/sbin/uadmin 2 6 >/dev/console 2>&1 </dev/console
rb:6:wait:/sbin/uadmin 2 1 >/dev/console 2>&1 </dev/console
sc:234:respawn:/usr/lib/saf/sac –t 300 co:234:respawn:/usr/lib/saf/ttymon -g
-h -p "`uname –n` console login: " -T sun -d /dev/console -1 console -m
ldternn,ttcompat
Las entradas del fichero inittab indican al proceso init qué procesos debe crear para cada nivel de
ejecución y qué acción debe realizar.
El fichero /etc/inittab indica los tres datos principales para el proceso /sbin/init:
Qué acción debe llevar a cabo cuando entra en el nuevo nivel de ejecución.
/etc/inittab
/sbón/ utopush
defónepónótdef ult
comopnóvelp3
/sbón/rcG
ejecut pl spentr d s
sysónót delpc mpop /sbón/rcY
procesopinit
acción
/sbón/rc3
ejecut pl spentr d s
3pdelpc mpopestado
de ejecución /usr/lób/s f/s c
Arr nquepdel
/usr/lób/s f/ttymon
sóstem
Ilustración 16 Proceso init
El proceso init lee el fichero inittab.
El proceso init busca el nivel de ejecución por defecto leyendo las entradas initdefault.
El proceso init ejecuta los comandos o scripts para las entradas sysinit del campo XXJóR, como en
/sbin/autopush. (autopush configura una lista de los módulos que deben estar disponibles cuando
se abre un dispositivo).
El proceso init ejecuta los scripts de todas las entradas que tengan 3 en el campo NCÓ IA,IN,
NjNXHXJóR, como en los ejecutables /sbin/rc2, /sbin/rc3, /usr/lib/saf/sac y /usr/lib/saf/ttymon.
22.3 CICLO rc
22.3.1 SCRIPTS rc
En la siguiente tabla se hace una referencia del propósito de cada script rc:
Script Propósito
/sbin/rc0 Este script es usado para llevar al sistema a nivel PROM. Todos los servicios y
procesos del sistema son parados. Todos los sistemas de ficheros son
desmontados. Es el nivel básico de administración del sistema
/sbin/rc1 Históricamente, este script es usado para llevar el sistema al nivel de ejecución
1. Para alcanzar el nivel 1, el sistema ejecuta el comando shutdown como
consta en el fichero /etc/inittab.
/sbin/rc2 Este script es usado para llevar al sistema al nivel de ejecución 2 (modo
multiusuario). Todos los sistemas de ficheros son montados y todos los servicios
de red son configurados excepto para compartir sistemas de ficheros (nfs).
/sbin/rc3. Este script es usado para llevar al sistema al nivel 3 (modo multiusuario con
recursos compartidos). El proceso servidor de nfs es arrancado.
/sbin/rc5 Este script es usado para parar eléctricamente la máquina en las arquitecturas
Script Propósito
Sun-4m y Sun-4u. Se paran todos los servicios y procesos del sistema. Se
desmontan todos los sistemas de ficheros.
/sbin/rc6 Este script se usa para reiniciar el sistema. Se ejecutan los scripts /etc/rc0.d/K*.
Todos los sistemas de ficheros son desmontados Se paran todos los procesos y
servicios del sistema. Después, se ejecuta la entrada initdefault del /etc/inittab.
/sbín/rcS Este script se usa para dejar la conectividad mínima de red a los clientes sin
disco (IJCLSNCC) y sin datos (I Ó SNCC), y chequea y monta los sistemas de
ficheros MAAÓ (/) y /usr durante todos los cambios de nivel. Se crean las entradas
de los dispositivos.
Ficheros de arranque
En el directorio /etc/rc3.d, por ejemplo, hay un script para controlar los procesos NFS.
README S15nfs.server
Cambiar al nivel de ejecución 0 significa que el sistema se cierra, por lo que todos los procesos deben
ser terminados. Esto significa que el directorio /etc/rc0.d contiene sólo ficheros K*.
Como los scripts se ejecutan por orden alfabético, el fichero K57sendmail se ejecutará antes que el
K66nfs.server.
Nota - Se pueden deshabilitar usando las minúsculas al principio del nombre del fichero ("s" o "k").
rcL rcL.d
K6Lnfs.server
rcY rcY.d
G71rpc
rc3 rc3.d
G8L1lp
Ilustración 17 Directorios rc
Los scripts rc están en el directorio /sbin. Llevan al sistema a leer los ficheros relativos al directorio del
nivel de ejecución localizados en el directorio /etc. Por ejemplo, El script /sbin/rc2 leerá los ficheros
localizados en el directorio /etc/rc2.d.
Nota - Para la compatibilidad de System V con SunOS, hay scripts rc en /etc que están enlazados
simbólicamente con /sbin. Por ejemplo /etc/rc2 es un enlace simbólico con /sbin/rc2.
rcL.d KYL1lp
/etc rc1.d
lp nfs.server
rcY.d G8L1lp
Una ventaja de tener los rc en el directorio /etc/init.d es que se puede parar y arrancar servicios y
procesos individuales sin cambiar los niveles de ejecución.
# /etc/init.d/lp stop
# /etc/init.d/lp start
state=$1
$1 es una variable que representa el primer argumento. Cuando se llama al script, en state se almacena
$1. La sentencia X CN compara el valor de la variable con los valores ' start' o ' stop' . Si la variable
coincide con 'start', entonces se ejecuta el comando /usr/lib/lpsched. Si la variable coincide con 'stop',
entonces se ejecuta el comando /usr/lib/lpshut.
Lea las instrucciones del fichero /etc/init.d/README para ver un ejemplo de cómo añadir un fichero
de arranque.
Asegurarse de que el servicio que se arranca lo hace después de los servicios necesarios para un
arranque satisfactorio.
# vi /etc/init.d/rdbms
# cd /etc/rc3.d
# ln /etc/init.d/rdbms S22rdbms
# cd /etc/rc0.d
# ln /etc/init.d/rdbms K88rdbms
El proceso será automáticamente arrancado durante el arranque o COHÓIADR desde init 0. Puede
entonces arrancar y parar el proceso desde la línea de comandos.
# /etc/init.d/rdbms stop
# /etc/ini.d/rdbms start
Añada la opción -Y al demonio rpc.nisd (NIS+) para que sea compatible con NIS:
# cp /etc/init.d/rpc /etc/init.d/rpc.cop
# vi /etc/init.d/rpc
................
# EMULYP=”-Y”
................
# /etc/init.d/rpc stop
# /etc/init.d/rpc start
Un módulo de LNMRNS es un IMJÍNM de un dispositivo hardware o un componente software que se usa para
realizar una tarea específica dentro del sistema. Un ejemplo de un módulo de LNMRNS que se puede
cargar es el IMJÍNM de un dispositivo que es cargado cuando se accede al mismo.
MódulopoFG
.......................
........................
Después el LNMRNS se configura dinámicamente, cargando en memoria los módulos que necesite. Tras
arrancar, los IMJÍNMC de los dispositivos son cargados en el momento que se accede a los mismos. A este
procedimiento se le llama auto configuración porque todos los módulos de los IMJÍNMC del kernel se
cargan automáticamente cuando son necesitados.
tórectoróop/kernel drv
exec
fs
mósc
kernel
sched
strmod
sys
genunix
Ilustración 20 Directorio /kernel
Cada subdirectorio contiene unos tipos particulares de subdirectorios:
Subdirectorio Descripción
drv Contiene IMJÍNMC de dispositivos y de seudo dispositivos.
exec Contiene módulos para lanzar varios ficheros ejecutables.
fs Módulos de sistemas de ficheros (ufs, nfs y proc).
misc Contiene módulos necesarios para la memoria virtual y la comunicación entre
procesos.
sched Contiene las clases de planificación (CXONIHSJRT) y módulos de las tablas de
distribución (IJCE ÓXOJRT).
sys Contiene las llamadas al sistema como las que están involucradas en una operación
con semáforos.
tórectoróop/usr/kernel drv
fs
mósc
/usr/kernel
sched
strmod
sys
Módulos que pueden ser compartidos entre plataformas, como el IMJÍNM de audio.
Si un módulo no es cargado durante el proceso de arranque, puede ser cargado cuando el servicio sea
requerido.
Use la variable moddir para variar el camino de búsqueda de los módulos que deben ser cargados
en el arranque.
Use set variable=value para sobrescribir los parámetros que tiene por defecto el kernel.
# cp /etc/system /etc/system.cop
set pt_cnt=100
3. Reiniciar el sistema
Nota - Una discusión más profunda sobre cómo poner a punto el LNMRNS sale de los objetivos de este
capítulo. Para ver las variables del LNMRNS use sysdef.
23 NIVELES DE EJECUCIÓN
23.1 INTRODUCCIÓN
Este capítulo describe los comandos que se utilizan para cambiar el nivel de ejecución del sistema.
Una vez analizados los procesos de arranque del sistema en el capítulo anterior, vamos a ver la forma
de llevar el sistema a los posibles diferentes niveles que puede adoptar, y las características de estos
niveles, que nos permitirán realizar unas ciertas tareas de mantenimiento necesarias para la
administración del sistema.
El sistema debe tener acceso restringido para la realización de ciertas tareas de mantenimiento, como:
Copias de seguridad
Un shutdown limpio implica la detención de todos los procesos y servicios, el desmontado de los
sistemas de ficheros disponibles, y el volcado de datos en memoria a disco (sync).
Nota - Todos los comandos de cambio de nivel de ejecución requieren permisos de súper usuario.
Formato
init <012356abcQqSs>
Opción Descripción
0 Lleva la máquina al nivel de la PROM.
1 Sitúa el sistema en modo monousuario, con algunos sistemas de ficheros
montados.
2 Sitúa el sistema en modo multiusuario sin recursos compartidos.
3 Sitúa el sistema en modo multiusuario con recursos compartidos.
5 Detiene y apaga los equipos 4m y 4u.
6 Detiene y rearranca, dejando la máquina en nivel 3.
a,b,c Procesa los registros del fichero /etc/inittab que estén etiquetados como de nivel
a, b o c. Estas letras permiten personalizar el nivel de ejecución.
Q,q Relee el fichero /etc/inittab. Se utiliza habitualmente para reinicializar nuevos
puertos serie.
S,s Sitúa el sistema en modo monousuario, con algunos sistemas de ficheros
montados.
Nota - Las plataformas Intel no soportan el nivel 0, ya que no tienen el equivalente al monitor de la
PROM.
*
* Wait for the Desktop Login screen before logging in.
*
*******************************************************
Las tareas asociadas con el mantenimiento hardware del equipo o aquellas que requieren una parada
del mismo no son fáciles de prever. Sin embargo, aquellas que son rutinarias, como las de copias de
seguridad y otras, deben ser previamente planificadas para que los usuarios no se vean afectados.
Si se usa para llevar el equipo a nivel 0, el sistema operativo se cierra sin anomalías, deteniendo todos
los procesos y desmontando los sistemas de ficheros.
Formato
Opciones
Opción Descripción
y YNC. Permite continuar la operación sin intervención alguna por parte del operador. Si no
se usa esta opción el comando pedirá confirmación para continuar.
g 0M XN4ENMJAI. Periodo de gracia. Concede una cantidad de tiempo antes de proceder al
cambio. Por defecto vale 60 segundos.
i Estado de init. Permite variar el estado al que se va a llevar al sistema. Las posibilidades
son 0, 1, 5 y 6.
mensaje Texto que se mostrará a lo usuarios conectados antes de proceder a la parada.
# shutdown
Shutdown started. Thu Feb 12 10:00:51 EDT 1999
Broadcast Message from root (console) on capuser Thu Feb 12 10:00:51
The system will be shut down in 1 minute
Broadcast Message from root (console) on capuser Thu Feb 12 10:00:29
The system will be shut down in 30 seconds
Do you want to continue? (y or n): y
Broadcast Message from root (console) on capuser Thu Feb 12 10:01:51
THE SYSTEM IS BEING SHUT DOWN NOW ! ! !
Log off now or risk your files being damaged
Changing to init state s - please wait
#
#
INIT: New run level: S
INIT: SINGLE USER MODE
Type Ctrl-d to proceed with normal startup,
(or give root password for system maintenance
# shutdown -y -g 300
Shutdown started. Thu Aug 14 15:22:49 PDT 1997
#pwhop–r
.pp run-levelp GpppFebp1Yp1gR17pppGppp1pppp3
E ntód dpdepvecespenpestepnóvelpdesdepelp
últómop rr nque
Cuando haya terminado la operación de mantenimiento en el nivel S, sitúe el equipo de nuevo en el nivel
3. Pulse Control-d, teclee 6 y pulse Return.
# reboot -- -r
# reboot -- -s
Archivos que describen la relación con el sistema en el que se quiere hacer la instalación (por
ejemplo el espacio de disco requerido).
Los scripts que deben ejecutarse antes y después de la instalación (o durante la desinstalación).
Una vez que están disponibles, los paquetes de software se añaden al sistema mediante los comandos
de administración de paquetes o usando el Admintool.
# pkginfo | more
application SUNWababe Solaris 2.6 User AnswerBook Vol 2
system SUNWaccr System Accounting, (Root)
system SUNWaccu System Accounting, (Usr)
system SUNWadmfw System & Network Administration Framework
system SUNWadmr System & Network Administration Root
system SUNWarc Archive Libraries
system SUNWast Automated Security Enhancement Tools
system SUNWaudio Audio applications
Columnas
Columna Descripción
pkg_category La categoría del paquete puede ser de sistema (CVCÓNU) o de aplicación
( EESJX ÓJARW.
pkg_name El nombre del paquete; si comienza por SUNW se trata de un producto
Sun.
Description Esta columna proporciona una breve descripción del producto.
Para obtener información detallada sobre un paquete, incluido el tamaño del mismo (en bloques
de disco)
La última línea del cuadro superior nos dice el tamaño del paquete. Con este dato y con el comando
df -k se puede determinar si tiene espacio suficiente en disco para instalar el paquete.
pkgrm nombre_paquete
Después de invocar el comando pkgrm se advierte de posibles dependencias del paquete y se pregunta
si se desea abortar la operación.
# pkgrm SUNWaudio
The following package is currently installed:
SUNWaudio Audio applications
(sparc) 3.6.3,REV=0.97.06.07
Do you want to remove this package [y,n,?,q] y
## Removing installed package instance <SUNwaudio>
## Verifying package dependencies.
WARNING: The <SUNWolrte> package depends on the package currently being
removed.
WARNING: The <SUNWolaud> package depends on the package currently beíng
removed.
WARNING: The <SITNWoldcv> package depends on the package currently being
removed.
Dependency checking failed.
Do you want to continue with the removal of this package [y, n, ? , q]
El comando pkgrm usa el archivo /var/sadm/install/contents para determinar dónde se encuentran los
archivos y pkgrm actualiza este archivo después de que se haya borrado un paquete. Si dos paquetes
comparten un mismo archivo, éste sólo se borrará cuando se haya borrado el último de los paquetes.
Este comando puede comprobar un paquete entero o sólo un nombre de camino en particular si se usa
con la opción -p. No se presentará ninguna información en pantalla si no se detecta ninguna disparidad.
# pkgchk SUNWaudio
# pkgchk -p /etc/group
ERROR: /etc/group
file size <278> expected <282> actual
file cksum <23586> expected <24038> actual
El fichero /etc/group ha variado en tamaño, luego el checksum del archivo contents está desactivado.
# pkgin£o SUNWcsu
system SUNWcsu Core Sparc, (Usr)
Localización de un comando
Algunos ejemplos:
setuid puede definirse con quit para abortar el proceso de instalación si se detectan procesos
setuid.
mail puede configurarse para que se le notifique a una lista de usuarios cuando haya sido instalado
un paquete.
Los siguientes comandos pkgadd ilustran cómo mover paquetes al área de CEAAS del directorio
/var/spool/pkg:
# mkdir /export/pkgs
# pkgadd -d /cdrom/cdrom0/s0/Solaris_2.6/Product \
-s /export/pkgs SUNWaudio
Transferring <SUNWaudio> package instance
# ls /export/pkgs
Los paquetes pueden borrarse de un directorio en zona de CEAAS en el servidor con la opción -s.
dselect
tasksel
aptitude
synaptic
gsynaptic
Los programas listados anteriormente están basados en APT. APT permite instalar y desinstalar
paquetes de forma manual desde la línea de comandos. APT es el acrónimo de AIÍ RXNI,i XL TJRT,
3AAS, que es el sistema de gestión de paquetes creado por Debian.
nombre-del-paquete_version(1.3.34-5).deb
La distribución Debian tiene diversas utilidades para la instalación de paquetes, entre ellas, APT, que
permite la instalación de paquetes de forma fácil y rápida, advirtiendo de las dependencias y
recomendando paquetes. El sistema APT engloba varios comandos como: apt-get, apt-cache,
apt-cdrom, etc.
File (podemos elegir un directorio arbitrario de donde bajar los paquetes; esto es útil para UJMMAMC
locales o carpetas NTFS)
De un CD-ROM
De un servidor FTP
Por rsh/ssh.
La diferencia entre deb y deb-src es que el primero indica la descarga de paquetes .deb, que son
ficheros binarios, es decir, preparados para ejecutarse, mientras que con el segundo podemos
descargarnos el código fuente del paquete (usando el comando apt-get source).
La siguiente parte de la línea es el URI, es decir, el tipo de sistema para la descarga, recordemos que
existen varios (file, cdrom, ftp, http, rsh/ssh). En este caso es de un servidor Web.
Seguidamente escribimos la localización del UJMMAM de paquetes, este caso tenemos varias líneas con
diferente localización, esto se debe a que en los Estados Unidas es ilegal utilizar aplicaciones de
encriptación, así que para bajar esos programas, existen líneas especiales que contienen la palabra
RAR4P5. Después de la localización, separado por un espacio, se escribe la versión de Debian, siendo
válido tanto el alias de la versión como en qué estado se encuentra (stable, unstable, testing).
Por último se escriben las secciones de software que usaremos (main, contrib, non-free). Debian
organiza los paquetes en varias carpetas según su licencia.
La sección main agrupa los paquetes en los que su licencia cumple con los criterios de la DGFS (Guías
de Debian del Software libre).
La sección contrib agrupa paquetes que tiene una licencia libre pero que sin embargo dependen de
otros paquetes que no cumple con las normas del DGFS.
Y por último, la sección non-free contienen paquetes que son de libre distribución pero que sin embargo
no cumplen las directrices de la DGFS (no distribuye el código, no se permite redistribuir el código, etc.)
En este archivo aquellas líneas que comienzan con # son las que son comentarios.
http://www.debian.org/mirror/mirrors_full
Si no se dispone de conexión a Internet lo normal es que el fichero sources.list contenga líneas que
apunten al medio de instalación que hemos usado para realizar la instalación. Si por ejemplo la hemos
instalado desde un CD-ROM, en el fichero podríamos encontrar líneas similares a esta:
24.7.2 APT-GET
El comando apt-get se utiliza para la manipulación de paquetes deb. Permite la instalación de paquetes,
borrado, etc.
Instala paquetes.
Borra paquetes.
apt-get update
apt-get upgrade
apt-get dist-upgrade
Función adicional de la opción upgrade que modifica las dependencias por la de las nuevas versiones
de los paquetes.
Instala los paquetes necesarios para la compilación del código fuente de los paquetes.
apt-get clean
-d, —download-only
-f, -fix-broken
Esta opción es importante, intenta arreglar problemas de dependencias que tengamos en el sistema.
-s, -simulate
-b, -build
24.7.3 APT-CACHE
El comando apt-cache trabaja con la caché de los paquetes. Este comando no manipula el estado del
sistema, así que lo pueden usar usuarios normales. Es de gran utilidad ya que nos muestra información
valiosa sobre los paquetes.
Este comando muestra la cabecera de los paquetes. Muestra el desarrollador, las dependencias, una
breve descripción del mismo, su tamaño, y el nombre del fichero donde se encuentra, entre otros.
Muestra una lista de todos los paquetes y una breve descripción relacionada con el texto que hemos
buscado.
apt-cache stats
/usr/share/doc/apt/examples/configure-index.gz
24.7.5 APT-CDROM
El comando apt-cdrom permite añadir nuevos CD-ROM al sources.list. Para añadir un CD-ROM, la
orden es apt-cdrom add
Buscará en los repositorios que tengamos configurados la lista con las últimas versiones de paquetes
disponibles y actualizará la lista de paquetes.
Antes de ejecutar el comando lo normal suele ser combinarlo con el comando apt-get update para
actualizar la lista de paquetes, y una vez actualizada, que se actualicen aquellos paquetes de los que
haya una versión superior a la disponible. Un ejemplo sería:
Si quisieramos solo actualizar un paquete del que hemos detectado que hay una versión más nueva, se
hace de la siguiente forma:
cdrom
http
ftp
Sistema de ficheros local
Editar manualmente la lista de fuentes
Para el caso de cdrom, nos irá solicitando los CD que queramos ir añadiendo.
Para los casos de http y ftp nos mostrará una lista con los diferentes servidores que hay disponibles
para que los seleccionemos a nuestro gusto.
En el caso del sistema de ficheros local, habrá que indicarle donde están los paquetes que deseamos
que se instalen.
Por último la opción de editar manualmente la lista de ficheros, lo que hace es abrir el fichero
sources.list con el editor que tengamos asociado, para configurarlo manualmente.
Ejemplo:
cd /etc/apt
netselect-apt stable
Estos archivos no se borran hasta que no se le indique. El motivo de quedar en caché es por necesidad
de instalar de nuevo el programa; en vez de ir a descargarlo de Internet o desde las fuentes de APT, se
mantienen en los directorios de caché para reinstalaciones posteriores más rápidas.
Al mantener las cachés en el sistema, estas van ocupando cierto espacio que en ocasiones puede llegar
a ocupar demasiado espacio. Para borrar esos ficheros podemos, o bien borrar el contenido del
directorio, o bien ejecutar el comando apt-get clean.
Existe también el comando apt-get autoclean que borra de la cache aquellos paquetes que son inútiles
o innecesarios.
El fichero /etc/profile
Otorga valor a la variable TERM para especificar el tipo de terminal por defecto.
skel
Nota - Admintool copia automáticamente los ficheros mencionados al directorio del usuario y los
renombra con los nombres de los ficheros ocultos. Admintool no lee los ficheros . kshrc ni local.kshrc
para la Korn CONSS.
El carácter almohadilla (#) en el fichero anterior se utiliza para comentar líneas, de modo que éstas no
son ejecutadas. La personalización del fichero .profile para cada usuario depende de las aplicaciones
que utilice y de otros aspectos de su entorno de trabajo, como editores de texto o impresoras.
DBTEMP="/tmp"
# DBPATH --> Directorios de localizacion de las Bases de Datos definidas
# y de residencia de los listados ".ace" y ".arc" (I-SQL)
DBPATH="$HOME/:$HOME/listados"
# DBDATE --> Parametrizacion de Campos Fecha
DBDATE="DMY4-"
# DBEDIT --> Comando a utilizar para edicion en Informix
DBEDIT="vi"
# DBMONEY --> Formato de Salida para Campos 'decimal'
# No utilizados actualmente por INGENIX-"MAC"
DBMONEY=".Pts"
# DBDELIMITER --> Caracter separador de campos para carga y descarga de datos
DBDELIMITER="~"
# DBPRINT --> Comando de impresion utilizado por Informix
DBPRINT="lp"
# SQLEXEC --> Tipo de agente de base de datos Informix utilizado
SQLEXEC="$MACINF/lib/sqlexec"
# ISAMBUFS --> Buffers C-ISAM a utilizar (4 por Indice activo)
# La variable ISAMBUFS se debe calcular de la siguiente forma:
# Numero Maximo de Indices activos en cada momento x 4 = Valor de ISAMBUFS
# Inicialmente esta parametrizado de la siguiente forma:
# Cada Fichero abierto tiene activado un Indice. Estimo un maximo de 10 Fi-
# cheros abiertos por proceso, con lo cual se ajusta al valor '40'
ISAMBUFS=40
export DBTEMP DBPATH DBDATE DBEDIT DBMONEY DBDELIMITER DBPRINT SQLEXEC
export ISAMBUFS INFORMIXDIR
# Environment de INGENIX-"MAC"
#
# MACDEFINE --> Residencia de Diccionarios
MACDEFINE="$HOME/define"
# MACSQL --> Residencia de Sentencias SQL
MACSQL="$HOME/sql"
# MACMENSA --> Residencia de Ficheros de Mensajes
MACMENSA="$MACHOM/mensa"
# MACPROGC --> Residencia de Fuentes de programas en lenguaje "C"
MACPROGC="$HOME/progc"
# MACBIN --> Residencia de programas Objeto y Ejecutables
MACBIN="$MACHOM/bin"
# MACPANT --> Residencia de Pantallas de Ficheros y Listados, y Menus
MACPANT="$HOME/screen"
# MACRELAC --> Residencia de Relaciones, Actualizaciones e Integridad
MACRELAC="$HOME/setup"
# MACVENTA --> Residencia de Ventanas
MACVENTA="$HOME/win"
# MACGENER --> Residencia de Parametros de Generacion de programas
MACGENER="$HOME/gen"
# MACMOD --> Residencia de Modelos y Varios de INGENIX-"MAC"
MACMOD="$MACHOM/datos"
# MACCARP --> Residencia de Carpetas de programas
MACCARP="$HOME/carpetas"
# MACCOPIAS --> Residencia de Control de Ficheros e Historico de Copias
MACCOPIAS="$HOME/copseg"
# MACSPOOL --> Residencia de Control del 'spool' de INGENIX-"MAC"
MACSPOOL="/usr/spool/mac_spool"
# MACINCLUDE --> Residencia de Ficheros de "include" de la aplicacion
MACINCLUDE="$HOME/include"
# MACLIB --> Residencia de Fuentes y Objetos de Libreria de aplicacion
MACLIB="$HOME/lib"
# MACCISAM --> Residencia Ficheros C-ISAM de Control y Diccionarios Tipo C
MACCISAM="$HOME/cisam"
# MACCURSES --> Nombre de la Opcion de Compilacion de Programas "C", para
# poder utiizar la Libreria 'curses' de Gestión de Terminal.
MACCURSES="-lcurses"
# MACFLAGS --> Flags de Compilacion de progamas generados o mantenidos con
# INGENIX-"MAC". Modificables por el Usuario
# Para IBM-RISC Serie 6000 colocar el 'flag' de compilacion
# -DNLS para asumir el 'National Support Languaje'.
# Poner los Nmbres de todas las Librerias de Compilacion
MACFLAGS="-I$MACINCLUDE -L$MACLIB -lmac $MACCURSES -lisam -lm"
# MACDESCAR --> Residencia de Ficheros secuenciales de descraga de la B.D.
# Comando "unload"
MACDESCAR="$HOME/descarga"
# MACLIBUSU --> Nombre de la Libreria de Usuario a utilizar en la Aplica-
# cion. Viene definido para el Nombre 'libusu'. Cambiarlo en
# caso necesario.
MACLIBUSU="libusu"
# MACTMP --> Residencia de Ficheros Temporales (y de otro uso) de
# INGENIX-"MAC"
MACTMP="$HOME/tmp"
# Ajuste del Fichero de Configuracion del Spooler del Sistema disponible
# El Fichero base de configuracion de Impresoras esta en /usr/spool/colas/cf
# Si se desea su reconfiguracion, se debe ajustar la Variable de Entorno
# MACIMPRE
MACIMPRE="/usr/spool/colas"
# Ajuste de Ficheros de Impresoras disponibles segun el Usuario de conexion.
# El Fichero base de configuracion de Impresoras esta en /usr/spool/conf_get
# Si se desea su reconfiguracion por Usuario, se debe ajustar en la siguiente
# tabla 'switch' y colocar dicho FICHERO en la Variable de Entorno MACCONFGET
case $LOGNAME in
# "xxxxx")
# MACCONFGET="$HOME/CONF_GET/xxxxx" ;;
default)
MACCONFGET="/usr/spool/conf_get";;
esac
export MACDEFINE MACSQL MACMENSA MACPROGC MACBIN MACPANT MACRELAC MACGENER
export MACMOD MACCARP MACCOPIAS MACSPOOL MACINCLUDE MACLIB MACCISAM MACFLAGS
export MACDESCAR MACCURSES MACLIBUSU MACVENTA
# Visualizacion de entrada. Solicitud del Tipo de Terminal a utilizar
tput clear
echo ""; echo "S.O. UNIX System V. Usuario: \c"; tput rev; tput blink
echo $LOGNAME
tput sgr0; echo "Conexion como Tipo de TERMINAL: \c"; tput smul
echo "$TERM\c"
tput sgr0; echo ". Linea `tty`."; echo "";
date '+Fecha: %d/%m/%y. Hora: %T.'
echo "DIRECTORIO de trabajo: \c"
tput rev; echo `pwd`; tput sgr0; echo ""
echo "Tipos de TERMINALES disponibles ....................................."
echo "---------------------------------------------------------------------"
tput bold
echo "vt220 vt100 d220 d220-w uvt1224 u220"
tput sgr0
echo "DEC-vt220 DEC-vt100 DSI-vt220 DSI-132col Unisys-uvt1224 Uniplex-vt220"
echo "---------------------------------------------------------------------"
echo ""; echo "Digite el Tipo de su Terminal \c"; tput bold
echo " <RETN - asume /"$TERM/">: \c"; tput sgr0
read TER
if test -z "$TER"
then
TER=$TERM
fi
case $TER in
"d220")
TERM="d220";;
"d220-w")
TERM="d220-w";;
"uvt1224")
TERM="uvt1224";;
"vt100")
TERM="vt100";;
"vt220")
TERM="vt220";;
"u220")
TERM="u220";;
esac
export TERM
echo ""
# CONTROL DE CORREO 'mail' DESACTIVADO. ACTIVARLO EN CASO NECESARIO.
# Chequeo de Correo
# 'mail -e' -> No visualiza Correo. Retorna '0' si existe Correo.
# En algunas implementaciones UNIX la opcion '-e' tiene otro nombre. Verifica
# No visualiza Correo. Retorna '0' si existe Correo
# TER=`mail -e`
# if [ $? -eq 0 ]
# then
# echo "Tiene CORREO en el Sistema, dejado por otro Usuario"
# echo "Digite <mail> para visualizarlo"
# echo ""
# fi
# Ajuste de parametros de 'tty'
stty erase ' ' echoe echok
stty -xcase -iuclc -olcuc
# Mascara de creacion de ficheros 'rwxr-----'
umask 027
# Sentencias para ejecutar menus de aplicacion segun el Usuario de 'login'
# Modificar segun la filosofia de trabajo de la aplicacion.
# Mostramos un posible ejemplo
#
# case $LOGNAME in
# "usuario1" | "usuario2")
# exec menu1;;
# "usuario3" | "usuario4")
# exec menu2;;
# "usuariox" | "usuarion")
# exec menux;;
# esac
set noclobber
set prompt="<$LOGNAME> ! => "
# Environment GENERAL
# TZ ajusta la hora del sistema para el Usuario segun Zona Horaria definida
setenv TZ GMT-0:0
# Colocar en PATH los siguientes directorios de busqueda
# . --> Directorio actual en el que se esta posicionado
# /bin --> Residencia de comandos del Sistema
# /usr/bin --> Otros comandos del Sistema
# /usr/lbin --> Otros comandos del Sistema
# /etc --> Comandos y Ficheros de Control del Sistema
# /usr/ucb --> Residencia de la 'csh' (en determinados sistemas)
# $MACHOM/bin --> Comandos de INGENIX-"MAC"
# $MACINF/bin --> Comandos de productos INFORMIX
# $HOME/bin --> Comandos y Programas propios del usuario
# ........... --> Otros directorios de busqueda
setenv PATH
".:$HOME/bin:$MACHOM/bin:/bin:/usr/bin:/usr/lbin:/etc:/usr/ucb:$MACINF/bin"
# Variable utizado por el comando 'vi'
setenv EXINIT "set redraw sw=4 report=2"
# TERMINFO por defecto en /usr/lib/terminfo
# TERMCAP por defecto en /etc/termcap
# Caso de querer ajustar estas variables poner directorios correspondientes
# setenv TERMINFO "/...../...../terminfo"
# setenv TERMCAP "/...../...../termcap"
# Environment de INFORMIX
# INFORMIXDIR --> Residencia de Ficheros de INFORMIX
setenv INFORMIXDIR "$MACINF"
# DBTEMP --> Residencia de Ficheros Temporales
# Cambiarla en caso necesario, por otra residencia de Temporales INFORMIX
setenv DBTEMP "/tmp"
# DBPATH --> Directorios de localizacion de las Bases de Datos definidas
# y de residencia de los listados ".ace" y ".arc" (I-SQL)
setenv DBPATH "$HOME/:$HOME/listados"
# DBDATE --> Parametrizacion de Campos Fecha
setenv DBDATE DMY4-
# DBEDIT --> Comando a utilizar para edicion en Informix
setenv DBEDIT vi
# DBMONEY --> Formato de Salida para Campos 'decimal'
# No utilizados actualmente por INGENIX-"MAC"
setenv DBMONEY .Pts
# DBDELIMITER --> Caracter separador de campos para carga y descarga de datos
setenv DBDELIMITER "~"
# DBPRINT --> Comando de impresion utilizado por Informix
setenv DBPRINT "lp"
# SQLEXEC --> Tipo de agente de Base de Datos Informix usado (SE-Online)
setenv SQLEXEC "$MACINF/lib/sqlexec"
# ISAMBUFS --> Buffers C-ISAM a utilizar (4 por Indice activo)
# La variable ISAMBUFS se debe calcular de la siguiente forma:
# Numero Maximo de Indices activos en cada momento x 4 = Valor de ISAMBUFS
# Inicialmente esta parametrizado de la siguiente forma:
# Cada Fichero abierto tiene activado un Indice. Estimo un maximo de 10 Fi-
# cheros abiertos por proceso, con lo cual se ajusta al valor '40'
setenv ISAMBUFS 40
# Environment de INGENIX-"MAC"
#
# MACDEFINE --> Residencia de Diccionarios
setenv MACDEFINE "$HOME/define"
# MACSQL --> Residencia de Sentencias SQL
setenv MACSQL "$HOME/sql"
# MACMENSA --> Residencia de Ficheros de Mensajes
breaksw
endsw
tput clear
# alias definidos para trabajo en desarrollo
#
alias h history
alias lis "ls -C | more"
alias rm rm -i
alias ldir "/bin/ls -pl | grep '/' | more"
alias fixtty1 "stty sane tab3 erase '^h' echoe echok"
alias fixtty2 "stty tab3 erase ' ' echoe echok"
# Modificar el 'device' del Dispositivo fisico de Copias
alias acinta1 "find . -print | cpio -ocvB | dd of=/dev/DEVICE bs=128k"
alias acinta2 "find . -print | cpio -ocvB | dd of=/dev/DEVICE bs=900k"
alias decinta1 "dd if=/dev/DEVICE bs=128k | cpio -icvdB"
alias decinta2 "dd if=/dev/DEVICE bs=900k | cpio -icvdB"
# Caso de que la maquina tenga mas de un Streamer (para cintas de 45 MB.)
alias cop_45 "find . -print | cpio -ocvB | dd of=/dev/rstp/35yy bs=128k"
alias rec_45 "dd if=/dev/rstp/35yy bs=128k | cpio -icvdB"
alias codbs1 "find prueba.dbs -print | cpio -ocvB | dd of=copia1 bs=900k"
alias codbs2 "find prueba.dbs -print | cpio -ocvB | dd of=copia2 bs=900k"
alias codbs3 "find prueba.dbs -print | cpio -ocvB | dd of=copia3 bs=900k"
alias redbs1 "cpio -icvduB < copia1"
alias redbs2 "cpio -icvduB < copia2"
alias redbs3 "cpio -icvduB < copia3"
alias ls ls -C
breaksw
case "vt220":
setenv TERM vt220
breaksw
case "u220":
setenv TERM u220
breaksw
default:
breaksw
endsw
echo ""
# CONTROL DE CORREO 'mail' DESACTIVADO. ACTIVARLO EN CASO NECESARIO.
# Chequeo de Correo
# 'mail -e' -> No visualiza Correo. Retorna '0' si existe Correo.
# En algunas implementaciones de UNIX la opcion '-e' tiene otro nombre.
Verifica
# No visualiza Correo. Retorna '0' si existe Correo
# set TER = `mail -e`
# if ( $status == 0) then
# echo "Tiene CORREO en el Sistema, dejado por otro Usuario"
# echo "Digite <mail> para visualizarlo"
# echo ""
# endif
# Ajuste de parametros de 'tty'
stty erase ' ' echoe echok
stty -xcase -iuclc -olcuc
set shell="/bin/sh"
# Variable de PORTNG para Compilaciones de Programas "C"
# OPCION -DOCHO --> Indica que el Sistema procesa caracteres de 8 bits en su
# gestion de Terminal.
# -DNLS --> Para el S.O. AIX-IBM, permite el trabajar con el
'National
# Languaje Support'
setenv PORT "-DOCHO -DNLS"
# Mascara de creacion de ficheros 'rwxr-----'
umask 027
Los siguientes ejemplos muestran cómo ejecutar los ficheros .profile y .kshrc, respectivamente, desde
la línea de comandos:
$ . ./.profile
$ . ./.kshrc
C Shell
Los siguientes ejemplos muestran como ejecutar los ficheros .login y .cshrc, respectivamente, desde la
línea de comandos:
% source ./.login
% source ./.cshrc
INDICE DE ILUSTRACIONES
Ilustración 1 Los archivos y carpetas se organizan jerárquicamente. ..................................................... 55
Ilustración 2 Ken Thompson y Dennis Ritchie, creadores de Unix.......................................................... 60
Ilustración 3 Desarrollo de familias UNIX............................................................................................... 66
Ilustración 4 Kernel ............................................................................................................................... 67
Ilustración 5 kernel y shell ..................................................................................................................... 68
Ilustración 6 El modelo cliente-servidor para estaciones de trabajo en red............................................. 70
Ilustración 7. Esquema básico interno de una máquina. Relación con UNIX.......................................... 72
Ilustración 8. Esquema básico interno de una máquina. Relación con UNIX.......................................... 73
Ilustración 9 Arquitectura de niveles del modelo OSI ............................................................................. 85
Ilustración 10 Diagrama de una arquitectura lógica de red (red única) en un entorno de PCs Virtuales.. 89
Ilustración 11 Diagrama de una arquitectura lógica de red (múltiples redes) en un entorno de PCs
Virtuales......................................................................................................................................... 90
Ilustración 12 Diagrama de utilización de memoria por un proceso .......................................................164
Ilustración 13 Memoria y breakpoints ...................................................................................................165
Ilustración 14 Fases de Arranque de un sistema ..................................................................................355
Ilustración 15 Fichero /etc/inittab ..........................................................................................................356
Ilustración 16 Proceso init ....................................................................................................................358
Ilustración 17 Directorios rc ..................................................................................................................360
Ilustración 18 Directorio /etc/init.d.........................................................................................................361
Ilustración 19 Módulos del kernel .........................................................................................................363
Ilustración 20 Directorio /kernel ............................................................................................................364
Ilustración 21 Directorio /usr/kernel ......................................................................................................365
Ilustración 22 Identificación del nivel de ejecución actual......................................................................371
Ilustración 23 Directorio /etc/skel..........................................................................................................384
BIBLIOGRAFIA
“Kernighan-Pike[1984]
Kernighan, Brian y Pike, Rob. "El entorno de programación UNIX", Prentice Hall, 1987 (Edición en inglés
de 1984).
“Morgan-McGilton[1989]
Morgan, Rachel y McGilton, Henry. "Introducción al UNIX Sistema V", McGraw-Hill, 1989 (Edición en
inglés de 1987).
“Coffin[1989]
Coffin, Stephen. "UNIX System V Release 4, the Complete Reference", Osborne McGraw-Hill, 1989.
“Welsh[1995]
Welsh, Matt. "Linux installation and getting started guide".
“Greenfield[]
Greenfield, Larry. "The Linux User's Guide".
“Tanenbaum[1992]
Tanenbaum, Andrew, "Sistemas operativos modernos", Prentice Hall, 1993 (Edición en inglés de 1992).
“Real world Unix. Managing a business with the Unix operating system”
Halanka, J.D.
1.984
“The Unix System Guide book. An introductory guide for serious users”
Silvester, P.P.
1984
“Comunicaciones en UNIX”
Jean-Marie Rifflet
McGraw-Hill
París, 1990
“Linux. 4ª Edición”
Jack Tackett, Jr. & Steve Burnett
Ed. Prentice may
1999
“Seguridad en UNIX”
Manuel Mediavilla
Ra-ma Editorial
Madrid, 1997
Brown, Robert G
Duke University, Physics Department
Book: Engineering a Beiowulf-style Computer XSHCÓNM.
http://www.phy.duke.edu/rgb
CATALÁN, MIQUEL
http://www.urjc.es/cat/hidra/manuales/openMosix/howToopenMosixES_
0.4beta.pdf
CATALÁN, MIQUEL
http://es.tldp.org/Manuales-LuCAS/doc-manual-openMosix-1.0/doc-manualopenMosix-1.0.pdf
CHIRINOV, ROUMEN
Proyecto XSHCÓNM openMosix (Linux)
http://www.noticias3d.com/articulo.asp?idarticulo=248&pag=2
OLEA, ISMAEL.
Introducción a los XSHCÓNM de computadoras
http://es.tldp.org/Manuales-LuCAS/doc-XSHCÓNM-computadoras/doc-XSHCÓNMcomputadoras-html/node7.html
WikiLearning
Wikipedia
CONTRAPORTADA
Desde su aparición comercial a finales de los años 70, el sistema operativo UNIX se ha convertido en un
estándar de mercado para los modernos microordenadores multiusuario y multitarea, aumentando
considerablemente el número de fabricantes y usuarios que hacen uso del mismo en los más diversos
campos de aplicación.
Espero haber conseguido reflejar los conceptos base sobre los que se sustenta el sistema, y servir de
inicio clarificador para futuros excelentes técnicos administradores de este sistema.